[jboss-svn-commits] JBL Code SVN: r30725 - in labs/jbossesb/branches/JBESB_4_7_CP/product/rosetta: tests/src/org/jboss/soa/esb/actions/transformation/xslt and 1 other directory.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Wed Dec 16 13:49:40 EST 2009
Author: dward
Date: 2009-12-16 13:49:40 -0500 (Wed, 16 Dec 2009)
New Revision: 30725
Added:
labs/jbossesb/branches/JBESB_4_7_CP/product/rosetta/tests/src/org/jboss/soa/esb/actions/transformation/xslt/malformed1.xml
Modified:
labs/jbossesb/branches/JBESB_4_7_CP/product/rosetta/src/org/jboss/soa/esb/actions/transformation/xslt/SourceFactory.java
labs/jbossesb/branches/JBESB_4_7_CP/product/rosetta/src/org/jboss/soa/esb/actions/transformation/xslt/XsltAction.java
labs/jbossesb/branches/JBESB_4_7_CP/product/rosetta/tests/src/org/jboss/soa/esb/actions/transformation/xslt/XsltActionUnitTest.java
Log:
Fix for JBESB-3036 ( https://jira.jboss.org/jira/browse/JBESB-3036 )
Modified: labs/jbossesb/branches/JBESB_4_7_CP/product/rosetta/src/org/jboss/soa/esb/actions/transformation/xslt/SourceFactory.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_7_CP/product/rosetta/src/org/jboss/soa/esb/actions/transformation/xslt/SourceFactory.java 2009-12-16 18:09:09 UTC (rev 30724)
+++ labs/jbossesb/branches/JBESB_4_7_CP/product/rosetta/src/org/jboss/soa/esb/actions/transformation/xslt/SourceFactory.java 2009-12-16 18:49:40 UTC (rev 30725)
@@ -29,9 +29,17 @@
import java.io.Reader;
import java.io.StringReader;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Source;
+import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamSource;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
/**
* Code contributed from the Smooks project.
*/
@@ -39,41 +47,117 @@
{
private static final SourceFactory factory = new SourceFactory();
- private SourceFactory()
- {
- }
+ private SourceFactory() {}
public static SourceFactory getInstance()
{
return factory;
}
+
+ public Source createSource(final Object from)
+ {
+ try
+ {
+ return createSource(from, null, null);
+ }
+ catch (SAXException e)
+ {
+ throw new RuntimeException("Should not occur when not validating XML InputSource!", e);
+ }
+ catch (ParserConfigurationException e)
+ {
+ throw new RuntimeException("Should not occur when not validating XML InputSource!", e);
+ }
+ }
- public Source createSource(final Object from)
+ public Source createSource(final Object from, final SAXParserFactory validationFactory, final ErrorHandler validationHandler)
+ throws SAXException, ParserConfigurationException
{
final Source source;
+ final XMLReader validationReader;
+ if (validationFactory != null)
+ {
+ validationReader = validationFactory.newSAXParser().getXMLReader();
+ if (validationHandler != null)
+ {
+ validationReader.setErrorHandler(validationHandler);
+ }
+ }
+ else
+ {
+ validationReader = null;
+ }
if (from instanceof String)
{
- source = new StreamSource(new StringReader((String) from));
+ Reader reader = new StringReader((String)from);
+ if (validationReader != null)
+ {
+ source = new SAXSource(validationReader, new InputSource(reader));
+ }
+ else
+ {
+ source = new StreamSource(reader);
+ }
}
else if (from instanceof byte[])
{
- source = new StreamSource(new ByteArrayInputStream((byte[]) from));
+ InputStream inputStream = new ByteArrayInputStream((byte[])from);
+ if (validationReader != null)
+ {
+ source = new SAXSource(validationReader, new InputSource(inputStream));
+ }
+ else
+ {
+ source = new StreamSource(inputStream);
+ }
}
else if (from instanceof Reader)
{
- source = new StreamSource((Reader) from);
+ Reader reader = (Reader)from;
+ if (validationReader != null)
+ {
+ source = new SAXSource(validationReader, new InputSource(reader));
+ }
+ else
+ {
+ source = new StreamSource(reader);
+ }
}
else if (from instanceof InputStream)
{
- source = new StreamSource((InputStream) from);
+ InputStream inputStream = (InputStream)from;
+ if (validationReader != null)
+ {
+ source = new SAXSource(validationReader, new InputSource(inputStream));
+ }
+ else
+ {
+ source = new StreamSource(inputStream);
+ }
}
else if (from instanceof File)
{
- source = fileSource((File) from);
+ InputStream inputStream;
+ try
+ {
+ inputStream = new BufferedInputStream(new FileInputStream((File)from));
+ }
+ catch (FileNotFoundException e)
+ {
+ throw new IllegalStateException(e.getMessage(), e);
+ }
+ if (validationReader != null)
+ {
+ source = new SAXSource(validationReader, new InputSource(inputStream));
+ }
+ else
+ {
+ source = new StreamSource(inputStream);
+ }
}
else if (from instanceof Source)
{
- source = (Source) from;
+ source = (Source)from;
}
else
{
@@ -81,17 +165,4 @@
}
return source;
}
-
- private Source fileSource(final File file)
- {
- try
- {
- return new StreamSource(new BufferedInputStream(new FileInputStream(file)));
- }
- catch (FileNotFoundException e)
- {
- throw new IllegalStateException(e.getMessage(), e);
- }
-
- }
}
Modified: labs/jbossesb/branches/JBESB_4_7_CP/product/rosetta/src/org/jboss/soa/esb/actions/transformation/xslt/XsltAction.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_7_CP/product/rosetta/src/org/jboss/soa/esb/actions/transformation/xslt/XsltAction.java 2009-12-16 18:09:09 UTC (rev 30724)
+++ labs/jbossesb/branches/JBESB_4_7_CP/product/rosetta/src/org/jboss/soa/esb/actions/transformation/xslt/XsltAction.java 2009-12-16 18:49:40 UTC (rev 30725)
@@ -25,6 +25,8 @@
import java.util.Map;
import java.util.Map.Entry;
+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;
@@ -36,6 +38,7 @@
import javax.xml.transform.URIResolver;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamSource;
import org.apache.log4j.Logger;
@@ -52,9 +55,12 @@
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.message.MessagePayloadProxy;
import org.jboss.soa.esb.util.ClassUtil;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
/**
- * ESB Action that performs xslt tranformation.
+ * ESB Action that performs xslt transformation.
* <p/>
* Example configuration:
* <pre>{@code
@@ -66,7 +72,7 @@
* }<pre>
*
* <h3>Configuration Properties</h3>
- * <lu>
+ * <ul>
* <li><i>templateFile</i>:
* The path to the xsl template to be used. Mandatory</li>
*
@@ -90,22 +96,23 @@
*
* <li><i>uriResolver</i>:
* Fully qualified class name of a class that implements {@link URIResolver}.
- * This will be set on the tranformation factory. Optional</li>
+ * This will be set on the transformation factory. Optional</li>
*
* <li><i>factory.feature.*</i>:
- * Factory features that will be set for the tranformation factory. Optional.
+ * Factory features that will be set for the transformation factory. Optional.
* The feature name, which are fully qualified URIs will should be specified
* after the 'factory.feature.' prefix. For example:
* factory.feature.http://javax.xml.XMLConstants/feature/secure-processing</li>
*
* <li><i>factory.attribute.*</i>:
- * Factory attributes that will be set for the tranformation factory. Optional.
+ * Factory attributes that will be set for the transformation factory. Optional.
* The attribute name should be specified after the 'factory.attribute.' prefix.
* For example:
* factory.attribute.someVendorAttributename</li>
- * </lu>
+ * </ul>
*
* @author <a href="mailto:dbevenius at jboss.com">Daniel Bevenius</a>
+ * @author dward at jboss.org
* @since 4.6
*/
public class XsltAction extends AbstractActionPipelineProcessor
@@ -116,7 +123,7 @@
private static Logger log = Logger.getLogger(XsltAction.class);
/**
- * Config object that holds tranformation factory config options.
+ * Config object that holds transformation factory config options.
*/
private TransformerFactoryConfig transformerConfig;
@@ -127,6 +134,11 @@
private boolean failOnWarning;
/**
+ * Used for validation on the XML InputSource during transformation.
+ */
+ private SAXParserFactory validationFactory;
+
+ /**
* The templates object.
*/
private Templates xslTemplate;
@@ -142,7 +154,7 @@
*
* @param config The {@link ConfigTree} instance.
*
- * @throws ConfigurationException if the mandatory attribute 'xslt' has not been set.
+ * @throws ConfigurationException if the mandatory attribute 'templateFile' has not been set.
*/
public XsltAction(final ConfigTree config) throws ConfigurationException
{
@@ -152,7 +164,7 @@
}
/**
- * Performs the xsl tranformation of the message payload.
+ * Performs the xsl transformation of the message payload.
*
* @param message The ESB {@link Message} object whose payload should be transformed.
* The payload is extracted and set using contract specified by {@link MessagePayloadProxy}.
@@ -167,24 +179,33 @@
{
final Transformer transformer = xslTemplate.newTransformer();
final Object payload = getPayload(message);
+ final ValidationHandler validationHandler;
final Source source;
final Result result;
- // If the payload is of SourceResult that use its source and result.
+ // If the payload is a SourceResult than use its source and result.
if (payload instanceof SourceResult)
{
- final SourceResult sourceResult = (SourceResult) payload;
+ validationHandler = null;
+ final SourceResult sourceResult = (SourceResult)payload;
source = sourceResult.getSource();
result = sourceResult.getResult();
}
else
{
- source = SourceFactory.getInstance().createSource(payload);
+ validationHandler = new ValidationHandler(failOnWarning);
+ source = SourceFactory.getInstance().createSource(payload, validationFactory, validationHandler);
result = ResultFactory.getInstance().createResult(transformerConfig.getResultType());
}
// Perform the transformation.
transformer.transform(source, result);
+ // Check for validation errors.
+ if (validationHandler != null)
+ {
+ validationHandler.check();
+ }
+
// Get the result and set on the message object
final Object object = ResultFactory.getInstance().extractResult(result, transformerConfig.getResultType());
@@ -194,6 +215,14 @@
{
throw new ActionProcessingException(e.getMessage(), e);
}
+ catch (SAXException e)
+ {
+ throw new ActionProcessingException(e.getMessage(), e);
+ }
+ catch (ParserConfigurationException e)
+ {
+ throw new ActionProcessingException(e.getMessage(), e);
+ }
catch (TransformerException e)
{
throw new ActionProcessingException(e.getMessage(), e);
@@ -215,8 +244,8 @@
addFeatures(transformerConfig.getFeatures(), factory);
addAttributes(transformerConfig.getAttributes(), factory);
setResolver(transformerConfig.getUriResolver(), factory);
- setErrorListener(new XslErrorListener(failOnWarning), factory);
-
+ setErrorListener(new TransformerListener(failOnWarning), factory);
+ createValidationFactory(factory);
xslTemplate = createTemplate(transformerConfig.getTemplateFile(), factory);
}
catch (final TransformerConfigurationException e)
@@ -249,10 +278,25 @@
}
}
- private void setErrorListener(final XslErrorListener xslErrorListener, final TransformerFactory factory)
+ private void setErrorListener(final ErrorListener errorListener, final TransformerFactory factory)
{
- factory.setErrorListener(xslErrorListener);
+ factory.setErrorListener(errorListener);
}
+
+ private void createValidationFactory(final TransformerFactory factory) throws ActionLifecycleException
+ {
+ if (factory.getFeature(SAXSource.FEATURE))
+ {
+ validationFactory = SAXParserFactory.newInstance();
+ validationFactory.setNamespaceAware(true);
+ // The code above enforces well-formed XML input, as described in JBESB-3036.
+ // TODO: Code below will be added to also do validation of XML input, as described in JBESB-3068.
+ }
+ else
+ {
+ log.warn("TransformerFactory does not support " + SAXSource.FEATURE);
+ }
+ }
private Templates createTemplate(final String templateFile, final TransformerFactory factory) throws ActionLifecycleException, TransformerConfigurationException
{
@@ -297,7 +341,7 @@
*
* @param config The ESB {@link ConfigTree}.
* @param builder The {@link TransformerFactoryConfig.Builder}.
- * @return Builder To support method chainging.
+ * @return Builder To support method chaining.
*/
void extractAttributes(final ConfigTree config, final Builder builder)
{
@@ -402,36 +446,79 @@
return String.format("%s templateFile=%s, failOnWarning=%b, features=%s, attributes=%s", getClass().getSimpleName(), transformerConfig.getTemplateFile(), failOnWarning, transformerConfig.getFeatures(), transformerConfig.getAttributes());
}
- private static class XslErrorListener implements ErrorListener
+ private static class TransformerListener implements ErrorListener
{
private final boolean failOnWarning;
- public XslErrorListener(boolean failOnWarning)
+ public TransformerListener(boolean failOnWarning)
{
this.failOnWarning = failOnWarning;
}
- public void warning(final TransformerException exception) throws TransformerException
+ public void warning(TransformerException exception) throws TransformerException
{
- if(failOnWarning)
+ if (failOnWarning)
{
throw exception;
}
else
{
- log.warn("XSL Warning.", exception);
+ log.warn("Transformation Warning.", exception);
}
}
- public void error(final TransformerException exception) throws TransformerException
+ public void error(TransformerException exception) throws TransformerException
{
throw exception;
}
- public void fatalError(final TransformerException exception) throws TransformerException
+ public void fatalError(TransformerException exception) throws TransformerException
{
throw exception;
}
}
+
+ private static class ValidationHandler implements ErrorHandler
+ {
+ private final boolean failOnWarning;
+ private SAXParseException exception = null;
+ public ValidationHandler(boolean failOnWarning)
+ {
+ this.failOnWarning = failOnWarning;
+ }
+
+ private void check() throws SAXParseException
+ {
+ if (exception != null)
+ {
+ throw exception;
+ }
+ }
+
+ public void warning(SAXParseException exception) throws SAXException
+ {
+ if (failOnWarning)
+ {
+ this.exception = exception;
+ throw exception;
+ }
+ else
+ {
+ log.warn("Validation Warning.", exception);
+ }
+ }
+
+ public void error(SAXParseException exception) throws SAXException
+ {
+ this.exception = exception;
+ throw exception;
+ }
+
+ public void fatalError(SAXParseException exception) throws SAXException
+ {
+ this.exception = exception;
+ throw exception;
+ }
+ }
}
Modified: labs/jbossesb/branches/JBESB_4_7_CP/product/rosetta/tests/src/org/jboss/soa/esb/actions/transformation/xslt/XsltActionUnitTest.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_7_CP/product/rosetta/tests/src/org/jboss/soa/esb/actions/transformation/xslt/XsltActionUnitTest.java 2009-12-16 18:09:09 UTC (rev 30724)
+++ labs/jbossesb/branches/JBESB_4_7_CP/product/rosetta/tests/src/org/jboss/soa/esb/actions/transformation/xslt/XsltActionUnitTest.java 2009-12-16 18:49:40 UTC (rev 30725)
@@ -23,6 +23,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.io.File;
import java.io.IOException;
@@ -63,6 +64,7 @@
private static final String PACKAGE_PATH = "/org/jboss/soa/esb/actions/transformation/xslt";
private static final String TEST_XSL_1 = PACKAGE_PATH + "/test1.xsl";
private static final String TEST_XML_1 = PACKAGE_PATH + "/example1.xml";
+ private static final String MALFORMED_XML_1 = PACKAGE_PATH + "/malformed1.xml";
@Test (expected = ConfigurationException.class)
public void shouldThrowIfNoTemplateIsConfigured() throws ConfigurationException
@@ -148,6 +150,22 @@
assertTrue("XML Comparison", XMLHelper.compareXMLContent("<xxx/>", (String) processed.getBody().get()));
}
+ @Test (expected = ActionProcessingException.class)
+ public void processMalformedFileSource() throws Exception
+ {
+ final XsltAction action = new XsltAction(new ConfigBuilder().resultType(ResultType.STRING).templateFile(TEST_XSL_1).build());
+ action.initialise();
+
+ final Message message = MessageFactory.getInstance().getMessage();
+ final URL resource = getClass().getResource(MALFORMED_XML_1);
+ final File xmlFile = new File(resource.getFile());
+ message.getBody().add(xmlFile);
+
+ @SuppressWarnings("unused")
+ final Message processed = action.process(message);
+ fail("shouldn't reach");
+ }
+
@Test public void processStringSource() throws Exception
{
final XsltAction action = new XsltAction(new ConfigBuilder().resultType(ResultType.STRING).templateFile(TEST_XSL_1).build());
Added: labs/jbossesb/branches/JBESB_4_7_CP/product/rosetta/tests/src/org/jboss/soa/esb/actions/transformation/xslt/malformed1.xml
===================================================================
--- labs/jbossesb/branches/JBESB_4_7_CP/product/rosetta/tests/src/org/jboss/soa/esb/actions/transformation/xslt/malformed1.xml (rev 0)
+++ labs/jbossesb/branches/JBESB_4_7_CP/product/rosetta/tests/src/org/jboss/soa/esb/actions/transformation/xslt/malformed1.xml 2009-12-16 18:49:40 UTC (rev 30725)
@@ -0,0 +1 @@
+<a></ab>
Property changes on: labs/jbossesb/branches/JBESB_4_7_CP/product/rosetta/tests/src/org/jboss/soa/esb/actions/transformation/xslt/malformed1.xml
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
More information about the jboss-svn-commits
mailing list