blob: 40c424c9c79921ca4c18951f15b8eaa19e223827 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007 Chase Technology Ltd - http://www.chasetechnology.co.uk
* 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:
* Doug Satchwell (Chase Technology Ltd) - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.xsl.jaxp.debug.invoker.internal;
import java.net.URL;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.URIResolver;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.wst.xsl.jaxp.debug.invoker.IProcessorInvoker;
import org.eclipse.wst.xsl.jaxp.debug.invoker.TransformationException;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;
/**
* An implementation of <code>IProcessorInvoker</code> that uses JAXP as the underlying
* transformation mechanism.
*
* @author Doug Satchwell
*/
public class JAXPSAXProcessorInvoker implements IProcessorInvoker
{
private static final Log log = LogFactory.getLog(JAXPSAXProcessorInvoker.class);
private XMLReader reader;
private SAXTransformerFactory tFactory;
private TransformerHandler th;
/**
* Create a new instance of this.
*
* @throws SAXException if errors occur while creating an <code>XMLReader</code>
* @throws ParserConfigurationException if errors occur while creating an <code>XMLReader</code>
*/
public JAXPSAXProcessorInvoker() throws SAXException, ParserConfigurationException
{
reader = createReader();
}
protected XMLReader createReader() throws SAXException, ParserConfigurationException
{
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
return spf.newSAXParser().getXMLReader();
}
public void setAttributes(Map attributes) throws TransformerFactoryConfigurationError
{
createTransformerFactory();
for (Iterator iter = attributes.entrySet().iterator(); iter.hasNext();)
{
Map.Entry entry = (Map.Entry) iter.next();
String uri = (String) entry.getKey();
Object value = entry.getValue();
log.info(Messages.getString("JAXPSAXProcessorInvoker.0") + uri + Messages.getString("JAXPSAXProcessorInvoker.1") + value); //$NON-NLS-1$ //$NON-NLS-2$
tFactory.setAttribute(uri, value);
}
}
protected TransformerFactory createTransformerFactory()
{
tFactory = (SAXTransformerFactory) TransformerFactory.newInstance();
tFactory.setErrorListener(new ErrorListener()
{
public void error(TransformerException exception) throws TransformerException
{
log.error(exception.getMessageAndLocation());
}
public void fatalError(TransformerException exception) throws TransformerException
{
log.error(exception.getMessageAndLocation(), exception);
throw exception;
}
public void warning(TransformerException exception) throws TransformerException
{
log.warn(exception.getMessageAndLocation());
}
});
return tFactory;
}
public void addStylesheet(URL stylesheet, Map parameters, Properties outputProperties, URIResolver resolver) throws TransformerConfigurationException
{
InputSource inputsource = new InputSource(stylesheet.toString());
// TODO parse document with linenumbers
// XMLReader reader = createReader();
// LineReadingContentHandler ch = new LineReadingContentHandler();
// reader.setContentHandler(ch);
SAXSource source = new SAXSource(inputsource);
addStylesheet(source, resolver, parameters, outputProperties);
}
protected Transformer addStylesheet(Source source, URIResolver resolver, Map parameters, Properties outputProperties) throws TransformerConfigurationException
{
if (tFactory == null)
createTransformerFactory();
TransformerHandler newTh = tFactory.newTransformerHandler(source);
Transformer transformer = newTh.getTransformer();
if (resolver != null)
transformer.setURIResolver(resolver);
if (parameters != null)
{
for (Iterator iter = parameters.entrySet().iterator(); iter.hasNext();)
{
Map.Entry entry = (Map.Entry) iter.next();
String name = (String) entry.getKey();
Object value = entry.getValue();
log.info(Messages.getString("JAXPSAXProcessorInvoker.2") + name + Messages.getString("JAXPSAXProcessorInvoker.3") + value); //$NON-NLS-1$ //$NON-NLS-2$
transformer.setParameter(name, value);
}
}
if (outputProperties != null)
{
StringBuffer sb = new StringBuffer();
for (Iterator iter = outputProperties.entrySet().iterator(); iter.hasNext();)
{
Map.Entry entry = (Map.Entry) iter.next();
sb.append(entry.getKey()).append("=").append(entry.getValue()).append(" "); //$NON-NLS-1$ //$NON-NLS-2$
}
if (outputProperties.size() > 0)
{
log.info(Messages.getString("JAXPSAXProcessorInvoker.6") + sb.toString()); //$NON-NLS-1$
transformer.setOutputProperties(outputProperties);
}
}
if (th != null)
th.setResult(new SAXResult(newTh));
else {
reader.setContentHandler(newTh);
try {
reader.setProperty("http://xml.org/sax/properties/lexical-handler", newTh);
} catch (SAXNotRecognizedException ex) {
log.warn("Unable to set lexical content handler. Comments and Processing instructions may be skipped");
} catch (SAXNotSupportedException e) {
log.warn("Lexical property not supported. Comments and Processing instructions may be skipped");
}
}
th = newTh;
return th.getTransformer();
}
public void transform(URL sourceURL, Result res) throws TransformationException
{
transform(new InputSource(sourceURL.toExternalForm()), res);
}
/**
* Transform using an InputSource rather than a URL
*
* @param inputsource the InputSource to use
* @param res the Result
* @throws TransformationException if an error occurred during transformation
*/
public void transform(InputSource inputsource, Result res) throws TransformationException
{
try
{
if (th == null)
{// no stylesheets have been added, so try to use embedded...
SAXSource saxSource = new SAXSource(inputsource);
Source src = saxSource;
String media = null, title = null, charset = null;
while (true)
{
src = tFactory.getAssociatedStylesheet(src, media, title, charset);
if (src != null)
{
addStylesheet(saxSource, null, Collections.EMPTY_MAP, new Properties());
}
else
{
throw new TransformationException(Messages.getString("JAXPSAXProcessorInvoker.7") + inputsource.getSystemId()); //$NON-NLS-1$
}
}
}
th.setResult(res);
log.info(Messages.getString("JAXPSAXProcessorInvoker.8")); //$NON-NLS-1$
reader.parse(inputsource);
log.info(Messages.getString("JAXPSAXProcessorInvoker.9")); //$NON-NLS-1$
}
catch (Exception e)
{
throw new TransformationException(e.getMessage(), e);
}
}
}