KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > cruisecontrol > Log


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

37 package net.sourceforge.cruisecontrol;
38
39 import net.sourceforge.cruisecontrol.util.DateUtil;
40 import net.sourceforge.cruisecontrol.util.XMLLogHelper;
41 import org.jdom.Content;
42 import org.jdom.Document;
43 import org.jdom.Element;
44 import org.jdom.output.Format;
45 import org.jdom.output.XMLOutputter;
46
47 import java.io.BufferedOutputStream JavaDoc;
48 import java.io.File JavaDoc;
49 import java.io.FileOutputStream JavaDoc;
50 import java.io.IOException JavaDoc;
51 import java.io.OutputStream JavaDoc;
52 import java.util.ArrayList JavaDoc;
53 import java.util.Date JavaDoc;
54 import java.util.Iterator JavaDoc;
55 import java.util.List JavaDoc;
56 import java.text.SimpleDateFormat JavaDoc;
57 import java.text.ParseException JavaDoc;
58
59
60 /**
61  * Handles the Log element, and subelements, of the CruiseControl configuration
62  * file. Also represents the Build Log used by the CruiseControl build process.
63  */

64 public class Log {
65     private static final org.apache.log4j.Logger LOG4J =
66             org.apache.log4j.Logger.getLogger(Log.class);
67
68     public static final int BEFORE_LENGTH = "logYYYYMMDDhhmmssL".length();
69     private static final int AFTER_LENGTH = ".xml".length();
70    
71     private transient String JavaDoc logDir;
72     private transient String JavaDoc logXmlEncoding;
73     private transient File JavaDoc lastLogFile;
74     private transient Element buildLog;
75     private transient List JavaDoc loggers = new ArrayList JavaDoc();
76     private transient List JavaDoc manipulators = new ArrayList JavaDoc();
77     private transient String JavaDoc projectName;
78
79     /**
80      * Log instances created this way must have their projectName set.
81      */

82     public Log() {
83         reset();
84     }
85
86     /**
87      * Although this property is required, it is implicitly defined by the
88      * project and doesn't map to a config file attribute.
89      * @throws NullPointerException is projectName is null
90      */

91     void setProjectName(String JavaDoc projectName) {
92         if (projectName == null) {
93             throw new NullPointerException JavaDoc("null projectName.");
94         }
95         this.projectName = projectName;
96         if (logDir == null) {
97             logDir = "logs" + File.separatorChar + projectName;
98         }
99     }
100
101     /**
102      * Validate the log. Also creates the log directory if it doesn't exist.
103      * @throws IllegalStateException if projectName wasn't set
104      */

105     public void validate() throws CruiseControlException {
106         if (projectName == null) {
107             // not a real validation. Not using ValidationHelper
108
throw new IllegalStateException JavaDoc("projectName unset.");
109         }
110         if (logDir != null) {
111             checkLogDirectory(logDir);
112         }
113
114         for (Iterator JavaDoc i = loggers.iterator(); i.hasNext();) {
115             BuildLogger logger = (BuildLogger) i.next();
116             logger.validate();
117         }
118         
119         for (Iterator JavaDoc i = manipulators.iterator(); i.hasNext();) {
120             Manipulator manipulator = (Manipulator) i.next();
121             manipulator.validate();
122         }
123     }
124
125     /**
126      * Adds a BuildLogger that will be called to manipulate the project log
127      * just prior to writing the log.
128      */

129     public void add(BuildLogger logger) {
130         loggers.add(logger);
131     }
132
133     /**
134      * Adds a Manipulator that will handle old log-files
135      */

136     public void add(Manipulator manipulator) {
137         manipulators.add(manipulator);
138     }
139     
140     public BuildLogger[] getLoggers() {
141         return (BuildLogger[]) loggers.toArray(new BuildLogger[loggers.size()]);
142     }
143
144     public String JavaDoc getLogXmlEncoding() {
145         return logXmlEncoding;
146     }
147
148     public String JavaDoc getProjectName() {
149         return projectName;
150     }
151
152     /**
153      * @param logDir
154      * @throws CruiseControlException
155      * @deprecated use {@link #setDir(String)}
156      */

157     public void setLogDir(String JavaDoc logDir) throws CruiseControlException {
158         setDir(logDir);
159     }
160
161     public void setDir(String JavaDoc logDir) throws CruiseControlException {
162         this.logDir = logDir;
163     }
164
165     /**
166      * @param logXmlEncoding
167      * @deprecated use {@link #setEncoding(String)}
168      */

169     public void setLogXmlEncoding(String JavaDoc logXmlEncoding) {
170         setEncoding(logXmlEncoding);
171     }
172
173     public void setEncoding(String JavaDoc logXmlEncoding) {
174         this.logXmlEncoding = logXmlEncoding;
175     }
176
177     public String JavaDoc getLogDir() {
178         return logDir;
179     }
180
181     /**
182      * @return The last log file that was written; null if none written yet.
183      */

184     public File JavaDoc getLastLogFile() {
185         return this.lastLogFile;
186     }
187
188     /**
189      * creates log directory if it doesn't already exist
190      * @throws CruiseControlException if directory can't be created or there is
191      * a file of the same name
192      */

193     private void checkLogDirectory(String JavaDoc logDir) throws CruiseControlException {
194         File JavaDoc logDirectory = new File JavaDoc(logDir);
195         if (!logDirectory.exists()) {
196             LOG4J.info(
197                 "log directory specified in config file does not exist; creating: "
198                     + logDirectory.getAbsolutePath());
199             if (!logDirectory.mkdirs()) {
200                 throw new CruiseControlException(
201                     "Can't create log directory specified in config file: "
202                         + logDirectory.getAbsolutePath());
203             }
204         } else if (!logDirectory.isDirectory()) {
205             throw new CruiseControlException(
206                 "Log directory specified in config file is not a directory: "
207                     + logDirectory.getAbsolutePath());
208         }
209     }
210
211     /**
212      * Writes the current build log to the appropriate directory and filename.
213      */

214     public void writeLogFile(Date JavaDoc now) throws CruiseControlException {
215
216         //Call the Loggers to let them do their thing
217
for (int i = 0; i < loggers.size(); i++) {
218             BuildLogger nextLogger = (BuildLogger) loggers.get(i);
219             //The buildloggers get the "real" build log, not a clone. Therefore,
220
// call getContent() wouldn't be appropriate here.
221
nextLogger.log(buildLog);
222         }
223
224         //Figure out what the log filename will be.
225
XMLLogHelper helper = new XMLLogHelper(buildLog);
226
227         String JavaDoc logFilename;
228         if (helper.isBuildSuccessful()) {
229             logFilename = formatLogFileName(now, helper.getLabel());
230         } else {
231             logFilename = formatLogFileName(now);
232         }
233
234         this.lastLogFile = new File JavaDoc(logDir, logFilename);
235         if (LOG4J.isDebugEnabled()) {
236             LOG4J.debug("Project " + projectName + ": Writing log file ["
237                 + lastLogFile.getAbsolutePath() + "]");
238         }
239
240         // Add the logDir as an info element
241
Element logDirElement = new Element("property");
242         logDirElement.setAttribute("name", "logdir");
243         logDirElement.setAttribute("value", new File JavaDoc(logDir).getAbsolutePath());
244         buildLog.getChild("info").addContent(logDirElement);
245
246         // Add the logFile as an info element
247
Element logFileElement = new Element("property");
248         logFileElement.setAttribute("name", "logfile");
249         logFileElement.setAttribute("value", logFilename);
250         buildLog.getChild("info").addContent(logFileElement);
251
252         //Write the log file out, let jdom care about the encoding by using
253
//an OutputStream instead of a Writer.
254
OutputStream JavaDoc logStream = null;
255         try {
256             Format format = Format.getPrettyFormat();
257             if (logXmlEncoding != null) {
258                 format.setEncoding(logXmlEncoding);
259             }
260             XMLOutputter outputter = new XMLOutputter(format);
261             logStream = new BufferedOutputStream JavaDoc(new FileOutputStream JavaDoc(lastLogFile));
262             outputter.output(new Document(buildLog), logStream);
263         } catch (IOException JavaDoc e) {
264             throw new CruiseControlException(e);
265         } finally {
266             if (logStream != null) {
267                 try {
268                     logStream.close();
269                 } catch (IOException JavaDoc e) {
270                     // nevermind, then
271
}
272             }
273         }
274         
275         callManipulators();
276     }
277
278     /**
279      * Calls all Manipulators to already existing logfiles.
280      */

281     protected void callManipulators() {
282         for (Iterator JavaDoc i = manipulators.iterator(); i.hasNext();) {
283             Manipulator manipulator = (Manipulator) i.next();
284             manipulator.execute(getLogDir());
285         }
286     }
287
288     public static String JavaDoc formatLogFileName(Date JavaDoc date) {
289         return formatLogFileName(date, null);
290     }
291
292     public static String JavaDoc formatLogFileName(Date JavaDoc date, String JavaDoc label) {
293         StringBuffer JavaDoc logFileName = new StringBuffer JavaDoc();
294         logFileName.append("log");
295         logFileName.append(DateUtil.getFormattedTime(date));
296         if (label != null) {
297             logFileName.append("L");
298             logFileName.append(label);
299         }
300         logFileName.append(".xml");
301
302         return logFileName.toString();
303     }
304
305     public void addContent(Content newContent) {
306         buildLog.addContent(newContent);
307     }
308
309     public Element getContent() {
310         return (Element) buildLog.clone();
311     }
312
313     public boolean wasBuildSuccessful() {
314         return new XMLLogHelper(buildLog).isBuildSuccessful();
315     }
316
317     /**
318      * Resets the build log. After calling this method a fresh build log
319      * will exist, ready for adding new content.
320      */

321     public void reset() {
322         this.buildLog = new Element("cruisecontrol");
323     }
324
325     public static boolean wasSuccessfulBuild(String JavaDoc filename) {
326         if (filename == null) {
327             return false;
328         }
329         boolean startsWithLog = filename.startsWith("log");
330         boolean hasLabelSeparator = filename.indexOf('L') == BEFORE_LENGTH - 1;
331         boolean isXmlFile = filename.endsWith(".xml");
332         return startsWithLog && hasLabelSeparator && isXmlFile;
333     }
334
335     public static Date JavaDoc parseDateFromLogFileName(String JavaDoc filename) throws ParseException JavaDoc {
336         SimpleDateFormat JavaDoc formatter = new SimpleDateFormat JavaDoc("yyyyMMddHHmmss");
337         return formatter.parse(filename.substring(3, BEFORE_LENGTH - 1));
338     }
339
340     public static String JavaDoc parseLabelFromLogFileName(String JavaDoc filename) {
341         if (!Log.wasSuccessfulBuild(filename)) {
342             return "";
343         }
344         return filename.substring(BEFORE_LENGTH, filename.length() - AFTER_LENGTH);
345     }
346
347 }
348
349
Popular Tags