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.Configurable;
18 import org.figure8.join.core.EntityObject;
19 import org.figure8.join.core.ParameterDefinition;
20 import org.figure8.join.core.InvalidParameterException;
21 import org.figure8.join.core.messaging.JMSConsumerBean;
22 import org.figure8.join.services.properties.PropertiesExtractor;
23 import org.figure8.join.util.LogUtil;
24
25 import org.apache.commons.logging.Log;
26
27 import javax.jms.Message;
28 import javax.jms.ObjectMessage;
29
30 import java.io.File;
31 import java.io.FileOutputStream;
32 import java.io.FileNotFoundException;
33 import java.util.Date;
34 import java.util.List;
35 import java.util.ArrayList;
36 import java.util.Properties;
37 /**
38 * This is a base class for JMS consumers that wants to launch scripts
39 * when a new message arrive. It acts as an adapter between the JMS world
40 * and the {@link ScriptLauncher} facilities.
41 * <br/>
42 * This class is a JMSConsumerBean that is {@link Configurable} : it defines
43 * an optional parameter that should be a {@link PropertiesExtractor} impl.
44 * This extractor help tha transition from a JMS view (that is object message
45 * based) to a general script view (that is properties and arguments based).
46 * <br/>
47 * Extensions of this class should specifiy which ScriptLauncher implementation
48 * to use when running scripts.
49 *
50 * @see org.figure8.join.core.Configurable
51 * @see org.figure8.join.core.messaging.JMSConsumerBean
52 * @see org.figure8.join.services.properties.PropertiesExtractor
53 *
54 * @author <a href="mailto:laurent.broudoux@free.fr">Laurent Broudoux</a>
55 * @version $Revision: 1.2 $
56 */
57 public abstract class ScriptLauncherJMSAdapter extends ScriptLauncherAdapterSupport implements JMSConsumerBean{
58
59
60
61 /** Get a commons logger. */
62 private static final Log log = LogUtil.getLog(ScriptLauncherJMSAdapter.class);
63
64 /** Name of configurable parameter denoting the propertiesExtractor to use for getting props. */
65 public static final String EXTRACTOR_PARAM = "propertiesExtractor";
66
67 /** List of {@link ParameterDefinition}s supported by this adapter */
68 protected static List parameters = new ArrayList();
69
70 /** ParameterDefinition representation of parameter denoting the propertiesExtractor to use. */
71 protected static final ParameterDefinition extractionParam = new ParameterDefinition(EXTRACTOR_PARAM,
72 "The PropertiesExtractor implementation to use", "org.figure8.join.services.properties.DefaultPropertiesExtractor", true);
73
74
75
76
77 /** The class name properties extractor implementation to use. */
78 private String extractorClass;
79 /** The PropertiesExtractor implementation to use. */
80 private PropertiesExtractor extractor = null;
81
82
83
84
85 /**
86 * Specify the class of PropertiesExtractor implementation to use
87 * @param extractorClass The FQN of Java class representing PropertiesExtractor impl
88 * @throws InvalidParameterException if <b>extractorClass</b> is not found or does
89 * not implement the PropertiesExtractor interface
90 */
91 public void setPropertiesExtractorClass(String extractorClass) throws InvalidParameterException{
92 this.extractorClass = extractorClass;
93
94 instantiatePropertiesExtractor();
95 }
96
97
98
99
100 /**
101 * This method is executed on message delivery. This implementation only
102 * process message of type ObjectMessage. The process is the following :<br/>
103 * first: retrieve object from message and eventually extract its properties,<br/>
104 * @param message
105 */
106 public void onMessage(Message message){
107 if (log.isInfoEnabled())
108 log.info("Message received by ScriptLauncherJMSAdapter '" + name + "'");
109 File logFile = null;
110 ScriptLogInfo logInfo = null;
111
112
113 if (message instanceof ObjectMessage){
114
115 Object obj = null;
116 try {obj = ((ObjectMessage)message).getObject();}
117 catch (Exception e){
118 log.fatal("Exception while extracting object from JMSMessage into '" + getName() + "'");
119 log.fatal("Here's the detailed message: " + e.getMessage());
120 return;
121 }
122
123 Properties props = new Properties();
124 if (extractor != null){
125 try {props.putAll(extractor.extract(obj));}
126 catch (InvalidParameterException ipe){
127 log.error("Exception while extracting properties from object into '" + getName() + "'");
128 log.error("Here's the detailed message: " + ipe.getMessage());
129 }
130 if (log.isDebugEnabled())
131 log.debug("Launching script with properties: " + props);
132 }
133
134 if (obj instanceof EntityObject){
135
136 logFile = createNewLogFile();
137 logInfo = new ScriptLogInfo((EntityObject)obj, logFile.getPath().replace('\\', '/'),
138 name, "JMSAdapter", getScriptLauncher().getScriptPath());
139 }
140
141 try{
142
143 if (log.isInfoEnabled())
144 log.info("Launching the script of '" + name + "' JMS adapter. Start time is: " + new Date());
145
146 getScriptLauncher().setLogOutputStream(new FileOutputStream(logFile));
147 getScriptLauncher().runScript(props);
148
149 if (logInfo != null)
150 logInfo.setExceptionMsg("Execution is properly terminated.");
151 }
152 catch (ScriptException se){
153
154 log.error("ScriptException when running " + getScriptLauncher().getScriptPath() + ": " + se.getMessage());
155 if (logInfo != null)
156 logInfo.setExceptionMsg(se.getMessage());
157 }
158 catch (FileNotFoundException fnfe){
159
160 log.error("FileNotFoundException while getting OS on " + logFile.getPath() + ": " + fnfe.getMessage());
161 if (logInfo != null)
162 logInfo.setExceptionMsg(fnfe.getMessage());
163 }
164 finally{
165
166 if (log.isInfoEnabled())
167 log.info("Script of '" + name + "' JMS adapter has end. Stop time is: " + new Date());
168 }
169
170 if (logInfo != null){
171 boolean done = saveLogInfoIfAvailable(logInfo);
172 }
173 }
174 return;
175 }
176
177 /**
178 * Implement this method to stop current process and free resources.
179 * This method should not throw exceptions.
180 */
181 public void stop(){
182 log.info("Stopping the ScriptLauncherJMSAdapter named '" + name + "'...");
183 }
184
185
186
187
188 /**
189 * Get this object parameters definitions as a list
190 * @return A list of {@code ParameterDefinition} objects
191 */
192 public List getParameterDefinitionsAsList(){
193
194 if (parameters.isEmpty()){
195 parameters.addAll(getScriptLauncher().getParameterDefinitionsAsList());
196 parameters.add(extractionParam);
197 }
198 return parameters;
199 }
200
201 /**
202 * Set the value of a parameter using its name
203 * @param parameterName The name of parameter so set value for
204 * @param parameterValue The value of the paramater
205 * @throws InvalidParameterException if this parameter is not supported by this object
206 */
207 public void setParameter(String parameterName, String parameterValue) throws InvalidParameterException{
208 try{
209
210 super.setParameter(parameterName, parameterValue);
211 }
212 catch (InvalidParameterException ipe){
213
214 if (EXTRACTOR_PARAM.equals(parameterName))
215 setPropertiesExtractorClass(parameterValue);
216 else{
217 log.error("The parameter '" + parameterName + "' is not supported by ScriptLauncherJMSAdapter");
218 throw new InvalidParameterException("The parameter '" + parameterName + "' is not supported by ScriptLauncherJMSAdapter");
219 }
220 }
221 }
222
223
224
225
226 /**
227 * Try to instantiate the <code>PropertieExtractor</code> associated with this adapter
228 * @throws InvalidParameterException if the <b>extractorClass</b> inner field is not valid
229 */
230 private void instantiatePropertiesExtractor() throws InvalidParameterException{
231 if (extractorClass != null && extractor == null){
232 try{
233
234 Class clazz = Thread.currentThread().getContextClassLoader().loadClass(extractorClass);
235 extractor = (PropertiesExtractor)clazz.newInstance();
236 }
237 catch (Exception e){
238
239 log.error("Exception while trying to instantiate extractor for ScriptLauncherJMSAdapter '" + name + "'");
240 log.error("Here's the exception message : " + e.getMessage());
241 throw new InvalidParameterException("'" + extractorClass +
242 "' cannot be found or does not implement PropertiesExtractor", e);
243 }
244 }
245 }
246 }