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.services.cms.actions.impl;
18  
19  import org.exoplatform.container.component.ComponentPlugin;
20  import org.exoplatform.services.cms.CmsService;
21  import org.exoplatform.services.cms.JcrInputProperty;
22  import org.exoplatform.services.cms.actions.ActionPlugin;
23  import org.exoplatform.services.cms.actions.ActionServiceContainer;
24  import org.exoplatform.services.cms.actions.DMSEvent;
25  import org.exoplatform.services.cms.impl.Utils;
26  import org.exoplatform.services.jcr.RepositoryService;
27  import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
28  import org.exoplatform.services.jcr.core.ManageableRepository;
29  import org.exoplatform.services.jcr.core.nodetype.ExtendedNodeTypeManager;
30  import org.exoplatform.services.jcr.core.nodetype.NodeTypeValue;
31  import org.exoplatform.services.jcr.core.nodetype.PropertyDefinitionValue;
32  import org.exoplatform.services.log.ExoLogger;
33  import org.exoplatform.services.log.Log;
34  import org.picocontainer.Startable;
35  
36  import javax.jcr.Node;
37  import javax.jcr.NodeIterator;
38  import javax.jcr.PathNotFoundException;
39  import javax.jcr.PropertyType;
40  import javax.jcr.RepositoryException;
41  import javax.jcr.Session;
42  import javax.jcr.Value;
43  import javax.jcr.nodetype.NodeType;
44  import javax.jcr.nodetype.NodeTypeIterator;
45  import javax.jcr.nodetype.NodeTypeManager;
46  import javax.jcr.nodetype.PropertyDefinition;
47  import javax.jcr.query.InvalidQueryException;
48  import javax.jcr.query.Query;
49  import javax.jcr.query.QueryManager;
50  import javax.jcr.query.QueryResult;
51  import javax.jcr.version.OnParentVersionAction;
52  import java.util.ArrayList;
53  import java.util.Collection;
54  import java.util.HashMap;
55  import java.util.List;
56  import java.util.Map;
57  
58  /**
59   * Process with action for node
60   * @author exo
61   *
62   */
63  public class ActionServiceContainerImpl implements ActionServiceContainer, Startable {
64  
65    /**
66     * Logger.
67     */
68    private static final Log LOG  = ExoLogger.getLogger(ActionServiceContainerImpl.class.getName());
69  
70    /**
71     * Define nodetype ACTIONABLE
72     */
73    private static final String         ACTIONABLE           = "exo:actionable";
74  
75    /**
76     * Define nodetype ACTION
77     */
78    private static final String         ACTION               = "exo:action";
79  
80    /**
81     * Define nodetype JOB_NAME_PROP
82     */
83    private static final String         JOB_NAME_PROP        = "exo:jobName";
84  
85    /**
86     * Define nodetype JOB_NAME_PROP
87     */
88    private static final String         JOB_GROUP_PROP       = "exo:jobGroup";
89  
90    /**
91     * Define nodetype JOB_CLASS_PROP
92     */
93    private static final String         JOB_CLASS_PROP       = "exo:jobClass";
94  
95    /**
96     * Define nodetype LIFECYCLE_PHASE_PROP
97     */
98    private static final String         LIFECYCLE_PHASE_PROP = "exo:lifecyclePhase" ;
99  
100   /**
101    * Define query statement
102    */
103   private static final String         ACTION_QUERY         = "//element(*, exo:action)" ;
104 
105   /**
106    * Define sql query statement
107    */
108   private static final String ACTION_SQL_QUERY =
109                 "select * from exo:action" ;
110 
111   /**
112    * Define sql append query operator.
113    */
114   private static final String WHERE_OPERATOR = " where" ;
115 
116   /**
117    * Define sql path.
118    */
119   private static final String JCR_PATH = " jcr:path" ;
120 
121   /**
122    * Define sql like operator.
123    */
124   private static final String LIKE_OPERATOR = " like" ;
125 
126   /**
127    * Sql query single quote.
128    */
129   private static final String SINGLE_QUOTE = "'";
130 
131   /**
132    * Define nodetype SCHEDULABLE_MIXIN
133    */
134   private static final String         SCHEDULABLE_MIXIN    = "exo:schedulableInfo";
135 
136   /**
137    * Define relative path for action node
138    */
139   private static final String         EXO_ACTIONS          = "exo:actions";
140 
141   /**
142    * Define nodetype ACTION_STORAGE
143    */
144   private static final String         ACTION_STORAGE       = "exo:actionStorage";
145 
146   /**
147    * Define nodetype EXO_HIDDENABLE
148    */
149   private static final String         EXO_HIDDENABLE       = "exo:hiddenable";
150 
151   /**
152    * RepositoryService
153    */
154   private RepositoryService           repositoryService_;
155 
156   /**
157    * CmsService
158    */
159   private CmsService                  cmsService_;
160 
161   /**
162    * Collection of ComponentPlugin
163    */
164   private Collection<ComponentPlugin> actionPlugins        = new ArrayList<ComponentPlugin>();
165 
166   /**
167    * Constructor method
168    * @param repositoryService RepositoryService
169    * @param cmsService        CmsService
170    * @throws Exception
171    */
172   public ActionServiceContainerImpl(RepositoryService repositoryService, CmsService cmsService
173       ) throws Exception {
174     repositoryService_ = repositoryService;
175     cmsService_ = cmsService;
176   }
177 
178   /**
179    * Implement method start service
180    * Add mixin exo:actionable for node
181    */
182   public void start() {
183     if (LOG.isInfoEnabled()) {
184       LOG.info("Start " + this.getClass().getSimpleName()+ "...");
185     }
186     try {
187       for (ComponentPlugin cPlungin : actionPlugins) {
188         BaseActionPlugin plugin = (BaseActionPlugin) cPlungin;
189         plugin.importPredefinedActionsInJcr();
190       }
191       initiateActionConfiguration();
192     } catch (Exception e) {
193       if (LOG.isErrorEnabled()) {
194         LOG.error("Cannot start ActionServiceContainerImpl", e);
195       }
196     }
197   }
198 
199   /**
200    * Implement method stop service
201    */
202   public void stop() {
203   }
204 
205   /**
206    * {@inheritDoc}
207    */
208   public void init() {
209     try {
210       for (ComponentPlugin cPlungin : actionPlugins) {
211         BaseActionPlugin plugin = (BaseActionPlugin) cPlungin;
212         plugin.reImportPredefinedActionsInJcr();
213       }
214       reInitiateActionConfiguration();
215     } catch (Exception e) {
216       if (LOG.isErrorEnabled()) {
217         LOG.error("Cannot initialize the ActionServiceContainerImpl", e);
218       }
219     }
220   }  
221 
222   /**
223    * {@inheritDoc}
224    */  
225   public Collection<String> getActionPluginNames() {
226     Collection<String> actionPluginNames = new ArrayList<String>(actionPlugins.size());
227     for (ComponentPlugin plugin : actionPlugins) {
228       actionPluginNames.add(plugin.getName());
229     }
230     return actionPluginNames;
231   }
232 
233   /**
234    * {@inheritDoc}
235    */  
236   public ActionPlugin getActionPlugin(String actionsServiceName) {
237     for (ComponentPlugin plugin : actionPlugins) {
238       if (plugin.getName().equals(actionsServiceName))
239         return (ActionPlugin) plugin;
240     }
241     return null;
242   }
243 
244   /**
245    * Create NodeTypeValue is in kind of ActionType following action type name
246    * @param actionTypeName        name of action type
247    * @param parentActionTypeName  name of parent action
248    * @param executable            String value of executable
249    * @param variableNames         List name of variable
250    * @param isMoveType            is moved or not
251    * @throws Exception
252    */
253   @SuppressWarnings("unchecked")
254   public void createActionType(String actionTypeName, String parentActionTypeName, String executable, String actionLabel,
255       List<String> variableNames, boolean isMoveType, boolean isUpdate) throws Exception {
256     NodeTypeValue nodeTypeValue = new NodeTypeValue();
257     nodeTypeValue.setName(actionTypeName);
258 
259     List<String> superTypes = new ArrayList<String>();
260     superTypes.add(parentActionTypeName);
261     if (isMoveType)
262       superTypes.add("exo:move");
263     nodeTypeValue.setDeclaredSupertypeNames(superTypes);
264 
265     List propDefs = new ArrayList();
266     PropertyDefinitionValue propDef = null;
267     for (String variableName : variableNames) {
268       propDef = createPropertyDef(variableName);
269       propDefs.add(propDef);
270     }
271     propDef = createPropertyDef(getActionPluginForActionType(parentActionTypeName).getExecutableDefinitionName());
272     List scriptDefaultValues = new ArrayList();
273     scriptDefaultValues.add(executable);
274     propDef.setDefaultValueStrings(scriptDefaultValues);
275     propDef.setMandatory(true);
276     propDefs.add(propDef);
277     propDef = createPropertyDef(getActionPluginForActionType(parentActionTypeName).getActionExecutableLabel());
278     List labelDefaultValues = new ArrayList();
279     labelDefaultValues.add(actionLabel);
280     propDef.setDefaultValueStrings(labelDefaultValues);
281     propDef.setMandatory(true);
282     propDefs.add(propDef);
283 
284     nodeTypeValue.setDeclaredPropertyDefinitionValues(propDefs);
285     nodeTypeValue.setDeclaredChildNodeDefinitionValues(new ArrayList());
286     ExtendedNodeTypeManager ntmanager = repositoryService_.getCurrentRepository().getNodeTypeManager();
287     if(isUpdate) ntmanager.registerNodeType(nodeTypeValue, ExtendedNodeTypeManager.REPLACE_IF_EXISTS);
288     ntmanager.registerNodeType(nodeTypeValue, ExtendedNodeTypeManager.IGNORE_IF_EXISTS);
289   }
290 
291   /**
292    * Definite new property with property name = name
293    * mandatory = false, multiple = false, readonly = false, autocreate = false, onversion = 1
294    * type = STRING, default value = new ArrayList(), Value constraints = new ArrayList()
295    * @param name name of property
296    * @return PropertyDefinitionValue
297    */
298   @SuppressWarnings("unchecked")
299   private PropertyDefinitionValue createPropertyDef(String name) {
300     PropertyDefinitionValue def = new PropertyDefinitionValue();
301     def.setName(name);
302     def.setRequiredType(PropertyType.STRING);
303     def.setMandatory(false);
304     def.setMultiple(false);
305     def.setReadOnly(false);
306     def.setAutoCreate(false);
307     def.setOnVersion(OnParentVersionAction.COPY);
308     def.setValueConstraints(new ArrayList());
309     def.setDefaultValueStrings(new ArrayList());
310     return def;
311   }
312 
313   /**
314    * Get all created node with nodetype = "exo:action
315    * @param repository  repository name
316    * @return Collection of NodeType
317    * @throws Exception
318    */
319   public Collection<NodeType> getCreatedActionTypes(String repository) throws Exception {
320     Collection<NodeType> createsActions = new ArrayList<NodeType>();
321     NodeTypeManager ntmanager = repositoryService_.getCurrentRepository().getNodeTypeManager();
322     for(NodeTypeIterator iter = ntmanager.getAllNodeTypes();iter.hasNext();) {
323       NodeType nt = (NodeType) iter.next();
324       String name = nt.getName();
325       if (nt.isNodeType(ACTION) && !isAbstractType(name) &&
326         !Utils.getAllEditedConfiguredData("ActionTypeList", "EditedConfiguredActionType", true).contains(name)) {
327         createsActions.add(nt);
328       }
329     }
330     return createsActions;
331   }
332 
333   /**
334    * Check ComponentPlugin is abstract type or not
335    * @param name  name of ComponentPlugin
336    * @return true: ComponentPlugin with name is abstract type
337    *         false: ComponentPlugin with name is not abstract type
338    */
339   private boolean isAbstractType(String name) {
340     for (ComponentPlugin plugin : actionPlugins) {
341       if (plugin.getName().equals(name))
342         return true;
343     }
344     return false;
345   }
346 
347   /**
348    * Get SystemSession of specific workspace and repository
349    * @param workspace
350    * @return
351    * @throws RepositoryException
352    * @throws RepositoryConfigurationException
353    */
354   private Session getSystemSession(String workspace) throws RepositoryException,
355   RepositoryConfigurationException {
356     ManageableRepository jcrRepository = repositoryService_.getCurrentRepository();
357     return jcrRepository.getSystemSession(workspace);
358   }
359 
360   /**
361    * {@inheritDoc}
362    */  
363   public ActionPlugin getActionPluginForActionType(String actionTypeName) {
364     for (ComponentPlugin plugin : actionPlugins) {
365       String actionServiceName = plugin.getName();
366       ActionPlugin actionService = getActionPlugin(actionServiceName);
367       if (actionService.isActionTypeSupported(actionTypeName)
368           || actionServiceName.equals(actionTypeName))
369         return actionService;
370     }
371     return null;
372   }
373 
374   /**
375    * {@inheritDoc}
376    */  
377   public Node getAction(Node node, String actionName) throws Exception {
378     if (node.hasNode(EXO_ACTIONS + "/"+actionName)) {
379       return node.getNode(EXO_ACTIONS + "/"+ actionName);
380     } 
381     return null;  
382   }
383   
384   /**
385    * {@inheritDoc}
386    */
387   public boolean hasActions(Node node) throws Exception {
388     return node.isNodeType(ACTIONABLE);
389   }
390   
391   /**
392    * {@inheritDoc}
393    */
394   public List<Node> getActions(Node node) throws Exception {
395     return getActions(node, null);
396   }
397 
398   /**
399    * {@inheritDoc}
400    */  
401   public List<Node> getCustomActionsNode(Node node, String lifecyclePhase) throws Exception {
402     try {
403       return getActions(node, lifecyclePhase) ;
404     } catch(Exception item) {
405       return null ;
406     }
407   }
408 
409   /**
410    * {@inheritDoc}
411    */
412   public List<Node> getActions(Node node, String lifecyclePhase) throws Exception {
413     List<Node> actions = new ArrayList<Node>();
414     Node actionStorage = null;
415     try{
416       actionStorage = node.getNode(EXO_ACTIONS);
417     }catch (Exception e) {
418       return actions;
419     }
420     for (NodeIterator iter = actionStorage.getNodes(); iter.hasNext();) {
421       Node tmpNode = iter.nextNode();
422       if (tmpNode.isNodeType(ACTION)
423           && (lifecyclePhase == null || parseValuesToList(
424               tmpNode.getProperty(LIFECYCLE_PHASE_PROP).getValues()).contains(lifecyclePhase))) {
425         actions.add(tmpNode);
426       }
427     }
428     return actions;
429   }
430 
431   /**
432    * {@inheritDoc}
433    */
434   public void removeAction(Node node, String repository) throws Exception {
435     if(!node.isNodeType(ACTIONABLE)) return ;
436     List<Node> actions = getActions(node);
437     for (Node action : actions) {
438       removeAction(node, action.getName(), repository);
439     }
440   }
441   
442   /**
443    * {@inheritDoc}
444    */
445   public void removeAction(Node node, String actionName, String repository) throws Exception {
446     if(!node.isNodeType(ACTIONABLE)) return  ;
447     Node action2Remove = node.getNode(EXO_ACTIONS+ "/" + actionName);
448     String[] lifecyclePhase = parseValuesToArray(action2Remove.getProperty(LIFECYCLE_PHASE_PROP)
449         .getValues());
450     String jobName = null, jobGroup = null, jobClassName = null;
451     if (action2Remove.isNodeType(SCHEDULABLE_MIXIN)) {
452       jobName = action2Remove.getProperty(JOB_NAME_PROP).getString();
453       jobGroup = action2Remove.getProperty(JOB_GROUP_PROP).getString();
454       jobClassName = action2Remove.getProperty(JOB_CLASS_PROP).getString();
455     }
456     String actionTypeName = action2Remove.getPrimaryNodeType().getName();
457     String actionPath = action2Remove.getPath();
458     for (ComponentPlugin plugin : actionPlugins) {
459       String actionServiceName = plugin.getName();
460       ActionPlugin actionService = getActionPlugin(actionServiceName);
461       if (actionService.isActionTypeSupported(actionTypeName)) {
462         if ((DMSEvent.getEventTypes(lifecyclePhase) & DMSEvent.SCHEDULE) > 0) {
463           actionService.removeActivationJob(jobName, jobGroup, jobClassName);
464         }
465         actionService.removeObservation(repository, actionPath);
466       }
467     }
468     action2Remove.remove();
469     node.save();
470   }
471   
472   /**
473    * {@inheritDoc}}
474    */
475   public void addAction(Node storeActionNode,
476                         String actionType,
477                         boolean isDeep,
478                         String[] uuid,
479                         String[] nodeTypeNames,
480                         Map mappings) throws Exception {
481     Node actionsNode = null;
482     try {
483       actionsNode = storeActionNode.getNode(EXO_ACTIONS);
484     } catch (PathNotFoundException e) {
485       actionsNode = storeActionNode.addNode(EXO_ACTIONS,ACTION_STORAGE) ;
486       actionsNode.addMixin(EXO_HIDDENABLE) ;
487       storeActionNode.save();
488     }
489     if (!storeActionNode.isNodeType(ACTIONABLE)) {
490       storeActionNode.addMixin(ACTIONABLE);
491       storeActionNode.save();
492     }
493     String newActionPath = cmsService_.storeNode(actionType, actionsNode, mappings,true);
494     storeActionNode.save();
495     String srcWorkspace = storeActionNode.getSession().getWorkspace().getName();
496 
497     String srcPath = storeActionNode.getPath();
498     ActionPlugin actionService = getActionPluginForActionType(actionType);
499     if (actionService == null)
500       throw new ClassNotFoundException("Not found any action's service compatible with action type "+actionType) ;
501     try {
502       actionService.addAction(actionType, srcWorkspace, srcPath, isDeep, uuid, nodeTypeNames, mappings);
503     } catch (Exception e) {
504       if (LOG.isErrorEnabled()) {
505         LOG.error(e);
506       }
507       Session session = getSystemSession(storeActionNode.getSession().getWorkspace().getName());
508       Node actionNode = (Node) session.getItem(newActionPath);
509       actionNode.remove();
510       session.save();
511       session.logout();
512       throw e;
513     }
514   }  
515 
516   /**
517    * {@inheritDoc}
518    */
519   public void addAction(Node storeActionNode, String actionType, Map mappings) throws Exception {
520     boolean isDeep = true;
521     String[] nodeTypeName = null;
522     String[] uuid = null;
523     if (mappings.containsKey("/node/exo:isDeep")) {
524       isDeep = Boolean.valueOf(((JcrInputProperty)mappings.get("/node/exo:isDeep")).getValue().toString());
525     }
526     if (mappings.containsKey("/node/exo:uuid")) {
527       uuid = (String[]) ((JcrInputProperty) mappings.get("/node/exo:uuid")).getValue();
528       if(uuid.length == 0) uuid = null;
529     }
530     if (mappings.containsKey("/node/exo:nodeTypeName")) {
531       nodeTypeName = (String[]) ((JcrInputProperty) mappings.get("/node/exo:nodeTypeName"))
532           .getValue();
533       if(nodeTypeName.length == 0) {
534         nodeTypeName = null;
535         mappings.remove("/node/exo:nodeTypeName");
536       }
537     }
538     addAction(storeActionNode, actionType, isDeep, uuid, nodeTypeName, mappings);
539   }  
540 
541   /**
542    * Call addAction(Node node, String repository, String type, Map mappings) to
543    * execute action following userId, node, repository, initiated variables
544    * @param userId user identify
545    * @param node current node
546    * @param actionName name of action
547    * @throws Exception
548    */
549   public void executeAction(String userId, Node node, String actionName) throws Exception {
550     Map<String, String> variables = new HashMap<String, String>();
551     variables.put("initiator", userId);
552     variables.put("actionName", actionName);
553     variables.put("nodePath", node.getPath());
554     variables.put("srcWorkspace", node.getSession().getWorkspace().getName());
555     variables.put("srcPath", node.getPath());
556 
557     NodeType nodeType = node.getPrimaryNodeType();
558     String nodeTypeName = nodeType.getName();
559     variables.put("document-type", nodeTypeName);
560     Node actionNode = getAction(node, actionName);
561     NodeType actionNodeType = actionNode.getPrimaryNodeType();
562     fillVariables(actionNode, actionNodeType, variables);
563 
564     NodeType[] actionMixinTypes = actionNode.getMixinNodeTypes();
565 
566     for (int i = 0; i < actionMixinTypes.length; i++) {
567       NodeType mixinType = actionMixinTypes[i];
568       fillVariables(actionNode, mixinType, variables);
569     }
570 
571     executeAction(userId, node, actionName, variables);
572   }
573 
574 
575   /**
576    * Put to Map with key = property name and value = value of property in actionNode
577    * @param actionNode  get value of property in this node
578    * @param nodeType    get property definition from this object
579    * @param variables   Map to keep (key, value) of all property
580    * @throws Exception
581    */
582   private void fillVariables(Node actionNode, NodeType nodeType, Map variables) throws Exception {
583     for(PropertyDefinition def:nodeType.getDeclaredPropertyDefinitions()) {
584       String propName = def.getName();
585       if (actionNode.hasProperty(propName)) {
586         if(actionNode.getProperty(propName).getDefinition().isMultiple()) {
587 
588         } else {
589           String propValue = actionNode.getProperty(propName).getString();
590           variables.put(propName, propValue);
591         }
592       }
593     }
594   }
595 
596   /**
597    * Execute action following userId, node, variables, repository
598    * @param userId      user identify
599    * @param node        current node
600    * @param actionName  name of action
601    * @param variables   Map with variables and value
602    * @throws Exception
603    */
604   public void executeAction(String userId, Node node, String actionName, Map variables) throws Exception {
605     if (!node.isNodeType(ACTIONABLE)) return ;
606     Node actionNode = getAction(node, actionName);
607     String actionTypeName = actionNode.getPrimaryNodeType().getName();
608     for (ComponentPlugin plugin : actionPlugins) {
609       String actionServiceName = plugin.getName();
610       ActionPlugin actionPlugin = getActionPlugin(actionServiceName);
611       if (actionPlugin.isActionTypeSupported(actionTypeName)) {
612         actionPlugin.executeAction(userId, actionNode, variables);
613       }
614     }
615   }
616 
617   /**
618    * Add ComponentPlugin
619    * @param plugin  ComponentPlugin
620    */
621   public void addPlugin(ComponentPlugin plugin) { actionPlugins.add(plugin); }
622 
623   /**
624    * Need implemented
625    * @param pluginName
626    * @return
627    */
628   public ComponentPlugin removePlugin(String pluginName) {
629     return null;
630   }
631 
632   /**
633    * Get all ComponentPlugin
634    * @return  Collection of ComponentPlugins
635    */
636   public Collection<ComponentPlugin> getPlugins() { return actionPlugins; }
637 
638   /**
639    * Get QueryManager, call initAction(QueryManager queryManager, String repository, String workspace)
640    * to initialize action listener for all available repositories and workspaces
641    * @throws Exception
642    */
643   private void initiateActionConfiguration() throws Exception {
644     ManageableRepository jcrRepository = null ;
645       jcrRepository = repositoryService_.getCurrentRepository();
646       String[] workspaces = jcrRepository.getWorkspaceNames();
647       for (String workspace : workspaces) {
648         Session session = jcrRepository.getSystemSession(workspace);
649         QueryManager queryManager = null;
650         try {
651           queryManager = session.getWorkspace().getQueryManager();
652         } catch (RepositoryException e) {
653           if (LOG.isWarnEnabled()) {
654             LOG.warn("ActionServiceContainer - Query Manager Factory of workspace "
655               + workspace + " not found. Check configuration.", e);
656           }
657         }
658         if (queryManager == null) {
659           session.logout();
660           continue;
661         }
662         initAction(queryManager, workspace) ;
663         session.logout();
664       }
665   }
666 
667   /**
668    * Get QueryManager, call initAction(QueryManager queryManager, String repository, String workspace)
669    * to initialize action listener
670    * @throws Exception
671    */
672   private void reInitiateActionConfiguration() throws Exception {
673     ManageableRepository jcrRepository = repositoryService_.getCurrentRepository();
674     for (String workspace : jcrRepository.getWorkspaceNames()) {
675       Session session = jcrRepository.getSystemSession(workspace);
676       QueryManager queryManager = null;
677       try {
678         queryManager = session.getWorkspace().getQueryManager();
679       } catch (RepositoryException e) {
680         if (LOG.isWarnEnabled()) {
681           LOG.warn("ActionServiceContainer - Query Manager Factory of workspace "
682             + workspace + " not found. Check configuration.", e);
683         }
684       }
685       if (queryManager == null)  {
686         session.logout();
687         continue;
688       }
689       initAction(queryManager, workspace) ;
690       session.logout();
691     }
692   }
693 
694   /**
695    * Initialize the action listener for all node in repository
696    * All node is got by query following ACTION_QUERY
697    * @param queryManager QueryManager
698    * @param workspace    workspace name
699    * @throws Exception
700    */
701   private void initAction(QueryManager queryManager, String workspace) throws Exception {
702     try {
703       Query query = queryManager.createQuery(ACTION_QUERY, Query.XPATH);
704       QueryResult queryResult = query.execute();
705       for (NodeIterator iter = queryResult.getNodes(); iter.hasNext();) {
706         Node actionNode = iter.nextNode();
707         String[] lifecyclePhase = parseValuesToArray(actionNode.getProperty(LIFECYCLE_PHASE_PROP)
708             .getValues());
709         String actionType = actionNode.getPrimaryNodeType().getName();
710         for (ComponentPlugin plugin : actionPlugins) {
711           String actionServiceName = plugin.getName();
712           ActionPlugin actionService = getActionPlugin(actionServiceName);
713           if (actionService.isActionTypeSupported(actionType)) {
714             if (DMSEvent.getEventTypes(lifecyclePhase) == DMSEvent.READ)
715               continue;
716             if ((DMSEvent.getEventTypes(lifecyclePhase) & DMSEvent.SCHEDULE) > 0) {
717               actionService.reScheduleActivations(actionNode);
718             }
719             if (DMSEvent.getEventTypes(lifecyclePhase) == DMSEvent.SCHEDULE)
720               continue;
721               actionService.initiateActionObservation(actionNode);
722           }
723         }
724       }
725     } catch (Exception e) {
726       if (LOG.isErrorEnabled()) {
727         LOG.error(">>>> Can not launch action listeners for workspace: "
728           + workspace + " in current repository", e);
729       }
730     }
731   }
732 
733   /**
734    * {@inheritDoc}
735    */
736   public void initiateObservation(Node node) throws Exception {
737     try {
738       Session session = node.getSession();
739       QueryManager queryManager = session.getWorkspace().getQueryManager();
740       String queryStr;
741       Query query = null;
742       try {
743         if (!"/".equals(node.getPath())) {
744           queryStr = "/jcr:root" + node.getPath() + ACTION_QUERY;
745         } else {
746           queryStr = ACTION_QUERY;
747         }
748         query = queryManager.createQuery(queryStr, Query.XPATH);
749       } catch(InvalidQueryException invalid) {
750       // With some special character, XPath will be invalid , try SQL
751         if (!"/".equals(node.getPath())) {
752           queryStr = ACTION_SQL_QUERY + WHERE_OPERATOR + JCR_PATH + LIKE_OPERATOR
753                                         + SINGLE_QUOTE + node.getPath() + "/" + "%" + SINGLE_QUOTE;
754         } else {
755           queryStr = ACTION_SQL_QUERY;
756         }
757         query = queryManager.createQuery(queryStr, Query.SQL);
758       }
759       QueryResult queryResult = query.execute();
760       for (NodeIterator iter = queryResult.getNodes(); iter.hasNext();) {
761         Node actionNode = iter.nextNode();
762         try {
763           String actionType = actionNode.getPrimaryNodeType().getName();
764           for (ComponentPlugin plugin : actionPlugins) {
765             String actionServiceName = plugin.getName();
766             ActionPlugin actionService = getActionPlugin(actionServiceName);
767             if (actionService.isActionTypeSupported(actionType)) {
768               actionService.initiateActionObservation(actionNode);
769             }
770           }
771         } catch (Exception e) {
772           if (LOG.isErrorEnabled()) {
773             LOG.error("Can not launch action listeners named is " + actionNode.getPath(), e);
774           }
775         }
776       }
777     } catch (Exception ex) {
778       if (LOG.isErrorEnabled()) {
779         LOG.error("Can not launch action listeners inside " + node.getPath() + " node.", ex);
780       }
781     }
782   }
783 
784   /**
785    * Parase Array Value to Array String
786    * @param values
787    * @return Array String
788    * @throws Exception
789    */
790   private String[] parseValuesToArray(Value[] values) throws Exception {
791     return parseValuesToList(values).toArray(new String[0]);
792   }
793 
794   /**
795    * Parse Array Value to List String
796    * @param values
797    * @return
798    * @throws Exception
799    */
800   private List<String> parseValuesToList(Value[] values) throws Exception {
801     List<String> lstValues = new ArrayList<String>();
802     for(Value value : values) {
803       lstValues.add(value.getString());
804     }
805     return lstValues;
806   }
807 }