View Javadoc

1   /*
2    * Copyright  2001-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.BufferedOutputStream;
19  import java.io.ByteArrayOutputStream;
20  import java.io.File;
21  import java.io.FileOutputStream;
22  import java.io.IOException;
23  import java.io.OutputStream;
24  import java.io.PrintWriter;
25  import java.io.StringWriter;
26  import java.lang.reflect.Field;
27  import org.apache.tools.ant.BuildException;
28  import org.apache.tools.ant.Project;
29  import org.apache.tools.ant.util.JavaEnvUtils;
30  
31  /***
32   * Command class that encapsulate specific behavior for each
33   * Xalan version. The right executor will be instantiated at
34   * runtime via class lookup. For instance, it will check first
35   * for Xalan2/XSLTC, then for Xalan1.
36   */
37  abstract class XalanExecutor {
38      private static final String pack = 
39          "org.woopi.ant.taskdefs.junit.";
40  
41      /*** the transformer caller */
42      protected AggregateTransformer caller;
43  
44      /*** set the caller for this object. */
45      private final void setCaller(AggregateTransformer caller) {
46          this.caller = caller;
47      }
48  
49      /*** get the appropriate stream based on the format (frames/noframes) */
50      protected final OutputStream getOutputStream() throws IOException {
51          if (AggregateTransformer.FRAMES.equals(caller.format)) {
52              // dummy output for the framed report
53              // it's all done by extension...
54              return new ByteArrayOutputStream();
55          } else {
56              return new BufferedOutputStream(new FileOutputStream(new File(caller.toDir, "junit-noframes.html")));
57          }
58      }
59  
60      /*** override to perform transformation */
61      abstract void execute() throws Exception;
62  
63      /***
64       * Create a valid Xalan executor. It checks first if Xalan2 is
65       * present, if not it checks for xalan1. If none is available, it
66       * fails.
67       * @param caller object containing the transformation information.
68       * @throws BuildException thrown if it could not find a valid xalan
69       * executor.
70       */
71      static XalanExecutor newInstance(AggregateTransformer caller) 
72          throws BuildException {
73          XalanExecutor executor = null;
74          try {
75              Class clazz = Class.forName(pack + "Xalan2Executor");
76              executor = (XalanExecutor)clazz.newInstance();
77          } catch (Exception xsltcApacheMissing){
78              caller.task.log(xsltcApacheMissing.toString());
79              try {
80                  Class clazz = Class.forName(pack + "Xalan1Executor");
81                  executor = (XalanExecutor) clazz.newInstance();
82              } catch (Exception xalan1Missing){
83                  caller.task.log(xalan1Missing.toString());
84                  throw new BuildException("Could not find xstlc nor xalan2 nor "
85                                           + "xalan1 in the classpath. Check "
86                                           + "http://xml.apache.org/xalan-j");
87              }
88          }
89          String classNameImpl = executor.getImplementation();
90          String version = executor.getProcVersion(classNameImpl);
91          caller.task.log("Using " + version, Project.MSG_VERBOSE);
92          executor.setCaller(caller);
93          return executor;
94      }
95  
96      /***
97       * This methods should return the classname implementation of the
98       * underlying xslt processor
99       * @return the classname of the implementation, for example:
100      * org.apache.xalan.processor.TransformerFactoryImpl
101      * @see #getProcVersion(String)
102      */
103     protected abstract String getImplementation();
104 
105     /***
106      * Try to discover the xslt processor version based on the
107      * className. There is nothing carved in stone and it can change
108      * anytime, so this is just for the sake of giving additional
109      * information if we can find it.
110      * @param classNameImpl the classname of the underlying xslt processor
111      * @return a string representing the implementation version.
112      * @throws BuildException
113      */
114     protected abstract String getProcVersion(String classNameImpl) 
115         throws BuildException;
116 
117     /*** a bit simplistic but xsltc data are conveniently private non final */
118     protected final String getXSLTCVersion(String procVersionClassName) 
119         throws ClassNotFoundException {
120         // there's a convenient xsltc class version but data are
121         // private so use package information
122         Class procVersion = Class.forName(procVersionClassName);
123         Package pkg = procVersion.getPackage();
124         return pkg.getName() + " " + pkg.getImplementationTitle() 
125             + " " + pkg.getImplementationVersion();
126     }
127 
128     /*** pretty useful data (Xalan version information) to display. */
129     protected final String getXalanVersion(String procVersionClassName) 
130         throws ClassNotFoundException {
131         Class procVersion = Class.forName(procVersionClassName);
132         String pkg = procVersion.getPackage().getName();
133         try {
134             Field f = procVersion.getField("S_VERSION");
135             return pkg + " " + f.get(null).toString();
136         } catch (Exception e) {
137             return pkg + " ?.?";
138         }
139     }
140 }