KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > cruisecontrol > builders > NantBuilder


1 /*******************************************************************************
2  * CruiseControl, a Continuous Integration Toolkit Copyright (c) 2001,
3  * ThoughtWorks, Inc. 651 W Washington Ave. Suite 600 Chicago, IL 60661 USA All
4  * rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met: +
8  * Redistributions of source code must retain the above copyright notice, this
9  * list of conditions and the following disclaimer. + Redistributions in binary
10  * form must reproduce the above copyright notice, this list of conditions and
11  * the following disclaimer in the documentation and/or other materials provided
12  * with the distribution. + Neither the name of ThoughtWorks, Inc.,
13  * CruiseControl, nor the names of its contributors may be used to endorse or
14  * promote products derived from this software without specific prior written
15  * permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  ******************************************************************************/

28
29 package net.sourceforge.cruisecontrol.builders;
30
31 import java.io.File JavaDoc;
32 import java.io.FileInputStream JavaDoc;
33 import java.io.FileOutputStream JavaDoc;
34 import java.io.IOException JavaDoc;
35 import java.util.ArrayList JavaDoc;
36 import java.util.List JavaDoc;
37 import java.util.Map JavaDoc;
38
39 import net.sourceforge.cruisecontrol.Builder;
40 import net.sourceforge.cruisecontrol.CruiseControlException;
41 import net.sourceforge.cruisecontrol.util.EmptyElementFilter;
42 import net.sourceforge.cruisecontrol.util.ValidationHelper;
43 import net.sourceforge.cruisecontrol.util.DateUtil;
44
45 import org.apache.log4j.Logger;
46 import org.jdom.Attribute;
47 import org.jdom.CDATA;
48 import org.jdom.Element;
49 import org.jdom.filter.ContentFilter;
50 import org.jdom.input.SAXBuilder;
51 import org.xml.sax.XMLFilter JavaDoc;
52
53 public class NantBuilder extends Builder {
54
55     protected static final String JavaDoc DEFAULT_LOGGER = "NAnt.Core.XmlLogger";
56     private static final Logger LOG = Logger.getLogger(NantBuilder.class);
57     private String JavaDoc nantWorkingDir = null;
58     private String JavaDoc buildFile = "default.build";
59     private String JavaDoc target = "";
60     private String JavaDoc tempFileName = "log.xml";
61     private boolean useLogger;
62     private List JavaDoc properties = new ArrayList JavaDoc();
63     private boolean useDebug = false;
64     private boolean useQuiet = false;
65     private String JavaDoc loggerClassName = DEFAULT_LOGGER;
66     private File JavaDoc saveLogDir = null;
67     private String JavaDoc targetFramework = null;
68     private long timeout = ScriptRunner.NO_TIMEOUT;
69
70     public void validate() throws CruiseControlException {
71         super.validate();
72
73         ValidationHelper.assertIsSet(buildFile, "buildFile", this.getClass());
74         ValidationHelper.assertIsSet(target, "target", this.getClass());
75
76         ValidationHelper.assertFalse(useDebug && useQuiet, "'useDebug' and 'useQuiet' can't be used together");
77
78         if (saveLogDir != null) {
79             ValidationHelper.assertTrue(saveLogDir.isDirectory(), "'saveLogDir' must exist and be a directory");
80         }
81     }
82
83     /**
84      * Build and return the results via xml. Debug status can be determined from
85      * log4j category once we get all the logging in place.
86      */

87     public Element build(Map JavaDoc buildProperties) throws CruiseControlException {
88
89         File JavaDoc workingDir = nantWorkingDir != null ? new File JavaDoc(nantWorkingDir) : null;
90         NantScript script = getNantScript();
91         script.setBuildFile(buildFile);
92         script.setBuildProperties(buildProperties);
93         script.setNantProperties(properties);
94         script.setLoggerClassName(loggerClassName);
95         script.setTarget(target);
96         script.setTargetFramework(targetFramework);
97         script.setTempFileName(tempFileName);
98         script.setUseDebug(useDebug);
99         // script.setUseDebug(useVerbose);
100
script.setUseLogger(useLogger);
101         script.setUseQuiet(useQuiet);
102         
103         long startTime = System.currentTimeMillis();
104
105         ScriptRunner scriptRunner = new ScriptRunner();
106         boolean scriptCompleted = scriptRunner.runScript(workingDir, script, timeout);
107         long endTime = System.currentTimeMillis();
108
109         File JavaDoc logFile = new File JavaDoc(nantWorkingDir, tempFileName);
110         Element buildLogElement;
111         if (!scriptCompleted) {
112             LOG.warn("Build timeout timer of " + timeout + " seconds has expired");
113             buildLogElement = new Element("build");
114             buildLogElement.setAttribute("error", "build timeout");
115         } else {
116             //read in log file as element, return it
117
buildLogElement = getNantLogAsElement(logFile);
118             saveNantLog(logFile);
119             logFile.delete();
120         }
121         final Element element = translateNantErrorElements(buildLogElement);
122         element.setAttribute("time", DateUtil.getDurationAsString((endTime - startTime)));
123         return element;
124     }
125
126     public Element buildWithTarget(Map JavaDoc properties, String JavaDoc buildTarget) throws CruiseControlException {
127         String JavaDoc origTarget = target;
128         try {
129             target = buildTarget;
130             return build(properties);
131         } finally {
132             target = origTarget;
133         }
134     }
135
136     // factory method for mock...
137
protected NantScript getNantScript() {
138         return new NantScript();
139     }
140
141     /**
142      * Set the location to which the NAnt log will be saved before Cruise
143      * Control merges the file into its log.
144      *
145      * @param dir
146      * the absolute path to the directory where the NAnt log will be
147      * saved or relative path to where you started CruiseControl
148      */

149     public void setSaveLogDir(String JavaDoc dir) {
150         saveLogDir = null;
151
152         if (dir != null && !dir.trim().equals("")) {
153             saveLogDir = new File JavaDoc(dir.trim());
154         }
155     }
156
157     /**
158      * Set the working directory where NAnt will be invoked. This parameter gets
159      * set in the XML file via the nantWorkingDir attribute. The directory can
160      * be relative (to the cruisecontrol current working directory) or absolute.
161      *
162      * @param dir
163      * the directory to make the current working directory.
164      */

165     public void setNantWorkingDir(String JavaDoc dir) {
166         nantWorkingDir = dir;
167     }
168
169     /**
170      * Set the name of the temporary file used to capture output.
171      *
172      * @param tempFileName
173      */

174     public void setTempFile(String JavaDoc tempFileName) {
175         this.tempFileName = tempFileName;
176     }
177
178     /**
179      * Set the Ant target(s) to invoke.
180      *
181      * @param target
182      * the target(s) name.
183      */

184     public void setTarget(String JavaDoc target) {
185         this.target = target;
186     }
187
188     /**
189      * Sets the name of the build file that NAnt will use. The NAnt default is
190      * default.build, use this to override it.
191      *
192      * @param buildFile
193      * the name of the build file.
194      */

195     public void setBuildFile(String JavaDoc buildFile) {
196         this.buildFile = buildFile;
197     }
198
199     /**
200      * Sets whether NAnt will use the custom loggers.
201      *
202      * @param useLogger
203      */

204     public void setUseLogger(boolean useLogger) {
205         this.useLogger = useLogger;
206     }
207
208     void saveNantLog(File JavaDoc logFile) {
209         if (saveLogDir == null) {
210             return;
211         }
212
213         try {
214             File JavaDoc newNantLogFile = new File JavaDoc(saveLogDir, tempFileName);
215             newNantLogFile.createNewFile();
216
217             FileInputStream JavaDoc in = new FileInputStream JavaDoc(logFile);
218             FileOutputStream JavaDoc out = new FileOutputStream JavaDoc(newNantLogFile);
219
220             byte[] buf = new byte[1024];
221             int len;
222             while ((len = in.read(buf)) > 0) {
223                 out.write(buf, 0, len);
224             }
225             in.close();
226             out.close();
227         } catch (IOException JavaDoc ioe) {
228             LOG.error(ioe);
229             LOG.error("Unable to create file: " + new File JavaDoc(saveLogDir, tempFileName));
230         }
231     }
232
233     public Property createProperty() {
234         Property property = new Property();
235         properties.add(property);
236         return property;
237     }
238
239     protected Element getNantLogAsElement(File JavaDoc file) throws CruiseControlException {
240         if (!file.exists()) {
241             throw new CruiseControlException("NAnt logfile " + file.getAbsolutePath() + " does not exist.");
242         }
243         try {
244             SAXBuilder builder = new SAXBuilder("org.apache.xerces.parsers.SAXParser");
245
246             // get rid of empty <task>- and <message>-elements created by Ant's
247
// XmlLogger
248
XMLFilter JavaDoc emptyTaskFilter = new EmptyElementFilter("task");
249             XMLFilter JavaDoc emptyMessageFilter = new EmptyElementFilter("message");
250             emptyMessageFilter.setParent(emptyTaskFilter);
251             builder.setXMLFilter(emptyMessageFilter);
252             return builder.build(file).getRootElement();
253         } catch (Exception JavaDoc ee) {
254             if (ee instanceof CruiseControlException) {
255                 throw (CruiseControlException) ee;
256             }
257             File JavaDoc saveFile = new File JavaDoc(file.getParentFile(), System.currentTimeMillis() + file.getName());
258             file.renameTo(saveFile);
259             throw new CruiseControlException("Error reading : " + file.getAbsolutePath() + ". Saved as : "
260                     + saveFile.getAbsolutePath(), ee);
261         }
262     }
263
264     public void setUseDebug(boolean debug) {
265         useDebug = debug;
266     }
267
268     public void setUseQuiet(boolean quiet) {
269         useQuiet = quiet;
270     }
271
272     public String JavaDoc getLoggerClassName() {
273         return loggerClassName;
274     }
275
276     public void setLoggerClassName(String JavaDoc logger) {
277         loggerClassName = logger;
278     }
279
280     public void setTargetFramework(String JavaDoc framework) {
281         this.targetFramework = framework;
282     }
283
284     protected Element translateNantErrorElements(Element buildLogElement) throws CruiseControlException {
285         buildLogElement.setName("build");
286         Element failure = buildLogElement.getChild("failure");
287         if (failure != null) {
288             Element buildError = failure.getChild("builderror");
289             if (buildError == null) {
290                  throw new CruiseControlException("Expected a builderror element under build/failure");
291              }
292             Element message = buildError.getChild("message");
293             if (message == null) {
294                 throw new CruiseControlException("Expected a message element under build/failure/builderror");
295             }
296             List JavaDoc matches = message.getContent(new ContentFilter(ContentFilter.CDATA));
297             if (matches.size() == 0) {
298                 throw new CruiseControlException("Expected CDATA content in build/failure/builderror/message/element");
299             }
300             String JavaDoc errorMessage = ((CDATA) matches.get(0)).getText();
301             buildLogElement.setAttribute(new Attribute("error", errorMessage));
302         }
303         return buildLogElement;
304     }
305     /**
306      * @param timeout The timeout to set.
307      */

308     public void setTimeout(long timeout) {
309         this.timeout = timeout;
310     }
311 }
312
Popular Tags