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.utils;
18  
19  import java.io.InputStream;
20  import java.io.UnsupportedEncodingException;
21  import java.net.URLEncoder;
22  import java.security.AccessControlException;
23  import java.text.DecimalFormat;
24  import java.util.*;
25  import java.util.regex.Matcher;
26  import java.util.regex.Pattern;
27  import java.util.zip.ZipInputStream;
28  
29  import javax.imageio.ImageIO;
30  import javax.jcr.*;
31  import javax.jcr.nodetype.NodeDefinition;
32  import javax.jcr.nodetype.NodeType;
33  import javax.jcr.nodetype.NodeTypeManager;
34  import javax.servlet.http.Cookie;
35  import javax.servlet.http.HttpServletRequest;
36  
37  import org.apache.commons.lang.StringEscapeUtils;
38  import org.apache.commons.lang.StringUtils;
39  
40  import org.exoplatform.commons.utils.HTMLSanitizer;
41  import org.exoplatform.container.ExoContainer;
42  import org.exoplatform.container.ExoContainerContext;
43  import org.exoplatform.container.definition.PortalContainerConfig;
44  import org.exoplatform.container.xml.PortalContainerInfo;
45  import org.exoplatform.download.DownloadService;
46  import org.exoplatform.download.InputStreamDownloadResource;
47  import org.exoplatform.ecm.webui.form.UIOpenDocumentForm;
48  import org.exoplatform.portal.webui.util.Util;
49  import org.exoplatform.services.cms.BasePath;
50  import org.exoplatform.services.cms.documents.TrashService;
51  import org.exoplatform.services.cms.drives.DriveData;
52  import org.exoplatform.services.cms.link.LinkManager;
53  import org.exoplatform.services.cms.templates.TemplateService;
54  import org.exoplatform.services.cms.thumbnail.ThumbnailService;
55  import org.exoplatform.services.jcr.RepositoryService;
56  import org.exoplatform.services.jcr.core.ManageableRepository;
57  import org.exoplatform.services.jcr.ext.app.SessionProviderService;
58  import org.exoplatform.services.jcr.ext.common.SessionProvider;
59  import org.exoplatform.services.jcr.ext.hierarchy.NodeHierarchyCreator;
60  import org.exoplatform.services.jcr.impl.Constants;
61  import org.exoplatform.services.jcr.impl.core.NodeImpl;
62  import org.exoplatform.services.jcr.impl.core.nodetype.NodeTypeImpl;
63  import org.exoplatform.services.log.ExoLogger;
64  import org.exoplatform.services.log.Log;
65  import org.exoplatform.services.resources.ResourceBundleService;
66  import org.exoplatform.services.security.ConversationState;
67  import org.exoplatform.services.security.Identity;
68  import org.exoplatform.services.wcm.publication.WCMComposer;
69  import org.exoplatform.services.wcm.utils.WCMCoreUtils;
70  import org.exoplatform.wcm.webui.reader.ContentReader;
71  import org.exoplatform.web.application.RequestContext;
72  import org.exoplatform.webui.application.WebuiRequestContext;
73  import org.exoplatform.webui.application.portlet.PortletRequestContext;
74  import org.exoplatform.webui.core.UIComponent;
75  import org.exoplatform.webui.core.UIContainer;
76  import org.exoplatform.webui.core.UIPopupContainer;
77  import org.exoplatform.webui.event.Event;
78  import org.exoplatform.webui.ext.UIExtension;
79  import org.exoplatform.webui.ext.UIExtensionManager;
80  
81  /**
82   * Created by The eXo Platform SARL Author : Dang Van Minh
83   * minh.dang@exoplatform.com May 8, 2008 3:13:32 PM
84   */
85  public class Utils {
86    final public static String   WORKSPACE_NAME             = "workspace";
87  
88    final public static String   JCR_PATH                   = "path";
89  
90    final public static String   DRIVE_FOLDER               = "allowCreateFolder";
91  
92    final public static String   MIN_WIDTH                  = "minwidth";
93  
94    final public static String   CB_DOCUMENT_NAME           = "documentName";
95  
96    final public static String   CB_SCRIPT_NAME             = "scriptName";
97  
98    final public static String   CB_REF_DOCUMENT            = "reference";
99  
100   final public static String   CB_CHILD_DOCUMENT          = "child";
101 
102   final public static String   CB_NB_PER_PAGE             = "nbPerPage";
103 
104   final public static String   CB_QUERY_STATEMENT         = "queryStatement";
105 
106   final public static String   CB_QUERY_ISNEW             = "isAddNew";
107 
108   final public static String   CB_QUERY_TYPE              = "queryType";
109 
110   final public static String   CB_QUERY_STORE             = "queryStore";
111 
112   final public static String   CB_QUERY_LANGUAGE          = "queryLanguage";
113 
114   final public static String   CB_VIEW_TOOLBAR            = "viewToolbar";
115 
116   final public static String   CB_VIEW_TAGMAP             = "viewTagMap";
117 
118   final public static String   CB_VIEW_COMMENT            = "viewComment";
119 
120   final public static String   CB_VIEW_VOTE               = "viewVote";
121 
122   final public static String   CB_SEARCH_LOCATION         = "searchLocation";
123 
124   final public static String   CB_ENABLE_SEARCH_LOCATION  = "enableSearch";
125 
126   final public static String   CB_FILTER_CATEGORY         = "filterCategory";
127 
128   final static public String   EXO_AUDITABLE              = "exo:auditable";
129 
130   final public static String   CB_BOX_TEMPLATE            = "boxTemplate";
131 
132   final public static String   CB_TEMPLATE                = "template";
133 
134   final public static String   CB_USECASE                 = "usecase";
135 
136   final public static String   CB_ALLOW_PUBLISH           = "isAllowPublish";
137 
138   final public static String   FROM_PATH                  = "From Path";
139 
140   final public static String   USE_DOCUMENT               = "Document";
141 
142   final public static String   USE_JCR_QUERY              = "Using a JCR query";
143 
144   final public static String   USE_SCRIPT                 = "Using a script";
145 
146   final public static String   CB_USE_FROM_PATH           = "path";
147 
148   final public static String   CB_USE_DOCUMENT            = "detail-document";
149 
150   final public static String   CB_USE_JCR_QUERY           = "query";
151 
152   final public static String   CB_USE_SCRIPT              = "script";
153 
154   final public static String   SEMI_COLON                 = ";";
155 
156   final public static String   COLON                      = ":";
157 
158   final public static String   SLASH                      = "/";
159 
160   final public static String   BACKSLASH                  = "\\";
161 
162   final public static String   EXO_CREATED_DATE           = "exo:dateCreated";
163 
164   final public static String   EXO_DATETIME               = "exo:datetime";
165 
166   final public static String   EXO_MODIFIED_DATE          = "exo:dateModified";
167 
168   final public static String   EXO_OWNER                  = "exo:owner";
169 
170   final public static String   SPECIALCHARACTER[]         = { SEMI_COLON, SLASH, BACKSLASH, "|", ">", "<", "\"", "?", "!", "#",
171       "$", "&", "*", "(", ")", "{", "}", "[", "]", ":", ".", "'" };
172 
173   final public static String   REPOSITORY                 = "repository";
174 
175   final public static String   VIEWS                      = "views";
176 
177   final public static String   DRIVE                      = "drive";
178 
179   final static public String   TRASH_HOME_NODE_PATH       = "trashHomeNodePath";
180 
181   final static public String   TRASH_REPOSITORY           = "trashRepository";
182 
183   final static public String   TRASH_WORKSPACE            = "trashWorkspace";
184 
185   final public static String   JCR_INFO                   = "jcrInfo";
186 
187   final static public String   NT_UNSTRUCTURED            = "nt:unstructured";
188 
189   final static public String   NT_FILE                    = "nt:file";
190 
191   final static public String   NT_FOLDER                  = "nt:folder";
192 
193   final static public String   NT_FROZEN                  = "nt:frozenNode";
194 
195   final static public String   EXO_TITLE                  = "exo:title";
196 
197   final static public String   EXO_SUMMARY                = "exo:summary";
198 
199   final static public String   EXO_RELATION               = "exo:relation";
200 
201   final static public String   EXO_TAXONOMY               = "exo:taxonomy";
202 
203   final static public String   EXO_IMAGE                  = "exo:image";
204 
205   final static public String   EXO_LANGUAGE               = "exo:language";
206 
207   final static public String   LANGUAGES                  = "languages";
208 
209   final static public String   EXO_METADATA               = "exo:metadata";
210 
211   final static public String   MIX_REFERENCEABLE          = "mix:referenceable";
212 
213   final static public String   MIX_VERSIONABLE            = "mix:versionable";
214 
215   final static public String   NT_RESOURCE                = "nt:resource";
216 
217   final static public String   NT_BASE                    = "nt:base";
218 
219   final static public String   DEFAULT                    = "default";
220 
221   final static public String   JCR_CONTENT                = "jcr:content";
222 
223   final static public String   JCR_CONTENT_DESCRIPTION    = "jcr:content/dc:description";
224 
225   final static public String   JCR_MIMETYPE               = "jcr:mimeType";
226 
227   final static public String   JCR_FROZEN                 = "jcr:frozenNode";
228 
229   final public static String   JCR_LASTMODIFIED           = "jcr:lastModified";
230 
231   final public static String   JCR_PRIMARYTYPE            = "jcr:primaryType";
232 
233   final static public String   JCR_DATA                   = "jcr:data";
234 
235   final static public String   JCR_SCORE                  = "jcr:score";
236 
237   final static public String   EXO_ROLES                  = "exo:roles";
238 
239   final static public String   EXO_TEMPLATEFILE           = "exo:templateFile";
240 
241   final static public String   EXO_TEMPLATE               = "exo:template";
242 
243   final static public String   EXO_ACTION                 = "exo:action";
244 
245   final static public String   EXO_ACTIONS                = "exo:actions";
246 
247   final static public String   MIX_LOCKABLE               = "mix:lockable";
248 
249   final static public String   EXO_CATEGORIZED            = "exo:categorized";
250 
251   final static public String   EXO_CATEGORY               = "exo:category";
252 
253   final static public String   EXO_HIDDENABLE             = "exo:hiddenable";
254 
255   final static public String   EXO_ACCESSPERMISSION       = "exo:accessPermissions";
256 
257   final static public String   EXO_PERMISSIONS            = "exo:permissions";
258 
259   final static public String   EXO_FAVOURITE              = "exo:favourite";
260 
261   final static public String   EXO_FAVOURITE_FOLDER       = "exo:favoriteFolder";
262 
263   final static public String   EXO_FAVOURITER             = "exo:favouriter";
264 
265   final static public String   EXO_RESTOREPATH            = "exo:restorePath";
266 
267   final static public String   EXO_RESTORELOCATION        = "exo:restoreLocation";
268 
269   final static public String   EXO_RESTORE_WORKSPACE      = "exo:restoreWorkspace";
270 
271   final static public String   EXO_LASTMODIFIER           = "exo:lastModifier";
272 
273   final static public String   EXO_TRASH_FOLDER           = "exo:trashFolder";
274 
275   final static public String   EXO_TOTAL                  = "exo:total";
276 
277   final static public String   EXO_WEBCONTENT             = "exo:webContent";
278 
279   final static public String   EXO_RSS_ENABLE             = "exo:rss-enable";
280 
281   final static public String   EXO_COMMENTS               = "exo:comments";
282 
283   final static public String   EXO_MUSICFOLDER            = "exo:musicFolder";
284 
285   final static public String   EXO_VIDEOFOLDER            = "exo:videoFolder";
286 
287   final static public String   EXO_PICTUREFOLDER          = "exo:pictureFolder";
288 
289   final static public String   EXO_DOCUMENTFOLDER         = "exo:documentFolder";
290 
291   final static public String   EXO_SEARCHFOLDER           = "exo:searchFolder";
292 
293   final static public String   MIX_COMMENTABLE            = "mix:commentable";
294 
295   final static public String   MIX_VOTABLE                = "mix:votable";
296 
297   final static public String   EXO_SYMLINK                = "exo:symlink";
298 
299   final static public String   EXO_PRIMARYTYPE            = "exo:primaryType";
300 
301   final static public String   INLINE_DRAFT               = "Draft";
302 
303   final static public String   INLINE_PUBLISHED           = "Published";
304 
305   final static public String   EXO_SORTABLE               = "exo:sortable";
306 
307   final static public String   EXO_RISIZEABLE             = "exo:documentSize";
308 
309   final static public String   FLASH_MIMETYPE             = "flash";
310 
311   final static public String[] SPECIFIC_FOLDERS           = { EXO_MUSICFOLDER, EXO_VIDEOFOLDER, EXO_PICTUREFOLDER,
312       EXO_DOCUMENTFOLDER, EXO_SEARCHFOLDER               };
313 
314   final static public String[] FOLDERS                    = { NT_UNSTRUCTURED, NT_FOLDER };
315 
316   final static public String[] NON_EDITABLE_NODETYPES     = { NT_UNSTRUCTURED, NT_FOLDER, NT_RESOURCE };
317 
318   final public static String[] CATEGORY_NODE_TYPES        = { NT_FOLDER, NT_UNSTRUCTURED, EXO_TAXONOMY };
319 
320   final static public String   CATEGORY_MANDATORY         = "categoryMandatoryWhenFileUpload";
321 
322   final static public String   UPLOAD_SIZE_LIMIT_MB       = "uploadFileSizeLimitMB";
323 
324   final static public String   FILE_VIEWER_EXTENSION_TYPE = "org.exoplatform.ecm.dms.FileViewer";
325 
326   final static public String   MIME_TYPE                  = "mimeType";
327 
328   final static public String   LOCALE_WEBUI_DMS           = "locale.portlet.i18n.WebUIDms";
329 
330   final static public String   REQUESTCONTEXT             = "requestcontext";
331 
332   final static public String   WORKSPACE_PARAM            = "workspaceName";
333 
334   final static public String   SPACE_GROUP                 = "/spaces";
335 
336   final static public String   SITES_PATH                 = "/sites";
337 
338   final static public String   COLLABORATION_WS           = "collaboration";
339 
340   final static public int      USER_DEPTH                 = 5;
341 
342   final static public String   EMPTY                      = "";
343 
344   final static public String   PUBLIC                     = "Public";
345 
346   final static public String   GROUP                      = "Group";
347 
348   final static public String   SITE                       = "Site";
349 
350   final static public String   PRIVATE                    = "Private";
351 
352   final static public String   URL_BACKTO                 = "backto";
353   public static final String   INPUT_TEXT_AREA            = "TEXTAREA";
354   public static final String   INPUT_WYSIWYG              = "WYSIWYG";
355   public static final String   INPUT_TEXT                 = "TEXT";
356   public static final String   DEFAULT_CSS_NAME           = "InlineText";
357   public static final String   LEFT2RIGHT                 = "left-to-right";
358   public static final String   RIGHT2LEFT                 = "right-to-left";
359   protected static final String SEPARATOR         = "=";
360   protected static final String TOOLBAR           = "toolbar";
361   protected static final String CSS               = "CSSData";
362   protected static final String HEIGHT            = "height";
363   protected static final String BUTTON_DIR        = "button_direction";
364   protected static final String PREV_HTML         = "prev_html";
365   protected static final String POST_HTML         = "post_html";
366   protected static final String FAST_PUBLISH_LINK = "fast_publish";
367   private static final Log     LOG                        = ExoLogger.getLogger(Utils.class.getName());
368 
369   public static String encodeHTML(String text) {
370     return text.replaceAll("&", "&amp;").replaceAll("\"", "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
371   }
372 
373   public static String formatNodeName(String text) {
374     return text.replaceAll("'", "\\\\'");
375   }
376 
377   public static boolean isVersionable(Node node) throws RepositoryException {
378     return node.isNodeType(MIX_VERSIONABLE);
379   }
380 
381   public static boolean isTrashHomeNode(Node node) throws RepositoryException {
382     return node.isNodeType(EXO_TRASH_FOLDER);
383   }
384 
385   public static boolean isInTrash(Node node) throws RepositoryException {
386     TrashService trashService = WCMCoreUtils.getService(TrashService.class);
387     return trashService.isInTrash(node);
388   }
389 
390   /** check a symlink node and its target are in Trash or not */
391   public static boolean targetNodeAndLinkInTrash(Node currentNode) throws Exception {
392     if (Utils.isInTrash(currentNode) && Utils.isSymLink(currentNode)) {
393       Node targetNode = Utils.getNodeSymLink(currentNode);
394       if (Utils.isInTrash(targetNode)) {
395         return true;
396       }
397     }
398     return false;
399   }
400 
401   /** check if we can restore a node */
402   public static boolean isAbleToRestore(Node currentNode) throws Exception {
403     String restorePath;
404     String restoreWorkspace;
405     Node restoreLocationNode;
406 
407     if (!Utils.isInTrash(currentNode)) {
408       return false;
409     }
410 
411     // return false if the node is exo:actions
412     if (Utils.EXO_ACTIONS.equals(currentNode.getName()) && Utils.isInTrash(currentNode)) {
413       return false;
414     }
415 
416     // return false if the target has been already in Trash.
417     if (Utils.targetNodeAndLinkInTrash(currentNode)) {
418       return false;
419     }
420 
421     if (ConversationState.getCurrent().getIdentity().getUserId().equalsIgnoreCase(WCMCoreUtils.getSuperUser())) {
422       return true;
423     }
424 
425     if (currentNode.isNodeType(TrashService.EXO_RESTORE_LOCATION)) {
426       restorePath = currentNode.getProperty(TrashService.RESTORE_PATH).getString();
427       restoreWorkspace = currentNode.getProperty(TrashService.RESTORE_WORKSPACE).getString();
428       restorePath = restorePath.substring(0, restorePath.lastIndexOf("/"));
429     } else {
430       // Is not a deleted node, may be groovy action, hidden node,...
431       return false;
432     }
433     Session session = WCMCoreUtils.getUserSessionProvider().getSession(restoreWorkspace, WCMCoreUtils.getRepository());
434     try {
435       if (restorePath == null || restorePath.length() == 0) {
436         restoreLocationNode = session.getRootNode();
437       } else {
438         restoreLocationNode = (Node) session.getItem(restorePath);
439       }
440     } catch (Exception e) {
441       return false;
442     }
443     return PermissionUtil.canAddNode(restoreLocationNode);
444   }
445 
446   public static boolean isReferenceable(Node node) throws RepositoryException {
447     return node.isNodeType(MIX_REFERENCEABLE);
448   }
449 
450   public static boolean isNameValid(String name, String[] regexpression) {
451     for (String c : regexpression) {
452       if (name == null || name.contains(c))
453         return false;
454     }
455     return true;
456   }
457 
458   public static boolean isNameEmpty(String name) {
459     return (name == null || name.trim().length() == 0);
460   }
461 
462   public static boolean isAuditable(Node node) throws RepositoryException {
463     return node.isNodeType(EXO_AUDITABLE);
464   }
465 
466   public static String getIndexName(Node node) throws RepositoryException {
467     StringBuilder buffer = new StringBuilder(128);
468     buffer.append(node.getName());
469     int index = node.getIndex();
470     if (index > 1) {
471       buffer.append('[');
472       buffer.append(index);
473       buffer.append(']');
474 
475     }
476     return buffer.toString();
477   }
478 
479   public static List<String> getListAllowedFileType(Node currentNode, TemplateService templateService) throws Exception {
480     List<String> nodeTypes = new ArrayList<String>();
481     NodeTypeManager ntManager = currentNode.getSession().getWorkspace().getNodeTypeManager();
482     NodeType currentNodeType = currentNode.getPrimaryNodeType();
483     NodeDefinition[] childDefs = currentNodeType.getChildNodeDefinitions();
484     List<String> templates = templateService.getDocumentTemplates();
485     try {
486       for (int i = 0; i < templates.size(); i++) {
487         String nodeTypeName = templates.get(i).toString();
488         NodeType nodeType = ntManager.getNodeType(nodeTypeName);
489         NodeType[] superTypes = nodeType.getSupertypes();
490         boolean isCanCreateDocument = false;
491         for (NodeDefinition childDef : childDefs) {
492           NodeType[] requiredChilds = childDef.getRequiredPrimaryTypes();
493           for (NodeType requiredChild : requiredChilds) {
494             if (nodeTypeName.equals(requiredChild.getName())) {
495               isCanCreateDocument = true;
496               break;
497             }
498           }
499           if (nodeTypeName.equals(childDef.getName()) || isCanCreateDocument) {
500             if (!nodeTypes.contains(nodeTypeName))
501               nodeTypes.add(nodeTypeName);
502             isCanCreateDocument = true;
503           }
504         }
505         if (!isCanCreateDocument) {
506           for (NodeType superType : superTypes) {
507             for (NodeDefinition childDef : childDefs) {
508               for (NodeType requiredType : childDef.getRequiredPrimaryTypes()) {
509                 if (superType.getName().equals(requiredType.getName())) {
510                   if (!nodeTypes.contains(nodeTypeName))
511                     nodeTypes.add(nodeTypeName);
512                   isCanCreateDocument = true;
513                   break;
514                 }
515               }
516               if (isCanCreateDocument)
517                 break;
518             }
519             if (isCanCreateDocument)
520               break;
521           }
522         }
523       }
524     } catch (Exception e) {
525       if (LOG.isErrorEnabled()) {
526         LOG.error("Unexpected error", e);
527       }
528     }
529     return nodeTypes;
530   }
531 
532   public static String getNodeTypeIcon(Node node, String appended, String mode) throws RepositoryException {
533     return org.exoplatform.services.cms.impl.Utils.getNodeTypeIcon(node, appended, mode);
534   }
535 
536   public static String getNodeTypeIcon(Node node, String appended) throws RepositoryException {
537     return org.exoplatform.services.cms.impl.Utils.getNodeTypeIcon(node, appended);
538   }
539 
540   public static NodeIterator getAuthorizedChildNodes(Node node) throws Exception {
541     NodeIterator iter = node.getNodes();
542     while (iter.hasNext()) {
543       if (!PermissionUtil.canRead(iter.nextNode()))
544         iter.remove();
545     }
546     return iter;
547   }
548 
549   public static List<Node> getAuthorizedChildList(Node node) throws Exception {
550     List<Node> children = new ArrayList<Node>();
551     NodeIterator iter = node.getNodes();
552     while (iter.hasNext()) {
553       Node child = iter.nextNode();
554       if (PermissionUtil.canRead(child))
555         children.add(child);
556     }
557     return children;
558   }
559 
560   public static boolean isLockTokenHolder(Node node) throws Exception {
561     if (node.getLock().getLockToken() != null) {
562       return true;
563     }
564     return false;
565   }
566 
567   public static List<String> getMemberships() throws Exception {
568     return org.exoplatform.services.cms.impl.Utils.getMemberships();
569   }
570 
571   public static List<String> getGroups() throws Exception {
572     ConversationState conversationState = ConversationState.getCurrent();
573     Identity identity = conversationState.getIdentity();
574     Set<String> groups = identity.getGroups();
575     return new ArrayList<String>(groups);
576   }
577 
578   public static String getNodeOwner(Node node) throws Exception {
579     try {
580       if (node.hasProperty(EXO_OWNER)) {
581         return node.getProperty(EXO_OWNER).getString();
582       }
583     } catch (Exception e) {
584       return null;
585     }
586     return null;
587   }
588 
589   public static Node findNodeByUUID(String uuid) throws Exception {
590     RepositoryService repositoryService = Util.getUIPortal().getApplicationComponent(RepositoryService.class);
591     SessionProviderService sessionProviderService = Util.getUIPortal().getApplicationComponent(SessionProviderService.class);
592     SessionProvider sessionProvider = sessionProviderService.getSessionProvider(null);
593     ManageableRepository manageableRepository = repositoryService.getCurrentRepository();
594     Node node = null;
595     for (String wsName : manageableRepository.getWorkspaceNames()) {
596       try {
597         node = sessionProvider.getSession(wsName, manageableRepository).getNodeByUUID(uuid);
598       } catch (ItemNotFoundException e) {
599         continue;
600       }
601     }
602     return node;
603   }
604 
605   public static boolean isSymLink(Node node) throws RepositoryException {
606     LinkManager linkManager = Util.getUIPortal().getApplicationComponent(LinkManager.class);
607     return linkManager.isLink(node);
608   }
609 
610   public static Node getNodeSymLink(Node node) throws Exception {
611     LinkManager linkManager = Util.getUIPortal().getApplicationComponent(LinkManager.class);
612     Node realNode = null;
613     if (linkManager.isLink(node)) {
614       if (linkManager.isTargetReachable(node)) {
615         realNode = linkManager.getTarget(node);
616       }
617     } else {
618       realNode = node;
619     }
620     return realNode;
621   }
622 
623   public static InputStream extractFirstEntryFromZipFile(ZipInputStream zipStream) throws Exception {
624     return zipStream.getNextEntry() == null ? null : zipStream;
625   }
626 
627   public static String getThumbnailImage(InputStream input, String downloadName) throws Exception {
628     DownloadService dservice = WCMCoreUtils.getService(DownloadService.class);
629     InputStreamDownloadResource dresource = new InputStreamDownloadResource(input, "image");
630     dresource.setDownloadName(downloadName);
631     return dservice.getDownloadLink(dservice.addDownloadResource(dresource));
632   }
633 
634   public static String getThumbnailImage(Node node, String propertyName) throws Exception {
635     ThumbnailService thumbnailService = Util.getUIPortal().getApplicationComponent(ThumbnailService.class);
636     if (node.isNodeType(NT_FILE)) {
637       String mimeType = node.getNode(JCR_CONTENT).getProperty(JCR_MIMETYPE).getString();
638       if (mimeType.startsWith("image")) {
639         Node thumbnailNode = thumbnailService.addThumbnailNode(node);
640         InputStream inputStream = node.getNode(JCR_CONTENT).getProperty(JCR_DATA).getStream();
641         thumbnailService.createSpecifiedThumbnail(thumbnailNode, ImageIO.read(inputStream), propertyName);
642       }
643     }
644     Node thumbnailNode = thumbnailService.getThumbnailNode(node);
645     if (thumbnailNode != null && thumbnailNode.hasProperty(propertyName)) {
646       DownloadService dservice = Util.getUIPortal().getApplicationComponent(DownloadService.class);
647       InputStream input = thumbnailNode.getProperty(propertyName).getStream();
648       InputStreamDownloadResource dresource = new InputStreamDownloadResource(input, "image");
649       dresource.setDownloadName(node.getName());
650       return dservice.getDownloadLink(dservice.addDownloadResource(dresource));
651     }
652     return null;
653   }
654 
655   public static String calculateFileSize(double fileLengthLong) {
656     int fileLengthDigitCount = Double.toString(fileLengthLong).length();
657     double fileSizeKB = 0.0;
658     String howBig = "";
659     if (fileLengthDigitCount < 5) {
660       fileSizeKB = Math.abs(fileLengthLong);
661       howBig = "Byte(s)";
662     } else if (fileLengthDigitCount >= 5 && fileLengthDigitCount <= 6) {
663       fileSizeKB = Math.abs((fileLengthLong / 1024));
664       howBig = "KB";
665     } else if (fileLengthDigitCount >= 7 && fileLengthDigitCount <= 9) {
666       fileSizeKB = Math.abs(fileLengthLong / (1024 * 1024));
667       howBig = "MB";
668     } else if (fileLengthDigitCount > 9) {
669       fileSizeKB = Math.abs((fileLengthLong / (1024 * 1024 * 1024)));
670       howBig = "GB";
671     }
672     String finalResult = roundTwoDecimals(fileSizeKB);
673     return finalResult + " " + howBig;
674   }
675 
676   private static String roundTwoDecimals(double d) {
677     DecimalFormat twoDForm = new DecimalFormat("#.##");
678     return twoDForm.format(d);
679   }
680 
681   /**
682    * Get resource bundle from PortalApplication resource bundle
683    *
684    * @param key
685    * @return
686    * @throws MissingResourceException
687    */
688   public static String getResourceBundle(String key) throws MissingResourceException {
689     RequestContext context = Util.getPortalRequestContext();
690     ResourceBundle res = context.getApplicationResourceBundle();
691     return res.getString(key);
692   }
693 
694   /**
695    * Get resource bundle from given resource file
696    *
697    * @param name : resource file name
698    * @param key : key
699    * @param cl : ClassLoader to load resource file
700    * @return
701    */
702   public static String getResourceBundle(String name, String key, ClassLoader cl) {
703     Locale locale = WebuiRequestContext.getCurrentInstance().getLocale();
704     ResourceBundleService resourceBundleService = WCMCoreUtils.getService(ResourceBundleService.class);
705     ResourceBundle resourceBundle = resourceBundleService.getResourceBundle(name, locale, cl);
706     try {
707       return resourceBundle.getString(key);
708     } catch (MissingResourceException ex) {
709       return key;
710     }
711   }
712 
713   public static String getRestContextName(String portalContainerName) {
714     ExoContainer container = ExoContainerContext.getCurrentContainer();
715     PortalContainerConfig portalContainerConfig = (PortalContainerConfig) container.getComponentInstance(PortalContainerConfig.class);
716     return portalContainerConfig.getRestContextName(portalContainerName);
717   }
718 
719   public static String getInlineEditingField(Node orgNode, String propertyName) throws Exception {
720     String defaultValue = "";
721     String idGenerator = "";
722     Pattern p = Pattern.compile("[^a-zA-Z0-9]");
723     Matcher m = p.matcher(propertyName);
724     if (orgNode.hasProperty(propertyName)) {
725       defaultValue = orgNode.getProperty(propertyName).getString();
726     }
727     idGenerator = m.replaceAll("_");
728     return getInlineEditingField(orgNode, propertyName, defaultValue, INPUT_TEXT, idGenerator, DEFAULT_CSS_NAME, true);
729   }
730 
731   /**
732    * @param orgNode Processed node
733    * @param propertyName which property used for editing
734    * @param inputType input type for editing: TEXT, TEXTAREA, WYSIWYG
735    * @param cssClass class name for CSS, should implement: cssClass,
736    *          [cssClass]Title Edit[cssClass] as relative css Should create the
737    *          function: InlineEditor.presentationRequestChange[cssClass] to
738    *          request the rest-service
739    * @param isGenericProperty set as true to use generic javascript function,
740    *          other wise, must create the correctspond function
741    *          InlineEditor.presentationRequestChange[cssClass]
742    * @param arguments Extra parameter for Input component (toolbar, width,
743    *          height,.. for CKEditor/TextArea)
744    * @return String that can be put on groovy template
745    * @throws Exception
746    * @author vinh_nguyen
747    */
748   public static String getInlineEditingField(Node orgNode,
749                                              String propertyName,
750                                              String defaultValue,
751                                              String inputType,
752                                              String idGenerator,
753                                              String cssClass,
754                                              boolean isGenericProperty,
755                                              String... arguments) throws Exception {
756     HashMap<String, String> parsedArguments = parseArguments(arguments);
757     String height = parsedArguments.get(HEIGHT);
758     String bDirection = parsedArguments.get(BUTTON_DIR);
759     String publishLink = parsedArguments.get(FAST_PUBLISH_LINK);
760 
761     Locale locale = WebuiRequestContext.getCurrentInstance().getLocale();
762     String language = locale.toString();
763     ResourceBundleService resourceBundleService = WCMCoreUtils.getService(ResourceBundleService.class);
764     ResourceBundle resourceBundle;
765     resourceBundle = resourceBundleService.getResourceBundle(LOCALE_WEBUI_DMS, locale);
766 
767     String draft = INLINE_DRAFT;
768     String published = INLINE_PUBLISHED;
769     try {
770       draft = StringEscapeUtils.escapeHtml(resourceBundle.getString("PublicationStates.draft"));
771       published = StringEscapeUtils.escapeHtml(resourceBundle.getString("PublicationStates.published"));
772     } catch (MissingResourceException ex) {
773       if (LOG.isWarnEnabled()) {
774         LOG.warn("Missing resource exception of draft/published status.", ex);
775       }
776     }
777 
778     String portletRealID;
779     if(WebuiRequestContext.getCurrentInstance() instanceof PortletRequestContext) {
780       portletRealID = org.exoplatform.wcm.webui.Utils.getRealPortletId((PortletRequestContext) WebuiRequestContext.getCurrentInstance());
781     } else {
782       portletRealID = "";
783     }
784     StringBuffer sb = new StringBuffer();
785     StringBuffer actionsb = new StringBuffer();
786     String repo = ((ManageableRepository) orgNode.getSession().getRepository()).getConfiguration().getName();
787     String workspace = orgNode.getSession().getWorkspace().getName();
788     String uuid = orgNode.getUUID();
789     String strSuggestion = "";
790     String acceptButton = "";
791     String cancelButton = "";
792     portletRealID = portletRealID.replace('-', '_');
793     String showBlockId = "Current" + idGenerator + "_" + portletRealID;
794     String editBlockEditorID = "Edit" + idGenerator + "_" + portletRealID;
795     String editFormID = "Edit" + idGenerator + "Form_" + portletRealID;
796     String newValueInputId = "new" + idGenerator + "_" + portletRealID;
797     String currentValueID = "old" + idGenerator + "_" + portletRealID;
798     String siteName = org.exoplatform.portal.webui.util.Util.getPortalRequestContext().getPortalOwner();
799     String currentValue = StringUtils.replace(defaultValue, "{portalName}", siteName);
800     try {
801       strSuggestion = StringEscapeUtils.escapeHtml(resourceBundle.getString("UIPresentation.label.EditingSuggestion"));
802       acceptButton = StringEscapeUtils.escapeHtml(resourceBundle.getString("UIPresentation.title.AcceptButton"));
803       cancelButton = StringEscapeUtils.escapeHtml(resourceBundle.getString("UIPresentation.title.CancelButton"));
804     } catch (MissingResourceException e) {
805       if (LOG.isWarnEnabled()) {
806         LOG.warn("MissingResourceException of EditingSuggestion/Accept/Cancel buttons.", e);
807       }
808     }
809     actionsb.append(" return InlineEditor.presentationRequestChange");
810 
811     if (isGenericProperty) {
812       actionsb.append("Property").append("('").append("/property?', '").append(propertyName).append("', '");
813     } else {
814       actionsb.append(cssClass).append("('");
815     }
816     actionsb.append(currentValueID)
817             .append("', '")
818             .append(newValueInputId)
819             .append("', '")
820             .append(repo)
821             .append("', '")
822             .append(workspace)
823             .append("', '")
824             .append(uuid)
825             .append("', '")
826             .append(editBlockEditorID)
827             .append("', '")
828             .append(showBlockId)
829             .append("', '")
830             .append(siteName)
831             .append("', '")
832             .append(language);
833 
834     if (inputType.equals(INPUT_WYSIWYG)) {
835       actionsb.append("', 1);");
836     } else {
837       actionsb.append("');");
838     }
839     String strAction = actionsb.toString();
840 
841     if (orgNode.hasProperty(propertyName)) {
842       try {
843         if (propertyName.equals(EXO_TITLE))
844           return ContentReader.getXSSCompatibilityContent(orgNode.getProperty(propertyName).getString());
845         String propertyValue;
846         if (propertyName.equals(JCR_CONTENT_DESCRIPTION)) {
847           propertyValue = orgNode.getProperty(propertyName).getValues()[0].getString();
848           return HTMLSanitizer.sanitize(propertyValue);
849         }
850         if (orgNode.getProperty(propertyName).getDefinition().isMultiple()) {
851           // The requested property is multiple-valued, inline editing enable
852           // users to edit the first value of property
853           propertyValue = orgNode.getProperty(propertyName).getValues()[0].getString();
854           propertyValue = ContentReader.simpleEscapeHtml(propertyValue);
855         } else {
856           propertyValue = orgNode.getProperty(propertyName).getString();
857         }
858         if (org.exoplatform.wcm.webui.Utils.getCurrentMode().equals(WCMComposer.MODE_LIVE))
859           return StringUtils.replace(propertyValue, "{portalName}", siteName);
860         else
861           return "<div class=\"WCMInlineEditable\" contenteditable=\"true\" propertyName=\"" + propertyName + "\" repo=\"" + repo
862               + "\" workspace=\"" + workspace + "\"" + " uuid=\"" + uuid + "\" siteName=\"" + siteName + "\" publishedMsg=\""
863               + published + "\" draftMsg=\"" + draft + "\" fastpublishlink=\"" + publishLink + "\" language=\"" + language
864               + "\" >" + propertyValue + "</div>";
865       } catch (Exception e) {
866         if (org.exoplatform.wcm.webui.Utils.getCurrentMode().equals(WCMComposer.MODE_LIVE))
867           return currentValue;
868         else
869           return "<div class=\"WCMInlineEditable\" contenteditable=\"true\" propertyName=\"" + propertyName + "\" repo=\"" + repo
870               + "\" workspace=\"" + workspace + "\" " + "uuid=\"" + uuid + "\" siteName=\"" + siteName + "\" publishedMsg=\""
871               + published + "\" draftMsg=\"" + draft + "\" fastpublishlink=\"" + publishLink + "\" language=\"" + language
872               + "\" >" + defaultValue + "</div>";
873       }
874     }
875 
876     sb.append("<div class=\"InlineEditing\" >\n");
877     sb.append("\n<div rel=\"tooltip\" data-placement=\"bottom\" id=\"")
878       .append(showBlockId)
879       .append("\" Class=\"")
880       .append(cssClass)
881       .append("\"");
882     sb.append("title=\"").append(strSuggestion).append("\"");
883     sb.append(" onClick=\"InlineEditor.presentationSwitchBlock('")
884       .append(showBlockId)
885       .append("', '")
886       .append(editBlockEditorID)
887       .append("');\"");
888 
889     sb.append("onmouseout=\"this.className='")
890       .append(cssClass)
891       .append("';\" onblur=\"this.className='")
892       .append(cssClass)
893       .append("';\" onfocus=\"this.className='")
894       .append(cssClass)
895       .append("Hover")
896       .append("';\" onmouseover=\"this.className='")
897       .append(cssClass)
898       .append("Hover';\">")
899       .append(currentValue)
900       .append("</div>\n");
901     sb.append("\t<div id=\"").append(editBlockEditorID).append("\" class=\"Edit").append(cssClass).append("\">\n");
902     sb.append("\t\t<form name=\"")
903       .append(editFormID)
904       .append("\" id=\"")
905       .append(editFormID)
906       .append("\" onSubmit=\"")
907       .append(strAction)
908       .append("\">\n");
909     sb.append("<DIV style=\"display:none; visible:hidden\" id=\"")
910       .append(currentValueID)
911       .append("\" name=\"")
912       .append(currentValueID)
913       .append("\">")
914       .append(currentValue)
915       .append("</DIV>");
916 
917     if (bDirection != null && bDirection.equals(LEFT2RIGHT)) {
918       sb.append("\t\t<a href=\"#\" rel=\"tooltip\" data-placement=\"bottom\"")
919         .append(" class =\"AcceptButton\" style=\"float:left\" onclick=\"")
920         .append(strAction)
921         .append("\" title=\"" + acceptButton + "\">&nbsp;</a>\n");
922       sb.append("\t\t<a href=\"#\" rel=\"tooltip\" data-placement=\"bottom\" class =\"CancelButton\" style=\"float:left\" ")
923         .append("onClick=\"InlineEditor.presentationSwitchBlock('");
924       sb.append(editBlockEditorID).append("', '").append(showBlockId).append("');\" title=\"" + cancelButton + "\">&nbsp;</a>\n");
925     } else {
926       sb.append("\t\t<a href=\"#\" rel=\"tooltip\" data-placement=\"bottom\" class =\"CancelButton\" ")
927         .append("onClick=\"InlineEditor.presentationSwitchBlock('");
928       sb.append(editBlockEditorID).append("', '").append(showBlockId).append("');\" title=\"" + cancelButton + "\">&nbsp;</a>\n");
929       sb.append("\t\t<a href=\"#\" rel=\"tooltip\" data-placement=\"bottom\" class =\"AcceptButton\" onclick=\"")
930         .append(strAction)
931         .append("\" title=\"" + acceptButton + "\">&nbsp;</a>\n");
932     }
933     sb.append("\t\t<div class=\"Edit").append(cssClass).append("Input\">\n ");
934 
935     sb.append("\n\t\t</div>\n\t</form>\n</div>\n\n</div>");
936     return sb.toString();
937   }
938 
939   private static HashMap<String, String> parseArguments(String... arguments) {
940     HashMap<String, String> map = new HashMap<String, String>();
941     int sIndex = -1;
942     for (String argument : arguments) {
943       String value = null;
944       sIndex = argument.indexOf(SEPARATOR);
945       if (sIndex > 0) {
946         value = argument.substring(sIndex + 1);
947       } else {
948         continue;
949       }
950       if (argument.startsWith(JCR_PATH)) {
951         map.put(JCR_PATH, value);
952         continue;
953       } else if (argument.startsWith(TOOLBAR)) {
954         map.put(TOOLBAR, value);
955         continue;
956       } else if (argument.startsWith(CSS)) {
957         map.put(CSS, value);
958         continue;
959       } else if (argument.startsWith(HEIGHT)) {
960         map.put(HEIGHT, value);
961         continue;
962       } else if (argument.startsWith(BUTTON_DIR)) {
963         map.put(BUTTON_DIR, value);
964         continue;
965       } else if (argument.startsWith(PREV_HTML)) {
966         map.put(PREV_HTML, value);
967         continue;
968       } else if (argument.startsWith(POST_HTML)) {
969         map.put(POST_HTML, value);
970         continue;
971       } else if (argument.startsWith(FAST_PUBLISH_LINK)) {
972         map.put(FAST_PUBLISH_LINK, value);
973         continue;
974       }
975     }
976     return map;
977   }
978 
979   /**
980    * Gets the title.
981    *
982    * @param node the node
983    * @return the title
984    * @throws Exception the exception
985    */
986   public static String getTitle(Node node) throws Exception {
987     String title = null;
988     try {
989       title = node.getProperty("exo:title").getValue().getString();
990     } catch (PathNotFoundException pnf1) {
991       try {
992         Value[] values = node.getNode("jcr:content").getProperty("dc:title").getValues();
993         if (values.length != 0) {
994           title = values[0].getString();
995         }
996       } catch (PathNotFoundException pnf2) {
997         title = null;
998       }
999     } catch (ValueFormatException e) {
1000       title = null;
1001     } catch (IllegalStateException e) {
1002       title = null;
1003     } catch (RepositoryException e) {
1004       title = null;
1005     }
1006     if (StringUtils.isBlank(title)) {
1007       title = node.getName();
1008     }
1009     return ContentReader.getXSSCompatibilityContent(title);
1010   }
1011 
1012   /**
1013    * @param node
1014    * @return
1015    * @throws Exception
1016    */
1017   public static String getTitleWithSymlink(Node node) throws Exception {
1018     String title = null;
1019     Node nProcessNode = node;
1020     if (title == null) {
1021       nProcessNode = node;
1022       if (nProcessNode.hasProperty("exo:title")) {
1023         title = nProcessNode.getProperty("exo:title").getValue().getString();
1024       }
1025       if (nProcessNode.hasNode("jcr:content")) {
1026         Node content = nProcessNode.getNode("jcr:content");
1027         if (content.hasProperty("dc:title")) {
1028           try {
1029             title = content.getProperty("dc:title").getValues()[0].getString();
1030           } catch (Exception e) {
1031             title = null;
1032           }
1033         }
1034       }
1035       if (title != null)
1036         title = title.trim();
1037     }
1038     if (title != null && title.length() > 0)
1039       return ContentReader.getXSSCompatibilityContent(title);
1040     if (isSymLink(node)) {
1041       nProcessNode = getNodeSymLink(nProcessNode);
1042       if (nProcessNode == null) {
1043         nProcessNode = node;
1044       }
1045       if (nProcessNode.hasProperty("exo:title")) {
1046         title = nProcessNode.getProperty("exo:title").getValue().getString();
1047       }
1048       if (nProcessNode.hasNode("jcr:content")) {
1049         Node content = nProcessNode.getNode("jcr:content");
1050         if (content.hasProperty("dc:title")) {
1051           try {
1052             title = content.getProperty("dc:title").getValues()[0].getString();
1053           } catch (Exception e) {
1054             title = null;
1055           }
1056         }
1057       }
1058       if (title != null) {
1059         title = title.trim();
1060         if (title.length() == 0)
1061           title = null;
1062       }
1063     }
1064 
1065     if (title == null)
1066       title = nProcessNode.getName();
1067     return ContentReader.getXSSCompatibilityContent(title);
1068   }
1069 
1070   /**
1071    * Get UIComponent to process render a node which has specified mimeType
1072    *
1073    * @param mimeType
1074    * @param container
1075    * @return
1076    * @throws Exception
1077    */
1078   public static UIComponent getUIComponent(String mimeType, UIContainer container) throws Exception {
1079     UIExtensionManager manager = WCMCoreUtils.getService(UIExtensionManager.class);
1080     List<UIExtension> extensions = manager.getUIExtensions(FILE_VIEWER_EXTENSION_TYPE);
1081     Map<String, Object> context = new HashMap<String, Object>();
1082     context.put(MIME_TYPE, mimeType.toLowerCase());
1083     for (UIExtension extension : extensions) {
1084       UIComponent uiComponent = manager.addUIExtension(extension, context, container);
1085       if (uiComponent != null)
1086         return uiComponent;
1087     }
1088     return null;
1089   }
1090 
1091   /*
1092    * Check the current node is eligible to add mix:versionable or not
1093    * @param node the current node
1094    * @param nodetypes The list of node types have child nodes which are not add
1095    * mix:versionaboe while enrolling.
1096    * @throws Exception the exception
1097    */
1098   public static boolean isMakeVersionable(Node node, String[] nodeTypes) throws Exception {
1099     String ws = node.getSession().getWorkspace().getName();
1100     SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
1101     ManageableRepository manageableRepository = WCMCoreUtils.getRepository();
1102     Session session = sessionProvider.getSession(ws, manageableRepository);
1103     node = (Node) session.getItem(node.getPath());
1104     int deep = node.getDepth();
1105     for (int i = 0; i < deep; i++) {
1106       Node parent = node.getParent();
1107       for (String nodeType : nodeTypes) {
1108         if (nodeType != null && nodeType.length() > 0 && parent.isNodeType(nodeType))
1109           return false;
1110       }
1111       node = parent;
1112     }
1113     return true;
1114   }
1115 
1116   /**
1117    * Get a cookie value with given name
1118    *
1119    * @param cookieName cookies
1120    * @return a cookies value
1121    */
1122   public static String getCookieByCookieName(String cookieName) {
1123     HttpServletRequest request = Util.getPortalRequestContext().getRequest();
1124     Cookie[] cookies = request.getCookies();
1125     if (cookies == null) {
1126       return null;
1127     }
1128     for (int loopIndex = 0; loopIndex < cookies.length; loopIndex++) {
1129       Cookie cookie1 = cookies[loopIndex];
1130       if (cookie1.getName().equals(cookieName))
1131         return cookie1.getValue();
1132     }
1133     return null;
1134   }
1135 
1136   /**
1137    * @param node nt:file node with have the data stream
1138    * @return Link to download the jcr:data of the given node
1139    * @throws Exception
1140    */
1141   public static String getDownloadRestServiceLink(Node node) throws Exception {
1142     ExoContainer container = ExoContainerContext.getCurrentContainer();
1143     PortalContainerInfo containerInfo = (PortalContainerInfo) container.getComponentInstanceOfType(PortalContainerInfo.class);
1144     String portalName = containerInfo.getContainerName();
1145     PortalContainerConfig portalContainerConfig = (PortalContainerConfig) container.getComponentInstance(PortalContainerConfig.class);
1146     String restContextName = portalContainerConfig.getRestContextName(portalName);
1147     StringBuilder sb = new StringBuilder();
1148     Node currentNode = org.exoplatform.wcm.webui.Utils.getRealNode(node);
1149     String ndPath = currentNode.getPath();
1150     if (ndPath.startsWith("/")) {
1151       ndPath = ndPath.substring(1);
1152     }
1153     String encodedPath = encodePath(ndPath,"UTF-8");
1154     sb.append("/").append(restContextName).append("/contents/download/");
1155     sb.append(currentNode.getSession().getWorkspace().getName()).append("/").append(encodedPath);
1156     if (node.isNodeType("nt:frozenNode")) {
1157       sb.append("?version=" + node.getParent().getName());
1158     }
1159     return sb.toString();
1160   }
1161 
1162   public static String getPDFViewerLink(Node node) throws Exception {
1163     ExoContainer container = ExoContainerContext.getCurrentContainer();
1164     PortalContainerInfo containerInfo = (PortalContainerInfo) container.getComponentInstanceOfType(PortalContainerInfo.class);
1165     String portalName = containerInfo.getContainerName();
1166     PortalContainerConfig portalContainerConfig = (PortalContainerConfig) container.getComponentInstance(PortalContainerConfig.class);
1167     String restContextName = portalContainerConfig.getRestContextName(portalName);
1168     StringBuilder sb = new StringBuilder();
1169     String repository = ((ManageableRepository) node.getSession().getRepository()).getConfiguration().getName();
1170     sb.append("/").append(restContextName).append("/pdfviewer/");
1171     sb.append(repository).append("/");
1172     sb.append(node.getSession().getWorkspace().getName()).append("/").append(node.getUUID());
1173     return sb.toString();
1174   }
1175 
1176   /**
1177    * Get allowed folder types in current path.
1178    *
1179    * @param currentNode
1180    * @param currentDrive
1181    * @return list of node types
1182    * @throws Exception
1183    */
1184   public static List<String> getAllowedFolderTypesInCurrentPath(Node currentNode, DriveData currentDrive) throws Exception {
1185     List<String> allowedTypes = new ArrayList<String>();
1186     NodeTypeImpl currentNodeType = (NodeTypeImpl) currentNode.getPrimaryNodeType();
1187     String[] arrFoldertypes = currentDrive.getAllowCreateFolders().split(",");
1188     NodeTypeManager ntManager = currentNode.getSession().getWorkspace().getNodeTypeManager();
1189 
1190     for (String strFolderType : arrFoldertypes) {
1191       if (strFolderType.isEmpty())
1192         continue;
1193       NodeType folderType = ntManager.getNodeType(strFolderType);
1194       if ((currentNodeType).isChildNodePrimaryTypeAllowed(Constants.JCR_ANY_NAME, ((NodeTypeImpl) folderType).getQName())) {
1195         allowedTypes.add(strFolderType);
1196       }
1197     }
1198 
1199     return allowedTypes;
1200   }
1201 
1202   /**
1203    * removes child nodes in path list if ancestor of the node exists in list
1204    *
1205    * @param srcPath the list of nodes
1206    * @return the node list with out child nodes
1207    */
1208   public static String[] removeChildNodes(String srcPath) {
1209     if (StringUtils.isEmpty(srcPath)) {
1210       return new String[] {};
1211     }
1212     if (!srcPath.contains(";")) {
1213       return new String[] { srcPath };
1214     }
1215     String[] paths = srcPath.split(";");
1216     List<String> ret = new ArrayList<String>();
1217     for (int i = 0; i < paths.length; i++) {
1218       boolean ok = true;
1219       for (int j = 0; j < paths.length; j++) {
1220         // check if [i] is child of [j]
1221         if ((i != j) && paths[i].startsWith(paths[j]) && (paths[i].length() > paths[j].length())
1222             && (paths[i].charAt(paths[j].length()) == '/')) {
1223           ok = false;
1224           break;
1225         }
1226       }
1227       if (ok) {
1228         ret.add(paths[i]);
1229       }
1230     }
1231     return ret.toArray(new String[] {});
1232   }
1233 
1234   public static void openDocumentInDesktop(Node currentNode, UIPopupContainer popupContainer, Event<? extends UIComponent> event) throws Exception {
1235     HttpServletRequest httpServletRequest = Util.getPortalRequestContext().getRequest();
1236 
1237     String nodePath = currentNode.getPath();
1238     String ws = currentNode.getSession().getWorkspace().getName();
1239     String repo = WCMCoreUtils.getRepository().getConfiguration().getName();
1240     String filePath = httpServletRequest.getScheme() + "://" + httpServletRequest.getServerName() + ":"
1241         + httpServletRequest.getServerPort() + "/" + WCMCoreUtils.getRestContextName() + "/private/jcr/" + repo + "/" + ws
1242         + nodePath;
1243     String workspaceMountPath = httpServletRequest.getScheme()+ "://" + httpServletRequest.getServerName() + ":"
1244         + httpServletRequest.getServerPort() + "/"
1245         + WCMCoreUtils.getRestContextName()+ "/private/jcr/" + repo + "/" + ws;
1246 
1247     NodeHierarchyCreator nodeHierarchyCreator = WCMCoreUtils.getService(NodeHierarchyCreator.class);
1248 
1249     String mountPath;
1250 
1251     if(((NodeImpl)currentNode.getParent()).isRoot()) {
1252       mountPath = workspaceMountPath;
1253     }
1254     else{
1255       mountPath = workspaceMountPath + checkMountPath(currentNode, generateMountURL(nodePath, ws, nodeHierarchyCreator.getJcrPath(BasePath.CMS_USERS_PATH),
1256               nodeHierarchyCreator.getJcrPath(BasePath.CMS_GROUPS_PATH)));
1257     }
1258 
1259 
1260     if (currentNode.isLocked()) {
1261       String[] userLock = { currentNode.getLock().getLockOwner() };
1262 
1263       UIOpenDocumentForm uiOpenDocumentForm = popupContainer.activate(UIOpenDocumentForm.class, 600);
1264       uiOpenDocumentForm.setId("UIReadOnlyFileConfirmMessage");
1265       uiOpenDocumentForm.setMessageKey("UIPopupMenu.msg.lock-node-read-only");
1266       uiOpenDocumentForm.setArguments(userLock);
1267       uiOpenDocumentForm.setFilePath(nodePath);
1268       uiOpenDocumentForm.setMountPath(mountPath);
1269       uiOpenDocumentForm.setAbsolutePath(filePath);
1270       event.getRequestContext()
1271            .getJavascriptManager()
1272            .require("SHARED/openDocumentInOffice")
1273            .addScripts("eXo.ecm.OpenDocumentInOffice.showConfirmBox();");
1274     } else {
1275       event.getRequestContext()
1276            .getJavascriptManager()
1277            .require("SHARED/openDocumentInOffice")
1278            .addScripts("eXo.ecm.OpenDocumentInOffice.openDocument('" + filePath + "', '" + mountPath + "');");
1279     }
1280     event.getRequestContext().addUIComponentToUpdateByAjax(popupContainer.getParent());
1281 
1282   }
1283 
1284   public static void logUnavaiblePreview(String path) {
1285     LOG.warn("Can not preview the document having path : " + path);
1286   }
1287 
1288   public static String encodePath(String path, String encoding) {
1289     try {
1290       String encodedPath = URLEncoder.encode(path,encoding);
1291       encodedPath = encodedPath.replaceAll("%2F","/");
1292       return encodedPath;
1293     } catch (UnsupportedEncodingException e){
1294       LOG.error("Failed to encode path '" + path + "' with encoding '" + encoding + "'",e);
1295     }
1296     return null;
1297   }
1298 
1299   static public class NodeTypeNameComparator implements Comparator<NodeType> {
1300     public int compare(NodeType n1, NodeType n2) throws ClassCastException {
1301       String name1 = n1.getName();
1302       String name2 = n2.getName();
1303       return name1.compareToIgnoreCase(name2);
1304     }
1305   }
1306 
1307   /**
1308    * Generate the webdav mount  URL
1309    * @param nodePath : jcr path
1310    * @param ws :  workspace name
1311    * @return
1312    */
1313   public static String generateMountURL(String nodePath, String ws, String userPath, String groupPath) {
1314     if (StringUtils.isNotBlank(nodePath) && COLLABORATION_WS.equals(ws)) {
1315       StringBuilder mountPath = new StringBuilder();
1316       String[] ancestors = nodePath.substring(1).split("/");
1317 
1318       if (ancestors.length <= 1)
1319         return "/";
1320       //User folder mount
1321       if (nodePath.startsWith(userPath)) {
1322         if (ancestors.length >= USER_DEPTH + 1)
1323           mountPath.append(nodePath.substring(0, nodePath.indexOf(ancestors[USER_DEPTH + 1])-1));
1324         else
1325           mountPath.append(nodePath.substring(0, nodePath.indexOf(ancestors[ancestors.length-1])-1));
1326       }
1327       //Space folder mount
1328       else if (nodePath.startsWith(groupPath + SPACE_GROUP)) {
1329         if (ancestors.length > 3)
1330           mountPath.append(nodePath.substring(0, nodePath.indexOf(ancestors[3])-1));
1331         else
1332           mountPath.append(groupPath + SPACE_GROUP);
1333       }
1334       //Group folder mount
1335       else if (nodePath.startsWith(groupPath)) {
1336         if (ancestors.length > 2)
1337           mountPath.append(nodePath.substring(0, nodePath.indexOf(ancestors[2])-1));
1338         else
1339           mountPath.append(groupPath);
1340       }
1341       //Site folder mount
1342       else if (nodePath.startsWith(SITES_PATH)) {
1343         if (ancestors.length > 2)
1344           mountPath.append(nodePath.substring(0, nodePath.indexOf(ancestors[2])-1));
1345         else
1346           mountPath.append(SITES_PATH);
1347       }
1348       //other case mount level -1
1349       else{
1350         if (ancestors.length > 4){
1351           mountPath.append(nodePath.substring(0, nodePath.indexOf(ancestors[3])-1));
1352         }else if (ancestors.length > 1){
1353           mountPath.append(nodePath.substring(0, nodePath.indexOf(ancestors[ancestors.length-1])-1));
1354         }
1355       }
1356       return mountPath.toString();
1357     }
1358 
1359     return "/";
1360   }
1361 
1362   private static String checkMountPath(Node node, String mountPath) throws AccessControlException, RepositoryException {
1363     NodeImpl parent = (NodeImpl) node.getParent();
1364     boolean hasPermission = false;
1365 
1366     while (PermissionUtil.canRead(parent)) {
1367       hasPermission = true;
1368       if(mountPath.equals(parent.getPath()) || parent.isRoot())
1369         break;
1370 
1371       parent = parent.getParent();
1372     }
1373     if (hasPermission) {
1374       return parent.getPath();
1375     } else {
1376       LOG.warn("Cannot mount webdav path {} You don't have read permission access", parent.getPath());
1377       throw new AccessControlException("You don't have read permission access to " + parent.getPath());
1378     }
1379   }
1380 }