/* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.qetest.xslwrapper; import java.util.Properties; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerFactory; /** * Helper interface to wrapper various XSLT processors for testing. * * A TransformWrapper wraps a particular 'flavor' of XSLT processing. This * includes both a particular XSLT implementation, such as Xalan or Saxon, as * well as a particular method to perform processing, like using streams or DOMs * to perform transforms. * * As an important side effect, this class should return timing information * about the steps done to perform the transformation. Note that exactly what is * timed and how it's timed should be clearly documented in implementing * classes! * * This is not a general-purpose wrapper for doing XSLT transformations: for * that, you might as well use the real javax.xml.transform package itself. * However this does allow many conformance and performance tests to run * comparatively between different flavors of processors. * * TransformWrapper is a bit of an awkward name, but I wanted to keep it * separate from the pre-existing ProcessorWrapper that this replaces so we can * ensure stability for Xalan testing while updating to this new class. * */ public interface TransformWrapper { /** * URL for set/getAttribute: should be an integer to set for the output * indent of the processor. * * This is a common enough attribute that most wrapper implementations * should be able to support it in a straightforward manner. */ public static final String ATTRIBUTE_INDENT = "http://xml.apache.org/xalan/wrapper/indent"; /** * URL for set/getAttribute: should be an Object to attempt to set as a * diagnostic log/stream for the processor. * */ public static final String ATTRIBUTE_DIAGNOSTICS = "http://xml.apache.org/xalan/wrapper/diagnostics"; /** * Marker for Attributes to set on Processors. * * Options that startWith() this constant will actually be attempted to be * set onto our underlying processor/transformer. */ public static final String SET_PROCESSOR_ATTRIBUTES = "Processor.setAttribute."; /** * Get a specific description of the wrappered processor. * * @return specific description of the underlying processor or transformer * implementation: this should include both the general product name, as * well as specific version info. If possible, should be implemented without * actively creating an underlying processor. */ public Properties getProcessorInfo(); /** * Actually create/initialize an underlying processor or factory. * * For TrAX/javax.xml.transform implementations, this creates a new * TransformerFactory. For Xalan-J 1.x this creates an XSLTProcessor. Other * implementations may or may not actually do any work in this method. * * @param options Properties of options, possibly specific to that * implementation. For future use. * * @return (Object)getProcessor() as a side-effect, this will be null if * there was any problem creating the processor OR if the underlying * implementation doesn't use this * @throws javax.xml.transform.TransformerConfigurationException when * actual implementation can't initiate a TransformerFactory. */ public TransformerFactory newProcessor(Properties options) throws TransformerConfigurationException; /** * Transform supplied xmlName file with the stylesheet in the xslName file * into a resultName file. * * Names are assumed to be local path\filename references, and will be * converted to URLs as needed for any underlying processor implementation. * * @param xmlName local path\filename of XML file to transform * @param xslName local path\filename of XSL stylesheet to use * @param resultName local path\filename to put result in * * @throws Exception any underlying exceptions from the wrapped processor * are simply allowed to propagate; throws a RuntimeException if any other * problems prevent us from actually completing the operation */ public void transform(String xmlName, String xslName, String resultName) throws Exception; /** * Pre-build/pre-compile a stylesheet. * * Although the actual mechanics are implementation-dependent, most * processors have some method of pre-setting up the data needed by the * stylesheet itself for later use in transforms. In * TrAX/javax.xml.transform, this equates to creating a Templates object. * * Sets isStylesheetReady() to true if it succeeds. Users can then call * transformWithStylesheet(xmlName, resultName) to actually perform a * transformation with this pre-built stylesheet. * * @param xslName local path\filename of XSL stylesheet to use * * @throws Exception any underlying exceptions from the wrapped processor * are simply allowed to propagate; throws a RuntimeException if any other * problems prevent us from actually completing the operation * * @see #transformWithStylesheet(String xmlName, String resultName) */ public void buildStylesheet(String xslName) throws Exception; /** * Reports if a pre-built/pre-compiled stylesheet is ready; presumably built * by calling buildStylesheet(xslName). * * @return true if one is ready; false otherwise * * @see #buildStylesheet(String xslName) */ public boolean isStylesheetReady(); /** * Transform supplied xmlName file with a pre-built/pre-compiled stylesheet * into a resultName file. * * User must have called buildStylesheet(xslName) beforehand, obviously. * Names are assumed to be local path\filename references, and will be * converted to URLs as needed. * * @param xmlName local path\filename of XML file to transform * @param resultName local path\filename to put result in * * @throws Exception any underlying exceptions from the wrappered processor * are simply allowed to propagate; throws a RuntimeException if any other * problems prevent us from actually completing the operation; throws an * IllegalStateException if isStylesheetReady() == false. * * @see #buildStylesheet(String xslName) */ public void transformWithStylesheet(String xmlName, String resultName) throws Exception; /** * Transform supplied xmlName file with a stylesheet found in an * xml-stylesheet PI into a resultName file. * * Names are assumed to be local path\filename references, and will be * converted to URLs as needed. Implementations will use whatever facilities * exist in their wrapped processor to fetch and build the stylesheet to * use for the transform. * * @param xmlName local path\filename of XML file to transform * @param resultName local path\filename to put result in * * @throws Exception any underlying exceptions from the wrapped processor * are simply allowed to propagate; throws a RuntimeException if any other * problems prevent us from actually completing the operation */ public void transformEmbedded(String xmlName, String resultName) throws Exception; /** * Set a stylesheet parameter for use in later transforms. * * This method merely stores the triple for use later in a transform * operation. Note that the actual mechanisims for setting parameters in * implementation differ, especially with regards to namespaces. * * Note that the namespace may not contain the "{" or "}" characters, since * these would be illegal XML namespaces anyways; an * IllegalArgumentException will be thrown; also the name must not be null. * * @param namespace for the parameter, must not contain {} * @param name of the parameter, must not be null * @param value of the parameter * * @throws IllegalArgumentException thrown if the namespace or name appears * to be illegal. */ public void setParameter(String namespace, String name, String value) throws IllegalArgumentException; /** * Get a parameter that was set with setParameter. * * Only returns parameters set locally, not parameters exposed by the * underlying processor implementation. Not terribly useful but I like * providing gets for any sets I define. * * @param namespace for the parameter, must not contain {} * @param name of the parameter, must not be null * * @return value of the parameter; null if not found */ public Object getParameter(String namespace, String name); /** * Reset our parameters and wrapper state, and optionally force creation of * a new underlying processor implementation. * * This always clears our built stylesheet and any parameters that have been * set. If newProcessor is true, also forces a re-creation of our underlying * processor as if by calling newProcessor(). * * @param newProcessor if we should reset our underlying processor * implementation as well */ public void reset(boolean newProcessor); }