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  package org.exoplatform.services.wcm.utils;
18  
19  import java.io.IOException;
20  import java.io.InputStream;
21  import java.util.ArrayList;
22  import java.util.Arrays;
23  import java.util.Collection;
24  import java.util.Collections;
25  import java.util.Comparator;
26  import java.util.Date;
27  import java.util.HashSet;
28  import java.util.Hashtable;
29  import java.util.Iterator;
30  import java.util.LinkedList;
31  import java.util.List;
32  import java.util.Properties;
33  
34  import javax.jcr.Item;
35  import javax.jcr.ItemNotFoundException;
36  import javax.jcr.Node;
37  import javax.jcr.NodeIterator;
38  import javax.jcr.PathNotFoundException;
39  import javax.jcr.RepositoryException;
40  import javax.jcr.Session;
41  import javax.jcr.ValueFormatException;
42  import javax.jcr.nodetype.NodeType;
43  import javax.jcr.nodetype.NodeTypeManager;
44  import javax.jcr.query.Query;
45  import javax.jcr.query.QueryManager;
46  import javax.jcr.query.QueryResult;
47  
48  import org.apache.commons.lang.StringUtils;
49  import org.exoplatform.commons.api.settings.SettingService;
50  import org.exoplatform.commons.api.settings.SettingValue;
51  import org.exoplatform.commons.api.settings.data.Context;
52  import org.exoplatform.commons.api.settings.data.Scope;
53  import org.exoplatform.commons.utils.ListAccess;
54  import org.exoplatform.container.ExoContainer;
55  import org.exoplatform.container.ExoContainerContext;
56  import org.exoplatform.container.PortalContainer;
57  import org.exoplatform.container.RootContainer;
58  import org.exoplatform.container.component.ComponentRequestLifecycle;
59  import org.exoplatform.container.configuration.ConfigurationManager;
60  import org.exoplatform.container.definition.PortalContainerConfig;
61  import org.exoplatform.container.xml.InitParams;
62  import org.exoplatform.container.xml.ObjectParameter;
63  import org.exoplatform.container.xml.PortalContainerInfo;
64  import org.exoplatform.container.xml.ValueParam;
65  import org.exoplatform.portal.config.UserACL;
66  import org.exoplatform.portal.webui.util.Util;
67  import org.exoplatform.services.cms.CmsService;
68  import org.exoplatform.services.cms.link.LinkManager;
69  import org.exoplatform.services.cms.metadata.MetadataService;
70  import org.exoplatform.services.cms.templates.TemplateService;
71  import org.exoplatform.services.deployment.plugins.LinkDeploymentDescriptor;
72  import org.exoplatform.services.jcr.RepositoryService;
73  import org.exoplatform.services.jcr.core.ManageableRepository;
74  import org.exoplatform.services.jcr.ext.app.SessionProviderService;
75  import org.exoplatform.services.jcr.ext.common.SessionProvider;
76  import org.exoplatform.services.jcr.impl.core.nodetype.registration.NodeTypeConverter;
77  import org.exoplatform.services.listener.ListenerService;
78  import org.exoplatform.services.log.ExoLogger;
79  import org.exoplatform.services.log.Log;
80  import org.exoplatform.services.organization.Membership;
81  import org.exoplatform.services.organization.OrganizationService;
82  import org.exoplatform.services.organization.idm.MembershipImpl;
83  import org.exoplatform.services.security.ConversationState;
84  import org.exoplatform.services.security.Identity;
85  import org.exoplatform.services.security.MembershipEntry;
86  import org.exoplatform.services.wcm.core.NodeLocation;
87  import org.exoplatform.services.wcm.core.NodetypeConstant;
88  import org.exoplatform.services.wcm.portal.LivePortalManagerService;
89  import org.quartz.JobExecutionContext;
90  import org.quartz.impl.JobDetailImpl;
91  
92  /**
93   * Created by The eXo Platform SAS
94   * Author : Tran Nguyen Ngoc
95   * ngoc.tran@exoplatform.com
96   * Sep 8, 2009
97   */
98  public class WCMCoreUtils {
99  
100   private static final Log LOG = ExoLogger.getLogger(WCMCoreUtils.class.getName());
101 
102   private static String WEBCONTENT_CSS_QUERY = "select * from exo:cssFile where jcr:path like '{path}/%' "
103       + "and exo:active='true' "
104       + "and jcr:mixinTypes <> 'exo:restoreLocation' "
105       + "order by exo:priority ASC";
106 
107   private static final String BAR_NAVIGATION_STYLE_KEY = "bar_navigation_style";
108 
109   /**
110    * Gets the service.
111    *
112    * @param clazz the clazz
113    *
114    * @return the service
115    */
116   public static <T> T getService(Class<T> clazz) {
117     return getService(clazz, null);
118   }
119 
120   /**
121    * Gets the system session provider.
122    *
123    * @return the system session provider
124    */
125   public static SessionProvider getSystemSessionProvider() {
126     SessionProviderService sessionProviderService = getService(SessionProviderService.class);
127     return sessionProviderService.getSystemSessionProvider(null);
128   }
129 
130   /**
131    * Use only on system process
132    * @param node
133    * @return
134    * @throws RepositoryException
135    */
136   public static Node getNodeBySystemSession(Node node) throws RepositoryException{
137     SessionProvider systemSessionProvider = getSystemSessionProvider();
138     return (Node)systemSessionProvider.getSession(node.getSession().getWorkspace().getName(), getRepository()).getItem(node.getPath());
139   }
140 
141   /**
142    * Check permission can access to parent
143    * @param node
144    * @return
145    */
146   public static boolean canAccessParentNode(Node node) {
147     try {
148       node.getParent();
149     } catch (Exception e) {
150       return false;
151     }
152     return true;
153   }
154 
155   /**
156    * Gets the session provider.
157    *
158    * @return the session provider
159    */
160   public static SessionProvider getUserSessionProvider() {
161     SessionProviderService sessionProviderService = getService(SessionProviderService.class);
162     return sessionProviderService.getSessionProvider(null);
163   }
164 
165   public static boolean isAnonim()
166   {
167     String userId = Util.getPortalRequestContext().getRemoteUser();
168     if (userId == null)
169       return true;
170     return false;
171   }
172 
173   public static SessionProvider createAnonimProvider()
174   {
175     return SessionProvider.createAnonimProvider();
176   }
177 
178   /**
179    * Gets the service.
180    *
181    * @param clazz the class
182    * @param containerName the container's name
183    *
184    * @return the service
185    */
186   public static <T> T getService(Class<T> clazz, String containerName) {
187     ExoContainer container = ExoContainerContext.getCurrentContainer();
188     if (containerName != null) {
189       container = RootContainer.getInstance().getPortalContainer(containerName);
190     }
191     if (container.getComponentInstanceOfType(clazz)==null) {
192       containerName = PortalContainer.getCurrentPortalContainerName();
193       container = RootContainer.getInstance().getPortalContainer(containerName);
194     }
195     return clazz.cast(container.getComponentInstanceOfType(clazz));
196   }
197 
198   public static String getContainerNameFromJobContext(JobExecutionContext context) {
199     return ((JobDetailImpl)context.getJobDetail()).getGroup().split(":")[0];
200   }
201 
202   /**
203    * Check current user has permission to access a node or not
204    * -    For each permission, compare with user's permissions
205    * -      If permission has membership type is "*", just check the user's group id only
206    * -      If permission has other membership types, then check the user's membership type and user's group id
207    *
208    * @param userId the current user's name
209    * @param permissions the current node
210    * @param isNeedFullAccess if true, count full access (4) then return true, if false, return true if match first permission
211    *
212    * @return true is user has permissions, otherwise return false
213    */
214   public static boolean hasPermission(String userId, List<String> permissions, boolean isNeedFullAccess) {
215     if (userId == null || userId.length() == 0) {
216       return false;
217     }
218     try {
219       OrganizationService organizationService = WCMCoreUtils.getService(OrganizationService.class);
220       startRequest(organizationService);
221       Identity identity = ConversationState.getCurrent().getIdentity();
222       Collection<?> memberships = null;
223       if (userId.equals(identity.getUserId())){
224         Collection<MembershipEntry> membershipsEntries = identity.getMemberships();
225         HashSet<MembershipImpl> membershipsHash = new HashSet<MembershipImpl>();
226         for (MembershipEntry membershipEntry : membershipsEntries) {
227           MembershipImpl m = new MembershipImpl();
228           m.setGroupId(membershipEntry.getGroup());
229           m.setMembershipType(membershipEntry.getMembershipType());
230           m.setUserName(userId);
231           membershipsHash.add(m);
232         }
233         memberships =  new LinkedList(membershipsHash);
234       } else {
235         memberships = organizationService.getMembershipHandler().findMembershipsByUser(userId);
236       }
237       String userMembershipTmp;
238       Membership userMembership;
239       int count = 0;
240       String permissionTmp = "";
241       for (String permission : permissions) {
242         if (!permissionTmp.equals(permission)) count = 0;
243         for (Object userMembershipObj : memberships) {
244           userMembership = (Membership) userMembershipObj;
245           if (permission.equals(userMembership.getUserName())) {
246             return true;
247           } else if ("any".equals(permission)) {
248             if (isNeedFullAccess) {
249               count++;
250               if (count == 4) return true;
251             }
252             else return true;
253           } else if (permission.startsWith("*") && permission.contains(userMembership.getGroupId())) {
254             if (isNeedFullAccess) {
255               count++;
256               if (count == 4) return true;
257             }
258             else return true;
259           } else {
260             userMembershipTmp = userMembership.getMembershipType() + ":" + userMembership.getGroupId();
261             if (permission.equals(userMembershipTmp)) {
262               if (isNeedFullAccess) {
263                 count++;
264                 if (count == 4) return true;
265               }
266               else return true;
267             }
268           }
269         }
270         permissionTmp = permission;
271       }
272       endRequest(organizationService);
273     } catch (Exception e) {
274       if (LOG.isErrorEnabled()) {
275         LOG.error("hasPermission() failed because of ", e);
276       }
277     }
278     return false;
279   }
280 
281   public static <T> List<T> getAllElementsOfListAccess(ListAccess<T> listAccess) {
282     try {
283       return Arrays.asList(listAccess.load(0, listAccess.getSize()));
284     } catch (Exception e) {
285       if (LOG.isErrorEnabled()) {
286         LOG.error("getAllElementsOfListAccess() failed because of ", e);
287       }
288     }
289     return null;
290   }
291 
292   /**
293    * Get the current repository
294    *
295    * @return the current manageable repository
296    */
297   public static ManageableRepository getRepository() {
298     try {
299       RepositoryService repositoryService = getService(RepositoryService.class);
300       return repositoryService.getCurrentRepository();
301     } catch (Exception e) {
302       if (LOG.isErrorEnabled()) {
303         LOG.error("getRepository() failed because of ", e);
304       }
305     }
306     return null;
307   }
308 
309   public static void startRequest(OrganizationService orgService) throws Exception
310   {
311     if(orgService instanceof ComponentRequestLifecycle) {
312       ((ComponentRequestLifecycle) orgService).startRequest(ExoContainerContext.getCurrentContainer());
313     }
314   }
315 
316   public static void endRequest(OrganizationService orgService) throws Exception
317   {
318     if(orgService instanceof ComponentRequestLifecycle) {
319       ((ComponentRequestLifecycle) orgService).endRequest(ExoContainerContext.getCurrentContainer());
320     }
321   }
322 
323   public static String getProjectVersion() throws Exception {
324     String filePath = "jar:/conf/projectInfo.properties";
325     Properties productInformationProperties = new Properties();
326     try {
327       ConfigurationManager configManager = WCMCoreUtils.getService(ConfigurationManager.class);
328       if (LOG.isInfoEnabled()) {
329         LOG.info("Read products versions from " + filePath);
330       }
331       InputStream inputStream = configManager.getInputStream(filePath);
332 
333       productInformationProperties.load(inputStream);
334     } catch (IOException exception) {
335       throw new RuntimeException("Couldn't parse the file " + filePath, exception);
336     } catch (Exception exception) {
337       throw new RuntimeException("Error occured while reading the file " + filePath, exception);
338     }
339 
340     if (!productInformationProperties.containsKey("project.current.version")) {
341       throw new RuntimeException("Missing product information.");
342     }
343     return productInformationProperties.getProperty("project.current.version");
344   }
345 
346   public static String getActiveStylesheet(Node webcontent) throws Exception {
347     StringBuilder buffer = new StringBuilder();
348     String cssQuery = StringUtils.replaceOnce(WEBCONTENT_CSS_QUERY, "{path}", webcontent.getPath());
349     // Need re-login to get session because this node is get from template and the session is not live anymore.
350     // If node is version (which is stored in system workspace) we have to login to system workspace to get data
351     NodeLocation webcontentLocation = NodeLocation.getNodeLocationByNode(webcontent);
352     ManageableRepository repository = (ManageableRepository)webcontent.getSession().getRepository();
353     Session session;
354     try {
355       if (webcontentLocation.getPath().startsWith("/jcr:system"))
356         session =
357         WCMCoreUtils.getSystemSessionProvider().getSession(repository.getConfiguration().getSystemWorkspaceName(), repository);
358       else {
359         session = WCMCoreUtils.getSystemSessionProvider().getSession(webcontentLocation.getWorkspace(), repository);
360       }
361 
362       QueryManager queryManager = session.getWorkspace().getQueryManager();
363       Query query = queryManager.createQuery(cssQuery, Query.SQL);
364       QueryResult queryResult = query.execute();
365       NodeIterator iterator = queryResult.getNodes();
366       while (iterator.hasNext()) {
367         Node registeredCSSFile = iterator.nextNode();
368         buffer.append(registeredCSSFile.getNode(NodetypeConstant.JCR_CONTENT)
369                       .getProperty(NodetypeConstant.JCR_DATA)
370                       .getString());
371       }
372     } catch(Exception e) {
373       if (LOG.isErrorEnabled()) {
374         LOG.error("Unexpected problem happen when active stylesheet", e);
375       }
376     }
377     return buffer.toString();
378   }
379 
380   /**
381    * gets the global css of given site node. For example, if the site is acme<br>
382    * we then return all css code only inside acme/css
383    * @param siteNode the root node of the site
384    * @return global css code inside this site
385    * @throws Exception
386    */
387   public static String getSiteGlobalActiveStylesheet(Node siteNode) throws Exception {
388     if (siteNode == null) return StringUtils.EMPTY;
389 
390     StringBuilder buffer = new StringBuilder();
391     try {
392       List<Node> cssNodeList = new ArrayList<Node>();
393       NodeIterator iterator = siteNode.getNodes();
394       //get all cssFolder child nodes of siteNode
395       while (iterator.hasNext()) {
396         Node cssFolder = iterator.nextNode();
397         if (cssFolder.isNodeType(NodetypeConstant.EXO_CSS_FOLDER)) {
398           NodeIterator iter = cssFolder.getNodes();
399           //get all cssFile child nodes of cssFolder node
400           while (iter.hasNext()) {
401             Node registeredCSSFile = iter.nextNode();
402             if (registeredCSSFile.isNodeType(NodetypeConstant.EXO_CSS_FILE) &&
403                 registeredCSSFile.getProperty(NodetypeConstant.EXO_ACTIVE).getBoolean()) {
404               cssNodeList.add(registeredCSSFile);
405             }
406           }
407         }
408       }
409       //sort cssFile by priority and merge them
410       Collections.sort(cssNodeList, new FileCSSComparatorByPriority());
411       for (Node registeredCSSFile : cssNodeList) {
412         try {
413           buffer.append(registeredCSSFile.getNode(NodetypeConstant.JCR_CONTENT)
414                         .getProperty(NodetypeConstant.JCR_DATA)
415                         .getString());
416         } catch (Exception e) {
417           continue;
418         }
419       }
420     } catch(Exception e) {
421       if (LOG.isErrorEnabled()) {
422         LOG.error("Unexpected problem happen when active stylesheet", e);
423       }
424     }
425     return buffer.toString();
426   }
427 
428   /**
429    * gets the global javascript of given site node. For example, if the site is acme<br>
430    * we then return all javascript code only inside acme/js
431    * @param siteNode the root node of the site
432    * @return global javascript code inside this site
433    * @throws Exception
434    */
435   public static String getSiteGlobalActiveJs(Node siteNode) throws Exception {
436     return getSiteGlobalActiveJs(siteNode, getSystemSessionProvider());
437   }
438 
439   /**
440    * gets the global javascript of given site node. For example, if the site is acme<br>
441    * we then return all javascript code only inside acme/js
442    * @param siteNode the root node of the site
443    * @return global javascript code inside this site
444    * @throws Exception
445    */
446   public static String getSiteGlobalActiveJs(Node siteNode, SessionProvider sessionProvider) throws Exception {
447     StringBuilder buffer = new StringBuilder();
448     LivePortalManagerService livePortalService = getService(LivePortalManagerService.class);
449     buffer.append(getSiteActiveJs(livePortalService.getLiveSharedPortal(sessionProvider))).append(getSiteActiveJs(siteNode));
450     return buffer.toString();
451   }
452 
453   public static String getSiteActiveJs(Node siteNode) throws Exception {
454     if (siteNode == null) return StringUtils.EMPTY;
455 
456     StringBuilder buffer = new StringBuilder();
457     try {
458       List<Node> jsNodeList = new ArrayList<Node>();
459       NodeIterator iterator = siteNode.getNodes();
460       //get all jsFolder child nodes of siteNode
461       while (iterator.hasNext()) {
462         Node jsFolder = iterator.nextNode();
463         if (jsFolder.isNodeType(NodetypeConstant.EXO_JS_FOLDER)) {
464           NodeIterator iter = jsFolder.getNodes();
465           //get all jsFile child nodes of jsFolder node
466           while (iter.hasNext()) {
467             Node registeredJSFile = iter.nextNode();
468             if (registeredJSFile.isNodeType(NodetypeConstant.EXO_JS_FILE) &&
469                 registeredJSFile.getProperty(NodetypeConstant.EXO_ACTIVE).getBoolean()) {
470               jsNodeList.add(registeredJSFile);
471             }
472           }
473         }
474       }
475       //sort jsFile by priority and merge them
476       Collections.sort(jsNodeList, new FileComparatorByPriority());
477       for (Node registeredJSFile : jsNodeList) {
478         try {
479           buffer.append(registeredJSFile.getNode(NodetypeConstant.JCR_CONTENT)
480                         .getProperty(NodetypeConstant.JCR_DATA)
481                         .getString());
482         } catch (Exception e) {
483           continue;
484         }
485       }
486     } catch(Exception e) {
487       if (LOG.isErrorEnabled()) {
488         LOG.error("Unexpected problem happen when active javascript", e);
489       }
490     }
491     return buffer.toString();
492   }
493 
494   public static Hashtable<String, String> getMetadataTemplates(Node node) throws Exception {
495     MetadataService metadataService = WCMCoreUtils.getService(MetadataService.class);
496     Hashtable<String, String> templates = new Hashtable<String, String>();
497     List<String> metaDataList = metadataService.getMetadataList();
498 
499     NodeType[] nodeTypes = node.getMixinNodeTypes();
500     for(NodeType nt : nodeTypes) {
501       if(metaDataList.contains(nt.getName())) {
502         templates.put(nt.getName(), metadataService.getMetadataPath(nt.getName(), false));
503       }
504     }
505     Item primaryItem;
506     try {
507       primaryItem = node.getPrimaryItem();
508     } catch (ItemNotFoundException e) {
509       primaryItem = null;
510     }
511     if (primaryItem != null && primaryItem.isNode()) {
512       Node primaryNode = (Node) node.getPrimaryItem();
513       NodeType[] primaryTypes = primaryNode.getMixinNodeTypes();
514       for(NodeType nt : primaryTypes) {
515         if(metaDataList.contains(nt.getName())) {
516           templates.put(nt.getName(), metadataService.getMetadataPath(nt.getName(), false));
517         }
518       }
519     }
520     return templates;
521   }
522 
523   public static String getRestContextName() {
524     ExoContainer container = ExoContainerContext.getCurrentContainer();
525     PortalContainerConfig portalContainerConfig = (PortalContainerConfig) container.
526         getComponentInstance(PortalContainerConfig.class);
527     PortalContainerInfo containerInfo =
528         (PortalContainerInfo)container.getComponentInstanceOfType(PortalContainerInfo.class) ;
529     return portalContainerConfig.getRestContextName(containerInfo.getContainerName());
530   }
531 
532   public static void deployLinkToPortal(InitParams initParams,
533                                         RepositoryService repositoryService,
534                                         LinkManager linkManager,
535                                         SessionProvider sessionProvider,
536                                         String portalName) throws Exception {
537     Iterator iterator = initParams.getObjectParamIterator();
538     LinkDeploymentDescriptor deploymentDescriptor = null;
539     ValueParam valueParam = initParams.getValueParam("override");
540     boolean overrideData = false;
541     if (valueParam != null) {
542         overrideData = "true".equals(valueParam.getValue());
543     }
544     try {
545       while (iterator.hasNext()) {
546         String sourcePath = null;
547         String targetPath = null;
548         try {
549           ObjectParameter objectParameter = (ObjectParameter) iterator.next();
550           deploymentDescriptor = (LinkDeploymentDescriptor) objectParameter.getObject();
551           sourcePath = deploymentDescriptor.getSourcePath();
552           targetPath = deploymentDescriptor.getTargetPath();
553   
554           //in case: create portal from template
555           if (portalName != null && portalName.length() > 0) {
556             sourcePath = StringUtils.replace(sourcePath, "{portalName}", portalName);
557             targetPath = StringUtils.replace(targetPath, "{portalName}", portalName);
558           }
559   
560           // sourcePath should looks like : repository:collaboration:/sites
561           // content/live/acme
562           String[] src = sourcePath.split(":");
563           String[] tgt = targetPath.split(":");
564   
565           if (src.length == 3 && tgt.length == 3) {
566             ManageableRepository repository = repositoryService.getCurrentRepository();
567             Session session = sessionProvider.getSession(src[1], repository);
568             ManageableRepository repository2 = repositoryService.getCurrentRepository();
569             Session session2 = sessionProvider.getSession(tgt[1], repository2);
570             Node nodeSrc = (Node) session.getItem(src[2]);
571             Node nodeTgt = (Node) session2.getItem(tgt[2]);
572             Node tnode = (Node) session.getItem(nodeTgt.getPath());
573             //check if the link node already exist then remove it 
574             if (overrideData && tnode.hasNode(nodeSrc.getName())) {
575                  NodeIterator nodeIterator = tnode.getNodes(nodeSrc.getName());
576                 while (nodeIterator.hasNext()) {
577                   String path = "";
578                   try {
579                     Node targetNode = nodeIterator.nextNode();
580                     path = targetNode.getPath();
581                     LOG.info(" - Remove " + targetNode.getPath());
582                     targetNode.remove();
583                     session.save();
584                   } catch (Exception e) {
585                     if (LOG.isDebugEnabled()) {
586                       LOG.debug("Can not remove node: " + path, e);
587                     } else if (LOG.isWarnEnabled()) {
588                       LOG.warn("Can not remove node: " + path);
589                     }
590                   }
591                 }
592             }
593             linkManager.createLink(nodeTgt, "exo:taxonomyLink", nodeSrc);
594             ExoContainer container = ExoContainerContext.getCurrentContainer();
595             PortalContainerInfo containerInfo =
596               (PortalContainerInfo) container.getComponentInstanceOfType(PortalContainerInfo.class);
597             String containerName = containerInfo.getContainerName();
598             ListenerService listenerService = WCMCoreUtils.getService(ListenerService.class,
599                                                                       containerName);
600             CmsService cmsService = WCMCoreUtils.getService(CmsService.class, containerName);
601             listenerService.broadcast("WCMPublicationService.event.updateState", cmsService, nodeSrc);
602           }
603           if (LOG.isInfoEnabled()) {
604             LOG.info(sourcePath + " has a link into " + targetPath);
605           }
606         } catch (Exception e) {
607           if (LOG.isDebugEnabled()) {
608             LOG.debug("An error occurs when deploy link from " + sourcePath + " to " + targetPath, e);
609           } else if (LOG.isWarnEnabled()) {
610             LOG.warn("Can not deploy link from " + sourcePath + " to " + targetPath + ": " + e.getMessage());
611           }
612         }
613       }
614     } catch (Exception ex) {
615       if (LOG.isErrorEnabled()) {
616         LOG.error("create link from " + deploymentDescriptor.getSourcePath() + " to "
617             + deploymentDescriptor.getTargetPath() + " is FAILURE at "
618             + new Date().toString() + "\n",
619             ex);
620       }
621       throw ex;
622     }
623   }
624 
625   /**
626    * compares two JsFile node by exo:priority value, tending to sort in DESC order
627    * because Js file with higher priority is loaded first
628    * @author vu_nguyen
629    *
630    */
631   private static class FileComparatorByPriority implements Comparator<Node> {
632     @Override
633     public int compare(Node o1, Node o2) {
634       try {
635         if (!o1.hasProperty(NodetypeConstant.EXO_PRIORITY) && !o2.hasProperty(NodetypeConstant.EXO_PRIORITY)) {
636           return o1.getName().compareTo(o2.getName());
637         } else if (!o1.hasProperty(NodetypeConstant.EXO_PRIORITY)) {
638           return 1;
639         } else if (!o2.hasProperty(NodetypeConstant.EXO_PRIORITY)) {
640           return -1;
641         } else if (o1.getProperty(NodetypeConstant.EXO_PRIORITY).getLong() == 
642                   o2.getProperty(NodetypeConstant.EXO_PRIORITY).getLong()){
643           return o1.getName().compareTo(o2.getName()); 
644         } else {
645           return (int)(o2.getProperty(NodetypeConstant.EXO_PRIORITY).getLong() -
646               o1.getProperty(NodetypeConstant.EXO_PRIORITY).getLong());
647         }
648       } catch (Exception e) {
649         return 0;
650       }
651     }
652   }
653   /**
654    * compares two CSSFile node by exo:priority value, tending to sort in ASC order
655    * because CSSFile file with higher priority is loaded last
656    * @author vinh_nguyen
657    */
658   private static class FileCSSComparatorByPriority implements Comparator<Node>{
659     @Override
660     public int compare(Node o1, Node o2) {
661       try {
662         if (!o1.hasProperty(NodetypeConstant.EXO_PRIORITY)) {
663           return -1;
664         } else if (!o2.hasProperty(NodetypeConstant.EXO_PRIORITY)) {
665           return 1;
666         } else {
667           return (int)(o1.getProperty(NodetypeConstant.EXO_PRIORITY).getLong() -
668               o2.getProperty(NodetypeConstant.EXO_PRIORITY).getLong());
669         }
670       } catch (ValueFormatException e) {
671         return 0;
672       } catch (PathNotFoundException e) {
673         return 0;
674       } catch (RepositoryException e) {
675         return 0;
676       }
677     }
678   }
679   /**
680    * Generate uri.
681    *
682    * @param file the node
683    * @param propertyName the image property name, null if file is an image node
684    *
685    * @return the string
686    *
687    * @throws Exception the exception
688    */
689   public static String generateImageURI(Node file, String propertyName) throws Exception {
690     StringBuilder builder = new StringBuilder();
691     NodeLocation fileLocation = NodeLocation.getNodeLocationByNode(file);
692     String repository = fileLocation.getRepository();
693     String workspaceName = fileLocation.getWorkspace();
694     String nodeIdentifiler = file.isNodeType("mix:referenceable") ? file.getUUID() : file.getPath().replaceFirst("/","");
695     String portalName = PortalContainer.getCurrentPortalContainerName();
696     String restContextName = PortalContainer.getCurrentRestContextName();
697 
698     if (propertyName == null) {
699       if (isNodeTypeOrFrozenType(file, NodetypeConstant.NT_FILE)) {
700         InputStream stream = file.getNode("jcr:content").getProperty("jcr:data").getStream();
701         if (stream.available() == 0) return null;
702         stream.close();
703         builder.append("/").append(portalName).append("/")
704         .append(restContextName).append("/")
705         .append("images/")
706         .append(repository).append("/")
707         .append(workspaceName).append("/")
708         .append(nodeIdentifiler)
709         .append("?param=file");
710         return builder.toString();
711       } else return null;
712     }
713     builder.append("/").append(portalName).append("/")
714     .append(restContextName).append("/")
715     .append("images/")
716     .append(repository).append("/")
717     .append(workspaceName).append("/")
718     .append(nodeIdentifiler)
719     .append("?param=").append(propertyName);
720     return builder.toString();
721   }
722   
723   public static boolean isNodeTypeOrFrozenType(Node node, String type) throws RepositoryException {
724     if (node.isNodeType(type)) return true;
725     if (!node.isNodeType(NodetypeConstant.NT_FROZEN_NODE)) return false;
726     String realType = node.getProperty("jcr:frozenPrimaryType").getString();
727     return getRepository().getNodeTypeManager().getNodeType(realType).isNodeType(type);
728   }
729   
730   public static String getPortalName() {
731     PortalContainerInfo containerInfo = WCMCoreUtils.getService(PortalContainerInfo.class) ;
732     return containerInfo.getContainerName() ;
733   }
734 
735   public static String getRemoteUser() {
736     try {
737       return ConversationState.getCurrent().getIdentity().getUserId();
738     } catch(NullPointerException npe) {
739       return null;
740     }
741   }
742 
743   public static String getSuperUser() {
744     return getService(UserACL.class).getSuperUser();
745   }
746 
747   public static boolean isDocumentNodeType(Node node) throws Exception {
748     boolean isDocument = true;
749     TemplateService templateService = WCMCoreUtils.getService(TemplateService.class);
750     isDocument = templateService.getAllDocumentNodeTypes().contains(node.getPrimaryNodeType().getName()); 
751     return isDocument;
752   }
753   
754   /**
755    * Get the bar navigation style of UIToolbarContainer.gtmpl
756    * 
757    * @return The String is style of bar navigation style
758    */
759   public static String getBarNavigationStyle() {
760     SettingService settingService = getService(SettingService.class);
761     String barNavigationStyle = "Dark";
762     SettingValue<?> value = settingService.get(Context.GLOBAL, Scope.GLOBAL, BAR_NAVIGATION_STYLE_KEY);
763     if (value != null) {
764       barNavigationStyle = (String) value.getValue();
765     } else {
766       settingService.set(Context.GLOBAL, Scope.GLOBAL, BAR_NAVIGATION_STYLE_KEY, SettingValue.create(barNavigationStyle));
767     }
768     return barNavigationStyle;
769   }
770 }