1 /* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 */ 4 /* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 package org.apache.qetest.xslwrapper; 21 22 import java.util.Properties; 23 import javax.xml.transform.TransformerConfigurationException; 24 import javax.xml.transform.TransformerFactory; 25 26 /** 27 * Helper interface to wrapper various XSLT processors for testing. 28 * 29 * A TransformWrapper wraps a particular 'flavor' of XSLT processing. This 30 * includes both a particular XSLT implementation, such as Xalan or Saxon, as 31 * well as a particular method to perform processing, like using streams or DOMs 32 * to perform transforms. 33 * 34 * As an important side effect, this class should return timing information 35 * about the steps done to perform the transformation. Note that exactly what is 36 * timed and how it's timed should be clearly documented in implementing 37 * classes! 38 * 39 * This is not a general-purpose wrapper for doing XSLT transformations: for 40 * that, you might as well use the real javax.xml.transform package itself. 41 * However this does allow many conformance and performance tests to run 42 * comparatively between different flavors of processors. 43 * 44 * TransformWrapper is a bit of an awkward name, but I wanted to keep it 45 * separate from the pre-existing ProcessorWrapper that this replaces so we can 46 * ensure stability for Xalan testing while updating to this new class. 47 * 48 */ 49 public interface TransformWrapper { 50 /** 51 * URL for set/getAttribute: should be an integer to set for the output 52 * indent of the processor. 53 * 54 * This is a common enough attribute that most wrapper implementations 55 * should be able to support it in a straightforward manner. 56 */ 57 public static final String ATTRIBUTE_INDENT 58 = "http://xml.apache.org/xalan/wrapper/indent"; 59 60 /** 61 * URL for set/getAttribute: should be an Object to attempt to set as a 62 * diagnostic log/stream for the processor. 63 * 64 */ 65 public static final String ATTRIBUTE_DIAGNOSTICS 66 = "http://xml.apache.org/xalan/wrapper/diagnostics"; 67 68 /** 69 * Marker for Attributes to set on Processors. 70 * 71 * Options that startWith() this constant will actually be attempted to be 72 * set onto our underlying processor/transformer. 73 */ 74 public static final String SET_PROCESSOR_ATTRIBUTES 75 = "Processor.setAttribute."; 76 77 /** 78 * Get a specific description of the wrappered processor. 79 * 80 * @return specific description of the underlying processor or transformer 81 * implementation: this should include both the general product name, as 82 * well as specific version info. If possible, should be implemented without 83 * actively creating an underlying processor. 84 */ 85 public Properties getProcessorInfo(); 86 87 /** 88 * Actually create/initialize an underlying processor or factory. 89 * 90 * For TrAX/javax.xml.transform implementations, this creates a new 91 * TransformerFactory. For Xalan-J 1.x this creates an XSLTProcessor. Other 92 * implementations may or may not actually do any work in this method. 93 * 94 * @param options Properties of options, possibly specific to that 95 * implementation. For future use. 96 * 97 * @return (Object)getProcessor() as a side-effect, this will be null if 98 * there was any problem creating the processor OR if the underlying 99 * implementation doesn't use this 100 * @throws javax.xml.transform.TransformerConfigurationException when 101 * actual implementation can't initiate a TransformerFactory. 102 */ 103 public TransformerFactory newProcessor(Properties options) throws TransformerConfigurationException; 104 105 /** 106 * Transform supplied xmlName file with the stylesheet in the xslName file 107 * into a resultName file. 108 * 109 * Names are assumed to be local path\filename references, and will be 110 * converted to URLs as needed for any underlying processor implementation. 111 * 112 * @param xmlName local path\filename of XML file to transform 113 * @param xslName local path\filename of XSL stylesheet to use 114 * @param resultName local path\filename to put result in 115 * 116 * @throws Exception any underlying exceptions from the wrapped processor 117 * are simply allowed to propagate; throws a RuntimeException if any other 118 * problems prevent us from actually completing the operation 119 */ 120 public void transform(String xmlName, String xslName, String resultName) 121 throws Exception; 122 123 /** 124 * Pre-build/pre-compile a stylesheet. 125 * 126 * Although the actual mechanics are implementation-dependent, most 127 * processors have some method of pre-setting up the data needed by the 128 * stylesheet itself for later use in transforms. In 129 * TrAX/javax.xml.transform, this equates to creating a Templates object. 130 * 131 * Sets isStylesheetReady() to true if it succeeds. Users can then call 132 * transformWithStylesheet(xmlName, resultName) to actually perform a 133 * transformation with this pre-built stylesheet. 134 * 135 * @param xslName local path\filename of XSL stylesheet to use 136 * 137 * @throws Exception any underlying exceptions from the wrapped processor 138 * are simply allowed to propagate; throws a RuntimeException if any other 139 * problems prevent us from actually completing the operation 140 * 141 * @see #transformWithStylesheet(String xmlName, String resultName) 142 */ 143 public void buildStylesheet(String xslName) throws Exception; 144 145 /** 146 * Reports if a pre-built/pre-compiled stylesheet is ready; presumably built 147 * by calling buildStylesheet(xslName). 148 * 149 * @return true if one is ready; false otherwise 150 * 151 * @see #buildStylesheet(String xslName) 152 */ 153 public boolean isStylesheetReady(); 154 155 /** 156 * Transform supplied xmlName file with a pre-built/pre-compiled stylesheet 157 * into a resultName file. 158 * 159 * User must have called buildStylesheet(xslName) beforehand, obviously. 160 * Names are assumed to be local path\filename references, and will be 161 * converted to URLs as needed. 162 * 163 * @param xmlName local path\filename of XML file to transform 164 * @param resultName local path\filename to put result in 165 * 166 * @throws Exception any underlying exceptions from the wrappered processor 167 * are simply allowed to propagate; throws a RuntimeException if any other 168 * problems prevent us from actually completing the operation; throws an 169 * IllegalStateException if isStylesheetReady() == false. 170 * 171 * @see #buildStylesheet(String xslName) 172 */ 173 public void transformWithStylesheet(String xmlName, String resultName) 174 throws Exception; 175 176 /** 177 * Transform supplied xmlName file with a stylesheet found in an 178 * xml-stylesheet PI into a resultName file. 179 * 180 * Names are assumed to be local path\filename references, and will be 181 * converted to URLs as needed. Implementations will use whatever facilities 182 * exist in their wrapped processor to fetch and build the stylesheet to 183 * use for the transform. 184 * 185 * @param xmlName local path\filename of XML file to transform 186 * @param resultName local path\filename to put result in 187 * 188 * @throws Exception any underlying exceptions from the wrapped processor 189 * are simply allowed to propagate; throws a RuntimeException if any other 190 * problems prevent us from actually completing the operation 191 */ 192 public void transformEmbedded(String xmlName, String resultName) 193 throws Exception; 194 195 /** 196 * Set a stylesheet parameter for use in later transforms. 197 * 198 * This method merely stores the triple for use later in a transform 199 * operation. Note that the actual mechanisims for setting parameters in 200 * implementation differ, especially with regards to namespaces. 201 * 202 * Note that the namespace may not contain the "{" or "}" characters, since 203 * these would be illegal XML namespaces anyways; an 204 * IllegalArgumentException will be thrown; also the name must not be null. 205 * 206 * @param namespace for the parameter, must not contain {} 207 * @param name of the parameter, must not be null 208 * @param value of the parameter 209 * 210 * @throws IllegalArgumentException thrown if the namespace or name appears 211 * to be illegal. 212 */ 213 public void setParameter(String namespace, String name, String value) 214 throws IllegalArgumentException; 215 216 /** 217 * Get a parameter that was set with setParameter. 218 * 219 * Only returns parameters set locally, not parameters exposed by the 220 * underlying processor implementation. Not terribly useful but I like 221 * providing gets for any sets I define. 222 * 223 * @param namespace for the parameter, must not contain {} 224 * @param name of the parameter, must not be null 225 * 226 * @return value of the parameter; null if not found 227 */ 228 public Object getParameter(String namespace, String name); 229 230 /** 231 * Reset our parameters and wrapper state, and optionally force creation of 232 * a new underlying processor implementation. 233 * 234 * This always clears our built stylesheet and any parameters that have been 235 * set. If newProcessor is true, also forces a re-creation of our underlying 236 * processor as if by calling newProcessor(). 237 * 238 * @param newProcessor if we should reset our underlying processor 239 * implementation as well 240 */ 241 public void reset(boolean newProcessor); 242 }