View Javadoc

1   /*
2    * Copyright  2001-2002,2004 The Apache Software Foundation
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   *
16   */
17  package org.woopi.ant.taskdefs.junit;
18  import java.io.File;
19  import java.io.FileInputStream;
20  import java.io.FileNotFoundException;
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.net.URL;
24  import javax.xml.parsers.DocumentBuilder;
25  import javax.xml.parsers.DocumentBuilderFactory;
26  import org.apache.tools.ant.BuildException;
27  import org.apache.tools.ant.Project;
28  import org.apache.tools.ant.Task;
29  import org.apache.tools.ant.util.JAXPUtils;
30  import org.apache.tools.ant.types.EnumeratedAttribute;
31  import org.w3c.dom.Document;
32  
33  /***
34   * Transform a JUnit xml report.
35   * The default transformation generates an html report in either framed or non-framed
36   * style. The non-framed style is convenient to have a concise report via mail, the
37   * framed report is much more convenient if you want to browse into different
38   * packages or testcases since it is a Javadoc like report.
39   *
40   */
41  public class AggregateTransformer {
42  
43      public static final String FRAMES = "frames";
44  
45      public static final String NOFRAMES = "noframes";
46  
47      public static class Format extends EnumeratedAttribute {
48          public String[] getValues() {
49              return new String[]{FRAMES, NOFRAMES};
50          }
51      }
52  
53      /*** Task */
54      protected Task task;
55  
56      /*** the xml document to process */
57      protected Document document;
58  
59      /*** the style directory. XSLs should be read from here if necessary */
60      protected File styleDir;
61  
62      /*** the destination directory, this is the root from where html should be generated */
63      protected File toDir;
64  
65      /*** the format to use for the report. Must be <tt>FRAMES</tt> or <tt>NOFRAMES</tt> */
66      protected String format = FRAMES;
67  
68      /*** XML Parser factory */
69      private static DocumentBuilderFactory privateDBFactory;
70  
71      /*** XML Parser factory accessible to subclasses */
72      protected static DocumentBuilderFactory dbfactory;
73  
74      static {
75         privateDBFactory = DocumentBuilderFactory.newInstance();
76         dbfactory = privateDBFactory;
77      }
78  
79      public AggregateTransformer(Task task) {
80          this.task = task;
81      }
82  
83      /***
84       * Get the Document Builder Factory
85       *
86       * @return the DocumentBuilderFactory instance in use
87       */
88      protected static DocumentBuilderFactory getDocumentBuilderFactory() {
89          return privateDBFactory;
90      }
91  
92      public void setFormat(Format format) {
93          this.format = format.getValue();
94      }
95  
96      public void setXmlDocument(Document doc) {
97          this.document = doc;
98      }
99  
100     /***
101      * Set the xml file to be processed. This is a helper if you want
102      * to set the file directly. Much more for testing purposes.
103      * @param xmlfile xml file to be processed
104      */
105     protected void setXmlfile(File xmlfile) throws BuildException {
106         try {
107             DocumentBuilder builder = privateDBFactory.newDocumentBuilder();
108             InputStream in = new FileInputStream(xmlfile);
109             try {
110                 Document doc = builder.parse(in);
111                 setXmlDocument(doc);
112             } finally {
113                 in.close();
114             }
115         } catch (Exception e) {
116             throw new BuildException("Error while parsing document: " + xmlfile, e);
117         }
118     }
119 
120     /***
121      * set the style directory. It is optional and will override the
122      * default xsl used.
123      * @param styledir  the directory containing the xsl files if the user
124      * would like to override with its own style.
125      */
126     public void setStyledir(File styledir) {
127         this.styleDir = styledir;
128     }
129 
130     /*** set the destination directory */
131     public void setTodir(File todir) {
132         this.toDir = todir;
133     }
134 
135     /*** set the extension of the output files */
136     public void setExtension(String ext) {
137         task.log("extension is not used anymore", Project.MSG_WARN);
138     }
139 
140     public void transform() throws BuildException {
141         checkOptions();
142         final long t0 = System.currentTimeMillis();
143         XalanExecutor executor = XalanExecutor.newInstance(this);
144         try {
145             executor.execute();
146         } catch (Exception e) {
147             throw new BuildException("Errors while applying transformations: "
148                 + e.getMessage(), e);
149         }
150         final long dt = System.currentTimeMillis() - t0;
151         task.log("Transform time: " + dt + "ms");
152     }
153 
154     /*** check for invalid options */
155     protected void checkOptions() throws BuildException {
156         // set the destination directory relative from the project if needed.
157         if (toDir == null) {
158             toDir = task.getProject().resolveFile(".");
159         } else if (!toDir.isAbsolute()) {
160             toDir = task.getProject().resolveFile(toDir.getPath());
161         }
162     }
163 
164     /***
165      * Get the systemid of the appropriate stylesheet based on its
166      * name and styledir. If no styledir is defined it will load
167      * it as a java resource in the xsl child package, otherwise it
168      * will get it from the given directory.
169      * @throws IOException thrown if the requested stylesheet does
170      * not exist.
171      */
172     protected String getStylesheetSystemId() throws IOException {
173         String xslname = "junit-frames.xsl";
174         if (NOFRAMES.equals(format)) {
175             xslname = "junit-noframes.xsl";
176         }
177         if (styleDir == null) {
178             URL url = getClass().getResource("xsl/" + xslname);
179             if (url == null) {
180                 throw new FileNotFoundException("Could not find jar resource " + xslname);
181             }
182             return url.toExternalForm();
183         }
184         File file = new File(styleDir, xslname);
185         if (!file.exists()) {
186             throw new FileNotFoundException("Could not find file '" + file + "'");
187         }
188         return JAXPUtils.getSystemId(file);
189     }
190 
191 }