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 java.util.ArrayList;
20  import java.util.Calendar;
21  import java.util.Collection;
22  import java.util.Date;
23  import java.util.GregorianCalendar;
24  import java.util.HashMap;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Set;
29  
30  import javax.jcr.Node;
31  import javax.jcr.Property;
32  import javax.jcr.PropertyType;
33  import javax.jcr.Session;
34  import javax.jcr.Value;
35  import javax.jcr.nodetype.NodeType;
36  import javax.jcr.nodetype.NodeTypeManager;
37  import javax.jcr.nodetype.PropertyDefinition;
38  import javax.jcr.observation.ObservationManager;
39  
40  import org.apache.commons.lang.StringUtils;
41  import org.exoplatform.services.cms.JcrInputProperty;
42  import org.exoplatform.services.cms.actions.ActionPlugin;
43  import org.exoplatform.services.cms.actions.ActionServiceContainer;
44  import org.exoplatform.services.cms.actions.DMSEvent;
45  import org.exoplatform.services.jcr.RepositoryService;
46  import org.exoplatform.services.jcr.core.ManageableRepository;
47  import org.exoplatform.services.log.ExoLogger;
48  import org.exoplatform.services.log.Log;
49  import org.exoplatform.services.scheduler.JobInfo;
50  import org.exoplatform.services.scheduler.JobSchedulerService;
51  import org.exoplatform.services.scheduler.PeriodInfo;
52  import org.exoplatform.services.wcm.utils.WCMCoreUtils;
53  import org.quartz.JobDataMap;
54  
55  abstract public class BaseActionPlugin implements ActionPlugin {
56  
57    final static String JOB_NAME_PREFIX = "activate_" ;
58    final static String PERIOD_JOB = "period" ;
59    final static String CRON_JOB = "cron" ;
60  
61    final static String SCHEDULABLE_INFO_MIXIN = "exo:schedulableInfo" ;
62    final static String SCHEDULED_INITIATOR = "exo:scheduledInitiator" ;
63    final static String JOB_NAME_PROP = "exo:jobName" ;
64    final static String JOB_GROUP_PROP = "exo:jobGroup" ;
65    final static String JOB_DESCRIPTION_PROP = "exo:jobDescription" ;
66    final static String JOB_CLASS_PROP = "exo:jobClass" ;
67    final static String SCHEDULE_TYPE_PROP = "exo:scheduleType" ;
68    final static String START_TIME_PROP = "exo:startTime" ;
69    final static String END_TIME_PROP = "exo:endTime" ;
70    final static String REPEAT_COUNT_PROP = "exo:repeatCount" ;
71    final static String TIME_INTERVAL_PROP = "exo:timeInterval" ;
72    final static String CRON_EXPRESSION_PROP = "exo:cronExpression" ;
73  
74    final static String LIFECYCLE_PHASE_PROP = "exo:lifecyclePhase" ;
75    final static String NODE_NAME_PROP = "exo:name" ;
76    final static String COUNTER_PROP = "exo:counter" ;
77    final static String EXO_ACTIONS = "exo:actions";
78    final static String ACTION_STORAGE= "exo:actionStorage";
79    final static long BUFFER_TIME = 500*1000 ;
80  
81    final static String actionNameVar = "actionName" ;
82    final static String srcRepository = "repository" ;
83    final static String srcWorkspaceVar = "srcWorkspace" ;
84    final static String initiatorVar = "initiator" ;
85    final static String srcPathVar = "srcPath" ;
86    final static String nodePath = "nodePath" ;
87    final static String executableVar = "executable" ;
88  
89    final static String MIX_AFFECTED_NODETYPE  = "mix:affectedNodeTypes";
90    final static String AFFECTED_NODETYPE      = "exo:affectedNodeTypeNames";
91    final static String ALL_DOCUMENT_TYPES     = "ALL_DOCUMENT_TYPES";
92  
93    protected Map<String, ECMEventListener> listeners_ = new HashMap<String, ECMEventListener>();
94    private static final Log LOG  = ExoLogger.getLogger(BaseActionPlugin.class.getName());
95  
96    abstract protected String getWorkspaceName();
97    abstract protected ManageableRepository getRepository() throws Exception;
98    abstract protected String getActionType();
99    abstract protected List getActions();
100   abstract protected ECMEventListener createEventListener(String actionName,
101       String actionExecutable, String repository, String srcWorkspace, String srcPath,
102       Map variables, String actiontype) throws Exception;
103 
104   abstract protected Class createActivationJob() throws Exception ;
105 
106   /**
107    * {@inheritDoc}
108    */
109   public void addAction(String actionType,
110                         String srcWorkspace,
111                         String srcPath,
112                         Map mappings) throws Exception {
113     addAction(actionType, srcWorkspace, srcPath, true, null, null, mappings);
114   }
115 
116   /**
117    * {@inheritDoc}
118    */
119   public void addAction(String actionType,
120                         String srcWorkspace,
121                         String srcPath,
122                         boolean isDeep,
123                         String[] uuid,
124                         String[] nodeTypeNames,
125                         Map mappings) throws Exception {
126     String repoName = WCMCoreUtils.getRepository().getConfiguration().getName();
127     String actionName =
128       (String) ((JcrInputProperty) mappings.get("/node/exo:name")).getValue();
129     mappings.remove("/node/exo:name");
130     Object typeObj =
131       ((JcrInputProperty) mappings.get("/node/exo:lifecyclePhase")).getValue();
132     String[] type = (typeObj instanceof String) ? new String[] { (String)typeObj} :
133       (String[]) typeObj;
134     String actionExecutable = getActionExecutable(actionType);
135     if (DMSEvent.getEventTypes(type) == DMSEvent.READ) return;
136     if ((DMSEvent.getEventTypes(type) & DMSEvent.SCHEDULE) > 0) {
137       scheduleActionActivationJob(srcWorkspace, srcPath, actionName, actionType,
138           actionExecutable, mappings);
139     }
140     if (DMSEvent.getEventTypes(type) == DMSEvent.SCHEDULE)
141       return;
142     Map<String, Object> variables = getExecutionVariables(mappings);
143     ECMEventListener listener = createEventListener(actionName, actionExecutable, repoName,
144         srcWorkspace, srcPath, variables, actionType);
145     Session session = getSystemSession(srcWorkspace);
146     ObservationManager obsManager = session.getWorkspace().getObservationManager();
147     String listenerKey = repoName + ":" + srcPath + "/exo:actions/" + actionName;
148     if (listeners_.containsKey(listenerKey)) {
149       obsManager.removeEventListener(listeners_.get(listenerKey));
150       listeners_.remove(listenerKey);
151     }
152     obsManager.addEventListener(listener, DMSEvent.getEventTypes(type), srcPath, isDeep, uuid,
153         nodeTypeNames, false);
154     session.logout();
155     listeners_.put(listenerKey, listener);
156   }
157 
158   /**
159    * {@inheritDoc}
160    */
161   public void initiateActionObservation(Node storedActionNode) throws Exception {
162     RepositoryService repositoryService = WCMCoreUtils.getService(RepositoryService.class);
163     String repository = repositoryService.getCurrentRepository().getConfiguration().getName();
164     String actionName = storedActionNode.getProperty("exo:name").getString() ;
165     String[] lifecyclePhase = storedActionNode.hasProperty("exo:lifecyclePhase") ? parseValuesToArray(storedActionNode
166         .getProperty("exo:lifecyclePhase").getValues())
167         : null;
168     if (DMSEvent.getEventTypes(lifecyclePhase) == DMSEvent.READ)
169       return;
170     String[] uuid = storedActionNode.hasProperty("exo:uuid") ?
171                      parseValuesToArray(storedActionNode.getProperty("exo:uuid").getValues())
172                      : null;
173     boolean isDeep = storedActionNode.hasProperty("exo:isDeep") ?
174                       storedActionNode.getProperty("exo:isDeep").getBoolean()
175                       : true;
176     String[] nodeTypeNames = storedActionNode.hasProperty("exo:nodeTypeName") ?
177                              parseValuesToArray(storedActionNode.getProperty("exo:nodeTypeName").getValues())
178                              : null;
179     String actionType = storedActionNode.getPrimaryNodeType().getName() ;
180     String srcWorkspace = storedActionNode.getSession().getWorkspace().getName() ;
181     String srcPath = storedActionNode.getParent().getParent().getPath() ;
182     Map<String,Object> variables = new HashMap<String,Object>() ;
183     NodeType nodeType = storedActionNode.getPrimaryNodeType() ;
184     PropertyDefinition[] defs = nodeType.getPropertyDefinitions() ;
185     for(PropertyDefinition propDef:defs) {
186       if(!propDef.isMultiple()) {
187         String key = propDef.getName() ;
188         try{
189           Object value = getPropertyValue(storedActionNode.getProperty(key)) ;
190           variables.put(key,value) ;
191         }catch(Exception e) {
192           variables.put(key,null) ;
193         }
194       }
195     }
196     String actionExecutable = getActionExecutable(actionType);
197     ECMEventListener listener =
198       createEventListener(actionName, actionExecutable, repository, srcWorkspace, srcPath, variables, actionType);
199     Session session = getSystemSession(srcWorkspace);
200     String listenerKey = repository + ":" + srcPath + "/exo:actions/" +actionName;
201     ObservationManager obsManager = session.getWorkspace().getObservationManager();
202     if(listeners_.containsKey(listenerKey)){
203       obsManager.removeEventListener(listeners_.get(listenerKey));
204       listeners_.remove(listenerKey) ;
205     }
206     obsManager.addEventListener(listener, DMSEvent.getEventTypes(lifecyclePhase), srcPath, isDeep, uuid,
207         nodeTypeNames, false);
208     session.logout();
209     listeners_.put(listenerKey, listener);
210   }
211 
212   public void reScheduleActivations(Node storedActionNode) throws Exception {
213     String jobClassName = storedActionNode.getProperty(JOB_CLASS_PROP).getString() ;
214     Class activationJobClass  = null ;
215     try {
216       activationJobClass = Class.forName(jobClassName) ;
217     }catch (Exception e) {
218       if (LOG.isErrorEnabled()) {
219         LOG.error("Unexpected error", e);
220       }
221       return ;
222     }
223     String actionName = storedActionNode.getProperty(NODE_NAME_PROP).getString() ;
224     String actionType = storedActionNode.getPrimaryNodeType().getName() ;
225     String srcWorkspace = storedActionNode.getSession().getWorkspace().getName() ;
226     String scheduleType = storedActionNode.getProperty(SCHEDULE_TYPE_PROP).getString() ;
227     String initiator = storedActionNode.getProperty(SCHEDULED_INITIATOR).getString() ;
228     String srcPath = storedActionNode.getParent().getParent().getPath() ;
229     String jobName = storedActionNode.getProperty(JOB_NAME_PROP).getString() ;
230     String jobGroup = storedActionNode.getProperty(JOB_GROUP_PROP).getString() ;
231     JobSchedulerService schedulerService = WCMCoreUtils.getService(JobSchedulerService.class) ;
232     Map<String,Object> variables = new HashMap<String,Object>() ;
233     NodeType nodeType = storedActionNode.getPrimaryNodeType() ;
234     PropertyDefinition[] defs = nodeType.getPropertyDefinitions() ;
235     for(PropertyDefinition propDef:defs) {
236       if(!propDef.isMultiple()) {
237         String key = propDef.getName() ;
238         try{
239           Object value = getPropertyValue(storedActionNode.getProperty(key)) ;
240           variables.put(key,value) ;
241         }catch(Exception e) {
242           variables.put(key,null) ;
243         }
244       }
245     }
246     String actionExecutable = getActionExecutable(actionType);
247     variables.put(initiatorVar,initiator) ;
248     variables.put(actionNameVar, actionName);
249     variables.put(executableVar,actionExecutable) ;
250     variables.put(srcWorkspaceVar, srcWorkspace);
251     variables.put(srcPathVar, srcPath);
252     JobDataMap jdatamap = new JobDataMap() ;
253     JobInfo jinfo = new JobInfo(jobName,jobGroup,activationJobClass) ;
254     jdatamap.putAll(variables) ;
255     if(CRON_JOB.equals(scheduleType)) {
256       String cronExpression = storedActionNode.getProperty(CRON_EXPRESSION_PROP).getString() ;
257       schedulerService.addCronJob(jinfo,cronExpression,jdatamap) ;
258     }else {
259       Calendar endTime = null ;
260       Date endDate = null ;
261       if(storedActionNode.hasProperty(END_TIME_PROP)) {
262         endTime = storedActionNode.getProperty(END_TIME_PROP).getDate() ;
263       }
264       if(endTime != null) endDate = endTime.getTime() ;
265       long timeInterval = storedActionNode.getProperty(TIME_INTERVAL_PROP).getLong() ;
266       Date startDate = new Date(System.currentTimeMillis()+BUFFER_TIME) ;
267       int repeatCount = (int)storedActionNode.getProperty(REPEAT_COUNT_PROP).getLong() ;
268       int counter = (int)storedActionNode.getProperty(COUNTER_PROP).getLong() ;
269       PeriodInfo pinfo = new PeriodInfo(startDate,endDate,repeatCount-counter,timeInterval) ;
270       schedulerService.addPeriodJob(jinfo,pinfo,jdatamap) ;
271     }
272   }
273 
274   protected Session getSystemSession(String workspace) throws Exception {
275     ManageableRepository jcrRepository = getRepository();
276     return  jcrRepository.getSystemSession(workspace);
277   }
278 
279   public String getActionExecutable(String actionTypeName) throws Exception {
280     NodeTypeManager ntManager = getRepository().getNodeTypeManager();
281     NodeType nt = ntManager.getNodeType(actionTypeName);
282     PropertyDefinition[] propDefs = nt.getDeclaredPropertyDefinitions();
283     for (int i = 0; i < propDefs.length; i++) {
284       PropertyDefinition definition = propDefs[i];
285       if (definition.getName().equals(getExecutableDefinitionName()) &&
286           definition.getDefaultValues() != null) {
287         return definition.getDefaultValues()[0].getString();
288       }
289     }
290     return null;
291   }
292 
293   public boolean isActionTypeSupported(String actionType) {
294     try {
295       NodeTypeManager ntmanager = getRepository().getNodeTypeManager();
296       for (NodeType type:ntmanager.getNodeType(actionType).getSupertypes()) {
297         if (getActionType().equals(type.getName())) {
298           return true;
299         }
300       }
301     } catch (Exception re) {
302       if (LOG.isWarnEnabled()) {
303         LOG.warn(re.getMessage());
304       }
305     }
306     return false ;
307   }
308 
309   public void removeObservation(String repository, String actionPath) throws Exception {
310 
311     ECMEventListener eventListener = listeners_.get(repository + ":" + actionPath);
312     if(eventListener != null){
313       String srcWorkspace = eventListener.getSrcWorkspace();
314       Session session = getSystemSession(srcWorkspace);
315       ObservationManager obsManager = session.getWorkspace().getObservationManager();
316       obsManager.removeEventListener(eventListener);
317       session.logout();
318     }
319     listeners_.remove(repository + ":" + actionPath);
320   }
321 
322   public void removeActivationJob(String jobName,String jobGroup,String jobClass) throws Exception {
323     JobSchedulerService schedulerService = WCMCoreUtils.getService(JobSchedulerService.class) ;
324     Class activationJob = null ;
325     try {
326       activationJob = Class.forName(jobClass) ;
327     }catch (Exception e) {
328       if (LOG.isErrorEnabled()) {
329         LOG.error("Unexpected error", e);
330       }
331     }
332     if(activationJob == null) return  ;
333     JobInfo jinfo = new JobInfo(jobName,jobGroup,activationJob) ;
334     schedulerService.removeJob(jinfo) ;
335   }
336 
337   public boolean isVariable(String variable) throws Exception {
338     NodeTypeManager ntManager = getRepository().getNodeTypeManager();
339     NodeType nt = ntManager.getNodeType(getActionType());
340     PropertyDefinition[] propDefs = nt.getDeclaredPropertyDefinitions();
341     for (int i = 0; i < propDefs.length; i++) {
342       PropertyDefinition definition = propDefs[i];
343       if (definition.getName().equals(variable)) {
344         return false;
345       }
346     }
347     return true;
348   }
349 
350   public Collection<String> getVariableNames(String actionTypeName) throws Exception {
351     Collection<String> variableNames = new ArrayList<String>();
352     NodeTypeManager ntManager = getRepository().getNodeTypeManager() ;
353     NodeType nt = ntManager.getNodeType(actionTypeName);
354     PropertyDefinition[] propDefs = nt.getDeclaredPropertyDefinitions();
355     for (int i = 0; i < propDefs.length; i++) {
356       PropertyDefinition definition = propDefs[i];
357       if (isVariable(definition.getName())) {
358         variableNames.add(definition.getName());
359       }
360     }
361     return variableNames;
362   }
363 
364   protected void importPredefinedActionsInJcr() throws Exception {
365     List actions = getActions();
366     if (actions.isEmpty()) return;
367     Session  session = null;
368     for (Iterator iter = actions.iterator(); iter.hasNext();) {
369       ActionConfig.Action action = (ActionConfig.Action) iter.next();
370       try {
371         session = getSystemSession(action.getSrcWorkspace());
372         importAction(action, session) ;
373         session.logout();
374       } catch (Exception e) {
375         if(session != null) session.logout();
376         if (LOG.isWarnEnabled()) {
377           LOG.warn(" ==> Can not init action '" + action.getName()
378             +"' and workspace '"+action.getSrcWorkspace()+"'") ;
379         }
380       }
381     }
382   }
383 
384   protected void reImportPredefinedActionsInJcr() throws Exception {
385     List actions = getActions();
386     if (actions.isEmpty()) return;
387     Session session = null ;
388     for (Iterator iter = actions.iterator(); iter.hasNext();) {
389       ActionConfig.Action action = (ActionConfig.Action) iter.next();
390       try {
391         session = getSystemSession(action.getSrcWorkspace());
392         importAction(action,session) ;
393       } catch (Exception e) {
394         if(session != null) session.logout();
395         if (LOG.isWarnEnabled()) {
396           LOG.warn(" ==> Can not init action '" + action.getName()
397             + "' in current repository and workspace '"+action.getSrcWorkspace()+"'") ;
398         }
399       }
400     }
401   }
402 
403   @SuppressWarnings("unchecked")
404   private void importAction(ActionConfig.Action action, Session session) throws Exception{
405     Node srcNode = (Node) session.getItem(action.getSrcPath());
406     Node actionNode = null;
407     boolean firstImport = false;
408     String actionsNodeName = EXO_ACTIONS + "/" + action.getName();
409     Node actionsNode = null;
410     if (!srcNode.hasNode(actionsNodeName)) {
411       RepositoryService repositoryService = WCMCoreUtils.getService(RepositoryService.class);
412       ManageableRepository manageRepo = repositoryService.getCurrentRepository();
413     
414       firstImport = true;
415       if (!srcNode.isNodeType("exo:actionable")) {
416         srcNode.addMixin("exo:actionable");
417       }
418       if(srcNode.hasNode(EXO_ACTIONS)) {
419         actionsNode = srcNode.getNode(EXO_ACTIONS);
420       }else {
421         actionsNode = srcNode.addNode(EXO_ACTIONS,ACTION_STORAGE);
422         srcNode.save();
423       }
424       actionNode = actionsNode.addNode(action.getName(), action.getType());
425       actionNode.setProperty("exo:name", action.getName());
426       actionNode.setProperty("exo:description", action.getDescription());
427       actionNode.setProperty("exo:isDeep", action.isDeep());
428       if (action.getUuid() != null)
429         actionNode.setProperty("exo:uuid", action.getUuid().toArray(new String[0]));
430       if (action.getNodeTypeName() != null)
431         actionNode.setProperty("exo:nodeTypeName", action.getNodeTypeName().toArray(new String[0]));
432       if (action.getLifecyclePhase() != null)
433         actionNode.setProperty("exo:lifecyclePhase", action.getLifecyclePhase().toArray(new String[0]));
434       if (action.getRoles() != null) {
435         String[] roles = StringUtils.split(action.getRoles(), ";");
436         actionNode.setProperty("exo:roles", roles);
437       }
438       Iterator mixins = action.getMixins().iterator();
439       NodeType nodeType;
440       String value;
441       while (mixins.hasNext()) {
442         ActionConfig.Mixin mixin = (ActionConfig.Mixin) mixins.next();
443         actionNode.addMixin(mixin.getName());
444         Map<String, String> props = mixin.getParsedProperties();
445         Set keys = props.keySet();
446         nodeType = manageRepo.getNodeTypeManager().getNodeType(mixin.getName());
447         for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
448           String key = (String) iterator.next();
449           for(PropertyDefinition pro : nodeType.getPropertyDefinitions()) {
450             if (pro.getName().equals(key)) {
451               if (pro.isMultiple()) {
452                 value = props.get(key);
453                     if (value != null) {
454                       actionNode.setProperty(key, value.split(","));
455                     }
456                   } else {
457                   actionNode.setProperty(key, props.get(key));
458                 }
459               break;
460             }
461           }
462         }
463       }
464     } else {
465       actionNode = srcNode.getNode(actionsNodeName);
466     }
467 
468     String unparsedVariables = action.getVariables();
469     Map variablesMap = new HashMap();
470     if (unparsedVariables != null && !"".equals(unparsedVariables)) {
471       String[] variables = StringUtils.split(unparsedVariables, ";");
472       for (int i = 0; i < variables.length; i++) {
473         String variable = variables[i];
474         String[] keyValue = StringUtils.split(variable, "=");
475         String variableKey = keyValue[0];
476         String variableValue = keyValue[1];
477         variablesMap.put(variableKey, variableValue);
478         if (firstImport)
479           actionNode.setProperty(variableKey, variableValue);
480       }
481     }
482     if (firstImport)
483       srcNode.save();
484   }
485 
486   private void scheduleActionActivationJob(String srcWorkspace,String srcPath,
487       String actionName,String actionType,String actionExecutable, Map mappings) throws Exception {
488     JobSchedulerService schedulerService = WCMCoreUtils.getService(JobSchedulerService.class) ;
489     ActionServiceContainer actionContainer = WCMCoreUtils.getService(ActionServiceContainer.class) ;
490 
491     Session session = getSystemSession(srcWorkspace) ;
492     Node srcNode = (Node)session.getItem(srcPath) ;
493     Node actionNode = actionContainer.getAction(srcNode,actionName) ;
494     if(!actionNode.isNodeType(SCHEDULABLE_INFO_MIXIN)) {
495       actionNode.addMixin(SCHEDULABLE_INFO_MIXIN) ;
496     }
497     Class activationJob = createActivationJob() ;
498     String jobName = JOB_NAME_PREFIX.concat(actionName) ;
499     String jobGroup = actionType ;
500     String userId = session.getUserID() ;
501     String scheduleType = null, repeatCount = null, timeInterval = null, cronExpress = null ;
502     GregorianCalendar startTime = new GregorianCalendar() ;
503     GregorianCalendar endTime = null ;
504     if(mappings.containsKey("/node/exo:scheduleType")) {
505       scheduleType = (String) ((JcrInputProperty) mappings.get("/node/exo:scheduleType")).getValue();
506       mappings.remove("/node/exo:scheduleType") ;
507     }
508     if(mappings.containsKey("/node/exo:startTime")) {
509       startTime = (GregorianCalendar) ((JcrInputProperty) mappings.get("/node/exo:startTime")).getValue();
510       mappings.remove("/node/exo:startTime") ;
511     }
512     if(mappings.containsKey("/node/exo:endTime")) {
513       endTime = (GregorianCalendar) ((JcrInputProperty) mappings.get("/node/exo:endTime")).getValue();
514       mappings.remove("/node/exo:endTime") ;
515     }
516     if(mappings.containsKey("/node/exo:repeatCount")) {
517       repeatCount = (String) ((JcrInputProperty) mappings.get("/node/exo:repeatCount")).getValue();
518       mappings.remove("/node/exo:repeatCount") ;
519     }
520     if(mappings.containsKey("/node/exo:timeInterval")) {
521       timeInterval = (String) ((JcrInputProperty) mappings.get("/node/exo:timeInterval")).getValue();
522       mappings.remove("/node/exo:timeInterval") ;
523     }
524     if(mappings.containsKey("/node/exo:cronExpression")) {
525       cronExpress = (String) ((JcrInputProperty) mappings.get("/node/exo:cronExpression")).getValue();
526       mappings.remove("/node/exo:cronExpression") ;
527     }
528     actionNode.setProperty(JOB_NAME_PROP,jobName) ;
529     actionNode.setProperty(JOB_GROUP_PROP,jobGroup) ;
530 
531     actionNode.setProperty(JOB_CLASS_PROP,activationJob.getName()) ;
532     actionNode.setProperty(SCHEDULED_INITIATOR,userId) ;
533     actionNode.setProperty(SCHEDULE_TYPE_PROP,scheduleType) ;
534     actionNode.save() ;
535     Map<String,Object> variables = new HashMap<String,Object>();
536     variables.put(initiatorVar, userId);
537     variables.put(actionNameVar, actionName);
538     variables.put(executableVar,actionExecutable) ;
539     variables.put(srcWorkspaceVar, srcWorkspace);
540     variables.put(srcPathVar, srcPath);
541     variables.put(nodePath, srcPath);
542     Map<String,Object> executionVariables = getExecutionVariables(mappings) ;
543     JobDataMap jdatamap = new JobDataMap() ;
544     jdatamap.putAll(variables) ;
545     jdatamap.putAll(executionVariables) ;
546     JobInfo jinfo = new JobInfo(jobName,jobGroup,activationJob) ;
547     if(scheduleType.equals(CRON_JOB)) {
548       actionNode.setProperty(CRON_EXPRESSION_PROP,cronExpress) ;
549       actionNode.save() ;
550       schedulerService.addCronJob(jinfo,cronExpress,jdatamap) ;
551     } else {
552       int repeatNum = Integer.parseInt(repeatCount) ;
553       long period = Long.parseLong(timeInterval) ;
554       actionNode.setProperty(START_TIME_PROP, startTime) ;
555       if(endTime != null ) {
556         actionNode.setProperty(END_TIME_PROP, endTime) ;
557       }
558       actionNode.setProperty(TIME_INTERVAL_PROP,period) ;
559       actionNode.setProperty(REPEAT_COUNT_PROP,repeatNum) ;
560       actionNode.save() ;
561       PeriodInfo pinfo ;
562       if(endTime != null) {
563         pinfo = new PeriodInfo(startTime.getTime(),endTime.getTime(),repeatNum,period) ;
564       } else {
565         pinfo = new PeriodInfo(repeatNum,period) ;
566       }
567       schedulerService.addPeriodJob(jinfo,pinfo,jdatamap) ;
568     }
569     session.save() ;
570     session.logout();
571   }
572   private Map<String,Object> getExecutionVariables(Map mappings) {
573     Map<String,Object> variables = new HashMap<String,Object>();
574     Set keys = mappings.keySet();
575     for (Iterator iter = keys.iterator(); iter.hasNext();) {
576       String key = (String) iter.next();
577       Object value = ((JcrInputProperty) mappings.get(key)).getValue();
578       key = key.substring(key.lastIndexOf("/") + 1);
579       variables.put(key, value);
580     }
581     return variables ;
582   }
583 
584   private Object getPropertyValue(Property property) throws Exception {
585     int propertyType = property.getType() ;
586     switch(propertyType) {
587     case PropertyType.STRING : return property.getValue().getString() ;
588     case PropertyType.BOOLEAN : return property.getValue().getBoolean() ;
589     case PropertyType.DATE : return property.getValue().getDate() ;
590     case PropertyType.DOUBLE : return property.getValue().getDouble() ;
591     case PropertyType.LONG : return property.getValue().getLong() ;
592     case PropertyType.NAME : return property.getValue().getString() ;
593     case PropertyType.UNDEFINED : return property.getValue() ;
594     }
595     return null ;
596   }
597 
598   private String[] parseValuesToArray(Value[] values) throws Exception {
599     String[] valueToString = new String[values.length];
600     int i = 0;
601     for(Value value : values) {
602       valueToString[i++] = value.getString();
603     }
604     return valueToString;
605   }
606 }
607