[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