View Javadoc
1   /***************************************************************************
2    * Copyright (C) 2003-2009 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   **************************************************************************/
18  package org.exoplatform.ecm.webui.component.explorer.rightclick.manager;
19  
20  import java.util.Arrays;
21  import java.util.List;
22  import java.util.regex.Matcher;
23  
24  import javax.jcr.AccessDeniedException;
25  import javax.jcr.Node;
26  import javax.jcr.PathNotFoundException;
27  import javax.jcr.Session;
28  import javax.jcr.lock.LockException;
29  import javax.jcr.nodetype.ConstraintViolationException;
30  
31  import org.exoplatform.services.log.Log;
32  import org.exoplatform.ecm.utils.text.Text;
33  import org.exoplatform.ecm.webui.component.explorer.UIJCRExplorer;
34  import org.exoplatform.ecm.webui.component.explorer.UIWorkingArea;
35  import org.exoplatform.ecm.webui.component.explorer.control.filter.IsNotInTrashFilter;
36  import org.exoplatform.ecm.webui.component.explorer.control.filter.IsNotTrashHomeNodeFilter;
37  import org.exoplatform.ecm.webui.component.explorer.control.listener.UIWorkingAreaActionListener;
38  import org.exoplatform.ecm.webui.utils.JCRExceptionManager;
39  import org.exoplatform.ecm.webui.utils.PermissionUtil;
40  import org.exoplatform.ecm.webui.utils.Utils;
41  import org.exoplatform.services.cms.link.LinkManager;
42  import org.exoplatform.services.log.ExoLogger;
43  import org.exoplatform.web.application.ApplicationMessage;
44  import org.exoplatform.webui.config.annotation.ComponentConfig;
45  import org.exoplatform.webui.config.annotation.EventConfig;
46  import org.exoplatform.webui.core.UIApplication;
47  import org.exoplatform.webui.core.UIComponent;
48  import org.exoplatform.webui.event.Event;
49  import org.exoplatform.webui.ext.filter.UIExtensionFilter;
50  import org.exoplatform.webui.ext.filter.UIExtensionFilters;
51  import org.exoplatform.webui.ext.manager.UIAbstractManager;
52  import org.exoplatform.webui.ext.manager.UIAbstractManagerComponent;
53  
54  /**
55   * Created by The eXo Platform SARL
56   * Author : Hoang Van Hung
57   *          hunghvit@gmail.com
58   * Aug 16, 2009
59   */
60  @ComponentConfig(
61      events = {
62        @EventConfig(listeners = CreateLinkManageComponent.CreateLinkActionListener.class)
63      }
64  )
65  public class CreateLinkManageComponent extends UIAbstractManagerComponent {
66  
67    private static final List<UIExtensionFilter> FILTERS
68            = Arrays.asList(new UIExtensionFilter[]{new IsNotInTrashFilter(),
69                                                    new IsNotTrashHomeNodeFilter()});
70  
71    private static final Log LOG = ExoLogger.getLogger(CreateLinkManageComponent.class.getName());
72    private static final String EXO_TRASH_FOLDER = "exo:trashFolder";
73  
74    @UIExtensionFilters
75    public List<UIExtensionFilter> getFilters() {
76      return FILTERS;
77    }
78  
79    private static void createMultiLink(String[] srcPaths, Node destNode,
80        Event<? extends UIComponent> event) throws Exception {
81      for (int i = 0; i < srcPaths.length; i++) {
82        createLink(srcPaths[i], destNode, event);
83      }
84    }
85  
86    private static void createLink(String srcPath, Node destNode, Event<? extends UIComponent> event)
87        throws Exception {
88  
89      UIJCRExplorer uiExplorer = event.getSource().getAncestorOfType(UIJCRExplorer.class);
90      Matcher matcher = UIWorkingArea.FILE_EXPLORER_URL_SYNTAX.matcher(srcPath);
91      String wsName = null;
92      if (matcher.find()) {
93        wsName = matcher.group(1);
94        srcPath = matcher.group(2);
95      } else {
96        throw new IllegalArgumentException("The ObjectId is invalid '" + srcPath + "'");
97      }
98      Session session = uiExplorer.getSessionByWorkspace(wsName);
99      Node selectedNode = uiExplorer.getNodeByPath(srcPath, session, false);
100     if (selectedNode.isNodeType(EXO_TRASH_FOLDER)) return;
101     UIApplication uiApp = event.getSource().getAncestorOfType(UIApplication.class);
102     LinkManager linkManager = event.getSource().getApplicationComponent(LinkManager.class);
103     if (linkManager.isLink(destNode)) {
104       Object[] args = { destNode.getPath() };
105       uiApp.addMessage(new ApplicationMessage("UIWorkingArea.msg.dest-node-is-link", args,
106           ApplicationMessage.WARNING));
107       
108       return;
109     }
110     if (linkManager.isLink(selectedNode)) {
111       Object[] args = { srcPath };
112       uiApp.addMessage(new ApplicationMessage("UIWorkingArea.msg.selected-is-link", args,
113           ApplicationMessage.WARNING));
114       
115       return;
116     }
117     try {
118       linkManager.createLink(destNode, Utils.EXO_SYMLINK, selectedNode, selectedNode.getName()
119           + ".lnk");
120     } catch (Exception e) {
121       Object[] args = { Text.unescapeIllegalJcrChars(srcPath), Text.unescapeIllegalJcrChars(destNode.getPath()) };
122       uiApp.addMessage(new ApplicationMessage("UIWorkingArea.msg.create-link-problem", args,
123           ApplicationMessage.WARNING));
124       
125       return;
126     }
127   }
128 
129   public static class CreateLinkActionListener extends UIWorkingAreaActionListener<CreateLinkManageComponent> {
130     public void processEvent(Event<CreateLinkManageComponent> event) throws Exception {
131       CreateLinkManageComponent.createLinkManager(event);
132     }
133   }
134 
135   private static void createLinkManager(Event<? extends UIComponent> event) throws Exception {
136     String nodePath = event.getRequestContext().getRequestParameter(OBJECTID);
137     String destPath = event.getRequestContext().getRequestParameter("destInfo");
138     processMultipleSelection(nodePath.trim(), destPath.trim(), event);
139   }
140 
141   private static void processMultipleSelection(String nodePath, String destPath,
142       Event<? extends UIComponent> event) throws Exception {
143     UIJCRExplorer uiExplorer = event.getSource().getAncestorOfType(UIJCRExplorer.class);
144     Matcher matcher = UIWorkingArea.FILE_EXPLORER_URL_SYNTAX.matcher(destPath);
145     String wsName = null;
146     if (matcher.find()) {
147       wsName = matcher.group(1);
148       destPath = matcher.group(2);
149     } else {
150       throw new IllegalArgumentException("The ObjectId is invalid '" + destPath + "'");
151     }
152     Session session = uiExplorer.getSessionByWorkspace(wsName);
153     UIApplication uiApp = event.getSource().getAncestorOfType(UIApplication.class);
154     if (destPath.startsWith(nodePath)) {
155       uiApp.addMessage(new ApplicationMessage("UIPopupMenu.msg.bound-move-exception", null,
156           ApplicationMessage.WARNING));
157       
158       return;
159     }
160     Node destNode;
161     try {
162       // Use the method getNodeByPath because it is link aware
163       destNode = uiExplorer.getNodeByPath(destPath, session);
164       // Reset the path to manage the links that potentially create virtual path
165       destPath = destNode.getPath();
166     } catch (PathNotFoundException path) {
167       uiApp.addMessage(new ApplicationMessage("UIPopupMenu.msg.path-not-found-exception", null,
168           ApplicationMessage.WARNING));
169       
170       return;
171     } catch (Exception e) {
172       JCRExceptionManager.process(uiApp, e);
173       return;
174     }
175     if (!PermissionUtil.canAddNode(destNode)) {
176       uiApp.addMessage(new ApplicationMessage("UIPopupMenu.msg.can-not-move-node", null,
177           ApplicationMessage.WARNING));
178       
179       uiExplorer.updateAjax(event);
180       return;
181     }
182     if (uiExplorer.nodeIsLocked(destNode)) {
183       Object[] arg = { destPath };
184       uiApp.addMessage(new ApplicationMessage("UIPopupMenu.msg.node-locked", arg,
185           ApplicationMessage.WARNING));
186       
187       return;
188     }
189     if (!destNode.isCheckedOut()) {
190       uiApp.addMessage(new ApplicationMessage("UIActionBar.msg.node-checkedin", null));
191       
192       return;
193     }
194     try {
195       if (nodePath.indexOf(";") > -1) {
196         createMultiLink(nodePath.split(";"), destNode, event);
197       } else {
198         createLink(nodePath, destNode, event);
199       }
200       destNode.save();
201       uiExplorer.updateAjax(event);
202     } catch (AccessDeniedException ace) {
203       Object[] arg = { destPath };
204       uiApp.addMessage(new ApplicationMessage("UIPopupMenu.msg.has-not-add-permission", arg,
205           ApplicationMessage.WARNING));
206       
207       return;
208     } catch (LockException lock) {
209       Object[] arg = { nodePath };
210       uiApp.addMessage(new ApplicationMessage("UIPopupMenu.msg.node-locked", arg,
211           ApplicationMessage.WARNING));
212       
213       return;
214     } catch (ConstraintViolationException constraint) {
215       uiApp.addMessage(new ApplicationMessage("UIPopupMenu.msg.move-constraint-exception", null,
216           ApplicationMessage.WARNING));
217       
218       return;
219     } catch (Exception e) {
220       if (LOG.isErrorEnabled()) {
221         LOG.error("an unexpected error occurs while selecting the node", e);
222       }
223       JCRExceptionManager.process(uiApp, e);
224       return;
225     }
226   }
227 
228   @Override
229   public Class<? extends UIAbstractManager> getUIAbstractManagerClass() {
230     return null;
231   }
232 
233 }