• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the  "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 /*
19  * $Id$
20  */
21 package org.apache.qetest.xslwrapper;
22 import java.util.Hashtable;
23 import java.util.Properties;
24 import java.util.StringTokenizer;
25 import java.util.Vector;
26 
27 import org.apache.qetest.QetestUtils;
28 
29 /**
30  * Implementation of TransformWrapper that calls Xalan's default
31  * command line class Process.main.
32  *
33  * This is similar to the common usage:
34  * java org.apache.xalan.xslt.Process -in foo.xml -xsl foo.xsl ...
35  *
36  * See OPT_PREFIX for how to pass miscellaneous cmdline args.
37  *
38  * //@todo support precompiled/serialized stylesheets
39  *
40  * @author Shane_Curcuru@us.ibm.com
41  * @version $Id$
42  */
43 public class XalanProcessWrapper extends TransformWrapperHelper
44 {
45 
46     /**
47      * Marker for cmdline items to add to optionArgs.
48      */
49     public static final String OPT_PREFIX = TransformWrapper.SET_PROCESSOR_ATTRIBUTES + "cmdline";
50 
51 
52     /**
53      * Array of additional or optional args for Process.main() calls.
54      */
55     protected String[] optionArgs = new String[0];
56 
57 
58     /**
59      * Cached copy of newProcessor() Hashtable.
60      */
61     protected Hashtable newProcessorOpts = null;
62 
63 
64     /**
65      * Get a general description of this wrapper itself.
66      *
67      * @return Calls org.apache.xalan.xslt.Process -in foo.xml -xsl foo.xsl ...
68      */
getDescription()69     public String getDescription()
70     {
71         return "Calls org.apache.xalan.xslt.Process -in foo.xml -xsl foo.xsl ...";
72     }
73 
74 
75     /**
76      * Get a specific description of the wrappered processor.
77      *
78      * @return specific description of the underlying processor or
79      * transformer implementation: this should include both the
80      * general product name, as well as specific version info.  If
81      * possible, should be implemented without actively creating
82      * an underlying processor.
83      */
getProcessorInfo()84     public Properties getProcessorInfo()
85     {
86         Properties p = TraxWrapperUtils.getTraxInfo();
87         p.put("traxwrapper.method", "xalanProcess");
88         p.put("traxwrapper.desc", getDescription());
89         return p;
90     }
91 
92 
93     /**
94      * Actually create/initialize an underlying processor or factory.
95      *
96      * No-op, since we always construct a new Process instance
97      * for every transformation.
98      *
99      * @param options Hashtable of options, unused.
100      *
101      * @return null, we don't use this
102      *
103      * @throws Exception covers any underlying exceptions thrown
104      * by the actual implementation
105      */
newProcessor(Hashtable options)106     public Object newProcessor(Hashtable options) throws Exception
107     {
108         newProcessorOpts = options;
109 
110         // semi-HACK: set any additional cmdline options from user
111         String extraOpts = null;
112         try
113         {
114             // Attempt to use as a Properties block..
115             extraOpts = ((Properties)options).getProperty(OPT_PREFIX);
116             // But, if null, then try getting as hash anyway
117             if (null == extraOpts)
118             {
119                 extraOpts = (String)options.get(OPT_PREFIX);
120             }
121         }
122         catch (ClassCastException cce)
123         {
124             // .. but fallback to get as Hashtable instead
125             extraOpts = (String)options.get(OPT_PREFIX);
126         }
127 
128         if ((null != extraOpts) && (extraOpts.length() > 0))
129         {
130             Vector v = new Vector();
131             StringTokenizer st = new StringTokenizer(extraOpts, " ");
132             while (st.hasMoreTokens())
133             {
134                 v.addElement(st.nextToken());
135             }
136             optionArgs = new String[v.size()];
137             v.copyInto(optionArgs);
138         }
139         //@todo do we need to do any other cleanup?
140         reset(false);
141         return null;
142     }
143 
144 
145     /**
146      * Transform supplied xmlName file with the stylesheet in the
147      * xslName file into a resultName file.
148      *
149      * Names are assumed to be local path\filename references, and
150      * will be converted to URLs as needed for any underlying
151      * processor implementation.
152      *
153      * //@todo attempt to capture any System.out/err output
154      * from this command line class for logging
155      *
156      * @param xmlName local path\filename of XML file to transform
157      * @param xslName local path\filename of XSL stylesheet to use
158      * @param resultName local path\filename to put result in
159      *
160      * @return array of longs denoting timing of only these parts of
161      * our operation: IDX_OVERALL
162      *
163      * @throws Exception any underlying exceptions from the
164      * wrappered processor are simply allowed to propagate; throws
165      * a RuntimeException if any other problems prevent us from
166      * actually completing the operation
167      */
transform(String xmlName, String xslName, String resultName)168     public long[] transform(String xmlName, String xslName, String resultName)
169         throws Exception
170     {
171         long startTime = 0;
172         long overall = 0;
173 
174         // Untimed: Apply any parameters needed
175         applyParameters(null);
176 
177         // Untimed: Construct command line array
178         final int NUM_FARGS = 6; // Need 6 extra slots for
179                                      // -in XML -xsl XSL -out OUT
180         String args[] = new String[optionArgs.length + NUM_FARGS];
181 
182         args[0] = "-in";
183         args[1] = QetestUtils.filenameToURL(xmlName);
184         args[2] = "-xsl";
185         args[3] = QetestUtils.filenameToURL(xslName);
186         args[4] = "-out";
187         args[5] = resultName;
188         System.arraycopy(optionArgs, 0, args, NUM_FARGS, optionArgs.length);
189 
190         // Timed: entire operation
191         //@todo attempt to capture any System.out/err output
192         //  from this command line class for logging
193         startTime = System.currentTimeMillis();
194         org.apache.xalan.xslt.Process.main(args);
195         overall = System.currentTimeMillis() - startTime;
196 
197         long[] times = getTimeArray();
198         times[IDX_OVERALL] = overall;
199         return times;
200     }
201 
202 
203     /**
204      * Pre-build/pre-compile a stylesheet.
205      *
206      * Although the actual mechanics are implementation-dependent,
207      * most processors have some method of pre-setting up the data
208      * needed by the stylesheet itself for later use in transforms.
209      * In TrAX/javax.xml.transform, this equates to creating a
210      * Templates object.
211      *
212      * Sets isStylesheetReady() to true if it succeeds.  Users can
213      * then call transformWithStylesheet(xmlName, resultName) to
214      * actually perform a transformation with this pre-built
215      * stylesheet.
216      *
217      * @param xslName local path\filename of XSL stylesheet to use
218      *
219      * @return array of longs denoting timing of only these parts of
220      * our operation: IDX_OVERALL, IDX_XSLBUILD
221      *
222      * @throws Exception any underlying exceptions from the
223      * wrappered processor are simply allowed to propagate; throws
224      * a RuntimeException if any other problems prevent us from
225      * actually completing the operation
226      *
227      * @see #transformWithStylesheet(String xmlName, String resultName)
228      */
buildStylesheet(String xslName)229     public long[] buildStylesheet(String xslName) throws Exception
230     {
231         throw new IllegalStateException("XalanProcessWrapper.transformWithStylesheet not implemented!");
232     }
233 
234 
235     /**
236      * Transform supplied xmlName file with a pre-built/pre-compiled
237      * stylesheet into a resultName file.
238      *
239      * User must have called buildStylesheet(xslName) beforehand,
240      * obviously.
241      * Names are assumed to be local path\filename references, and
242      * will be converted to URLs as needed.
243      *
244      * @param xmlName local path\filename of XML file to transform
245      * @param resultName local path\filename to put result in
246      *
247      * @return array of longs denoting timing of only these parts of
248      * our operation: IDX_OVERALL, IDX_XSLBUILD, IDX_TRANSFORM
249      *
250      * @throws Exception any underlying exceptions from the
251      * wrappered processor are simply allowed to propagate; throws
252      * a RuntimeException if any other problems prevent us from
253      * actually completing the operation; throws an
254      * IllegalStateException if isStylesheetReady() == false.
255      *
256      * @see #buildStylesheet(String xslName)
257      */
transformWithStylesheet(String xmlName, String resultName)258     public long[] transformWithStylesheet(String xmlName, String resultName)
259         throws Exception
260     {
261         throw new IllegalStateException("XalanProcessWrapper.transformWithStylesheet not implemented!");
262     }
263 
264 
265     /**
266      * Transform supplied xmlName file with a stylesheet found in an
267      * xml-stylesheet PI into a resultName file.
268      *
269      * Names are assumed to be local path\filename references, and
270      * will be converted to URLs as needed.  Implementations will
271      * use whatever facilities exist in their wrappered processor
272      * to fetch and build the stylesheet to use for the transform.
273      *
274      * @param xmlName local path\filename of XML file to transform
275      * @param resultName local path\filename to put result in
276      *
277      * @return array of longs denoting timing of only these parts of
278      * our operation: IDX_OVERALL, IDX_XSLREAD (time to find XSL
279      * reference from the xml-stylesheet PI), IDX_XSLBUILD, (time
280      * to then build the Transformer therefrom), IDX_TRANSFORM
281      *
282      * @throws Exception any underlying exceptions from the
283      * wrappered processor are simply allowed to propagate; throws
284      * a RuntimeException if any other problems prevent us from
285      * actually completing the operation
286      */
transformEmbedded(String xmlName, String resultName)287     public long[] transformEmbedded(String xmlName, String resultName)
288         throws Exception
289     {
290         throw new IllegalStateException("XalanProcessWrapper.transformWithStylesheet not implemented!");
291     }
292 
293 
294     /**
295      * Reset our parameters and wrapper state, and optionally
296      * force creation of a new underlying processor implementation.
297      *
298      * This always clears our built stylesheet and any parameters
299      * that have been set.  If newProcessor is true, also forces a
300      * re-creation of our underlying processor as if by calling
301      * newProcessor().
302      *
303      * @param newProcessor if we should reset our underlying
304      * processor implementation as well
305      */
reset(boolean newProcessor)306     public void reset(boolean newProcessor)
307     {
308         super.reset(newProcessor); // clears indent and parameters
309         m_stylesheetReady = false;
310     }
311 
312 
313     /**
314      * Apply a single parameter to a Transformer.
315      *
316      * No-op, we don't yet support parameters.
317      *
318      * @param passThru to be passed to each applyParameter() method
319      * @param namespace for the parameter, may be null
320      * @param name for the parameter, should not be null
321      * @param value for the parameter, may be null
322      */
applyParameter(Object passThru, String namespace, String name, Object value)323     protected void applyParameter(Object passThru, String namespace,
324                                   String name, Object value)
325     {
326         return;
327     }
328 
329 
330 }
331