blob: 3b07fcdd4ac9140215c4e6ec23fd342ae9d6513e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 Standards for Technology in Automotive Retail
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* David Carver - STAR - bug 224197 - initial API and implementation
* based on work from Apache Xalan 2.7.0
*******************************************************************************/
/*
* Copyright 1999-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
*
* 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.
*/
/*
* $Id: TransformerFactoryImpl.java,v 1.4 2008/03/28 02:38:16 dacarver Exp $
*/
package org.eclipse.wst.xsl.core.internal.compiler.xslt10.processor;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.xml.XMLConstants;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
//import javax.xml.transform.URIResolver;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TemplatesHandler;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.apache.xalan.res.XSLMessages;
import org.apache.xalan.res.XSLTErrorResources;
import org.apache.xalan.transformer.TrAXFilter;
import org.apache.xalan.transformer.TransformerIdentityImpl;
import org.apache.xalan.transformer.TransformerImpl;
import org.apache.xalan.transformer.XalanProperties;
import org.apache.xerces.xni.Augmentations;
import org.apache.xerces.xni.NamespaceContext;
import org.apache.xerces.xni.QName;
import org.apache.xerces.xni.XMLAttributes;
import org.apache.xerces.xni.XMLLocator;
import org.apache.xerces.xni.XMLResourceIdentifier;
import org.apache.xerces.xni.XNIException;
import org.apache.xerces.xni.parser.XMLEntityResolver;
import org.apache.xerces.xni.parser.XMLInputSource;
import org.apache.xml.utils.SystemIDResolver;
import org.apache.xml.utils.TreeWalker;
import org.apache.xml.utils.StylesheetPIHandler;
import org.apache.xml.utils.StopParseException;
import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin;
import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver;
import org.eclipse.wst.xml.core.internal.validation.core.LazyURLInputStream;
import org.w3c.dom.Node;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.XMLFilter;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* The TransformerFactoryImpl, which implements the TRaX TransformerFactory
* interface, processes XSLT stylesheets into a Templates object (a
* StylesheetRoot).
*/
public class TransformerFactoryImpl extends SAXTransformerFactory {
/**
* The path/filename of the property file: XSLTInfo.properties Maintenance
* note: see also
* <code>org.apache.xpath.functions.FuncSystemProperty.XSLT_PROPERTIES</code>
*/
public static final String XSLT_PROPERTIES = "org/apache/xalan/res/XSLTInfo.properties"; //$NON-NLS-1$
/**
* <p>
* State of secure processing feature.
* </p>
*/
private boolean m_isSecureProcessing = false;
private org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver uriResolver = URIResolverPlugin.createResolver();
/**
* Constructor TransformerFactoryImpl
*
*/
public TransformerFactoryImpl() {
}
/** Static string to be used for incremental feature */
public static final String FEATURE_INCREMENTAL = "http://xml.apache.org/xalan/features/incremental"; //$NON-NLS-1$
/** Static string to be used for optimize feature */
public static final String FEATURE_OPTIMIZE = "http://xml.apache.org/xalan/features/optimize"; //$NON-NLS-1$
/** Static string to be used for source_location feature */
public static final String FEATURE_SOURCE_LOCATION = XalanProperties.SOURCE_LOCATION;
/**
* @param node
* @return
* @throws TransformerConfigurationException
*/
public javax.xml.transform.Templates processFromNode(Node node)
throws TransformerConfigurationException {
try {
TemplatesHandler builder = newTemplatesHandler();
TreeWalker walker = new TreeWalker(builder,
new org.apache.xml.utils.DOM2Helper(), builder
.getSystemId());
walker.traverse(node);
return builder.getTemplates();
} catch (org.xml.sax.SAXException se) {
if (m_errorListener != null) {
try {
m_errorListener.fatalError(new TransformerException(se));
} catch (TransformerConfigurationException ex) {
throw ex;
} catch (TransformerException ex) {
throw new TransformerConfigurationException(ex);
}
return null;
} else {
// Should remove this later... but right now diagnostics from
// TransformerConfigurationException are not good.
// se.printStackTrace();
throw new TransformerConfigurationException(XSLMessages
.createMessage(
XSLTErrorResources.ER_PROCESSFROMNODE_FAILED,
null), se);
// "processFromNode failed", se);
}
} catch (TransformerConfigurationException tce) {
// Assume it's already been reported to the error listener.
throw tce;
}
/*
* catch (TransformerException tce) { // Assume it's already been
* reported to the error listener. throw new
* TransformerConfigurationException(tce.getMessage(), tce); }
*/
catch (Exception e) {
if (m_errorListener != null) {
try {
m_errorListener.fatalError(new TransformerException(e));
} catch (TransformerConfigurationException ex) {
throw ex;
} catch (TransformerException ex) {
throw new TransformerConfigurationException(ex);
}
return null;
} else {
// Should remove this later... but right now diagnostics from
// TransformerConfigurationException are not good.
// se.printStackTrace();
throw new TransformerConfigurationException(XSLMessages
.createMessage(
XSLTErrorResources.ER_PROCESSFROMNODE_FAILED,
null), e); // "processFromNode failed",
// e);
}
}
}
/**
* The systemID that was specified in processFromNode(Node node, String
* systemID).
*/
private String m_DOMsystemID = null;
/**
* The systemID that was specified in processFromNode(Node node, String
* systemID).
*
* @return The systemID, or null.
*/
public String getDOMsystemID() {
return m_DOMsystemID;
}
/**
* Process the stylesheet from a DOM tree, if the processor supports the
* "http://xml.org/trax/features/dom/input" feature.
*
* @param node
* A DOM tree which must contain valid transform instructions
* that this processor understands.
* @param systemID
* The systemID from where xsl:includes and xsl:imports should be
* resolved from.
*
* @return A Templates object capable of being used for transformation
* purposes.
*
* @throws TransformerConfigurationException
*/
public javax.xml.transform.Templates processFromNode(Node node,
String systemID) throws TransformerConfigurationException {
m_DOMsystemID = systemID;
return processFromNode(node);
}
/**
* Get InputSource specification(s) that are associated with the given
* document specified in the source param, via the xml-stylesheet processing
* instruction (see http://www.w3.org/TR/xml-stylesheet/), and that matches
* the given criteria. Note that it is possible to return several
* stylesheets that match the criteria, in which case they are applied as if
* they were a list of imports or cascades.
*
* <p>
* Note that DOM2 has it's own mechanism for discovering stylesheets.
* Therefore, there isn't a DOM version of this method.
* </p>
*
*
* @param source
* The XML source that is to be searched.
* @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 capable of being used to create a Templates
* object.
*
* @throws TransformerConfigurationException
*/
@Override
public Source getAssociatedStylesheet(Source source, String media,
String title, String charset)
throws TransformerConfigurationException {
String baseID;
InputSource isource = null;
Node node = null;
XMLReader reader = null;
if (source instanceof DOMSource) {
DOMSource dsource = (DOMSource) source;
node = dsource.getNode();
baseID = dsource.getSystemId();
} else {
isource = SAXSource.sourceToInputSource(source);
baseID = isource.getSystemId();
}
// What I try to do here is parse until the first startElement
// is found, then throw a special exception in order to terminate
// the parse.
StylesheetPIHandler handler = new StylesheetPIHandler(baseID, media,
title, charset);
// Use URIResolver. Patch from Dmitri Ilyin
if (m_uriResolver != null) {
handler.setURIResolver(m_uriResolver);
}
try {
if (null != node) {
TreeWalker walker = new TreeWalker(handler,
new org.apache.xml.utils.DOM2Helper(), baseID);
walker.traverse(node);
} else {
// Use JAXP1.1 ( if possible )
try {
javax.xml.parsers.SAXParserFactory factory = javax.xml.parsers.SAXParserFactory
.newInstance();
factory.setNamespaceAware(true);
if (m_isSecureProcessing) {
try {
factory.setFeature(
XMLConstants.FEATURE_SECURE_PROCESSING,
true);
} catch (org.xml.sax.SAXException e) {
}
}
javax.xml.parsers.SAXParser jaxpParser = factory
.newSAXParser();
reader = jaxpParser.getXMLReader();
} catch (javax.xml.parsers.ParserConfigurationException ex) {
throw new org.xml.sax.SAXException(ex);
} catch (javax.xml.parsers.FactoryConfigurationError ex1) {
throw new org.xml.sax.SAXException(ex1.toString());
} catch (NoSuchMethodError ex2) {
} catch (AbstractMethodError ame) {
}
if (null == reader) {
reader = XMLReaderFactory.createXMLReader();
}
// Need to set options!
reader.setContentHandler(handler);
reader.parse(isource);
}
} catch (StopParseException spe) {
// OK, good.
} catch (org.xml.sax.SAXException se) {
throw new TransformerConfigurationException(
"getAssociatedStylesheets failed", se);
} catch (IOException ioe) {
throw new TransformerConfigurationException(
"getAssociatedStylesheets failed", ioe);
}
return handler.getAssociatedStylesheet();
}
/**
* Create a new Transformer object that performs a copy of the source to the
* result.
*
* @return A Transformer object that may be used to perform a transformation
* in a single thread, never null.
*
* @throws TransformerConfigurationException
* May throw this during the parse when it is constructing the
* Templates object and fails.
*/
@Override
public TemplatesHandler newTemplatesHandler()
throws TransformerConfigurationException {
return new StylesheetHandler(this);
}
/**
* <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.
*/
@Override
public void setFeature(String name, boolean value)
throws TransformerConfigurationException {
// feature name cannot be null
if (name == null) {
throw new NullPointerException(XSLMessages.createMessage(
XSLTErrorResources.ER_SET_FEATURE_NULL_NAME, null));
}
// secure processing?
if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
m_isSecureProcessing = value;
}
// This implementation does not support the setting of a feature other
// than
// the secure processing feature.
else {
throw new TransformerConfigurationException(XSLMessages
.createMessage(XSLTErrorResources.ER_UNSUPPORTED_FEATURE,
new Object[] { name }));
}
}
/**
* Look up the value of a feature.
* <p>
* The feature name is any fully-qualified URI. It is possible for an
* TransformerFactory to recognize a feature name but to be unable to return
* its value; this is especially true in the case of an adapter for a SAX1
* Parser, which has no way of knowing whether the underlying parser is
* validating, for example.
* </p>
*
* @param name
* The feature name, which is a fully-qualified URI.
* @return The current state of the feature (true or false).
*/
@Override
public boolean getFeature(String name) {
// feature name cannot be null
if (name == null) {
throw new NullPointerException(XSLMessages.createMessage(
XSLTErrorResources.ER_GET_FEATURE_NULL_NAME, null));
}
// Try first with identity comparison, which
// will be faster.
if ((DOMResult.FEATURE == name) || (DOMSource.FEATURE == name)
|| (SAXResult.FEATURE == name) || (SAXSource.FEATURE == name)
|| (StreamResult.FEATURE == name)
|| (StreamSource.FEATURE == name)
|| (SAXTransformerFactory.FEATURE == name)
|| (SAXTransformerFactory.FEATURE_XMLFILTER == name))
return true;
else if ((DOMResult.FEATURE.equals(name))
|| (DOMSource.FEATURE.equals(name))
|| (SAXResult.FEATURE.equals(name))
|| (SAXSource.FEATURE.equals(name))
|| (StreamResult.FEATURE.equals(name))
|| (StreamSource.FEATURE.equals(name))
|| (SAXTransformerFactory.FEATURE.equals(name))
|| (SAXTransformerFactory.FEATURE_XMLFILTER.equals(name)))
return true;
// secure processing?
else if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING))
return m_isSecureProcessing;
else
// unknown feature
return false;
}
/**
* Flag set by FEATURE_OPTIMIZE. This feature specifies whether to Optimize
* stylesheet processing. By default it is set to true.
*/
private boolean m_optimize = true;
/**
* Flag set by FEATURE_SOURCE_LOCATION. This feature specifies whether the
* transformation phase should keep track of line and column numbers for the
* input source document. Note that this works only when that information is
* available from the source -- in other words, if you pass in a DOM,
* there's little we can do for you.
*
* The default is false. Setting it true may significantly increase storage
* cost per node.
*/
private boolean m_source_location = false;
/**
* Flag set by FEATURE_INCREMENTAL. This feature specifies whether to
* produce output incrementally, rather than waiting to finish parsing the
* input before generating any output. By default this attribute is set to
* false.
*/
private boolean m_incremental = false;
/**
* Allows the user to set specific attributes on the underlying
* implementation.
*
* @param name
* The name of the attribute.
* @param value
* The value of the attribute; Boolean or String="true"|"false"
*
* @throws IllegalArgumentException
* thrown if the underlying implementation doesn't recognize the
* attribute.
*/
@Override
public void setAttribute(String name, Object value)
throws IllegalArgumentException {
if (name.equals(FEATURE_INCREMENTAL)) {
if (value instanceof Boolean) {
// Accept a Boolean object..
m_incremental = ((Boolean) value).booleanValue();
} else if (value instanceof String) {
// .. or a String object
m_incremental = (new Boolean((String) value)).booleanValue();
} else {
// Give a more meaningful error message
throw new IllegalArgumentException(XSLMessages.createMessage(
XSLTErrorResources.ER_BAD_VALUE, new Object[] { name,
value })); // name + " bad value " + value);
}
} else if (name.equals(FEATURE_OPTIMIZE)) {
if (value instanceof Boolean) {
// Accept a Boolean object..
m_optimize = ((Boolean) value).booleanValue();
} else if (value instanceof String) {
// .. or a String object
m_optimize = (new Boolean((String) value)).booleanValue();
} else {
// Give a more meaningful error message
throw new IllegalArgumentException(XSLMessages.createMessage(
XSLTErrorResources.ER_BAD_VALUE, new Object[] { name,
value })); // name + " bad value " + value);
}
}
// Custom Xalan feature: annotate DTM with SAX source locator fields.
// This gets used during SAX2DTM instantiation.
//
// %REVIEW% Should the name of this field really be in XalanProperties?
// %REVIEW% I hate that it's a global static, but didn't want to change
// APIs yet.
else if (name.equals(FEATURE_SOURCE_LOCATION)) {
if (value instanceof Boolean) {
// Accept a Boolean object..
m_source_location = ((Boolean) value).booleanValue();
} else if (value instanceof String) {
// .. or a String object
m_source_location = (new Boolean((String) value))
.booleanValue();
} else {
// Give a more meaningful error message
throw new IllegalArgumentException(XSLMessages.createMessage(
XSLTErrorResources.ER_BAD_VALUE, new Object[] { name,
value })); // name + " bad value " + value);
}
}
else {
throw new IllegalArgumentException(XSLMessages.createMessage(
XSLTErrorResources.ER_NOT_SUPPORTED, new Object[] { name })); // name
// +
// "not
// supported");
}
}
/**
* Allows the user to retrieve specific attributes on the underlying
* implementation.
*
* @param name
* The name of the attribute.
* @return value The value of the attribute.
*
* @throws IllegalArgumentException
* thrown if the underlying implementation doesn't recognize the
* attribute.
*/
@Override
public Object getAttribute(String name) throws IllegalArgumentException {
if (name.equals(FEATURE_INCREMENTAL)) {
return new Boolean(m_incremental);
} else if (name.equals(FEATURE_OPTIMIZE)) {
return new Boolean(m_optimize);
} else if (name.equals(FEATURE_SOURCE_LOCATION)) {
return new Boolean(m_source_location);
} else
throw new IllegalArgumentException(XSLMessages.createMessage(
XSLTErrorResources.ER_ATTRIB_VALUE_NOT_RECOGNIZED,
new Object[] { name })); // name + " attribute not
// recognized");
}
/**
* 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
*/
@Override
public XMLFilter newXMLFilter(Source src)
throws TransformerConfigurationException {
Templates templates = newTemplates(src);
if (templates == null)
return null;
return newXMLFilter(templates);
}
/**
* Create an XMLFilter that uses the given source as the transformation
* instructions.
*
* @param templates
* non-null reference to Templates object.
*
* @return An XMLFilter object, or null if thi
*
*
* s feature is not supported.
*
* @throws TransformerConfigurationException
*/
@Override
public XMLFilter newXMLFilter(Templates templates)
throws TransformerConfigurationException {
try {
return new TrAXFilter(templates);
} catch (TransformerConfigurationException ex) {
if (m_errorListener != null) {
try {
m_errorListener.fatalError(ex);
return null;
} catch (TransformerConfigurationException ex1) {
throw ex1;
} catch (TransformerException ex1) {
throw new TransformerConfigurationException(ex1);
}
}
throw ex;
}
}
/**
* 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 TransformerHandler ready to transform SAX events.
*
* @throws TransformerConfigurationException
*/
@Override
public TransformerHandler newTransformerHandler(Source src)
throws TransformerConfigurationException {
Templates templates = newTemplates(src);
if (templates == null)
return null;
return newTransformerHandler(templates);
}
/**
* Get a TransformerHandler object that can process SAX ContentHandler
* events into a Result, based on the Templates argument.
*
* @param templates
* The source of the transformation instructions.
*
* @return TransformerHandler ready to transform SAX events.
* @throws TransformerConfigurationException
*/
@Override
public TransformerHandler newTransformerHandler(Templates templates)
throws TransformerConfigurationException {
try {
TransformerImpl transformer = (TransformerImpl) templates
.newTransformer();
transformer.setURIResolver(m_uriResolver);
TransformerHandler th = (TransformerHandler) transformer
.getInputContentHandler(true);
return th;
} catch (TransformerConfigurationException ex) {
if (m_errorListener != null) {
try {
m_errorListener.fatalError(ex);
return null;
} catch (TransformerConfigurationException ex1) {
throw ex1;
} catch (TransformerException ex1) {
throw new TransformerConfigurationException(ex1);
}
}
throw ex;
}
}
// /** The identity transform string, for support of newTransformerHandler()
// * and newTransformer(). */
// private static final String identityTransform =
// "<xsl:stylesheet " + "xmlns:xsl='http://www.w3.org/1999/XSL/Transform' "
// + "version='1.0'>" + "<xsl:template match='/|node()'>"
// + "<xsl:copy-of select='.'/>" + "</xsl:template>" + "</xsl:stylesheet>";
//
// /** The identity transform Templates, built from identityTransform,
// * for support of newTransformerHandler() and newTransformer(). */
// private static Templates m_identityTemplate = null;
/**
* Get a TransformerHandler object that can process SAX ContentHandler
* events into a Result.
*
* @return TransformerHandler ready to transform SAX events.
*
* @throws TransformerConfigurationException
*/
@Override
public TransformerHandler newTransformerHandler()
throws TransformerConfigurationException {
return new TransformerIdentityImpl(m_isSecureProcessing);
}
/**
* Process the source into a Transformer object. Care must be given to know
* that this object can not be used concurrently in multiple threads.
*
* @param source
* An object that holds a URL, input stream, etc.
*
* @return A Transformer object capable of being used for transformation
* purposes in a single thread.
*
* @throws TransformerConfigurationException
* May throw this during the parse when it is constructing the
* Templates object and fails.
*/
@Override
public Transformer newTransformer(Source source)
throws TransformerConfigurationException {
try {
Templates tmpl = newTemplates(source);
/*
* this can happen if an ErrorListener is present and it doesn't
* throw any exception in fatalError. The spec says: "a Transformer
* must use this interface instead of throwing an exception" - the
* newTemplates() does that, and returns null.
*/
if (tmpl == null)
return null;
Transformer transformer = tmpl.newTransformer();
transformer.setURIResolver(m_uriResolver);
return transformer;
} catch (TransformerConfigurationException ex) {
if (m_errorListener != null) {
try {
m_errorListener.fatalError(ex);
return null;
} catch (TransformerConfigurationException ex1) {
throw ex1;
} catch (TransformerException ex1) {
throw new TransformerConfigurationException(ex1);
}
}
throw ex;
}
}
/**
* Create a new Transformer object that performs a copy of the source to the
* result.
*
* @return A Transformer object capable of being used for transformation
* purposes in a single thread.
*
* @throws TransformerConfigurationException
* May throw this during the parse when it is constructing the
* Templates object and it fails.
*/
@Override
public Transformer newTransformer()
throws TransformerConfigurationException {
return new TransformerIdentityImpl(m_isSecureProcessing);
}
/**
* Process the source into a Templates object, which is likely a compiled
* representation of the source. This Templates object may then be used
* concurrently across multiple threads. Creating a Templates object allows
* the TransformerFactory to do detailed performance optimization of
* transformation instructions, without penalizing runtime transformation.
*
* @param source
* An object that holds a URL, input stream, etc.
* @return A Templates object capable of being used for transformation
* purposes.
*
* @throws TransformerConfigurationException
* May throw this during the parse when it is constructing the
* Templates object and fails.
*/
@Override
public Templates newTemplates(Source source)
throws TransformerConfigurationException {
String baseID = source.getSystemId();
if (null != baseID) {
baseID = SystemIDResolver.getAbsoluteURI(baseID);
}
if (source instanceof DOMSource) {
DOMSource dsource = (DOMSource) source;
Node node = dsource.getNode();
if (null != node)
return processFromNode(node, baseID);
else {
String messageStr = XSLMessages.createMessage(
XSLTErrorResources.ER_ILLEGAL_DOMSOURCE_INPUT, null);
throw new IllegalArgumentException(messageStr);
}
}
TemplatesHandler builder = newTemplatesHandler();
builder.setSystemId(baseID);
try {
InputSource isource = SAXSource.sourceToInputSource(source);
isource.setSystemId(baseID);
XMLReader reader = null;
if (source instanceof SAXSource)
reader = new org.apache.xerces.parsers.SAXParser()
{
private XMLLocator locator = null;
/* (non-Javadoc)
* @see org.apache.xerces.parsers.AbstractSAXParser#startDocument(org.apache.xerces.xni.XMLLocator, java.lang.String, org.apache.xerces.xni.NamespaceContext, org.apache.xerces.xni.Augmentations)
*/
public void startDocument(org.apache.xerces.xni.XMLLocator theLocator, java.lang.String encoding, NamespaceContext nscontext, org.apache.xerces.xni.Augmentations augs)
{
locator = theLocator;
super.startDocument(theLocator, encoding, nscontext, augs);
}
/* (non-Javadoc)
* @see org.apache.xerces.parsers.AbstractSAXParser#startElement(org.apache.xerces.xni.QName, org.apache.xerces.xni.XMLAttributes, org.apache.xerces.xni.Augmentations)
*/
public void startElement(QName arg0, XMLAttributes arg1, Augmentations arg2) throws XNIException
{
super.startElement(arg0, arg1, arg2);
}
/* (non-Javadoc)
* @see org.apache.xerces.parsers.AbstractSAXParser#endElement(org.apache.xerces.xni.QName, org.apache.xerces.xni.Augmentations)
*/
public void endElement(QName arg0, Augmentations arg1) throws XNIException {
super.endElement(arg0, arg1);
}
};
reader.setProperty("http://apache.org/xml/properties/internal/entity-resolver", new MyEntityResolver(uriResolver)); //$NON-NLS-1$
if (null == reader) {
// Use JAXP1.1 ( if possible )
try {
javax.xml.parsers.SAXParserFactory factory = javax.xml.parsers.SAXParserFactory
.newInstance();
factory.setNamespaceAware(true);
if (m_isSecureProcessing) {
try {
factory.setFeature(
XMLConstants.FEATURE_SECURE_PROCESSING,
true);
} catch (org.xml.sax.SAXException se) {
}
}
// TODO: Look at adding a custom SaxParser here to correctly
// handle
// Location information. This could be based off the SAX
// Parser Customizations done
// within WTP. In fact maybe do the same inner class
// creation as was done there.
javax.xml.parsers.SAXParser jaxpParser = factory
.newSAXParser();
reader = jaxpParser.getXMLReader();
} catch (javax.xml.parsers.ParserConfigurationException ex) {
throw new org.xml.sax.SAXException(ex);
} catch (javax.xml.parsers.FactoryConfigurationError ex1) {
throw new org.xml.sax.SAXException(ex1.toString());
} catch (NoSuchMethodError ex2) {
} catch (AbstractMethodError ame) {
}
}
if (null == reader)
reader = XMLReaderFactory.createXMLReader();
// If you set the namespaces to true, we'll end up getting double
// xmlns attributes. Needs to be fixed. -sb
// reader.setFeature("http://xml.org/sax/features/namespace-prefixes",
// true);
reader.setContentHandler(builder);
reader.parse(isource);
} catch (org.xml.sax.SAXException se) {
if (m_errorListener != null) {
try {
m_errorListener.fatalError(new TransformerException(se));
se.printStackTrace();
} catch (TransformerConfigurationException ex1) {
throw ex1;
} catch (TransformerException ex1) {
throw new TransformerConfigurationException(ex1);
}
} else {
throw new TransformerConfigurationException(se.getMessage(), se);
}
} catch (Exception e) {
if (m_errorListener != null) {
try {
m_errorListener.fatalError(new TransformerException(e));
e.printStackTrace();
return null;
} catch (TransformerConfigurationException ex1) {
throw ex1;
} catch (TransformerException ex1) {
throw new TransformerConfigurationException(ex1);
}
} else {
throw new TransformerConfigurationException(e.getMessage(), e);
}
}
return builder.getTemplates();
}
/**
* The object that implements the URIResolver interface, or null.
*/
private javax.xml.transform.URIResolver m_uriResolver;
/**
* Set an object that will be used to resolve URIs used in xsl:import, etc.
* This will be used as the default for the transformation.
*
* @param resolver
* An object that implements the URIResolver interface, or null.
*/
@Override
public void setURIResolver(javax.xml.transform.URIResolver resolver) {
m_uriResolver = resolver;
}
/**
* Get the object that will be used to resolve URIs used in xsl:import, etc.
* This will be used as the default for the transformation.
*
* @return The URIResolver that was set with setURIResolver.
*/
@Override
public javax.xml.transform.URIResolver getURIResolver() {
return m_uriResolver;
}
/** The error listener. */
private ErrorListener m_errorListener = new org.apache.xml.utils.DefaultErrorHandler(
false);
/**
* Get the error listener in effect for the TransformerFactory.
*
* @return A non-null reference to an error listener.
*/
@Override
public ErrorListener getErrorListener() {
return m_errorListener;
}
/**
* Set an error listener for the TransformerFactory.
*
* @param listener
* Must be a non-null reference to an ErrorListener.
*
* @throws IllegalArgumentException
* if the listener argument is null.
*/
@Override
public void setErrorListener(ErrorListener listener)
throws IllegalArgumentException {
if (null == listener)
throw new IllegalArgumentException(XSLMessages.createMessage(
XSLTErrorResources.ER_ERRORLISTENER, null));
// "ErrorListener");
m_errorListener = listener;
}
/**
* Return the state of the secure processing feature.
*
* @return state of the secure processing feature.
*/
public boolean isSecureProcessing() {
return m_isSecureProcessing;
}
/**
* A custom entity resolver that uses the URI resolver specified to resolve entities.
*/
protected class MyEntityResolver implements XMLEntityResolver
{
private URIResolver uriResolver;
/**
* Constructor.
*
* @param uriResolver The URI resolver to use with this entity resolver.
*/
public MyEntityResolver(URIResolver uriResolver)
{
this.uriResolver = uriResolver;
}
/* (non-Javadoc)
* @see org.apache.xerces.xni.parser.XMLEntityResolver#resolveEntity(org.apache.xerces.xni.XMLResourceIdentifier)
*/
public XMLInputSource resolveEntity(XMLResourceIdentifier rid) throws XNIException, IOException
{
try
{
return _internalResolveEntity(uriResolver, rid);
}
catch(IOException e)
{
//e.printStackTrace();
}
return null;
}
}
// cs : I've refactored the common SAX based resolution code into this method for use by other validators
// (i.e. XML Schema, WSDL etc). The other approach is maintain a copy for each validator that has
// identical code. In any case we should strive to ensure that the validators perform resolution consistently.
public static XMLInputSource _internalResolveEntity(URIResolver uriResolver, XMLResourceIdentifier rid) throws IOException
{
XMLInputSource is = null;
if (uriResolver != null)
{
String id = rid.getPublicId();
if(id == null)
{
id = rid.getNamespace();
}
org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver eclipseURI = (org.eclipse.wst.common.uriresolver.internal.provisional.URIResolver)uriResolver;
String location = null;
if (id != null || rid.getLiteralSystemId() != null)
{
location = eclipseURI.resolve(rid.getBaseSystemId(), id, rid.getLiteralSystemId());
}
if (location != null)
{
String physical = eclipseURI.resolvePhysicalLocation(rid.getBaseSystemId(), id, location);
is = new XMLInputSource(rid.getPublicId(), location, location);
// This block checks that the file exists. If it doesn't we need to throw
// an exception so Xerces will report an error. note: This may not be
// necessary with all versions of Xerces but has specifically been
// experienced with the version included in IBM's 1.4.2 JDK.
InputStream isTemp = null;
try
{
isTemp = new URL(physical).openStream();
}
finally
{
if(isTemp != null)
{
isTemp.close();
}
}
is.setByteStream(new LazyURLInputStream(physical));
}
}
return is;
}
}