View Javadoc

1   /**
2    * Copyright 2005-2006 the original author or authors.
3    *
4    * Licensed under the Gnu General Pubic License, Version 2.0 (the
5    * "License"); you may not use this file except in compliance with
6    * the License. You may obtain a copy of the License at
7    *
8    *      http://www.opensource.org/licenses/gpl-license.php
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13   * See the Gnu General Public License for more details.
14   */
15  package org.figure8.join.services.scripting;
16  
17  import org.figure8.join.core.EntityObject;
18  import org.figure8.join.core.InvalidParameterException;
19  import org.figure8.join.services.scheduling.QuartzCronManager;
20  import org.figure8.join.services.scheduling.QuartzCronParameterInfo;
21  import org.figure8.join.util.LogUtil;
22  
23  import org.apache.commons.logging.Log;
24  import org.quartz.Job;
25  import org.quartz.JobExecutionContext;
26  import org.quartz.JobExecutionException;
27  
28  import java.io.File;
29  import java.io.FileOutputStream;
30  import java.io.FileNotFoundException;
31  import java.util.Date;
32  import java.util.Iterator;
33  import java.util.Properties;
34  /**
35   * This is a base class for Quartz jobs that wants to launch script when
36   * the time scheduled with cron arrive. It acts as an adapter between the
37   * scheduled batch world and the {@link ScriptLauncher} facilities.
38   * <br/>
39   * This class is a Quartz {@link Job} that is {@link org.figure8.join.core.Configurable}.
40   * <br/>
41   *
42   * @see org.figure8.join.core.Configurable
43   * 
44   * @author <a href="mailto:jerome.evrard@gmail.com">Jerome Evrard</a>
45   * @version $Revision: 1.2 $
46   */
47  public abstract class ScriptLauncherQuartzAdapter extends ScriptLauncherAdapterSupport implements Job{
48  
49     // Static -------------------------------------------------------------------
50     
51     /** Get a commons logger. */
52     private static final Log log = LogUtil.getLog(ScriptLauncherQuartzAdapter.class);
53  
54  
55     // Implementation of Job ----------------------------------------------------
56     
57     /**
58      * This method is executed when scheduled time is reached.
59      * @param context The execution context of the job (contains job's user parameters)
60      */
61     public void execute(JobExecutionContext context) throws JobExecutionException{
62        // Name has not been set, so correct before creating log.
63        setName(context.getJobDetail().getName());
64        ScriptLogInfo logInfo = null;
65        File logFile = createNewLogFile();
66  
67        // First, check if the cron entity is present in context & create the script log.
68        Object entity = getParameterFromContext(QuartzCronManager.JOB_ENTITY, context);
69        if (entity != null && entity instanceof EntityObject){
70           log.debug("An Entity is present into execution context: " + entity);
71           logInfo = new ScriptLogInfo((EntityObject)entity, logFile.getPath().replace('\\', '/'),
72                   context.getJobDetail().getName(), "QuartzAdapter", "Unknown file path");
73        }
74        else{
75           logInfo = new ScriptLogInfo(logFile.getPath().replace('\\', '/'),
76                   context.getJobDetail().getName(), "QuartzAdapter", "Unknown file path");
77        }
78        // Configure the job using parameters from context.
79        try {configureJobFromContext(context);}
80        catch (InvalidParameterException ipe){
81           log.fatal("Exception while configuring the Job using parameters present into JobExecutionContext");
82           log.fatal("Here's the detailed message: " + ipe.getMessage());
83           // Save the log info if it exists and if context is available.
84           if (logInfo != null){
85              logInfo.setExceptionMsg(ipe.getMessage());
86              saveLogInfoIfAvailable(logInfo);
87           }
88           return;
89        }
90        // Complete the script log info instance with script path.
91        if (logInfo != null){
92           logInfo.setScriptFile(getScriptLauncher().getScriptPath());
93        }
94  
95        // Transform the JobDataMap into properties
96        Properties jobProperties = new Properties(); 
97        Iterator dataKeys = context.getJobDetail().getJobDataMap().keySet().iterator();
98        while (dataKeys.hasNext()){
99           // Get the next data map key and value.
100          Object key = dataKeys.next();
101          Object value = getParameterFromContext(key.toString(), context);
102          if (value != null && value instanceof QuartzCronParameterInfo){
103             QuartzCronParameterInfo param = (QuartzCronParameterInfo)value;
104             if (!param.isJobParameter())
105                jobProperties.put(key.toString(), param.getValue());
106          }
107          else jobProperties.put(key.toString(), value);
108       }
109 
110       try{
111          // Launching script (log start time).
112          if (log.isInfoEnabled())
113             log.info("Launching the script of '" + name + "' Quartz adapter. Start time is: " + new Date());
114          // Set the log outputstream and run the job script !
115          getScriptLauncher().setLogOutputStream(new FileOutputStream(logFile));
116          getScriptLauncher().runScript(jobProperties);
117          // Log the execution result.
118          context.setResult(new Integer(0));
119          logInfo.setExceptionMsg("Execution is properly terminated.");
120       }
121       catch (ScriptException se){
122          // Store and log the exception
123          context.setResult(new Integer(1));
124          log.error("ScriptException when running " + getScriptLauncher().getScriptPath() + ": " + se.getMessage());
125          // Put exception message into log info instance.
126          if (logInfo != null)
127             logInfo.setExceptionMsg(se.getMessage());
128       }
129       catch (FileNotFoundException fnfe){
130          // Store and log the exception.
131          log.error("FileNotFoundException while getting OS on " + logFile.getPath() + ": " + fnfe.getMessage());
132          context.setResult(new Integer(1));
133          // Put exception message into log info instance.
134          if (logInfo != null)
135             logInfo.setExceptionMsg(fnfe.getMessage());
136       }
137       finally{
138          // Log end date.
139          if (log.isInfoEnabled())
140             log.info("Script of '" + name + "' Quartz adapter has end. Stop time is: " + new Date());
141       }
142 
143       // Save the log info instance
144       if (logInfo != null){
145          boolean done = saveLogInfoIfAvailable(logInfo);
146       }
147       return;
148    }
149 
150 
151    // Protected ----------------------------------------------------------------
152 
153    /**
154     * This is a convenient method for retrieving a cron parameter value from context.
155     * @param key The key of cron parameter to retrieve.
156     * @param context The job context to retrieve parameter from
157     * @return An object representing Quartz Cron parameter value
158     */
159    protected Object getParameterFromContext(String key, JobExecutionContext context){
160       return context.getJobDetail().getJobDataMap().get(key);
161    }
162 
163    /**
164     * Configure this job instance using the {@link QuartzCronParameterInfo} that
165     * may be present into the execution context. This may be necessary because when
166     * launched by a scheduler, job instance is not directly available so configuration
167     * parameters may be passed using the job details data map.
168     * @param context
169     * @throws InvalidParameterException
170     */
171    protected void configureJobFromContext(JobExecutionContext context) throws InvalidParameterException{
172       Iterator values = context.getJobDetail().getJobDataMap().values().iterator();
173       while (values != null && values.hasNext()){
174          Object value = values.next();
175          if (value instanceof QuartzCronParameterInfo){
176             QuartzCronParameterInfo paramInfo = (QuartzCronParameterInfo)value;
177             if (paramInfo.isJobParameter()){
178                // Output some debug message before configuring job with this parameter.
179                if (log.isDebugEnabled())
180                   log.debug("Configuring the ScriptLauncher with: " + paramInfo.getName() + "[" + paramInfo.getValue() + "]");
181                setParameter(paramInfo.getName(), paramInfo.getValue());
182             }
183          }
184       }
185    }
186 }