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