View Javadoc

1   ////////////////////////////////////////////////////////////////////////////////
2   //                  ObjectLab is sponsoring QALab
3   // 
4   // Based in London, we are world leaders in the design and development 
5   // of bespoke applications for the Securities Financing markets.
6   // 
7   // <a href="http://www.objectlab.co.uk/open">Click here to learn more</a>
8   //           ___  _     _           _   _          _
9   //          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
10  //         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
11  //         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
12  //          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
13  //                   |__/
14  //
15  //                   http://www.ObjectLab.co.uk
16  // ---------------------------------------------------------------------------
17  //
18  //QALab is released under the GNU General Public License.
19  //
20  //QALab: Collects QA Statistics from your build over time.
21  //2005+, ObjectLab Ltd
22  //
23  //This library is free software; you can redistribute it and/or
24  //modify it under the terms of the GNU General Public
25  //License as published by the Free Software Foundation; either
26  //version 2.1 of the License, or (at your option) any later version.
27  //
28  //This library is distributed in the hope that it will be useful,
29  //but WITHOUT ANY WARRANTY; without even the implied warranty of
30  //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
31  //General Public License for more details.
32  //
33  //You should have received a copy of the GNU General Public
34  //License along with this library; if not, write to the Free Software
35  //Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
36  //
37  ////////////////////////////////////////////////////////////////////////////////
38  package net.objectlab.qalab.ant;
39  
40  import net.objectlab.qalab.interfaces.QALabExporter;
41  import net.objectlab.qalab.parser.StatMerger;
42  import net.objectlab.qalab.util.TaskLogger;
43  
44  import org.apache.tools.ant.BuildException;
45  import org.apache.tools.ant.Task;
46  import org.xml.sax.InputSource;
47  
48  import java.io.File;
49  import java.io.FileInputStream;
50  import java.io.FileNotFoundException;
51  import java.io.FileReader;
52  import java.io.IOException;
53  
54  import java.util.Hashtable;
55  import java.util.Iterator;
56  import java.util.Map;
57  import java.util.Properties;
58  
59  /**
60   * The ant task that handles the merger of statistics into qalab.xml.
61   * 
62   * @author Benoit Xhenseval
63   * @version $Revision: 187 $
64   */
65  public class BuildStatMergeTask extends Task {
66      // ~ Instance fields
67      // ------------------------------------------------------------------------
68  
69      /** the base properties file. */
70      private File inputFile = null;
71  
72      /** the merged properties file. */
73      private File outputFile = null;
74  
75      /** if true, logging output will be suppressed. */
76      private boolean quiet = false;
77  
78      /** the directory where the source code is. */
79      private String srcDir;
80  
81      /** the handler for these statistics. */
82      private String handler;
83  
84      /** a given timestamp for the stats. */
85      private String mergerTimeStamp;
86  
87      /** exporter class name. */
88      private String exporterClassName = "net.objectlab.qalab.exporter.QALabXMLExporter";
89  
90      /** properties file to use instead of setting them one by one. */
91      private File propertiesFile;
92  
93      /** the loaded properties. */
94      private Properties properties = null;
95  
96      // ~ Methods
97      // ------------------------------------------------------------------------
98  
99      /**
100      * Sets the class name for the handler for the given statistics.
101      * 
102      * @param theHandler
103      *            class name for the handler.
104      */
105     public final void setHandler(final String theHandler) {
106         this.handler = theHandler;
107     }
108 
109     /**
110      * @return the handler
111      */
112     private String getHandler() {
113         return handler;
114     }
115 
116     /**
117      * @param sourceDirectory
118      *            directory where the source code is.
119      */
120     public final void setSrcDir(final String sourceDirectory) {
121         this.srcDir = sourceDirectory;
122     }
123 
124     /**
125      * Sets the input file containing the new statistics (checkstyle,etc).
126      * 
127      * @param newStatisticsFile
128      *            the whose values will be incorporated in the qalab.xml
129      */
130     public final void setInputFile(final File newStatisticsFile) {
131         this.inputFile = newStatisticsFile;
132     }
133 
134     /**
135      * Set the to output file (typically qalab.xml).
136      * 
137      * @param consolidatedFile
138      *            the destination file where the statistics are written. The
139      *            file may or may not exists.
140      */
141     public final void setOutputFile(final File consolidatedFile) {
142         this.outputFile = consolidatedFile;
143     }
144 
145     /**
146      * Sets the quiet mode.
147      * 
148      * @param noLog
149      *            if true, no messages are displayed while merging stats.
150      */
151     public final void setQuiet(final boolean noLog) {
152         this.quiet = noLog;
153     }
154 
155     /**
156      * Sets the timestamp mode.
157      * 
158      * @param timestamp
159      *            if present, uses this as timestamp for stats.
160      */
161     public final void setMergerTimeStamp(final String timestamp) {
162         this.mergerTimeStamp = timestamp;
163     }
164 
165     /**
166      * Method invoked by the ant framework to execute the action associated with
167      * this task. This will validate the input parameters then merge the
168      * statistics.
169      */
170     public final void execute() {
171         properties = createOverridingProperties();
172 
173         // validate the provided parameters
174         validate();
175 
176         // Display the files being processed
177         if (!quiet) {
178             log("inputFile='" + inputFile.getPath() + "', outputFile='"
179                     + outputFile.getPath());
180             log("srcDir='" + srcDir + "', mergerTimeStamp=" + mergerTimeStamp);
181             log("quiet='"
182                     + quiet
183                     + "', propertiesFile="
184                     + (propertiesFile != null ? propertiesFile.getPath() : null));
185             for (Iterator it = properties.entrySet().iterator(); it.hasNext();) {
186                 final Map.Entry entry = (Map.Entry) it.next();
187                 final String key = entry.getKey().toString();
188                 if (key.indexOf("qalab") >= 0) {
189                     log(key + " = '" + entry.getValue() + "'");
190                 }
191             }
192         }
193 
194         mergeFiles();
195     }
196 
197     /**
198      * Merge the statistics into the qalab.xml.
199      */
200     private void mergeFiles() {
201         try {
202             TaskLogger logger = new AntTaskLogger(this);
203 
204             // create the exporter
205             QALabExporter exporter = (QALabExporter) Class.forName(
206                     getExporterClassName()).newInstance();
207 
208             properties.setProperty("qalab.merge.output.file", outputFile
209                     .getAbsolutePath());
210 
211             exporter.setQuiet(quiet);
212             exporter.setTaskLogger(logger);
213 
214             StatMerger merger = (StatMerger) Class.forName(getHandler())
215                     .newInstance();
216 
217             merger.setQuiet(quiet);
218             merger.setSrcDir(srcDir);
219             merger.setTaskLogger(logger);
220             final String tsOnly = properties
221                     .getProperty("qalab.merge.timestampdateonly");
222             merger.setMergerTimeStamp(mergerTimeStamp, tsOnly != null
223                     && (tsOnly.equalsIgnoreCase("yes") || tsOnly
224                             .equalsIgnoreCase("true")));
225 
226             properties.setProperty("qalab.merge.output.timestamp", merger
227                     .getMergerTimeStamp());
228             properties.setProperty("qalab.merge.type", merger.getType());
229             exporter.configure(properties);
230 
231             merger.mergeStats(new InputSource(new FileReader(inputFile)),
232                     exporter);
233             log("Files: " + merger.getFileCount() + " Statistics:"
234                     + merger.getTotalStatistics());
235 
236             exporter.save();
237         } catch (IllegalAccessException e) {
238             e.printStackTrace();
239             throw new BuildException(e.toString());
240         } catch (FileNotFoundException e) {
241             e.printStackTrace();
242             throw new BuildException(e.toString());
243         } catch (IOException e) {
244             e.printStackTrace();
245             throw new BuildException(e.toString());
246         } catch (ClassNotFoundException e) {
247             e.printStackTrace();
248             throw new BuildException(e.toString());
249         } catch (InstantiationException e) {
250             e.printStackTrace();
251             throw new BuildException(e.toString());
252         } catch (Exception e) {
253             e.printStackTrace();
254             throw new BuildException(e.toString());
255         }
256     }
257 
258     /**
259      * Validates the parameters supplied by ant.
260      */
261     private void validate() {
262         if (inputFile == null) {
263             throw new BuildException("inputFile is mandatory");
264         }
265 
266         if (!inputFile.canRead()) {
267             final String message = "Unable to read from " + inputFile + ".";
268 
269             throw new BuildException(message);
270         }
271     }
272 
273     /**
274      * @param exporterClass
275      *            The exporterClassName to set.
276      */
277     public final void setExporterClassName(final String exporterClass) {
278         this.exporterClassName = exporterClass;
279     }
280 
281     /**
282      * @return Returns the exporterClassName.
283      */
284     public final String getExporterClassName() {
285         if (exporterClassName != null) {
286             return exporterClassName;
287         } else {
288             return properties.getProperty("qalab.merge.exporterclass");
289         }
290     }
291 
292     /**
293      * Sets a properties file for use instead of individually setting them.
294      * 
295      * @param aProps
296      *            the properties File to use
297      */
298     public final void setPropertiesFile(final File aProps) {
299         propertiesFile = aProps;
300     }
301 
302     /**
303      * Create the Properties object based on the arguments specified to the ANT
304      * task.
305      * 
306      * @return the properties for property expansion expansion
307      */
308     private Properties createOverridingProperties() {
309         final Properties retVal = new Properties();
310 
311         // Load the properties file if specified
312         if (propertiesFile != null && propertiesFile.canRead()
313                 && propertiesFile.isFile()) {
314             FileInputStream inStream = null;
315             if (!quiet) {
316                 log("loading " + propertiesFile);
317             }
318             try {
319                 inStream = new FileInputStream(propertiesFile);
320                 retVal.load(inStream);
321             } catch (FileNotFoundException e) {
322                 throw new BuildException("Could not find Properties file '"
323                         + propertiesFile + "'", e, getLocation());
324             } catch (IOException e) {
325                 throw new BuildException("Error loading Properties file '"
326                         + propertiesFile + "'", e, getLocation());
327             } finally {
328                 try {
329                     if (inStream != null) {
330                         inStream.close();
331                     }
332                 } catch (IOException e) {
333                     throw new BuildException("Error closing Properties file '"
334                             + propertiesFile + "'", e, getLocation());
335                 }
336             }
337         }
338 
339         // override with Ant properties like ${basedir}
340         final Hashtable antProps = this.getProject().getProperties();
341 
342         for (Iterator it = antProps.entrySet().iterator(); it.hasNext();) {
343             final Map.Entry entry = (Map.Entry) it.next();
344             final String value = String.valueOf(entry.getValue());
345             if (!quiet && entry.getKey().toString().indexOf("qalab") >= 0) {
346                 log("Adding Prop: " + entry.getKey() + " / [" + value + "]");
347             }
348             retVal.put(entry.getKey(), value);
349         }
350 
351         return retVal;
352     }
353 }
354 /*
355  *                   ObjectLab is sponsoring QALab
356  * 
357  * Based in London, we are world leaders in the design and development 
358  * of bespoke applications for the securities financing markets.
359  * 
360  * <a href="http://www.objectlab.co.uk/open">Click here to learn more about us</a>
361  *           ___  _     _           _   _          _
362  *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
363  *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
364  *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
365  *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
366  *                   |__/
367  *
368  *                     www.ObjectLab.co.uk
369  */