• 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 
22 package org.apache.qetest.xslwrapper;
23 
24 import java.io.File;
25 import java.net.URL;
26 import java.util.Hashtable;
27 import java.util.Properties;
28 
29 import org.xml.sax.InputSource;
30 
31 /**
32  * Implementation of TransformWrapper that uses the simplest method
33  * possible to use James Clark's XT processor.
34  *
35  * @author Shane Curcuru
36  * @version $Id$
37  */
38 public class XTWrapper extends TransformWrapperHelper
39 {
40 
41     /**
42      * Get a general description of this wrapper itself.
43      *
44      * @return Uses XT in simplest manner possible
45      */
getDescription()46     public String getDescription()
47     {
48         return "Uses XT in simplest manner possible";
49     }
50 
51 
52     /** No-op Ctor for the Xalan-J 1.x wrapper. */
XTWrapper()53     public XTWrapper(){}
54 
55     /** Reference to current processor - XT flavor - convenience method. */
56     protected com.jclark.xsl.sax.XSLProcessorImpl processor = null;
57 
58     /**
59      * Cached copy of newProcessor() Hashtable.
60      */
61     protected Hashtable newProcessorOpts = null;
62 
63     /**
64      * Get a specific description of the wrappered processor.
65      *
66      * @return specific description of the underlying processor or
67      * transformer implementation: this should include both the
68      * general product name, as well as specific version info.  If
69      * possible, should be implemented without actively creating
70      * an underlying processor.
71      */
getProcessorInfo()72     public Properties getProcessorInfo()
73     {
74         Properties p = new Properties();
75         p.put("traxwrapper.method", "simple");
76         p.put("traxwrapper.desc", getDescription());
77         //@todo call XT to find version info
78         return p;
79     }
80 
81     /**
82      * Actually create/initialize an underlying processor or factory.
83      * This creates a com.jclark.xsl.sax.XSLProcessorImpl.
84      *
85      * @param options Hashtable of options, unused.
86      *
87      * @return (Object)getProcessor() as a side-effect, this will
88      * be null if there was any problem creating the processor OR
89      * if the underlying implementation doesn't use this
90      *
91      * @throws Exception covers any underlying exceptions thrown
92      * by the actual implementation
93      */
newProcessor(Hashtable options)94     public Object newProcessor(Hashtable options) throws Exception
95     {
96         newProcessorOpts = options;
97         // Cleanup any prior objects
98         reset(false);
99 
100         processor = new com.jclark.xsl.sax.XSLProcessorImpl();
101 
102         String liaisonClassName = "com.jclark.xml.sax.CommentDriver";  // default
103 
104         try
105         {
106             Object parserObj = Class.forName(liaisonClassName).newInstance();
107 
108             if (parserObj instanceof XMLProcessorEx)
109                 processor.setParser((XMLProcessorEx) parserObj);
110             else
111                 processor.setParser((org.xml.sax.Parser) parserObj);
112         }
113         catch (Exception e)
114         {
115             System.err.println("createNewProcesor(xt) threw: "
116                                + e.toString());
117             e.printStackTrace();
118 
119             processor = null;
120         }
121 
122         return (Object)processor;
123     }
124 
125     /**
126      * Transform supplied xmlName file with the stylesheet in the
127      * xslName file into a resultName file using XT.
128      *
129      * @param xmlName local path\filename of XML file to transform
130      * @param xslName local path\filename of XSL stylesheet to use
131      * @param resultName local path\filename to put result in
132      *
133      * @return array of longs denoting timing of all parts of
134      * our operation: IDX_OVERALL, IDX_XSLREAD, IDX_XSLBUILD,
135      * IDX_TRANSFORM, IDX_RESULTWRITE
136      *
137      * @throws Exception any underlying exceptions from the
138      * wrappered processor are simply allowed to propagate; throws
139      * a RuntimeException if any other problems prevent us from
140      * actually completing the operation
141      */
transform(String xmlName, String xslName, String resultName)142     public long[] transform(String xmlName, String xslName, String resultName)
143         throws Exception
144     {
145         // Declare variables ahead of time to minimize latency
146         long startTime = 0;
147         long endTime = 0;
148 
149         // Create XT-specific sources
150         OutputMethodHandlerImpl outHandler =
151             new OutputMethodHandlerImpl(processor);
152 
153         outHandler.setDestination(new FileDestination(new File(resultName)));
154 
155         InputSource xmlIS = xtInputSourceFromString(xmlName);
156         InputSource xslIS = xtInputSourceFromString(xslName);
157 
158         // Begin timing the process: stylesheet, output, and process
159         startTime = System.currentTimeMillis();
160 
161         processor.loadStylesheet(xslIS);
162         processor.setOutputMethodHandler(outHandler);
163         processor.parse(xmlIS);
164 
165         endTime = System.currentTimeMillis();
166 
167         long[] times = getTimeArray();
168         times[IDX_OVERALL] = endTime - startTime;
169         return times;
170     }
171 
172 
173     /**
174      * Pre-build/pre-compile a stylesheet.
175      *
176      * Although the actual mechanics are implementation-dependent,
177      * most processors have some method of pre-setting up the data
178      * needed by the stylesheet itself for later use in transforms.
179      * In TrAX/javax.xml.transform, this equates to creating a
180      * Templates object.
181      *
182      * Sets isStylesheetReady() to true if it succeeds.  Users can
183      * then call transformWithStylesheet(xmlName, resultName) to
184      * actually perform a transformation with this pre-built
185      * stylesheet.
186      *
187      * @param xslName local path\filename of XSL stylesheet to use
188      *
189      * @return array of longs denoting timing of all parts of
190      * our operation: IDX_OVERALL, IDX_XSLBUILD
191      *
192      * @throws Exception any underlying exceptions from the
193      * wrappered processor are simply allowed to propagate; throws
194      * a RuntimeException if any other problems prevent us from
195      * actually completing the operation
196      *
197      * @see #transformWithStylesheet(String xmlName, String resultName)
198      */
buildStylesheet(String xslName)199     public long[] buildStylesheet(String xslName) throws Exception
200     {
201         // Declare variables ahead of time to minimize latency
202         long startTime = 0;
203         long endTime = 0;
204 
205         // Create XT-specific source
206         InputSource xslIS = xtInputSourceFromString(xslName);
207 
208         // Begin timing loading the stylesheet
209         startTime = System.currentTimeMillis();
210 
211         processor.loadStylesheet(xslIS);  // side effect: also sets the stylesheet
212 
213         endTime = System.currentTimeMillis();
214         m_stylesheetReady = true;
215 
216         long[] times = getTimeArray();
217         times[IDX_OVERALL] = endTime - startTime;
218         return times;
219     }
220 
221     /**
222      * Transform supplied xmlName file with a pre-built/pre-compiled
223      * stylesheet into a resultName file.
224      *
225      * User must have called buildStylesheet(xslName) beforehand,
226      * obviously.
227      * Names are assumed to be local path\filename references, and
228      * will be converted to URLs as needed.
229      *
230      * @param xmlName local path\filename of XML file to transform
231      * @param resultName local path\filename to put result in
232      *
233      * @return array of longs denoting timing of all parts of
234      * our operation: IDX_OVERALL,
235      * IDX_XMLREAD, IDX_TRANSFORM, IDX_RESULTWRITE
236      *
237      * @throws Exception any underlying exceptions from the
238      * wrappered processor are simply allowed to propagate; throws
239      * a RuntimeException if any other problems prevent us from
240      * actually completing the operation; throws an
241      * IllegalStateException if isStylesheetReady() == false.
242      *
243      * @see #buildStylesheet(String xslName)
244      */
transformWithStylesheet(String xmlName, String resultName)245     public long[] transformWithStylesheet(String xmlName, String resultName)
246         throws Exception
247     {
248         if (!isStylesheetReady())
249             throw new IllegalStateException("transformWithStylesheet() when isStylesheetReady() == false");
250 
251         // Declare variables ahead of time to minimize latency
252         long startTime = 0;
253         long endTime = 0;
254 
255         // Create XT-specific sources
256         OutputMethodHandlerImpl outHandler =
257             new OutputMethodHandlerImpl(processor);
258 
259         outHandler.setDestination(new FileDestination(new File(resultName)));
260 
261         InputSource xmlIS = xtInputSourceFromString(xmlName);
262 
263         // Begin timing the process: stylesheet, output, and process
264         startTime = System.currentTimeMillis();
265 
266         processor.setOutputMethodHandler(outHandler);
267         processor.parse(xmlIS);
268 
269         endTime = System.currentTimeMillis();
270 
271         long[] times = getTimeArray();
272         times[IDX_OVERALL] = endTime - startTime;
273         return times;
274     }
275 
276     /**
277      * Transform supplied xmlName file with a stylesheet found in an
278      * xml-stylesheet PI into a resultName file.
279      *
280      * Names are assumed to be local path\filename references, and
281      * will be converted to URLs as needed.  Implementations will
282      * use whatever facilities exist in their wrappered processor
283      * to fetch and build the stylesheet to use for the transform.
284      *
285      * @param xmlName local path\filename of XML file to transform
286      * @param resultName local path\filename to put result in
287      *
288      * @return array of longs denoting timing of only these parts of
289      * our operation: IDX_OVERALL, IDX_XSLREAD (time to find XSL
290      * reference from the xml-stylesheet PI), IDX_XSLBUILD, (time
291      * to then build the Transformer therefrom), IDX_TRANSFORM
292      *
293      * @throws Exception any underlying exceptions from the
294      * wrappered processor are simply allowed to propagate; throws
295      * a RuntimeException if any other problems prevent us from
296      * actually completing the operation
297      */
transformEmbedded(String xmlName, String resultName)298     public long[] transformEmbedded(String xmlName, String resultName)
299         throws Exception
300     {
301         throw new RuntimeException("XTWrapper.transformEmbedded not implemented yet!");
302     }
303 
304     /**
305      * Worker method for using XT to process.
306      *
307      * @param name local name of file
308      *
309      * @return InputSource for XT after munging name as needed
310      */
xtInputSourceFromString(String name)311     private InputSource xtInputSourceFromString(String name)
312     {
313 
314         File file = new File(name);
315         String path = file.getAbsolutePath();
316 
317         // Add absolute / to beginning if needed
318         if (path.charAt(0) != '/')
319             path = '/' + path;
320 
321         try
322         {
323             java.net.URL temp = new URL("file", "", path);
324 
325             return (new InputSource(temp.toString()));
326         }
327         catch (Exception e)
328         {
329             System.err.println("xtInputSourceFromString(xt) of: " + name
330                                + " threw: " + e.toString());
331             e.printStackTrace();
332 
333             return (null);
334         }
335     }
336 
337     /**
338      * Reset our parameters and wrapper state, and optionally
339      * force creation of a new underlying processor implementation.
340      *
341      * This always clears our built stylesheet and any parameters
342      * that have been set.  If newProcessor is true, also forces a
343      * re-creation of our underlying processor as if by calling
344      * newProcessor().
345      *
346      * @param newProcessor if we should reset our underlying
347      * processor implementation as well
348      */
reset(boolean newProcessor)349     public void reset(boolean newProcessor)
350     {
351         super.reset(newProcessor); // clears indent and parameters
352         m_stylesheetReady = false;
353         if (newProcessor)
354         {
355             try
356             {
357                 newProcessor(newProcessorOpts);
358             }
359             catch (Exception e)
360             {
361                 //@todo Hmm: what should we do here?
362             }
363         }
364     }
365 
366     /**
367      * Apply a single parameter to a Transformer.
368      *
369      * Overridden for XT to call setParameter().
370      *
371      * @param passThru to be passed to each applyParameter() method
372      * call - for TrAX, you might pass a Transformer object.
373      * @param namespace for the parameter, may be null
374      * @param name for the parameter, should not be null
375      * @param value for the parameter, may be null
376      */
applyParameter(Object passThru, String namespace, String name, Object value)377     protected void applyParameter(Object passThru, String namespace,
378                                   String name, Object value)
379     {
380         try
381         {
382             XSLProcessorImpl p = (XSLProcessorImpl)passThru;
383             //@todo: HACK: smash the namespace in - not sure if this is correct
384             if (null != namespace)
385             {
386                 name = namespace + ":" + name;
387             }
388             p.setParameter(name, value);
389         }
390         catch (Exception e)
391         {
392             throw new IllegalArgumentException("applyParameter threw: " + e.toString());
393         }
394     }
395 
396 }  // end of class XTWrapper
397 
398