/*
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
/*
* Copyright 2001-2004 The Apache Software Foundation.
*
* Licensed 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
*
*
* 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.
*/
/*
* $Id: TransformerFactoryImpl.java,v 1.8 2007/04/09 21:30:41 joehw Exp $
*/
/**
* Implementation of a JAXP1.1 TransformerFactory for Translets.
* @author G. Todd Miller
* @author Morten Jorgensen
* @author Santiago Pericas-Geertsen
*/
public class TransformerFactoryImpl
{
// Public constants for attributes supported by the XSLTC TransformerFactory.
/**
* This error listener is used only for this factory and is not passed to
* the Templates or Transformer objects that we create.
*/
/**
* This URIResolver is passed to all created Templates and Transformers
*/
/**
* As Gregor Samsa awoke one morning from uneasy dreams he found himself
* transformed in his bed into a gigantic insect. He was lying on his hard,
* as it were armour plated, back, and if he lifted his head a little he
* could see his big, brown belly divided into stiff, arched segments, on
* top of which the bed quilt could hardly keep in position and was about
* to slide off completely. His numerous legs, which were pitifully thin
* compared to the rest of his bulk, waved helplessly before his eyes.
* "What has happened to me?", he thought. It was no dream....
*/
/**
* The class name of the translet
*/
/**
* The destination directory for the translet
*/
/**
* The package name prefix for all generated translet classes
*/
/**
* The jar file name which the translet classes are packaged into
*/
/**
* This Hashtable is used to store parameters for locating
* <?xml-stylesheet ...?> processing instructions in XML docs.
*/
/**
* The above hashtable stores objects of this class.
*/
private static class PIParamWrapper {
}
}
/**
* Set to <code>true</code> when debugging is enabled.
*/
private boolean _debug = false;
/**
* Set to <code>true</code> when templates are inlined.
*/
private boolean _enableInlining = false;
/**
* Set to <code>true</code> when we want to generate
* translet classes from the stylesheet.
*/
private boolean _generateTranslet = false;
/**
* If this is set to <code>true</code>, we attempt to use translet classes
* for transformation if possible without compiling the stylesheet. The
* translet class is only used if its timestamp is newer than the timestamp
* of the stylesheet.
*/
private boolean _autoTranslet = false;
/**
* If this is set to <code>true</code>, we attempt to load the translet
* from the CLASSPATH.
*/
private boolean _useClasspath = false;
/**
* Number of indent spaces when indentation is turned on.
*/
/**
* The provider of the XSLTC DTM Manager service. This is fixed for any
* instance of this class. In order to change service providers, a new
* XSLTC <code>TransformerFactory</code> must be instantiated.
* @see XSLTCDTMManager#getDTMManagerClass()
*/
/**
* <p>State of secure processing feature.</p>
*/
private boolean _isNotSecureProcessing = true;
/**
* <p>State of secure mode.</p>
*/
private boolean _isSecureMode = false;
/**
* Indicates whether implementation parts should use
* service loader (or similar).
* Note the default value (false) is the safe option..
*/
private boolean _useServicesMechanism;
/**
* protocols allowed for external references set by the stylesheet processing instruction, Import and Include element.
*/
/**
*/
/**
* javax.xml.transform.sax.TransformerFactory implementation.
*/
public TransformerFactoryImpl() {
this(true);
}
return new TransformerFactoryImpl(false);
}
_isSecureMode = true;
_isNotSecureProcessing = false;
}
}
/**
* javax.xml.transform.sax.TransformerFactory implementation.
* Set the error event listener for the TransformerFactory, which is used
* for the processing of transformation instructions, and not for the
* transformation itself.
*
* @param listener The error listener to use with the TransformerFactory
* @throws IllegalArgumentException
*/
throws IllegalArgumentException
{
"TransformerFactory");
}
}
/**
* javax.xml.transform.sax.TransformerFactory implementation.
* Get the error event handler for the TransformerFactory.
*
* @return The error listener used with the TransformerFactory
*/
return _errorListener;
}
/**
* javax.xml.transform.sax.TransformerFactory implementation.
* Returns the value set for a TransformerFactory attribute
*
* @param name The attribute name
* @return An object representing the attribute value
* @throws IllegalArgumentException
*/
throws IllegalArgumentException
{
// Return value for attribute 'translet-name'
return _transletName;
}
return new Boolean(_generateTranslet);
}
return new Boolean(_autoTranslet);
}
if (_enableInlining)
else
}
return _accessExternalStylesheet;
}
return _accessExternalDTD;
}
// Throw an exception for all other attributes
}
/**
* javax.xml.transform.sax.TransformerFactory implementation.
* Sets the value for a TransformerFactory attribute.
*
* @param name The attribute name
* @param value An object representing the attribute value
* @throws IllegalArgumentException
*/
throws IllegalArgumentException
{
// Set the default translet name (ie. class name), which will be used
// for translets that cannot be given a name from their system-id.
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
}
return;
}
return;
}
}
return;
}
return;
}
}
return;
}
return;
}
}
return;
}
return;
}
}
try {
return;
}
catch (NumberFormatException e) {
// Falls through
}
}
return;
}
}
return;
}
return;
}
// Throw an exception for all other attributes
}
/**
* <p>Set a feature for this <code>TransformerFactory</code> and <code>Transformer</code>s
* or <code>Template</code>s created by this factory.</p>
*
* <p>
* Feature names are fully qualified {@link java.net.URI}s.
* Implementations may define their own features.
* An {@link TransformerConfigurationException} is thrown if this <code>TransformerFactory</code> or the
* <code>Transformer</code>s or <code>Template</code>s it creates cannot support the feature.
* It is possible for an <code>TransformerFactory</code> to expose a feature value but be unable to change its state.
* </p>
*
* <p>See {@link javax.xml.transform.TransformerFactory} for full documentation of specific features.</p>
*
* @param name Feature name.
* @param value Is feature state <code>true</code> or <code>false</code>.
*
* @throws TransformerConfigurationException if this <code>TransformerFactory</code>
* or the <code>Transformer</code>s or <code>Template</code>s it creates cannot support this feature.
* @throws NullPointerException If the <code>name</code> parameter is null.
*/
throws TransformerConfigurationException {
// feature name cannot be null
}
// secure processing?
if ((_isSecureMode) && (!value)) {
}
// set restriction, allowing no access to external stylesheet
if (value) {
}
return;
}
//in secure mode, let _useServicesMechanism be determined by the constructor
if (!_isSecureMode)
}
else {
// unknown feature
}
}
/**
* javax.xml.transform.sax.TransformerFactory implementation.
* Look up the value of a feature (to see if it is supported).
* This method must be updated as the various methods and features of this
* class are implemented.
*
* @param name The feature name
* @return 'true' if feature is supported, 'false' if not
*/
// All supported features should be listed here
};
// feature name cannot be null
}
// Inefficient, but array is small
return true;
}
}
// secure processing?
return !_isNotSecureProcessing;
}
// Feature not supported
return false;
}
/**
* Return the state of the services mechanism feature.
*/
public boolean useServicesMechnism() {
return _useServicesMechanism;
}
/**
* javax.xml.transform.sax.TransformerFactory implementation.
* Get the object that is used by default during the transformation to
* resolve URIs used in document(), xsl:import, or xsl:include.
*
* @return The URLResolver used for this TransformerFactory and all
* Templates and Transformer objects created using this factory
*/
return _uriResolver;
}
/**
* javax.xml.transform.sax.TransformerFactory implementation.
* Set the object that is used by default during the transformation to
* resolve URIs used in document(), xsl:import, or xsl:include. Note that
* this does not affect Templates and Transformers that are already
* created with this factory.
*
* @param resolver The URLResolver used for this TransformerFactory and all
* Templates and Transformer objects created using this factory
*/
}
/**
* javax.xml.transform.sax.TransformerFactory implementation.
* Get the stylesheet specification(s) associated via the xml-stylesheet
* processing instruction (see http://www.w3.org/TR/xml-stylesheet/) with
* the document document specified in the source parameter, and that match
* the given criteria.
*
* @param source The XML source document.
* @param media The media attribute to be matched. May be null, in which
* case the prefered templates will be used (i.e. alternate = no).
* @param title The value of the title attribute to match. May be null.
* @param charset The value of the charset attribute to match. May be null.
* @return A Source object suitable for passing to the TransformerFactory.
* @throws TransformerConfigurationException
*/
throws TransformerConfigurationException {
/**
* Fix for bugzilla bug 24187
*/
try {
} else {
factory.setNamespaceAware(true);
if (!_isNotSecureProcessing) {
try {
}
}
}
}
if (_uriResolver != null ) {
}
} catch (StopParseException e ) {
// startElement encountered so do not parse further
throw new TransformerConfigurationException(
"getAssociatedStylesheets failed", e);
throw new TransformerConfigurationException(
"getAssociatedStylesheets failed", se);
} catch (IOException ioe ) {
throw new TransformerConfigurationException(
"getAssociatedStylesheets failed", ioe);
}
return _stylesheetPIHandler.getAssociatedStylesheet();
}
/**
* javax.xml.transform.sax.TransformerFactory implementation.
* Create a Transformer object that copies the input document to the result.
*
* @return A Transformer object that simply copies the source to the result.
* @throws TransformerConfigurationException
*/
{
_indentNumber, this);
if (_uriResolver != null) {
}
if (!_isNotSecureProcessing) {
result.setSecureProcessing(true);
}
return result;
}
/**
* javax.xml.transform.sax.TransformerFactory implementation.
* Process the Source into a Templates object, which is a a compiled
* representation of the source. Note that this method should not be
* used with XSLTC, as the time-consuming compilation is done for each
* and every transformation.
*
* @return A Templates object that can be used to create Transformers.
* @throws TransformerConfigurationException
*/
{
if (_uriResolver != null) {
}
return(transformer);
}
/**
* Pass warning messages from the compiler to the error listener
*/
throws TransformerException
{
return;
}
// Pass messages to listener, one by one
// Workaround for the TCK failure ErrorListener.errorTests.error001.
if (msg.isWarningError())
else
}
}
/**
* Pass error messages from the compiler to the error listener
*/
try {
return;
}
// Pass messages to listener, one by one
}
}
catch (TransformerException e) {
// nada
}
}
/**
* javax.xml.transform.sax.TransformerFactory implementation.
* Process the Source into a Templates object, which is a a compiled
* representation of the source.
*
* @param source The input stylesheet - DOMSource not supported!!!
* @return A Templates object that can be used to create Transformers.
* @throws TransformerConfigurationException
*/
{
// If the _useClasspath attribute is true, try to load the translet from
// the CLASSPATH and create a template object using the loaded
// translet.
if (_useClasspath) {
if (_packageName != null)
try {
}
catch (ClassNotFoundException cnfe) {
}
catch (Exception e) {
+ e.getMessage());
}
}
// If _autoTranslet is true, we will try to load the bytecodes
// from the translet classes without compiling the stylesheet.
if (_autoTranslet) {
if (_packageName != null)
if (_jarFileName != null)
else
if (_debug) {
if (_jarFileName != null)
else
}
// Reset the per-session attributes to their default values
// after each newTemplates() call.
}
}
// Create and initialize a stylesheet compiler
if (_enableInlining)
xsltc.setTemplateInlining(true);
else
xsltc.setTemplateInlining(false);
if (_uriResolver != null) {
xsltc.setSourceLoader(this);
}
// Pass parameters to the Parser to make sure it locates the correct
// <?xml-stylesheet ...?> PI in an XML input document
// Get the parameters for this Source object
// Pass them on to the compiler (which will pass then to the parser)
if (p != null) {
}
}
// Set the attributes for translet generation
if (_generateTranslet || _autoTranslet) {
// Set the translet name
if (_destinationDirectory != null)
else {
}
}
if (_packageName != null)
if (_jarFileName != null) {
}
else
}
// Compile the stylesheet
// Output to the jar file if the jar file name is set.
if ((_generateTranslet || _autoTranslet)
try {
xsltc.outputToJar();
}
}
// Reset the per-session attributes to their default values
// after each newTemplates() call.
// Pass compiler warnings to the error listener
if (_errorListener != this) {
try {
}
catch (TransformerException e) {
throw new TransformerConfigurationException(e);
}
}
else {
}
// Check that the transformation went well before returning
} else {
}
} else {
}
// Pass compiler errors to the error listener
if (_errorListener != null) {
// As required by TCK 1.2, send a fatalError to the
// error listener because compilation of the stylesheet
// failed and no further processing will be possible.
try {
} catch (TransformerException te) {
// well, we tried.
}
}
else {
xsltc.printErrors();
}
throw exc;
}
}
/**
* javax.xml.transform.sax.SAXTransformerFactory implementation.
* Get a TemplatesHandler object that can process SAX ContentHandler
* events into a Templates object.
*
* @return A TemplatesHandler object that can handle SAX events
* @throws TransformerConfigurationException
*/
{
final TemplatesHandlerImpl handler =
new TemplatesHandlerImpl(_indentNumber, this);
if (_uriResolver != null) {
}
return handler;
}
/**
* javax.xml.transform.sax.SAXTransformerFactory implementation.
* Get a TransformerHandler object that can process SAX ContentHandler
* events into a Result. This method will return a pure copy transformer.
*
* @return A TransformerHandler object that can handle SAX events
* @throws TransformerConfigurationException
*/
{
if (_uriResolver != null) {
}
}
/**
* javax.xml.transform.sax.SAXTransformerFactory implementation.
* Get a TransformerHandler object that can process SAX ContentHandler
* events into a Result, based on the transformation instructions
* specified by the argument.
*
* @param src The source of the transformation instructions.
* @return A TransformerHandler object that can handle SAX events
* @throws TransformerConfigurationException
*/
{
if (_uriResolver != null) {
}
}
/**
* javax.xml.transform.sax.SAXTransformerFactory implementation.
* Get a TransformerHandler object that can process SAX ContentHandler
* events into a Result, based on the transformation instructions
* specified by the argument.
*
* @param templates Represents a pre-processed stylesheet
* @return A TransformerHandler object that can handle SAX events
* @throws TransformerConfigurationException
*/
{
return new TransformerHandlerImpl(internal);
}
/**
* javax.xml.transform.sax.SAXTransformerFactory implementation.
* Create an XMLFilter that uses the given source as the
* transformation instructions.
*
* @param src The source of the transformation instructions.
* @return An XMLFilter object, or null if this feature is not supported.
* @throws TransformerConfigurationException
*/
{
return newXMLFilter(templates);
}
/**
* javax.xml.transform.sax.SAXTransformerFactory implementation.
* Create an XMLFilter that uses the given source as the
* transformation instructions.
*
* @param templates The source of the transformation instructions.
* @return An XMLFilter object, or null if this feature is not supported.
* @throws TransformerConfigurationException
*/
{
try {
}
catch (TransformerConfigurationException e1) {
if (_errorListener != null) {
try {
return null;
}
catch (TransformerException e2) {
}
}
throw e1;
}
}
/**
* Receive notification of a recoverable error.
* The transformer must continue to provide normal parsing events after
* invoking this method. It should still be possible for the application
* to process the document through to the end.
*
* @param e The warning information encapsulated in a transformer
* exception.
* @throws TransformerException if the application chooses to discontinue
* the transformation (always does in our case).
*/
throws TransformerException
{
wrapped.getMessage()));
} else {
e.getMessageAndLocation()));
}
throw e;
}
/**
* Receive notification of a non-recoverable error.
* The application must assume that the transformation cannot continue
* after the Transformer has invoked this method, and should continue
* (if at all) only to collect addition error messages. In fact,
* Transformers are free to stop reporting events once this method has
* been invoked.
*
* @param e warning information encapsulated in a transformer
* exception.
* @throws TransformerException if the application chooses to discontinue
* the transformation (always does in our case).
*/
throws TransformerException
{
wrapped.getMessage()));
} else {
e.getMessageAndLocation()));
}
throw e;
}
/**
* Receive notification of a warning.
* Transformers can use this method to report conditions that are not
* errors or fatal errors. The default behaviour is to take no action.
* After invoking this method, the Transformer must continue with the
* transformation. It should still be possible for the application to
* process the document through to the end.
*
* @param e The warning information encapsulated in a transformer
* exception.
* @throws TransformerException if the application chooses to discontinue
* the transformation (never does in our case).
*/
throws TransformerException
{
wrapped.getMessage()));
} else {
e.getMessageAndLocation()));
}
}
/**
* This method implements XSLTC's SourceLoader interface. It is used to
* glue a TrAX URIResolver to the XSLTC compiler's Input and Import classes.
*
* @param href The URI of the document to load
* @param context The URI of the currently loaded document
* @param xsltc The compiler that resuests the document
* @return An InputSource with the loaded document
*/
try {
if (_uriResolver != null) {
}
}
}
catch (TransformerException e) {
// should catch it when the resolver explicitly throws the exception
}
return null;
}
/**
* Reset the per-session attributes to their default values
*/
private void resetTransientAttributes() {
_packageName = null;
_jarFileName = null;
}
/**
* Load the translet classes from local .class files and return
* the bytecode array.
*
* @param source The xsl source
* @param fullClassName The full name of the translet
* @return The bytecode array
*/
{
if (fullClassName == null)
return null;
if (xslFileName != null)
// Find the base name of the translet
final String transletName;
if (lastDotIndex > 0)
else
// Construct the path name for the translet class file
if (_destinationDirectory != null) {
}
else {
else
}
// Return null if the translet class file does not exist.
if (!transletFile.exists())
return null;
// Compare the timestamps of the translet and the xsl file.
// If the translet is older than the xsl file, return null
// so that the xsl file is used for the transformation and
// the translet is regenerated.
if (transletTimestamp < xslTimestamp)
return null;
}
// Load the translet into a bytecode array.
if (fileLength > 0) {
try {
}
catch (FileNotFoundException e) {
return null;
}
byte[] bytes = new byte[fileLength];
try {
}
catch (IOException e) {
return null;
}
}
else
return null;
// Find the parent directory of the translet.
if (transletParentDir == null)
// Find all the auxiliary files which have a name pattern of "transletClass$nnn.class".
{
}
});
// Load the auxiliary class files and add them to the bytecode array.
{
if (auxlength > 0) {
try {
}
catch (FileNotFoundException e) {
continue;
}
try {
}
catch (IOException e) {
continue;
}
}
}
// Convert the Vector of byte[] to byte[][].
if ( count > 0) {
for (int i = 0; i < count; i++) {
}
return result;
}
else
return null;
}
/**
* Load the translet classes from the jar file and return the bytecode.
*
* @param source The xsl source
* @param fullClassName The full name of the translet
* @return The bytecode array
*/
{
if (xslFileName != null)
// Construct the path for the jar file
if (_destinationDirectory != null)
else {
else
}
// Return null if the jar file does not exist.
return null;
// Compare the timestamps of the jar file and the xsl file. Return null
// if the xsl file is newer than the jar file.
if (transletTimestamp < xslTimestamp)
return null;
}
// Create a ZipFile object for the jar file
try {
}
catch (IOException e) {
return null;
}
// Iterate through all entries in the jar file to find the
// translet and auxiliary classes.
while (entries.hasMoreElements())
{
{
try {
}
catch (IOException e) {
return null;
}
}
}
// Convert the Vector of byte[] to byte[][].
if (count > 0) {
for (int i = 0; i < count; i++) {
}
return result;
}
else
return null;
}
/**
* Read a given number of bytes from the InputStream into a byte array.
*
* @param bytes The byte array to store the input content.
* @param input The input stream.
* @param size The number of bytes to read.
*/
throws IOException
{
int n = 0;
int offset = 0;
}
}
/**
* Return the base class name of the translet.
* The translet name is resolved using the following rules:
* 1. if the _transletName attribute is set and its value is not "GregorSamsa",
* then _transletName is returned.
* 2. otherwise get the translet name from the base name of the system ID
* 3. return "GregorSamsa" if the result from step 2 is null.
*
* @param source The input Source
* @return The name of the translet class
*/
{
return _transletName;
else {
}
}
}
}
/**
* Return the local file name from the systemId of the Source object
*
* @param source The Source
* @return The file name in the local filesystem, or null if the
* systemId does not represent a local file.
*/
{
return systemId;
else {
try {
}
catch (MalformedURLException e) {
return null;
}
else
return null;
}
}
else
return null;
}
/**
* Returns the Class object the provides the XSLTC DTM Manager service.
*/
return m_DTMManagerClass;
}
}