View Javadoc
1   /*
2    * Copyright (C) 2003-2007 eXo Platform SAS.
3    *
4    * This program is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Affero General Public License
6    * as published by the Free Software Foundation; either version 3
7    * of the License, or (at your option) any later version.
8    *
9    * This program is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU General Public License for more details.
13   *
14   * You should have received a copy of the GNU General Public License
15   * along with this program; if not, see<http://www.gnu.org/licenses/>.
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   * Created by The eXo Platform SARL
66   * Author : Chien Nguyen Van
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     * Logger.
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 }