1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.exoplatform.ecm.webui.component.explorer.rightclick.manager;
19
20 import java.util.Arrays;
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.regex.Matcher;
26
27 import javax.jcr.AccessDeniedException;
28 import javax.jcr.Node;
29 import javax.jcr.NodeIterator;
30 import javax.jcr.PathNotFoundException;
31 import javax.jcr.Session;
32 import javax.jcr.Workspace;
33 import javax.jcr.lock.LockException;
34 import javax.jcr.nodetype.ConstraintViolationException;
35 import javax.portlet.PortletPreferences;
36
37 import org.exoplatform.ecm.webui.component.explorer.UIJCRExplorer;
38 import org.exoplatform.ecm.webui.component.explorer.UIWorkingArea;
39 import org.exoplatform.ecm.webui.component.explorer.control.filter.IsNotTrashHomeNodeFilter;
40 import org.exoplatform.ecm.webui.component.explorer.control.listener.UIWorkingAreaActionListener;
41 import org.exoplatform.ecm.webui.utils.JCRExceptionManager;
42 import org.exoplatform.ecm.utils.lock.LockUtil;
43 import org.exoplatform.ecm.webui.utils.PermissionUtil;
44 import org.exoplatform.ecm.webui.utils.Utils;
45 import org.exoplatform.services.cms.jcrext.activity.ActivityCommonService;
46 import org.exoplatform.services.cms.thumbnail.ThumbnailService;
47 import org.exoplatform.services.listener.ListenerService;
48 import org.exoplatform.services.log.ExoLogger;
49 import org.exoplatform.services.log.Log;
50 import org.exoplatform.services.wcm.core.NodetypeConstant;
51 import org.exoplatform.services.wcm.utils.WCMCoreUtils;
52 import org.exoplatform.web.application.ApplicationMessage;
53 import org.exoplatform.webui.application.WebuiRequestContext;
54 import org.exoplatform.webui.application.portlet.PortletRequestContext;
55 import org.exoplatform.webui.config.annotation.ComponentConfig;
56 import org.exoplatform.webui.config.annotation.EventConfig;
57 import org.exoplatform.webui.core.UIApplication;
58 import org.exoplatform.webui.core.UIComponent;
59 import org.exoplatform.webui.event.Event;
60 import org.exoplatform.webui.ext.filter.UIExtensionFilter;
61 import org.exoplatform.webui.ext.filter.UIExtensionFilters;
62 import org.exoplatform.webui.ext.manager.UIAbstractManager;
63 import org.exoplatform.webui.ext.manager.UIAbstractManagerComponent;
64
65
66
67
68
69
70
71
72 @ComponentConfig(
73 events = {
74 @EventConfig(listeners = MoveNodeManageComponent.MoveNodeActionListener.class, confirm="UIWorkingArea.msg.confirm-move")
75 }
76 )
77
78 public class MoveNodeManageComponent extends UIAbstractManagerComponent {
79
80 private static final List<UIExtensionFilter> FILTERS
81 = Arrays.asList(new UIExtensionFilter[]{ new IsNotTrashHomeNodeFilter()} );
82
83 @UIExtensionFilters
84 public List<UIExtensionFilter> getFilters() {
85 return FILTERS;
86 }
87
88 private static final Log LOG = ExoLogger.getLogger(MoveNodeManageComponent.class.getName());
89
90 private static void processMultipleSelection(String nodePath, String destPath,
91 Event<? extends UIComponent> event) throws Exception {
92 UIJCRExplorer uiExplorer = event.getSource().getAncestorOfType(UIJCRExplorer.class);
93 Matcher matcher = UIWorkingArea.FILE_EXPLORER_URL_SYNTAX.matcher(destPath);
94 String wsName = null;
95 if (matcher.find()) {
96 wsName = matcher.group(1);
97 destPath = matcher.group(2);
98 } else {
99 throw new IllegalArgumentException("The ObjectId is invalid '" + destPath + "'");
100 }
101 Session session = uiExplorer.getSessionByWorkspace(wsName);
102 UIApplication uiApp = event.getSource().getAncestorOfType(UIApplication.class);
103 if (destPath.startsWith(nodePath)) {
104 uiApp.addMessage(new ApplicationMessage("UIPopupMenu.msg.bound-move-exception", null,
105 ApplicationMessage.WARNING));
106
107 return;
108 }
109 Node destNode;
110 try {
111
112 destNode = uiExplorer.getNodeByPath(destPath, session);
113
114 destPath = destNode.getPath();
115
116
117 session = destNode.getSession();
118 } catch (PathNotFoundException path) {
119 uiApp.addMessage(new ApplicationMessage("UIPopupMenu.msg.path-not-found-exception", null,
120 ApplicationMessage.WARNING));
121
122 return;
123 } catch (Exception e) {
124 JCRExceptionManager.process(uiApp, e);
125 return;
126 }
127 if (!PermissionUtil.canAddNode(destNode)) {
128 uiApp.addMessage(new ApplicationMessage("UIPopupMenu.msg.can-not-move-node", null,
129 ApplicationMessage.WARNING));
130
131 uiExplorer.updateAjax(event);
132 return;
133 }
134 if (uiExplorer.nodeIsLocked(destNode)) {
135 Object[] arg = { destPath };
136 uiApp.addMessage(new ApplicationMessage("UIPopupMenu.msg.node-locked", arg,
137 ApplicationMessage.WARNING));
138
139 return;
140 }
141 if (!destNode.isCheckedOut()) {
142 uiApp.addMessage(new ApplicationMessage("UIActionBar.msg.node-checkedin", null));
143
144 return;
145 }
146 try {
147 if (nodePath.indexOf(";") > -1) {
148 moveMultiNode(nodePath.split(";"), destNode, event);
149 } else {
150 moveNode(nodePath, null, destNode, event);
151 }
152 session.save();
153 uiExplorer.updateAjax(event);
154 } catch (AccessDeniedException ace) {
155 Object[] arg = { destPath };
156 uiApp.addMessage(new ApplicationMessage("UIPopupMenu.msg.has-not-add-permission", arg,
157 ApplicationMessage.WARNING));
158
159 return;
160 } catch (LockException lock) {
161 Object[] arg = { nodePath };
162 uiApp.addMessage(new ApplicationMessage("UIPopupMenu.msg.node-locked", arg,
163 ApplicationMessage.WARNING));
164
165 return;
166 } catch (ConstraintViolationException constraint) {
167 uiApp.addMessage(new ApplicationMessage("UIPopupMenu.msg.move-constraint-exception", null,
168 ApplicationMessage.WARNING));
169
170 return;
171 } catch (Exception e) {
172 if (LOG.isErrorEnabled()) {
173 LOG.error("an unexpected error occurs while selecting the node", e);
174 }
175 JCRExceptionManager.process(uiApp, e);
176 return;
177 }
178 }
179
180 private static Node getNodeByPath(String srcPath, UIJCRExplorer uiExplorer) throws Exception {
181 Matcher matcher = UIWorkingArea.FILE_EXPLORER_URL_SYNTAX.matcher(srcPath);
182 String wsName = null;
183 if (matcher.find()) {
184 wsName = matcher.group(1);
185 srcPath = matcher.group(2);
186 } else {
187 throw new IllegalArgumentException("The ObjectId is invalid '" + srcPath + "'");
188 }
189 Session srcSession = uiExplorer.getSessionByWorkspace(wsName);
190 return uiExplorer.getNodeByPath(srcPath, srcSession, false);
191 }
192
193 private static void moveNode(String srcPath, Node selectedNode, Node destNode, Event<?> event) throws Exception {
194 UIComponent uiComponent = (UIComponent)event.getSource();
195 UIJCRExplorer uiExplorer = uiComponent.getAncestorOfType(UIJCRExplorer.class);
196 UIApplication uiApp = uiComponent.getAncestorOfType(UIApplication.class);
197 if (srcPath.indexOf(":/") > -1 || (selectedNode != null)) {
198 String[] arrSrcPath = srcPath.split(":/");
199 if ((srcPath.contains(":/") && ("/" + arrSrcPath[1]).equals(destNode.getPath()))
200 || (selectedNode != null && selectedNode.equals(destNode))) {
201 uiApp.addMessage(new ApplicationMessage("UIWorkingArea.msg.can-not-move-to-itself",
202 null,
203 ApplicationMessage.WARNING));
204
205 return;
206 }
207 }
208 if(uiExplorer.isEditingDocument()) {
209 uiApp.addMessage(new ApplicationMessage("UIWorkingArea.msg.is-editing", null,
210 ApplicationMessage.WARNING));
211 return;
212 }
213 String messagePath = "";
214 try {
215 if (selectedNode == null) {
216 selectedNode = getNodeByPath(srcPath, uiExplorer);
217 }
218 Session srcSession = selectedNode.getSession();
219 if (!selectedNode.isCheckedOut()) {
220 uiApp.addMessage(new ApplicationMessage("UIActionBar.msg.node-checkedin", null,
221 ApplicationMessage.WARNING));
222
223 return;
224 }
225 uiExplorer.addLockToken(selectedNode);
226 String destPath = destNode.getPath();
227 messagePath = destPath;
228
229 destPath = destPath.concat("/").concat(selectedNode.getName());
230 Workspace srcWorkspace = srcSession.getWorkspace();
231 Workspace destWorkspace = destNode.getSession().getWorkspace();
232 if (srcPath.indexOf(":/") > -1)
233 srcPath = srcPath.substring(srcPath.indexOf(":/") + 1);
234
235
236 ThumbnailService thumbnailService = WCMCoreUtils.getService(ThumbnailService.class);
237 Node srcThumbnailNode = thumbnailService.getThumbnailNode(selectedNode);
238
239 ListenerService listenerService = WCMCoreUtils.getService(ListenerService.class);
240 ActivityCommonService activityService = WCMCoreUtils.getService(ActivityCommonService.class);
241 Node desNode = null;
242 if (srcWorkspace.equals(destWorkspace)) {
243 srcWorkspace.move(srcPath, destPath);
244
245 removeMixinEXO_RESTORE_LOCATION(srcSession, destPath);
246 desNode = (Node)srcSession.getItem(destPath);
247 LockUtil.changeLockToken(srcPath, desNode);
248 if (activityService.isAcceptedNode(desNode) || desNode.getPrimaryNodeType().getName().equals(NodetypeConstant.NT_FILE)) {
249 listenerService.broadcast(ActivityCommonService.NODE_MOVED_ACTIVITY, desNode, desNode.getPath());
250 }
251 srcSession.save();
252 } else {
253 destWorkspace.clone(srcWorkspace.getName(), srcPath, destPath, false);
254 desNode =(Node) destWorkspace.getSession().getItem(destPath);
255 if (activityService.isAcceptedNode(desNode) || desNode.getPrimaryNodeType().getName().equals(NodetypeConstant.NT_FILE)) {
256 listenerService.broadcast(ActivityCommonService.NODE_MOVED_ACTIVITY, desNode, destPath);
257 }
258
259 removeMixinEXO_RESTORE_LOCATION(destWorkspace.getSession(), destPath);
260 destWorkspace.getSession().save();
261 }
262
263
264 thumbnailService.copyThumbnailNode(srcThumbnailNode, desNode);
265
266 } catch (Exception e) {
267 Object[] args = { srcPath, messagePath };
268 uiApp.addMessage(new ApplicationMessage("UIWorkingArea.msg.move-problem", args,
269 ApplicationMessage.WARNING));
270
271 return;
272 }
273 }
274
275 private static void removeMixinEXO_RESTORE_LOCATION(Session session, String restorePath) throws Exception {
276 Node sameNameNode = ((Node) session.getItem(restorePath));
277 Node parent = sameNameNode.getParent();
278 String name = sameNameNode.getName();
279 NodeIterator nodeIter = parent.getNodes(name);
280 while (nodeIter.hasNext()) {
281 Node node = nodeIter.nextNode();
282 if (node.isNodeType(Utils.EXO_RESTORELOCATION))
283 node.removeMixin(Utils.EXO_RESTORELOCATION);
284 }
285 }
286
287 private static void moveMultiNode(String[] srcPaths, Node destNode, Event<? extends UIComponent> event) throws Exception {
288 Map<String, Node> mapNode = new HashMap <String, Node>();
289 UIJCRExplorer uiExplorer = event.getSource().getAncestorOfType(UIJCRExplorer.class);
290 Node node;
291 for (int i = 0; i < srcPaths.length; i++) {
292 node = getNodeByPath(srcPaths[i], uiExplorer);
293 mapNode.put(node.getPath(), node);
294 }
295 String path = null;
296 Iterator<String> iterator = mapNode.keySet().iterator();
297 while (iterator.hasNext()) {
298 path = iterator.next();
299 node = mapNode.get(path);
300 node.refresh(true);
301 moveNode(node.getPath(), node, destNode, event);
302 }
303 }
304
305 public static class MoveNodeActionListener extends UIWorkingAreaActionListener<MoveNodeManageComponent> {
306 public void processEvent(Event<MoveNodeManageComponent> event) throws Exception {
307 String nodePath = event.getRequestContext().getRequestParameter(OBJECTID);
308 String destPath = event.getRequestContext().getRequestParameter("destInfo");
309
310 if (isInTrash(nodePath) && isInTrash(destPath))
311 return;
312 else if (isInTrash(destPath))
313 ((UIWorkingArea)event.getSource().getParent()).getChild(DeleteManageComponent.class).doDelete(nodePath, event);
314 else
315 MoveNodeManageComponent.processMultipleSelection(nodePath.trim(), destPath.trim(), event);
316 }
317
318 private static boolean isInTrash(String path) {
319 PortletRequestContext pcontext = (PortletRequestContext)WebuiRequestContext.getCurrentInstance();
320 PortletPreferences portletPref = pcontext.getRequest().getPreferences();
321 String trashHomeNodePath = portletPref.getValue(Utils.TRASH_HOME_NODE_PATH, "");
322 String trashWorkspace = portletPref.getValue(Utils.TRASH_WORKSPACE, "");
323
324 return (path.startsWith(trashHomeNodePath) ||
325 path.startsWith(trashWorkspace + ":" + trashHomeNodePath));
326 }
327 }
328 @Override
329 public Class<? extends UIAbstractManager> getUIAbstractManagerClass() {
330 return null;
331 }
332
333 }