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.ant;
16
17 import org.figure8.join.core.ParameterDefinition;
18 import org.figure8.join.core.InvalidParameterException;
19 import org.figure8.join.services.scripting.ScriptLauncher;
20 import org.figure8.join.services.scripting.ScriptException;
21 import org.figure8.join.util.LogUtil;
22
23 import org.apache.commons.logging.Log;
24 import org.apache.tools.ant.Project;
25 import org.apache.tools.ant.ProjectHelper;
26 import org.apache.tools.ant.BuildLogger;
27 import org.apache.tools.ant.DefaultLogger;
28 import org.apache.tools.ant.BuildException;
29
30 import java.io.File;
31 import java.io.PrintStream;
32 import java.io.OutputStream;
33 import java.util.List;
34 import java.util.Iterator;
35 import java.util.ArrayList;
36 import java.util.Properties;
37 /**
38 * Extension of {@link ScriptLauncher} dedicated to the Apache Ant build
39 * tool (see http://ant.apache.org). This implementation lets you wrap the
40 * execution of an Ant script within a ScriptLauncher.<br/>
41 * As a {@link org.figure8.join.core.Configurable} implementation, this
42 * launcher defines 2 more configurable parameters that are the build file
43 * target to execute and the log level to apply onto the logger build listener.
44 *
45 * @see org.figure8.join.core.Configurable
46 *
47 * @author <a href="mailto:laurent.broudoux@free.fr">Laurent Broudoux</a>
48 * @version $Revision: 1.2 $
49 */
50 public class AntScriptLauncher extends ScriptLauncher{
51
52
53
54 /** Get a commons logger. */
55 private static final Log log = LogUtil.getLog(AntScriptLauncher.class);
56
57 /** Name of configurable parameter denoting the target to execute in Ant script. */
58 public static final String TARGET_PARAM = "target";
59 /** Name of configurable parameter denoting the log level of script execution. */
60 public static final String LOG_LEVEL_PARAM = "logLevel";
61
62 /** List of {@link ParameterDefinition}s supported by this launcher */
63 protected static List parameters = new ArrayList();
64
65 /** ParameterDefinition representation of parameter denoting the target to execute. */
66 protected static final ParameterDefinition targetParam = new ParameterDefinition(TARGET_PARAM,
67 "The target to execute in Ant script", "default", false);
68 /** ParameterDefinition representation of parameter denoting the log level of execution. */
69 protected static final ParameterDefinition logLevelParam = new ParameterDefinition(LOG_LEVEL_PARAM,
70 "The level of logging for script execution", "info", false);
71
72
73
74
75 /** The target to execute in Ant script. */
76 private String target;
77 /** The level of log during execution. */
78 private String logLevel;
79
80
81
82
83 /** Create a new instance of AntScriptLauncher. */
84 public AntScriptLauncher(){
85 }
86
87 /**
88 * Creates a new instance of AntScriptLauncher with script path
89 * @param scriptPath the path of script to later execute
90 * @throws InvalidParameterException if path cannot be accessed
91 */
92 public AntScriptLauncher(String scriptPath) throws InvalidParameterException{
93 super(scriptPath);
94 }
95
96
97
98
99 /** @return The target to execute in Ant script */
100 public String getTarget(){
101 return target;
102 }
103 /** @param target The target to execute in Ant script */
104 public void setTarget(String target){
105 this.target = target;
106 }
107
108 /** @return The level of log during execution */
109 public String getLogLevel(){
110 return logLevel;
111 }
112 /** @param logLevel The level of log during execution */
113 public void setLogLevel(String logLevel){
114 this.logLevel = logLevel;
115 }
116
117
118
119
120 /**
121 * Run the Ant build file identified by <code>scriptPath</code> inner
122 * field. Properties passed as param are injected into the Ant project
123 * as user properties. Script can directly use them using the ${property.name}
124 * form.
125 * @param properties The runtime properties to inject into execution environment
126 * @throws ScriptException if something wrong occurs during script parsing, evaluation, ...
127 */
128 public void runScript(Properties properties) throws ScriptException{
129
130
131 Project project = new Project();
132 project.setCoreLoader(Thread.currentThread().getContextClassLoader());
133
134 File buildFile = getScript();
135 Throwable exception = null;
136 try{
137
138 ProjectHelper.configureProject(project, buildFile);
139 project.init();
140
141
142 Iterator keys = properties.keySet().iterator();
143 while (keys != null && keys.hasNext()){
144 String key = (String)keys.next();
145 String value = properties.getProperty(key);
146 if (log.isDebugEnabled())
147 log.debug("Adding property '" + key + "' (" + value + ") as project property");
148 project.setUserProperty(key, value);
149 }
150
151
152 if (getLogOutputStream() != null)
153 addBuildListener(project, getLogOutputStream());
154
155
156 if (target == null || target.trim().length() == 0)
157 target = project.getDefaultTarget();
158
159
160 project.fireBuildStarted();
161 project.executeTarget(target);
162 }
163 catch (BuildException be){
164 exception = be;
165
166 log.error("BuildException during initialization or evaluation of script '" + getScriptPath() + "'");
167 log.error("Here's the detailed exception message: " + be.getMessage() + " @ " + be.getLocation());
168 throw new ScriptException("BuildException: " + be.getMessage() + " @ " + be.getLocation());
169 }
170 finally{
171
172 project.fireBuildFinished(exception);
173
174 if (getLogOutputStream() != null){
175 try {getLogOutputStream().close();}
176 catch (Exception e){
177 log.warn("Exception while closing the log output stream: " + e.getMessage());
178 }
179 }
180 }
181 }
182
183
184
185
186 /**
187 * Get this object parameters definitions as a list
188 * @return A list of {@code ParameterDefinition} objects
189 */
190 public List getParameterDefinitionsAsList(){
191
192 if (parameters.isEmpty()){
193 parameters.addAll(super.getParameterDefinitionsAsList());
194 parameters.add(targetParam);
195 parameters.add(logLevelParam);
196 }
197 return parameters;
198 }
199
200 /**
201 * Set the value of a parameter using its nama
202 * @param parameterName The name of parameter so set value for
203 * @param parameterValue The value of the paramater
204 * @throws org.figure8.join.core.InvalidParameterException if this parameter is not supported by this object
205 */
206 public void setParameter(String parameterName, String parameterValue) throws InvalidParameterException{
207 try{
208
209 super.setParameter(parameterName, parameterValue);
210 }
211 catch (InvalidParameterException ipe){
212
213 if (TARGET_PARAM.equals(parameterName))
214 setTarget(parameterValue);
215 else if (LOG_LEVEL_PARAM.equals(parameterName))
216 setLogLevel(parameterValue);
217 else{
218 log.warn("The parameter '" + parameterName + "' is not supported by AntScriptLauncher");
219 throw new InvalidParameterException("The parameter '" + parameterName + "' is not supported by AntScriptLauncher");
220 }
221 }
222 }
223
224
225
226
227 /**
228 * Add a build listener to the specified project. This build listener
229 * is the Ant default logger which output stream points to specified file.
230 * @param project The project to add listeners to. Must not be null.
231 * @param os The output stream that stores log messages.
232 */
233 private void addBuildListener(Project project, OutputStream os){
234
235 PrintStream out = new PrintStream(os);
236
237 int outputLevel = Project.MSG_INFO;
238 if ("debug".equalsIgnoreCase(logLevel))
239 outputLevel = Project.MSG_DEBUG;
240 else if ("info".equalsIgnoreCase(logLevel))
241 outputLevel = Project.MSG_INFO;
242 else if ("quiet".equalsIgnoreCase(logLevel))
243 outputLevel = Project.MSG_WARN;
244 else if ("verbose".equalsIgnoreCase(logLevel))
245 outputLevel = Project.MSG_VERBOSE;
246
247
248 BuildLogger logger = new DefaultLogger();
249 logger.setMessageOutputLevel(outputLevel);
250 logger.setOutputPrintStream(out);
251 logger.setErrorPrintStream(out);
252 logger.setEmacsMode(false);
253
254 project.addBuildListener(logger);
255 }
256 }