1 /*
   2  * Copyright (c) 2014, 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 }