View Javadoc
1   /**
2    *
3    */
4   package org.exoplatform.services.wcm.publication;
5   
6   import java.util.ArrayList;
7   import java.util.HashMap;
8   import java.util.List;
9   
10  import javax.jcr.*;
11  import javax.jcr.query.Query;
12  import javax.jcr.query.QueryManager;
13  
14  import org.exoplatform.container.xml.InitParams;
15  import org.exoplatform.container.xml.ValueParam;
16  import org.exoplatform.management.annotations.Managed;
17  import org.exoplatform.management.annotations.ManagedDescription;
18  import org.exoplatform.management.jmx.annotations.NameTemplate;
19  import org.exoplatform.management.jmx.annotations.Property;
20  import org.exoplatform.management.rest.annotations.RESTEndpoint;
21  import org.exoplatform.portal.webui.util.Util;
22  import org.exoplatform.services.cms.documents.TrashService;
23  import org.exoplatform.services.cms.i18n.MultiLanguageService;
24  import org.exoplatform.services.cms.link.LinkManager;
25  import org.exoplatform.services.cms.taxonomy.TaxonomyService;
26  import org.exoplatform.services.cms.templates.TemplateService;
27  import org.exoplatform.services.ecm.publication.NotInPublicationLifecycleException;
28  import org.exoplatform.services.ecm.publication.PublicationPlugin;
29  import org.exoplatform.services.ecm.publication.PublicationService;
30  import org.exoplatform.services.jcr.RepositoryService;
31  import org.exoplatform.services.jcr.access.AccessControlEntry;
32  import org.exoplatform.services.jcr.access.PermissionType;
33  import org.exoplatform.services.jcr.core.ManageableRepository;
34  import org.exoplatform.services.jcr.ext.common.SessionProvider;
35  import org.exoplatform.services.jcr.impl.core.query.QueryImpl;
36  import org.exoplatform.services.jcr.sessions.ACLSessionProviderService;
37  import org.exoplatform.services.log.ExoLogger;
38  import org.exoplatform.services.log.Log;
39  import org.exoplatform.services.wcm.core.NodeLocation;
40  import org.exoplatform.services.wcm.core.NodetypeConstant;
41  import org.exoplatform.services.wcm.core.WCMService;
42  import org.exoplatform.services.wcm.utils.WCMCoreUtils;
43  import org.picocontainer.Startable;
44  
45  /**
46   * The Class WCMComposerImpl.
47   *
48   * @author benjamin
49   */
50  @Managed
51  @NameTemplate( { @Property(key = "view", value = "portal"),
52      @Property(key = "service", value = "composer"), @Property(key = "type", value = "content") })
53  @ManagedDescription("WCM Composer service")
54  @RESTEndpoint(path = "wcmcomposerservice")
55  public class WCMComposerImpl implements WCMComposer, Startable {
56  
57      final static public String EXO_RESTORELOCATION = "exo:restoreLocation";
58  
59    /** The repository service. */
60    private RepositoryService repositoryService;
61  
62    /** The link manager service. */
63    private LinkManager linkManager;
64  
65    private PublicationService  publicationService;
66  
67    private TaxonomyService  taxonomyService;
68  
69    private TemplateService templateService;
70  
71    private WCMService wcmService;
72  
73    private MultiLanguageService multiLanguageService;
74  
75    private ACLSessionProviderService aclSessionProviderService;
76  
77    private TrashService trashService;
78  
79    /** The log. */
80    private static final Log LOG = ExoLogger.getLogger(WCMComposerImpl.class.getName());
81  
82    /** The template filter query */
83    private String templatesFilter;
84  
85    /** OrderBy properties accessed on Front side */
86    private List<String> usedOrderBy;
87    /** Languages properties accessed on Front side */
88    private List<String> usedLanguages;
89    /** PrimaryTypes properties accessed on Front side */
90    private List<String> usedPrimaryTypes;
91    /** shared group membership */
92    private String sharedGroup;
93  
94    /**
95     * Instantiates a new WCM composer impl.
96     *
97     * @throws Exception the exception
98     */
99    public WCMComposerImpl(InitParams params) throws Exception {
100     if (params!=null) {
101       ValueParam sharedGroupParam = params.getValueParam("sharedGroup");
102       if (sharedGroupParam != null) {
103         this.sharedGroup = sharedGroupParam.getValue();
104       }
105     }
106 
107     repositoryService = WCMCoreUtils.getService(RepositoryService.class);
108     linkManager = WCMCoreUtils.getService(LinkManager.class);
109     publicationService = WCMCoreUtils.getService(PublicationService.class);
110     templateService = WCMCoreUtils.getService(TemplateService.class);
111     wcmService = WCMCoreUtils.getService(WCMService.class);
112     multiLanguageService = WCMCoreUtils.getService(MultiLanguageService.class);
113     aclSessionProviderService = WCMCoreUtils.getService(ACLSessionProviderService.class);
114 
115     usedLanguages = new ArrayList<String>();
116     usedLanguages.add(null);
117     usedOrderBy = new ArrayList<String>();
118     usedOrderBy.add(null);
119     usedPrimaryTypes = new ArrayList<String>();
120     usedPrimaryTypes.add(null);
121 
122   }
123 
124   /*
125    * (non-Javadoc)
126    * @see
127    * org.exoplatform.services.wcm.publication.WCMComposer#getContent(java.lang
128    * .String, java.lang.String, java.lang.String, java.util.HashMap)
129    */
130   public Node getContent(String workspace,
131                          String nodeIdentifier,
132                          HashMap<String, String> filters,
133                          SessionProvider sessionProvider) throws Exception {
134     String mode = filters.get(FILTER_MODE);
135     String version = filters.get(FILTER_VERSION);
136     String visibility = filters.get(FILTER_VISIBILITY);
137     String remoteUser = getRemoteUser();
138     String repository = null;
139 
140     try {
141       repository = repositoryService.getCurrentRepository().getConfiguration().getName();
142     } catch (Exception e) {
143       if (LOG.isWarnEnabled()) {
144         LOG.warn(e.getMessage());
145       }
146     }
147 
148     if (workspace==null) {
149       if (nodeIdentifier.lastIndexOf("/") == 0) nodeIdentifier = nodeIdentifier.substring(1);
150       String[] params = nodeIdentifier.split("/");
151       workspace = params[1];
152       try {
153         nodeIdentifier = nodeIdentifier.substring(repository.length()+workspace.length()+1);
154       } catch (Exception e) {
155         if (LOG.isWarnEnabled()) {
156           LOG.warn(e.getMessage());
157         }
158       }
159     }
160 
161     Node node = null;
162     try {
163     if (WCMComposer.VISIBILITY_PUBLIC.equals(visibility) && MODE_LIVE.equals(mode)) {
164         sessionProvider = remoteUser == null?
165                           aclSessionProviderService.getAnonymSessionProvider() :
166                           aclSessionProviderService.getACLSessionProvider(getAnyUserACL());
167       }
168       node = wcmService.getReferencedContent(sessionProvider, workspace, nodeIdentifier);
169     } catch (RepositoryException e) {
170       node = getNodeByCategory(nodeIdentifier);
171     }
172     if (version == null || !BASE_VERSION.equals(version)) {
173       node = getViewableContent(node, filters);
174     }
175 
176     return node;
177   }
178 
179   public List<Node> getContents(String workspace,
180                                 String path,
181                                 HashMap<String, String> filters,
182                                 SessionProvider sessionProvider) throws Exception {
183     String mode = filters.get(FILTER_MODE);
184     String version = filters.get(FILTER_VERSION);
185     String orderBy = filters.get(FILTER_ORDER_BY);
186     String orderType = filters.get(FILTER_ORDER_TYPE);
187     String visibility = filters.get(FILTER_VISIBILITY); 
188     String remoteUser = null;
189     if (WCMComposer.VISIBILITY_PUBLIC.equals(visibility)) {
190       remoteUser = "##PUBLIC##VISIBILITY";
191     } else {
192       remoteUser = getRemoteUser();
193     }
194 
195     if (MODE_EDIT.equals(mode) && "publication:liveDate".equals(orderBy)) {
196       orderBy = "exo:dateModified";
197       filters.put(FILTER_ORDER_BY, orderBy);
198     }
199     if ("exo:title".equals(orderBy)) {
200       if(MODE_LIVE.equals(mode)) {
201         orderBy = "exo:titlePublished "+orderType+", exo:title";
202       }
203       if ("exo:taxonomy".equals(this.getTypeFromPath(workspace, path, sessionProvider))) {
204         orderBy = "exo:title "+orderType+", exo:titlePublished";
205       }
206       filters.put(FILTER_ORDER_BY, orderBy);
207     }
208 
209     List<Node> nodes = new ArrayList<Node>();
210     try {
211       if (WCMComposer.VISIBILITY_PUBLIC.equals(visibility) && MODE_LIVE.equals(mode) && remoteUser != null) {
212         sessionProvider = aclSessionProviderService.getACLSessionProvider(getAnyUserACL());
213       }
214       if (LOG.isDebugEnabled()) LOG.debug("##### "+path+":"+version+":"+remoteUser+":"+orderBy+":"+orderType);
215       NodeIterator nodeIterator = getViewableContents(workspace, path, filters, sessionProvider, false);
216 
217       Node node = null, viewNode = null;
218       while (nodeIterator != null && nodeIterator.hasNext()) {
219         node = nodeIterator.nextNode();
220         viewNode = getViewableContent(node, filters);
221         if (viewNode != null) {
222           nodes.add(viewNode);
223         }
224       }
225     } catch (Exception e) {
226       if (LOG.isWarnEnabled()) {
227         LOG.warn(e.getMessage());
228       }
229     }
230 
231     return nodes;
232   }
233 
234   public Result getPaginatedContents(NodeLocation nodeLocation,
235                                      HashMap<String, String> filters,
236                                      SessionProvider sessionProvider) throws Exception {
237     String path = nodeLocation.getPath();
238     String workspace = nodeLocation.getWorkspace();
239 
240     String mode = filters.get(FILTER_MODE);
241     String version = filters.get(FILTER_VERSION);
242     String orderBy = filters.get(FILTER_ORDER_BY);
243     String orderType = filters.get(FILTER_ORDER_TYPE);
244     String visibility = filters.get(FILTER_VISIBILITY);
245 
246 
247     String remoteUser = getRemoteUser();
248 
249     if (MODE_EDIT.equals(mode) && "publication:liveDate".equals(orderBy)) {
250       orderBy = "exo:dateModified";
251       filters.put(FILTER_ORDER_BY, orderBy);
252     }
253     if (MODE_LIVE.equals(mode) && "exo:title".equals(orderBy)) {
254       orderBy = "exo:titlePublished "+orderType+", exo:title";
255       filters.put(FILTER_ORDER_BY, orderBy);
256     }
257 
258     if (LOG.isDebugEnabled()) LOG.debug("##### "+path+":"+version+":"+remoteUser+":"+orderBy+":"+orderType);
259 
260 
261 
262     if (WCMComposer.VISIBILITY_PUBLIC.equals(visibility) && MODE_LIVE.equals(mode)) {
263       sessionProvider = remoteUser == null?
264                         aclSessionProviderService.getAnonymSessionProvider() :
265                         aclSessionProviderService.getACLSessionProvider(getAnyUserACL());
266     }
267     ManageableRepository manageableRepository = repositoryService.getCurrentRepository();
268     Session session = sessionProvider.getSession(workspace, manageableRepository);
269     Node currentFolder = null;
270 
271     Item item = session.getItem(path);
272     if (item != null) {
273       currentFolder = (Node) item;
274     }
275 
276     Result result;
277     //Distinguish whether the targeted nodes are symlinks or not
278     if (currentFolder != null && currentFolder.isNodeType("exo:taxonomy")) {
279       result = getPaginatedTaxonomiesContent(nodeLocation, workspace, filters, sessionProvider);
280     } else {
281       result = getPaginatedNodesContent(nodeLocation, workspace, filters, sessionProvider);
282     }
283 
284     return result;
285   }
286 
287   /**
288    * return paginated result in case of taxonomies nodes. This nodes are loaded in memory from jcr then
289    * filtered against publication because the information about publication is not in the symlink but in its target
290    * node
291    * @param nodeLocation
292    * @param workspace
293    * @param filters
294    * @param sessionProvider
295    * @return current page result with populating taxonomies
296    * @throws Exception
297    */
298   private Result getPaginatedTaxonomiesContent(NodeLocation nodeLocation, String workspace,
299                                                HashMap<String, String> filters,
300                                                SessionProvider sessionProvider) throws Exception{
301     List<Node> nodes = new ArrayList<Node>();
302     long totalSize;
303     long offset = (filters.get(FILTER_OFFSET)!=null)?new Long(filters.get(FILTER_OFFSET)):0;
304     String path = nodeLocation.getPath();
305     NodeIterator taxonomyNodeIterator = getViewableContents(workspace, path, filters, sessionProvider, false);
306     List<Node> taxonomyNodes = new ArrayList<Node>();
307     Node taxonomyNode = null, taxonomyViewNode = null;
308     if (taxonomyNodeIterator != null) {
309       while (taxonomyNodeIterator.hasNext()) {
310         taxonomyNode = taxonomyNodeIterator.nextNode();
311         taxonomyViewNode = getViewableContent(taxonomyNode, filters);
312         if (taxonomyViewNode != null) {
313           taxonomyNodes.add(taxonomyViewNode);
314         }
315       }
316     }
317     long limit = (filters.get(FILTER_LIMIT)!=null)?new Integer(filters.get(FILTER_LIMIT)):0;
318     long max = offset + limit;
319     totalSize = taxonomyNodes.size();
320     if (max > totalSize){
321       max = totalSize;
322     }
323     for (long i = offset ; i < max ; i++ ){
324       nodes.add(taxonomyNodes.get((int)i));
325     }
326 
327     Result result = new Result(nodes, offset, totalSize, nodeLocation, filters);
328     return result;
329 
330   }
331 
332   /**
333    * return paginated result in case of document nodes. The nodes are filtered in jcr side. The publication statut is
334    * part of node's properties
335    * @param nodeLocation
336    * @param workspace
337    * @param filters
338    * @param sessionProvider
339    * @return current page result with populating nodes
340    * @throws Exception
341    */
342   private Result getPaginatedNodesContent(NodeLocation nodeLocation, String workspace,
343                                           HashMap<String, String> filters,
344                                           SessionProvider sessionProvider) throws Exception{
345     List<Node> nodes = new ArrayList<Node>();
346     long totalSize;
347     long offset = (filters.get(FILTER_OFFSET)!=null)?new Long(filters.get(FILTER_OFFSET)):0;
348     String path = nodeLocation.getPath();
349     totalSize = getViewabaleContentsSize(path, workspace, filters, sessionProvider);
350     NodeIterator nodeIterator = getViewableContents(workspace, path, filters, sessionProvider, true);
351     Node node = null, viewNode = null;
352     if (nodeIterator != null) {
353       while (nodeIterator.hasNext()) {
354         node = nodeIterator.nextNode();
355         viewNode = getViewableContent(node, filters);
356         if (viewNode != null) {
357           nodes.add(viewNode);
358         }
359       }
360     }
361 
362     Result result = new Result(nodes, offset, totalSize, nodeLocation, filters);
363     return result;
364 
365   }
366 
367   /**
368    * get total contents' size
369    * @param path
370    * @param workspace
371    * @param filters
372    * @param sessionProvider
373    * @return
374    * @throws Exception
375    */
376   private long getViewabaleContentsSize(String path, String workspace,HashMap<String, String> filters,
377                                       SessionProvider sessionProvider) throws Exception {
378 
379     long totalSize = (filters.get(FILTER_TOTAL)!=null)?new Long(filters.get(FILTER_TOTAL)):0;
380     if (totalSize == 0) {
381       NodeIterator nodeIterator = getViewableContents(workspace, path, filters, sessionProvider, false);
382       if (nodeIterator != null) {
383         totalSize = nodeIterator.getSize();
384       }
385     }
386     return totalSize;
387   }
388 
389   /*
390    * (non-Javadoc)
391    * @see
392    * org.exoplatform.services.wcm.publication.WCMComposer#getContents(java.lang
393    * .String, java.lang.String, java.lang.String, java.util.HashMap)
394    */
395   private NodeIterator getViewableContents(String workspace,
396                                            String path,
397                                            HashMap<String, String> filters,
398                                            SessionProvider sessionProvider, boolean paginated) throws Exception {
399     ManageableRepository manageableRepository = repositoryService.getCurrentRepository();
400     Session session = sessionProvider.getSession(workspace, manageableRepository);
401     QueryManager manager = session.getWorkspace().getQueryManager();
402     String mode = filters.get(FILTER_MODE);
403     String orderBy = filters.get(FILTER_ORDER_BY);
404     String orderFilter = getOrderSQLFilter(filters);
405     String recursive = filters.get(FILTER_RECURSIVE);
406     String primaryType = filters.get(FILTER_PRIMARY_TYPE);
407     String queryFilter = filters.get(FILTER_QUERY);
408     String queryFilterFull = filters.get(FILTER_QUERY_FULL);
409     StringBuffer statement = new StringBuffer();
410     boolean filterTemplates = true;
411     if (queryFilterFull!=null) {
412       statement.append(queryFilterFull);
413       updateSymlinkByQuery(workspace, queryFilterFull, sessionProvider);
414     } else {
415       addUsedPrimaryTypes(primaryType);
416       if (primaryType == null) {
417         primaryType = "nt:base";
418         Node currentFolder = null;
419         if ("/".equals(path)) {
420           currentFolder = session.getRootNode();
421         } else {
422           Item item = session.getItem(path);
423           if (item != null) {
424             currentFolder = (Node) item;
425           }
426         }
427 
428         if (currentFolder != null && currentFolder.isNodeType("exo:taxonomy")) {
429           primaryType = "exo:taxonomyLink";
430         }
431       } else {
432         filterTemplates = false;
433       }
434       addUsedOrderBy(orderBy);
435 
436       statement.append("SELECT * FROM " + primaryType + " WHERE (jcr:path LIKE '" + path + "/%'");
437       if (recursive==null || "false".equals(recursive)) {
438         statement.append(" AND NOT jcr:path LIKE '" + path + "/%/%')");
439       } else {
440         statement.append(")");
441       }
442       // If clv view mode is live, only get nodes which has published version
443       if (MODE_LIVE.equals(mode) && !"exo:taxonomyLink".equals(primaryType))
444         statement.append(" AND NOT publication:currentState = 'unpublished' AND (publication:currentState IS NULL OR publication:currentState = 'published' " +
445         		"OR exo:titlePublished IS NOT NULL)");
446       if (filterTemplates) statement.append(" AND " + getTemplatesSQLFilter());
447       if (queryFilter!=null) {
448         statement.append(queryFilter);
449       }
450       statement.append(orderFilter);
451       updateSymlink(workspace, path, sessionProvider);
452     }
453     Query query = manager.createQuery(statement.toString(), Query.SQL);
454 
455     if (paginated) {
456       long offset = (filters.get(FILTER_OFFSET)!=null)?new Long(filters.get(FILTER_OFFSET)):0;
457       long limit = (filters.get(FILTER_LIMIT)!=null)?new Long(filters.get(FILTER_LIMIT)):0;
458       if (limit>0) {
459         ((QueryImpl)query).setOffset(offset);
460         ((QueryImpl)query).setLimit(limit);
461       }
462     }
463 
464     // order by title with in-sensitive case.
465     ((QueryImpl)query).setCaseInsensitiveOrder(true);
466 
467     return query.execute().getNodes();
468   }
469 
470   /**
471    * Gets the node view.
472    *
473    * @param node the node
474    *
475    * @return the node view
476    *
477    * @throws Exception the exception
478    */
479   private Node getViewableContent(Node node, HashMap<String, String> filters) throws Exception {
480     Node viewNode = null;
481     if (trashService == null) {
482       trashService = WCMCoreUtils.getService(TrashService.class);
483     }
484     try {
485       node = getTargetNode(node);
486     } catch (AccessDeniedException ade) {
487       return null;
488     }
489 
490     if (node != null && trashService.isInTrash(node)) {
491       return null;
492     }
493 
494     String languageFilter = filters.get(FILTER_LANGUAGE);
495     if (languageFilter!=null) {
496       addUsedLanguage(languageFilter);
497       Node lnode = null;
498       try {
499         lnode = multiLanguageService.getLanguage(node, languageFilter);
500       } catch (AccessDeniedException e) {
501         if (LOG.isTraceEnabled()) LOG.trace("AccessDenied on "+languageFilter+" translation for "+node.getPath());
502       }
503       if (lnode!=null) {
504 
505         viewNode = getPublishedContent(lnode, filters);
506         if (viewNode!=null) {
507           return viewNode;
508         }
509         return null;
510       }
511     }
512 
513     if (node != null) {
514       viewNode = getPublishedContent(node, filters);
515     }
516 
517     return viewNode;
518   }
519 
520 
521   private Node getPublishedContent(Node node, HashMap<String, String> filters) throws Exception {
522     HashMap<String, Object> context = new HashMap<String, Object>();
523     String mode = filters.get(FILTER_MODE);
524     context.put(WCMComposer.FILTER_MODE, mode);
525     context.put(WCMComposer.PORTLET_MODE, filters.get(PORTLET_MODE));
526     String lifecyleName = null;
527     try {
528       lifecyleName = publicationService.getNodeLifecycleName(node);
529     } catch (NotInPublicationLifecycleException e) {
530       // Don't log here, this is normal
531     }
532     if (lifecyleName == null) return node;
533     PublicationPlugin publicationPlugin = publicationService.getPublicationPlugins().get(lifecyleName);
534     Node viewNode = publicationPlugin.getNodeView(node, context);
535     return viewNode;
536 
537   }
538 
539   private Node getTargetNode(Node showingNode) throws Exception {
540     Node targetNode = null;
541     if (linkManager.isLink(showingNode)) {
542       try {
543         targetNode = linkManager.getTarget(showingNode);
544       } catch (ItemNotFoundException e) {
545         targetNode = showingNode;
546       }
547     } else {
548       targetNode = showingNode;
549     }
550     return targetNode;
551   }
552 
553   public List<Node> getCategories(Node node) throws Exception {
554     if (taxonomyService==null) taxonomyService = WCMCoreUtils.getService(TaxonomyService.class);
555     List<Node> listCategories = new ArrayList<Node>();
556     List<Node> listNode = getAllTaxonomyTrees();
557     for(Node itemNode : listNode) {
558       listCategories.addAll(taxonomyService.getCategories(node, itemNode.getName()));
559     }
560     return listCategories;
561   }
562 
563   List<Node> getAllTaxonomyTrees() throws RepositoryException {
564     if (taxonomyService==null) taxonomyService = WCMCoreUtils.getService(TaxonomyService.class);
565     return taxonomyService.getAllTaxonomyTrees();
566   }
567 
568   String displayCategory(Node node, List<Node> taxonomyTrees) {
569     try {
570       for (Node taxonomyTree : taxonomyTrees) {
571         if (node.getPath().contains(taxonomyTree.getPath())) {
572           return node.getPath().replace(taxonomyTree.getPath(), taxonomyTree.getName());
573         }
574       }
575     } catch (RepositoryException e) {
576       if (LOG.isErrorEnabled())LOG.error("Unexpected error when getting node taxonomies");
577     }
578     return "";
579   }
580 
581   /**
582    * We currently support 2 modes :
583    * MODE_LIVE : PUBLISHED state only
584    * MODE_EDIT : PUBLISHED, DRAFT, PENDING, STAGED, APPROVED allowed.
585    *
586    * @param mode the current mode (MODE_LIVE or MODE_EDIT)
587    *
588    * @return the allowed states
589    */
590   public List<String> getAllowedStates(String mode) {
591     List<String> states = new ArrayList<String>();
592     if (MODE_LIVE.equals(mode)) {
593       states.add(PublicationDefaultStates.PUBLISHED);
594     } else if (MODE_EDIT.equals(mode)) {
595       states.add(PublicationDefaultStates.PUBLISHED);
596       states.add(PublicationDefaultStates.DRAFT);
597       states.add(PublicationDefaultStates.PENDING);
598       states.add(PublicationDefaultStates.STAGED);
599       states.add(PublicationDefaultStates.APPROVED);
600     }
601     return states;
602   }
603 
604 
605   @Managed
606   @ManagedDescription("Clean all templates in Composer")
607     public void cleanTemplates() throws Exception {
608       this.templatesFilter = null;
609       getTemplatesSQLFilter();
610       if (LOG.isDebugEnabled()) LOG.debug("WCMComposer templates have been cleaned !");
611     }
612 
613   @Managed
614   @ManagedDescription("Used Languages")
615   public List<String> getUsedLanguages() {
616     return usedLanguages;
617   }
618 
619   @Managed
620   @ManagedDescription("Used Primary Types")
621   public List<String> getUsedPrimaryTypes() {
622     return usedPrimaryTypes;
623   }
624 
625   @Managed
626   @ManagedDescription("Used Order By")
627   public List<String> getUsedOrderBy() {
628     return usedOrderBy;
629   }
630 
631 
632   /* (non-Javadoc)
633    * @see org.picocontainer.Startable#start()
634    */
635   public void start() {}
636 
637   /* (non-Javadoc)
638    * @see org.picocontainer.Startable#stop()
639    */
640   public void stop() {}
641 
642   /**
643    * Gets the order sql filter.
644    *
645    * @param filters the filters
646    *
647    * @return the order sql filter
648    */
649   private String getOrderSQLFilter(HashMap<String, String> filters) {
650     StringBuffer orderQuery = new StringBuffer(" ORDER BY ");
651     String orderBy = filters.get(FILTER_ORDER_BY);
652     String orderType = filters.get(FILTER_ORDER_TYPE);
653     if (orderType == null)
654       orderType = "DESC";
655     if (orderBy == null)
656       orderBy = "exo:title";
657     orderQuery.append(orderBy).append(" ").append(orderType);
658     return orderQuery.toString();
659   }
660 
661   /**
662    * Gets all document nodetypes and write a query statement
663    * @return a part of the query allow search all document node and taxonomy link also. Return null if there is any exception.
664    */
665   private String getTemplatesSQLFilter() {
666     if (templatesFilter != null) return templatesFilter;
667     return updateTemplatesSQLFilter();
668   }
669   /**
670    * Update all document nodetypes and write a query statement
671    * @return a part of the query allow search all document node and taxonomy link also. Return null if there is any exception.
672    */
673   public String updateTemplatesSQLFilter() {
674     try {
675       List<String> documentTypes = templateService.getDocumentTemplates();
676       StringBuffer documentTypeClause = new StringBuffer("(");
677       for (int i = 0; i < documentTypes.size(); i++) {
678         String documentType = documentTypes.get(i);
679         documentTypeClause.append("jcr:primaryType = '" + documentType + "'");
680         if (i != (documentTypes.size() - 1)) documentTypeClause.append(" OR ");
681       }
682       templatesFilter = documentTypeClause.toString();
683       templatesFilter += " OR jcr:primaryType = 'exo:taxonomyLink' OR jcr:primaryType = 'exo:symlink')";
684       return templatesFilter;
685     } catch (Exception e) {
686       if (LOG.isErrorEnabled()) {
687         LOG.error("Error when perform getTemlatesSQLFilter: ", e);
688       }
689       return null;
690     }
691   }
692 
693   /**
694    * Gets the node by category.
695    *
696    * @param parameters the parameters
697    *
698    * @return the node by category
699    *
700    * @throws Exception the exception
701    */
702   private Node getNodeByCategory(String parameters) throws Exception {
703     try {
704       if (taxonomyService==null) taxonomyService = WCMCoreUtils.getService(TaxonomyService.class);
705       Node taxonomyTree = taxonomyService.getTaxonomyTree(parameters.split("/")[0]);
706       Node symlink = taxonomyTree.getNode(parameters.substring(parameters.indexOf("/") + 1));
707       return linkManager.getTarget(symlink);
708     } catch (Exception e) {
709       return null;
710     }
711   }
712 
713   private void addUsedLanguage(String lang) {
714     if (!usedLanguages.contains(lang)) usedLanguages.add(lang);
715   }
716 
717   private void addUsedOrderBy(String orderBy) {
718     if (!usedOrderBy.contains(orderBy)) usedOrderBy.add(orderBy);
719   }
720   private void addUsedPrimaryTypes(String primaryType) {
721     if (!usedPrimaryTypes.contains(primaryType)) usedPrimaryTypes.add(primaryType);
722   }
723 
724   private List<AccessControlEntry> getAnyUserACL() {
725     List<AccessControlEntry> ret = new ArrayList<AccessControlEntry>();
726     ret.add(new AccessControlEntry(sharedGroup, PermissionType.READ));
727     return ret;
728   }
729 
730   /**
731    * Get login User
732    * @return user name
733    */
734   private String getRemoteUser() {
735     String remoteUser = null;
736     try {
737       remoteUser = Util.getPortalRequestContext().getRemoteUser();
738     } catch (Exception e) {
739       remoteUser = null;
740     }
741     return remoteUser;
742   }
743 
744   private void updateSymlink(String workspace, String path, SessionProvider sessionProvider) {
745     if ("/".equals(path)) {
746       path = "";
747     }
748     StringBuilder statement = new StringBuilder();
749     statement.append("SELECT * FROM " + NodetypeConstant.EXO_SYMLINK + " WHERE (jcr:path LIKE '" + path + "/%'")
750              .append(" AND NOT jcr:path LIKE '" + path + "/%/%')");
751     updateSymlinkByQuery(workspace, statement.toString(), sessionProvider);
752   }
753 
754   private void updateSymlinkByQuery(String workspace, String statement, SessionProvider sessionProvider) {
755     try {
756       ManageableRepository manageableRepository = repositoryService.getCurrentRepository();
757       Session session = sessionProvider.getSession(workspace, manageableRepository);
758       QueryManager manager = session.getWorkspace().getQueryManager();
759       NodeIterator iter = manager.createQuery(statement, Query.SQL).execute().getNodes();
760       while (iter.hasNext()) {
761         try {
762           Node currentNode = iter.nextNode();
763           linkManager.updateSymlink(currentNode);
764         } catch (Exception ex) {
765           if (LOG.isErrorEnabled()) {
766             LOG.error("Can not update symlink data", ex);
767           }
768         }
769       }
770     } catch (RepositoryException e) {
771       if (LOG.isErrorEnabled()) {
772         LOG.error("Can not update symlinks data", e);
773       }
774     }
775   }
776   
777   private String getTypeFromPath (String workspace, String path, SessionProvider sessionProvider) throws Exception {
778     ManageableRepository manageableRepository = repositoryService.getCurrentRepository();
779     Session session = sessionProvider.getSession(workspace, manageableRepository);
780     Node currentFolder = null;
781     try {
782        Node node = (Node)session.getItem(path);
783        return node.getPrimaryNodeType().getName();
784     } catch(PathNotFoundException pne) {
785       return null;
786     }
787   }
788 }