1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.exoplatform.ecm.webui.component.explorer.symlink;
18 import java.security.AccessControlException;
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import javax.jcr.AccessDeniedException;
23 import javax.jcr.ItemExistsException;
24 import javax.jcr.ItemNotFoundException;
25 import javax.jcr.Node;
26 import javax.jcr.RepositoryException;
27 import javax.jcr.UnsupportedRepositoryOperationException;
28 import javax.jcr.nodetype.ConstraintViolationException;
29
30 import org.apache.commons.lang.StringUtils;
31 import org.exoplatform.ecm.webui.component.explorer.UIJCRExplorer;
32 import org.exoplatform.ecm.webui.selector.UISelectable;
33 import org.exoplatform.ecm.webui.tree.selectone.UIOneNodePathSelector;
34 import org.exoplatform.ecm.webui.utils.Utils;
35 import org.exoplatform.services.cms.drives.DriveData;
36 import org.exoplatform.services.cms.drives.ManageDriveService;
37 import org.exoplatform.services.cms.i18n.MultiLanguageService;
38 import org.exoplatform.services.cms.link.LinkManager;
39 import org.exoplatform.services.cms.link.NodeFinder;
40 import org.exoplatform.services.exceptions.SameAsDefaultLangException;
41 import org.exoplatform.services.jcr.util.Text;
42 import org.exoplatform.services.log.ExoLogger;
43 import org.exoplatform.services.log.Log;
44 import org.exoplatform.services.wcm.utils.WCMCoreUtils;
45 import org.exoplatform.wcm.webui.selector.content.one.UIContentBrowsePanelOne;
46 import org.exoplatform.wcm.webui.selector.content.one.UIContentSelectorOne;
47 import org.exoplatform.web.application.ApplicationMessage;
48 import org.exoplatform.webui.config.annotation.ComponentConfig;
49 import org.exoplatform.webui.config.annotation.ComponentConfigs;
50 import org.exoplatform.webui.config.annotation.EventConfig;
51 import org.exoplatform.webui.core.UIApplication;
52 import org.exoplatform.webui.core.UIComponent;
53 import org.exoplatform.webui.core.UIPopupComponent;
54 import org.exoplatform.webui.core.UIPopupWindow;
55 import org.exoplatform.webui.core.lifecycle.UIFormLifecycle;
56 import org.exoplatform.webui.event.Event;
57 import org.exoplatform.webui.event.EventListener;
58 import org.exoplatform.webui.event.Event.Phase;
59 import org.exoplatform.webui.form.UIForm;
60 import org.exoplatform.webui.form.UIFormMultiValueInputSet;
61 import org.exoplatform.webui.form.UIFormStringInput;
62 import org.exoplatform.webui.form.validator.MandatoryValidator;
63
64
65
66
67
68
69
70 @ComponentConfigs( {
71 @ComponentConfig(lifecycle = UIFormLifecycle.class, template = "system:/groovy/webui/form/UIForm.gtmpl", events = {
72 @EventConfig(listeners = UISymLinkForm.SaveActionListener.class),
73 @EventConfig(listeners = UISymLinkForm.CancelActionListener.class, phase = Phase.DECODE) }),
74 @ComponentConfig(type = UIFormMultiValueInputSet.class, id = "SymLinkMultipleInputset", events = {
75 @EventConfig(listeners = UISymLinkForm.RemoveActionListener.class, phase = Phase.DECODE),
76 @EventConfig(listeners = UISymLinkForm.AddActionListener.class, phase = Phase.DECODE) }) })
77
78 public class UISymLinkForm extends UIForm implements UIPopupComponent, UISelectable {
79
80
81
82
83 private static final Log LOG = ExoLogger.getLogger(UISymLinkForm.class.getName());
84
85 final static public String FIELD_NAME = "symLinkName";
86 final static public String FIELD_PATH = "pathNode";
87 final static public String FIELD_SYMLINK = "fieldPathNode";
88 final static public String POPUP_SYMLINK = "UIPopupSymLink";
89 final static public String DEFAULT_NAME = "untitled";
90
91 final static public byte DRIVE_SELECTOR_MODE = 0;
92 final static public byte WORSPACE_SELECTOR_MODE = 1;
93
94 private byte selectorMode=DRIVE_SELECTOR_MODE;
95
96 private boolean localizationMode = false;
97
98 public UISymLinkForm() throws Exception {
99 }
100
101 public void activate() {}
102 public void deActivate() {}
103
104 public void initFieldInput() throws Exception {
105 UIFormMultiValueInputSet uiFormMultiValue = createUIComponent(UIFormMultiValueInputSet.class,
106 "SymLinkMultipleInputset",
107 null);
108 uiFormMultiValue.setId(FIELD_PATH);
109 uiFormMultiValue.setName(FIELD_PATH);
110 uiFormMultiValue.setEditable(false);
111 uiFormMultiValue.setType(UIFormStringInput.class);
112 addUIFormInput(uiFormMultiValue);
113 if (!localizationMode)
114 addUIFormInput(new UIFormStringInput(FIELD_NAME, FIELD_NAME, null).addValidator(MandatoryValidator.class));
115 }
116
117 public void enableLocalizationMode() {
118 this.localizationMode = true;
119 }
120
121 public void doSelect(String selectField, Object value) throws Exception {
122 String valueNodeName = String.valueOf(value).trim();
123 String workspaceName = valueNodeName.substring(0, valueNodeName.lastIndexOf(":/"));
124 valueNodeName = valueNodeName.substring(workspaceName.lastIndexOf(":")+1);
125 List<String> listNodeName = new ArrayList<String>();
126 listNodeName.add(valueNodeName);
127 UIFormMultiValueInputSet uiFormMultiValueInputSet = getChild(UIFormMultiValueInputSet.class);
128 uiFormMultiValueInputSet.setValue(listNodeName);
129 String symLinkName = valueNodeName.substring(valueNodeName.lastIndexOf("/") + 1);
130 int squareBracketIndex = symLinkName.indexOf('[');
131 if (squareBracketIndex > -1)
132 symLinkName = symLinkName.substring(0, squareBracketIndex);
133 if (symLinkName.indexOf(".lnk") < 0) {
134 StringBuffer sb = new StringBuffer();
135 sb.append(symLinkName).append(".lnk");
136 symLinkName = sb.toString();
137 }
138 symLinkName = Text.unescapeIllegalJcrChars(symLinkName);
139 if (!localizationMode) getUIStringInput(FIELD_NAME).setValue(symLinkName);
140 UISymLinkManager uiSymLinkManager = getParent();
141 uiSymLinkManager.removeChildById(POPUP_SYMLINK);
142 }
143
144 static public class SaveActionListener extends EventListener<UISymLinkForm> {
145 public void execute(Event<UISymLinkForm> event) throws Exception {
146 UISymLinkForm uiSymLinkForm = event.getSource();
147 UIJCRExplorer uiExplorer = uiSymLinkForm.getAncestorOfType(UIJCRExplorer.class);
148 UIApplication uiApp = uiSymLinkForm.getAncestorOfType(UIApplication.class);
149 String symLinkName = "";
150 String symLinkTitle = "";
151 if (!uiSymLinkForm.localizationMode) symLinkName = uiSymLinkForm.getUIStringInput(FIELD_NAME).getValue();
152
153 String pathNode = "";
154 UIFormMultiValueInputSet uiSet = uiSymLinkForm.getChild(UIFormMultiValueInputSet.class);
155 List<UIComponent> listChildren = uiSet.getChildren();
156 for (UIComponent component : listChildren) {
157 UIFormStringInput uiStringInput = (UIFormStringInput)component;
158 if(uiStringInput.getValue() != null) {
159 pathNode = uiStringInput.getValue().trim();
160 }
161 }
162
163 Node node = uiExplorer.getCurrentNode() ;
164 if(uiExplorer.nodeIsLocked(node)) {
165 uiApp.addMessage(new ApplicationMessage("UIPopupMenu.msg.node-locked", null)) ;
166 return ;
167 }
168 symLinkTitle = symLinkName;
169 symLinkName = org.exoplatform.services.cms.impl.Utils.cleanString(symLinkName);
170 if (StringUtils.isEmpty(symLinkName)) {
171 symLinkName = DEFAULT_NAME;
172 }
173
174 if(!uiSymLinkForm.localizationMode && StringUtils.isEmpty(symLinkTitle)) {
175 uiApp.addMessage(new ApplicationMessage("UISymLinkForm.msg.name-invalid", null)) ;
176 return ;
177 }
178 if(pathNode == null || pathNode.length() ==0) {
179 uiApp.addMessage(new ApplicationMessage("UISymLinkForm.msg.path-node-invalid", null));
180
181 return ;
182 }
183 String workspaceName = pathNode.substring(0, pathNode.lastIndexOf(":/"));
184 pathNode = pathNode.substring(pathNode.lastIndexOf(":/") + 1);
185
186 NodeFinder nodeFinder = uiSymLinkForm.getApplicationComponent(NodeFinder.class);
187 try {
188 nodeFinder.getItem(workspaceName, pathNode);
189 } catch (ItemNotFoundException e) {
190 uiApp.addMessage(new ApplicationMessage("UISymLinkForm.msg.non-node", null,
191 ApplicationMessage.WARNING));
192
193 return;
194 } catch (RepositoryException re) {
195 uiApp.addMessage(new ApplicationMessage("UISymLinkForm.msg.non-node", null,
196 ApplicationMessage.WARNING));
197
198 return;
199 } catch(Exception e) {
200 if (LOG.isErrorEnabled()) {
201 LOG.error("An unexpected error occurs", e);
202 }
203 uiApp.addMessage(new ApplicationMessage("UISymLinkForm.msg.non-node", null,ApplicationMessage.WARNING));
204 return;
205 }
206 try {
207 Node targetNode = (Node) nodeFinder.getItem(workspaceName, pathNode);
208 if(targetNode.isLocked()) {
209 uiApp.addMessage(new ApplicationMessage("UIPopupMenu.msg.node-locked", new String[] {targetNode.getPath()})) ;
210 return;
211 }
212 if (uiSymLinkForm.localizationMode) {
213 MultiLanguageService langService = uiSymLinkForm.getApplicationComponent(MultiLanguageService.class);
214 langService.addSynchronizedLinkedLanguage(node, targetNode);
215 } else {
216 LinkManager linkManager = uiSymLinkForm.getApplicationComponent(LinkManager.class);
217 linkManager.createLink(node, Utils.EXO_SYMLINK, targetNode, symLinkName, symLinkTitle);
218 }
219 uiExplorer.updateAjax(event);
220 } catch (AccessControlException ace) {
221 uiApp.addMessage(new ApplicationMessage("UISymLinkForm.msg.repository-exception", null, ApplicationMessage.WARNING));
222
223 return;
224 } catch (AccessDeniedException ade) {
225 uiApp.addMessage(new ApplicationMessage("UISymLinkForm.msg.repository-exception", null, ApplicationMessage.WARNING));
226
227 return;
228 } catch(NumberFormatException nume) {
229 uiApp.addMessage(new ApplicationMessage("UISymLinkForm.msg.numberformat-exception", null, ApplicationMessage.WARNING));
230
231 return;
232 } catch(ConstraintViolationException cve) {
233 uiApp.addMessage(new ApplicationMessage("UISymLinkForm.msg.cannot-save", null, ApplicationMessage.WARNING));
234
235 return;
236 } catch(ItemExistsException iee) {
237 uiApp.addMessage(new ApplicationMessage("UISymLinkForm.msg.item-exists-exception", null, ApplicationMessage.WARNING));
238
239 return;
240 } catch(UnsupportedRepositoryOperationException unOperationException) {
241 uiApp.addMessage(new ApplicationMessage("UISymLinkForm.msg.UnsupportedRepositoryOperationException", null,
242 ApplicationMessage.WARNING));
243
244 return;
245 } catch (SameAsDefaultLangException unOperationException) {
246 uiApp.addMessage(new ApplicationMessage("UISymLinkForm.msg.translation-node-same-language-default",
247 null,
248 ApplicationMessage.WARNING));
249
250 return;
251 } catch (Exception e) {
252 if (LOG.isErrorEnabled()) {
253 LOG.error("Unexpected error", e);
254 }
255 uiApp.addMessage(new ApplicationMessage("UISymLinkForm.msg.cannot-save", null, ApplicationMessage.WARNING));
256
257 return;
258 }
259 }
260 }
261
262 static public class CancelActionListener extends EventListener<UISymLinkForm> {
263 public void execute(Event<UISymLinkForm> event) throws Exception {
264 UIJCRExplorer uiExplorer = event.getSource().getAncestorOfType(UIJCRExplorer.class);
265 uiExplorer.cancelAction();
266 }
267 }
268
269 static public class RemoveActionListener extends EventListener<UIFormMultiValueInputSet> {
270 public void execute(Event<UIFormMultiValueInputSet> event) throws Exception {
271 UIFormMultiValueInputSet uiSet = event.getSource();
272 UIComponent uiComponent = uiSet.getParent();
273 if (uiComponent instanceof UISymLinkForm) {
274 UISymLinkForm uiSymLinkForm = (UISymLinkForm)uiComponent;
275 String id = event.getRequestContext().getRequestParameter(OBJECTID);
276 UIFormStringInput uiInput = uiSymLinkForm.getUIStringInput(FIELD_NAME);
277 if (uiInput!=null) uiInput.setValue("");
278 uiSet.removeChildById(id);
279 event.getRequestContext().addUIComponentToUpdateByAjax(uiSymLinkForm);
280 }
281 }
282 }
283
284 static public class AddActionListener extends EventListener<UIFormMultiValueInputSet> {
285 private String fixPath(String path, String driveName, String repo, UISymLinkForm uiSymlinkForm) throws Exception {
286 if (path == null || path.length() == 0 ||
287 driveName == null || driveName.length() == 0 ||
288 repo == null || repo.length() == 0)
289 return "";
290 ManageDriveService managerDriveService = uiSymlinkForm.getApplicationComponent(ManageDriveService.class);
291 DriveData driveData = managerDriveService.getDriveByName(driveName);
292 if (!path.startsWith(driveData.getHomePath()))
293 return "";
294 if ("/".equals(driveData.getHomePath()))
295 return path;
296 return path.substring(driveData.getHomePath().length());
297 }
298 public void execute(Event<UIFormMultiValueInputSet> event) throws Exception {
299 UIFormMultiValueInputSet uiSet = event.getSource();
300 UISymLinkForm uiSymLinkForm = (UISymLinkForm) uiSet.getParent();
301 UISymLinkManager uiSymLinkManager = uiSymLinkForm.getParent();
302 UIJCRExplorer uiExplorer = uiSymLinkForm.getAncestorOfType(UIJCRExplorer.class);
303 String workspaceName = uiExplorer.getCurrentWorkspace();
304 String param = "returnField=" + FIELD_SYMLINK;
305 UIPopupWindow uiPopupWindow = uiSymLinkManager.initPopupTaxonomy(POPUP_SYMLINK);
306
307 if (uiSymLinkForm.isUseWorkspaceSelector()) {
308 UIOneNodePathSelector uiNodePathSelector = uiSymLinkManager.createUIComponent(UIOneNodePathSelector.class, null, null);
309 uiPopupWindow.setUIComponent(uiNodePathSelector);
310 uiNodePathSelector.setIsDisable(workspaceName, false);
311 uiNodePathSelector.setExceptedNodeTypesInPathPanel(new String[] {Utils.EXO_SYMLINK, Utils.MIX_LOCKABLE});
312 uiNodePathSelector.setRootNodeLocation(uiExplorer.getRepositoryName(), workspaceName, "/");
313 uiNodePathSelector.setIsShowSystem(false);
314 uiNodePathSelector.init(WCMCoreUtils.getUserSessionProvider());
315 uiNodePathSelector.setSourceComponent(uiSymLinkForm, new String[]{param});
316 }else {
317 Node node =uiExplorer.getCurrentNode();
318 UIContentSelectorOne uiNodePathSelector = uiSymLinkForm.createUIComponent(UIContentSelectorOne.class, null, null);
319 uiPopupWindow.setUIComponent(uiNodePathSelector);
320 uiNodePathSelector.init(uiExplorer.getDriveData().getName(),
321 fixPath(node == null ? "" : node.getPath(),
322 uiExplorer.getDriveData().getName(),
323 uiExplorer.getRepositoryName(),
324 uiSymLinkForm));
325 uiNodePathSelector.getChild(UIContentBrowsePanelOne.class).setSourceComponent(uiSymLinkForm, new String[] { param });
326 }
327 uiPopupWindow.setRendered(true);
328 uiPopupWindow.setShow(true);
329 event.getRequestContext().addUIComponentToUpdateByAjax(uiSymLinkManager);
330 }
331 }
332 public void useWorkspaceSelector() {
333 this.selectorMode = WORSPACE_SELECTOR_MODE;
334 }
335 public void useDriveSelector() {
336 this.selectorMode = DRIVE_SELECTOR_MODE;
337 }
338 public boolean isUseWorkspaceSelector() {
339 return this.selectorMode==WORSPACE_SELECTOR_MODE;
340 }
341 }