Package org.jboss.soa.esb.actions.transformation.xslt

Source Code of org.jboss.soa.esb.actions.transformation.xslt.XsltAction$ValidationHandler

/*
* JBoss, Home of Professional Open Source Copyright 2009, Red Hat Middleware
* LLC, and individual contributors by the @authors tag. See the copyright.txt
* in the distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this software; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
* site: http://www.fsf.org.
*/
package org.jboss.soa.esb.actions.transformation.xslt;

import static org.jboss.soa.esb.listeners.ListenerTagNames.MAX_THREADS_TAG;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ArrayBlockingQueue;

import javax.xml.XMLConstants;
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.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
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 javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import org.apache.log4j.Logger;
import org.jboss.internal.soa.esb.assertion.AssertArgument;
import org.jboss.internal.soa.esb.util.StreamUtils;
import org.jboss.soa.esb.ConfigurationException;
import org.jboss.soa.esb.actions.AbstractActionPipelineProcessor;
import org.jboss.soa.esb.actions.ActionLifecycleException;
import org.jboss.soa.esb.actions.ActionProcessingException;
import org.jboss.soa.esb.actions.transformation.xslt.ResultFactory.ResultType;
import org.jboss.soa.esb.actions.transformation.xslt.TransformerFactoryConfig.Builder;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.listeners.ListenerTagNames;
import org.jboss.soa.esb.listeners.message.MessageDeliverException;
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.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.SAXParseException;

/**
* ESB Action that performs xslt transformation.
* <p/>
* Example configuration:
* <pre>{@code
* <action name="xslt-transform" class="org.jboss.soa.esb.actions.transformation.xslt.XsltAction">
*    <property name="templateFile" value="/sample.xsl"/>
*    <property name="failOnWarning" value="true"/>
*    <property name="validation" value="true"/>
*    <property name="schemaFile" value="/sample.xsd"/>
*    <property name="schemaLanguage" value="http://www.w3.org/2001/XMLSchema"/>
*    <property name="resultType" value="STRING"/>
* </action>
* }<pre>
*
* <h3>Configuration Properties</h3>
* <ul>
<li><i>templateFile</i>:
*  The path to the xsl template to be used. Mandatory</li>
<li><i>resultType</i>:
*  This property controls the output result of the transformation.
*  The following values are currently available:
{@link ResultType.STRING} - will produce a string.
{@link ResultType.BYTES} - will produce a byte[].
{@link ResultType.DOM} - will produce a {@link DOMResult}.
{@link ResultType.SAX} - will produce a {@link SAXResult}.
</li>
*  If the above does not suite your needs then you have the option of specifying both the
*  Source and Result by creating {@link SourceResult} object instance. This is a simple
*  object that holds both a {@link Source} and a {@link Result}.
*  You need to create this object prior to calling this action and the type of {@link Result}
*  returned will be the type that was used to create the {@link SourceResult}.
<li><i>failOnWarning</i>:
*  If true will cause a transformation warning to cause an exception to be thrown.
*  If false the failure will be logged. Default is true if not specified.</li>
<li><i>validation</i>:
*  If true will cause an invalid source document to cause an exception to be thrown.
*  If false validation will not occur, although well-formed documents are enforced.
*  Default is false if not specified.<br/>
*  Please refer to <b>Validation Configuration</b> chart below.</li>
<li><i>schemaFile</i>:
*  The input schema file (xsd) to use, located on the classpath.
*  Default is null (unset) if not specified.<br/>
*  Please refer to <b>Validation Configuration</b> chart below.</li>
<li><i>schemaLanguage</i>:
*  The input schema language to use.
*  Default is null (unset) if not specified.<br/>
*  Please refer to <b>Validation Configuration</b> chart below.</li>
<li><i>uriResolver</i>:
*  Fully qualified class name of a class that implements {@link URIResolver}.
*  This will be set on the transformation factory. Optional</li>
<li><i>factory.feature.*</i>:
*  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 transformation factory. Optional.
*  The attribute name should be specified after the 'factory.attribute.' prefix.
*  For example:
*  factory.attribute.someVendorAttributename</li>
* </ul>
*
<table border="1" cellpadding="5" cellspacing="0">
*     <thead>
*         <tr valign="top">
*             <th>Validation Configuration</th>
*             <th>XML Input</th>
*             <th>Processing Outcome</th>
*         </tr>
*     </thead>
*     <tbody>
*         <tr valign="top">
*             <td rowspan="3">
*                 <u>Default</u><p/>
*                 <i>nothing</i><p/>or
* <pre> &lt;property name="validation" value="false"/&gt;</pre>
*             </td>
*             <td>
*                 <ul>
*                     <li><b>mal</b>formed</li>
*                 </ul>
*             </td>
*             <td>
*                 <ul>
*                     <li>error logged</li>
*                     <li><pre>SAXParseException causes ActionProcessingException</pre></li>
*                     <li><i>pipeline stops</i></li>
*                 </ul>
*             </td>
*         </tr>
*         <tr valign="top">
*             <td>
*                 <ul>
*                     <li>well-formed</li>
*                     <li>valid</li>
*                 </ul>
*             </td>
*             <td>
*                 <ul>
*                     <li><i>pipeline continues</i></li>
*                 </ul>
*             </td>
*         </tr>
*         <tr valign="top">
*             <td>
*                 <ul>
*                     <li>well-formed</li>
*                     <li><b>in</b>valid</li>
*                 </ul>
*             </td>
*             <td>
*                 <ul>
*                     <li><b>transformation may fail</b></li>
*                     <li><i>pipeline continues</i></li>
*                 </ul>
*             </td>
*         </tr>
*         <tr valign="top">
*             <td rowspan="3">
*                 <u>DTD</u><br/>
* <pre> &lt;property name="validation" value="true"/&gt;
* &lt;property name="schemaLanguage" value="http://www.w3.org/TR/REC-xml"/&gt;</pre>
* or
* <pre> &lt;property name="validation" value="true"/&gt;
* &lt;property name="schemaLanguage" value=""/&gt;</pre>
*             </td>
*             <td>
*                 <ul>
*                     <li><b>mal</b>formed</li>
*                 </ul>
*             </td>
*             <td>
*                 <ul>
*                     <li>error logged</li>
*                     <li><pre>SAXParseException causes ActionProcessingException</pre></li>
*                     <li><i>pipeline stops</i></li>
*                 </ul>
*             </td>
*         </tr>
*         <tr valign="top">
*             <td>
*                 <ul>
*                     <li>well-formed</li>
*                     <li>valid</li>
*                 </ul>
*             </td>
*             <td>
*                 <ul>
*                     <li><i>pipeline continues</i></li>
*                 </ul>
*             </td>
*         </tr>
*         <tr valign="top">
*             <td>
*                 <ul>
*                     <li>well-formed</li>
*                     <li><b>in</b>valid</li>
*                 </ul>
*             </td>
*             <td>
*                 <ul>
*                     <li>error logged</li>
*                     <li><pre>SAXParseException causes ActionProcessingException</pre></li>
*                     <li><i>pipeline stops</i></li>
*                 </ul>
*             </td>
*         </tr>
*         <tr valign="top">
*             <td rowspan="3">
*                 <u>W3C XML Schema</u> or <u>RELAX NG</u><br/>
* <pre> &lt;property name="validation" value="true"/&gt;</pre>
* or
* <pre> &lt;property name="validation" value="true"/&gt;
* &lt;property name="schemaLanguage" value="http://www.w3.org/2001/XMLSchema"/&gt;</pre>
* or
* <pre> &lt;property name="validation" value="true"/&gt;
* &lt;property name="schemaLanguage" value="http://relaxng.org/ns/structure/1.0"/&gt;</pre>
*             </td>
*             <td>
*                 <ul>
*                     <li><b>mal</b>formed</li>
*                 </ul>
*             </td>
*             <td>
*                 <ul>
*                     <li>error logged</li>
*                     <li><pre>SAXParseException causes ActionProcessingException</pre></li>
*                     <li><i>pipeline stops</i></li>
*                 </ul>
*             </td>
*         </tr>
*         <tr valign="top">
*             <td>
*                 <ul>
*                     <li>well-formed</li>
*                     <li>valid</li>
*                 </ul>
*             </td>
*             <td>
*                 <ul>
*                     <li><i>pipeline continues</i></li>
*                 </ul>
*             </td>
*         </tr>
*         <tr valign="top">
*             <td>
*                 <ul>
*                     <li>well-formed</li>
*                     <li><b>in</b>valid</li>
*                 </ul>
*             </td>
*             <td>
*                 <ul>
*                     <li>error logged</li>
*                     <li><pre>SAXParseException causes ActionProcessingException</pre></li>
*                     <li><i>pipeline stops</i></li>
*                 </ul>
*             </td>
*         </tr>
*         <tr valign="top">
*             <td rowspan="3">
*                 <u>W3C XML Schema</u> or <u>RELAX NG</u> <i>with included schemaFile</i><br/>
* <pre> &lt;property name="validation" value="true"/&gt;
* &lt;property name="schemaFile" value="/example.xsd"/&gt;
* </pre>
* or
* <pre> &lt;property name="validation" value="true"/&gt;
* &lt;property name="schemaLanguage" value="http://www.w3.org/2001/XMLSchema"/&gt;
* &lt;property name="schemaFile" value="/example.xsd"/&gt;
* </pre>
* or
* <pre> &lt;property name="validation" value="true"/&gt;
* &lt;property name="schemaLanguage" value="http://relaxng.org/ns/structure/1.0"/&gt;
* &lt;property name="schemaFile" value="/example.rng"/&gt;
* </pre>
*             </td>
*             <td>
*                 <ul>
*                     <li><b>mal</b>formed</li>
*                 </ul>
*             </td>
*             <td>
*                 <ul>
*                     <li>error logged</li>
*                     <li><pre>SAXParseException causes ActionProcessingException</pre></li>
*                     <li><i>pipeline stops</i></li>
*                 </ul>
*             </td>
*         </tr>
*         <tr valign="top">
*             <td>
*                 <ul>
*                     <li>well-formed</li>
*                     <li>valid</li>
*                 </ul>
*             </td>
*             <td>
*                 <ul>
*                     <li><i>pipeline continues</i></li>
*                 </ul>
*             </td>
*         </tr>
*         <tr valign="top">
*             <td>
*                 <ul>
*                     <li>well-formed</li>
*                     <li><b>in</b>valid</li>
*                 </ul>
*             </td>
*             <td>
*                 <ul>
*                     <li>error logged</li>
*                     <li><pre>SAXParseException causes ActionProcessingException</pre></li>
*                     <li><i>pipeline stops</i></li>
*                 </ul>
*             </td>
*         </tr>
*     </tbody>
* </table>
*
* @author <a href="mailto:dbevenius@jboss.com">Daniel Bevenius</a>
* @author dward at jboss.org
* @since 4.6
*/
public class XsltAction extends AbstractActionPipelineProcessor
{
    /**
     * Logger instance.
     */
    private static Logger log = Logger.getLogger(XsltAction.class);
   
    /**
     * Config object that holds transformation factory config options.
     */
    private TransformerFactoryConfig transformerConfig;
   
    /**
     * Can be used to control whether a warning should be reported
     * as an exception during transformation.
     */
    private boolean failOnWarning;
   
    /**
     * Used for validation on the XML InputSource during transformation.
     */
    private boolean validation;
   
    /**
     * Used for validation on the XML InputSource during transformation.
     */
    private SAXParserFactory validationFactory;
   
    /**
     * Used for validation on the XML InputSource during transformation.
     */
    private String schemaFile;
   
    /**
     * Used for validation on the XML InputSource during transformation.
     */
    private String schemaLanguage;
   
    /**
     * The templates object.
     */
    private Templates xslTemplate;
   
    /**
     * The {@link MessagePayloadProxy}.
     */
    private MessagePayloadProxy payloadProxy;
   
    /**
     * The number of transformer instances to create upon initialization.
     * This will be the value of the {@link ListenerTagNames#MAX_THREADS_TAG} value.
     */
    private int transformerPoolSize;
   
    /**
     * A queue of Transformer instance which will be populated upon initialization.
     * The size of this queue will be that of {@link #transformerPoolSize}.
     */
    private ArrayBlockingQueue<Transformer> transformers;
   
    /**
     * Sole constructor that parses the passed-in {@link ConfigTree} for
     * mandatory attributes and sets the fields of this instance.
     *
     * @param config The {@link ConfigTree} instance.
     *
     * @throws ConfigurationException if the mandatory attribute 'templateFile' has not been set.
     */
    public XsltAction(final ConfigTree config) throws ConfigurationException
    {
        transformerConfig = createConfig(config);
        failOnWarning = config.getBooleanAttribute("failOnWarning", true);
        validation = config.getBooleanAttribute("validation", false);
        schemaFile = config.getAttribute("schemaFile");
        schemaLanguage = config.getAttribute("schemaLanguage");
        payloadProxy = new MessagePayloadProxy(config);
        transformerPoolSize = getMaxThreadsFromParentConfigTree(config);
    }
   
    /**
     * Will try to extract and parse a configuration attribute named {@link ListenerTagNames#MAX_THREADS_TAG}
     * from the parent of the passed-in ConfigTree instance. If no parent exists (that is if the ConfigTree
     * instance passed into this method is the root), or if the property is not defined on the parent, then
     * the same attribute is extracted and parsed into an integer but from the config element.
     *
     * @param config The {@link ConfigTree} instance.
     * @return int The parsed value the {@link ListenerTagNames#MAX_THREADS_TAG} configuration attribute
     * @throws ConfigurationException If it was not possible to parse the {@link ListenerTagNames#MAX_THREADS_TAG} attribute into a
     * positive integer value.
     */
    int getMaxThreadsFromParentConfigTree(final ConfigTree config) throws ConfigurationException
    {
        try
        {
            final ConfigTree parent = config.getParent();
            String maxThreadsStr = null;
            if (parent != null) {
              maxThreadsStr = parent.getAttribute(MAX_THREADS_TAG);
            }
            if (maxThreadsStr == null) {
              maxThreadsStr = config.getAttribute(MAX_THREADS_TAG, "1");
            }
           
          int maxThreads = Integer.parseInt(maxThreadsStr);
          if (maxThreads <= 0)
              throw new ConfigurationException(MAX_THREADS_TAG + " must be a positive integer. Was [" + maxThreads +"]");
         
          return maxThreads;
        }
        catch (final NumberFormatException e)
        {
            throw new ConfigurationException("Could not parse " + MAX_THREADS_TAG + " to an int.", e);
        }
    }
   
    /**
     * 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}.
     *     
     * @return {@link Message} The same ESB Message instance passed-in but with it payload transformed.
     * @throws ActionProcessingException if an error occurs while trying to perform the transformation.
     */
    public Message process(final Message message) throws ActionProcessingException
    {
        AssertArgument.isNotNull(message, "message");
        try
        {
            final Object payload = getPayload(message);
            final ValidationHandler validationHandler;
            final Source source;
            final Result result;
            // If the payload is a SourceResult than use its source and result.
            if (payload instanceof SourceResult)
            {
                validationHandler = null;
                final SourceResult sourceResult = (SourceResult)payload;
                source = sourceResult.getSource();
                result = sourceResult.getResult();
            }
            else
            {
              validationHandler = new ValidationHandler(failOnWarning);
                source = SourceFactory.getInstance().createSource(payload, validationFactory, validationHandler);
                result = ResultFactory.getInstance().createResult(transformerConfig.getResultType());
            }
           
            // Perform the transformation.
            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());
           
            return setPayload(message, object);
        }
        catch (final TransformerConfigurationException e)
        {
            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);
        }
    }

    private void transform (final Source source, final Result result) throws TransformerException, ActionProcessingException
    {
        Transformer transformer = null;
        try
        {
            transformer = transformers.take();
        }
        catch (final InterruptedException e)
        {
            throw new ActionProcessingException(e.getMessage(), e);
        }
       
        try
        {
            transformer.transform(source, result);
        }
        finally
        {
            try
            {
                transformer.reset();
                transformers.put(transformer);
            }
            catch (final InterruptedException e)
            {
                throw new ActionProcessingException(e.getMessage(), e);
            }
        }
    }

    /**
     * Creates the XSLTemplate.
     *
     * @throws ActionLifecycleException if the {@link Templates} could not be created.
     *
     */
    @Override
    public void initialise() throws ActionLifecycleException
    {
        try
        {
            final TransformerFactory factory = TransformerFactory.newInstance();
            addFeatures(transformerConfig.getFeatures(), factory);
            addAttributes(transformerConfig.getAttributes(), factory);
            setResolver(transformerConfig.getUriResolver(), factory);
            setErrorListener(new TransformerListener(failOnWarning), factory);
            createValidationFactory(factory);
            xslTemplate = createTemplate(transformerConfig.getTemplateFile(), factory);
           
            transformers = new ArrayBlockingQueue<Transformer>(transformerPoolSize);
            for (int i = transformerPoolSize; --i>=0 ;)
            {
                transformers.add(xslTemplate.newTransformer());
            }
        }
        catch (final TransformerConfigurationException e)
        {
            throw new ActionLifecycleException(e.getMessage(), e);
        }
    }
   
    private void addFeatures(final Map<String, Boolean> features, final TransformerFactory factory) throws TransformerConfigurationException
    {
        for (Entry<String, Boolean> entry : features.entrySet())
        {
            factory.setFeature(entry.getKey(), entry.getValue());
        }
    }

    private void addAttributes(final Map<String, Object> attributes, final TransformerFactory factory) throws TransformerConfigurationException
    {
        for (Entry<String, Object> entry : attributes.entrySet())
        {
            factory.setAttribute(entry.getKey(), entry.getValue());
        }
    }

    private void setResolver(final URIResolver uriResolver, final TransformerFactory factory)
    {
        if (uriResolver != null)
        {
            factory.setURIResolver(uriResolver);
        }
    }

    private void setErrorListener(final ErrorListener errorListener, final TransformerFactory factory)
    {
        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.
        // The code below conditionally enforces valid XML input, as described in JBESB-3068.
        if (validation)
        {
          validationFactory.setValidating(true);
          if (!XMLConstants.XML_DTD_NS_URI.equals(schemaLanguage) && !XMLConstants.NULL_NS_URI.equals(schemaLanguage))
          {
            // W3C XML Schema or RELAX NG validation
            for (String name : new String[]{"http://xml.org/sax/features/validation/schema", "http://apache.org/xml/features/validation/schema"})
            {
              try
              {
                validationFactory.setFeature(name, true);
              }
              catch (ParserConfigurationException ignored) {}
              catch (SAXNotRecognizedException ignored) {}
              catch (SAXNotSupportedException ignored) {}
            }
            if (schemaFile != null)
            {
              SchemaFactory schemaFactory = SchemaFactory.newInstance(schemaLanguage != null ? schemaLanguage : XMLConstants.W3C_XML_SCHEMA_NS_URI);
              try
              {
                Schema schema = schemaFactory.newSchema(new StreamSource(ClassUtil.getResourceAsStream(schemaFile, getClass())));
                validationFactory.setSchema(schema);
              }
              catch (SAXException e)
              {
                throw new ActionLifecycleException("problem creating schema '" + schemaFile + "'", e);
              }
            }
          }
          // else { DTD validation }
        }
      }
      else
      {
        log.warn("TransformerFactory does not support " + SAXSource.FEATURE);
      }
    }

    private Templates createTemplate(final String templateFile, final TransformerFactory factory) throws ActionLifecycleException, TransformerConfigurationException
    {
        InputStream stream = null;
        try
        {
            stream = StreamUtils.getResource(templateFile);
            return factory.newTemplates(new StreamSource(stream));
        }
        catch (final ConfigurationException e)
        {
            throw new ActionLifecycleException(e.getMessage(), e);
        }
        finally
        {
            if (stream != null)
            {
                try { stream.close(); } catch (final IOException ignore) { log.error("Exception while closing stream", ignore); }
            }
        }
    }

    /**
     * Parses the passed-in ESB {@link ConfigTree} and populates a {@link TransformerFactoryConfig}.
     *
     * @param config The ESB {@link ConfigTree}.
     * @return {@link TransformerFactoryConfig}.
     * @throws ConfigurationException
     */
    private TransformerFactoryConfig createConfig(final ConfigTree config) throws ConfigurationException
    {
        final Builder builder = new TransformerFactoryConfig.Builder(config.getRequiredAttribute("templateFile"));
        extractFeatures(config, builder);
        extractAttributes(config, builder);
        createUrlResolver(config, builder);
        builder.resultType(ResultType.valueOf(config.getAttribute("resultType", ResultType.STRING.name())));
        return builder.build();
    }

    /**
     * Extracts the factory attributes and adds them to the builder.
     *
     * @param config The ESB {@link ConfigTree}.
     * @param builder The {@link TransformerFactoryConfig.Builder}.
     * @return Builder To support method chaining.
     */
    void extractAttributes(final ConfigTree config, final Builder builder)
    {
        for (final String attrName : config.getAttributeNames())
        {
            int idx = attrName.indexOf("factory.attribute.");
            if (idx != -1)
            {
                final Object value = config.getAttribute(attrName);
                final String name = attrName.substring(idx + "factory.attribute.".length());
                builder.attribute(name, value);
            }
        }
    }

    /**
     * Extracts the 'uriResolver' attribute from the ESB {@link ConfigTree} and instantiates a class
     * of that type. This class will be set on the passed-in builder.
     * @param config The ESB {@link ConfigTree}.
     * @param builder The {@link TransformerFactoryConfig.Builder}.
     * @throws ConfigurationException If the class could not be created.
     */
    void createUrlResolver(final ConfigTree config, final Builder builder) throws ConfigurationException
    {
        final String className = config.getAttribute("uriResolver");
        if (className != null)
        {
            try
            {
                final Class<?> resolver = ClassUtil.forName(className, getClass());
                URIResolver uriResolver = (URIResolver) resolver.newInstance();
                builder.uriResolver(uriResolver);
            }
            catch (final ClassNotFoundException e)
            {
                throw new ConfigurationException(e.getMessage(), e);
            }
            catch (InstantiationException e)
            {
                throw new ConfigurationException(e.getMessage(), e);
            }
            catch (IllegalAccessException e)
            {
                throw new ConfigurationException(e.getMessage(), e);
            }
        }
    }

    /**
     * Extracts the factory features and adds them to the builder.
     *
     * @param config The ESB {@link ConfigTree}.
     * @param builder The {@link TransformerFactoryConfig.Builder}.
     */
    void extractFeatures(final ConfigTree config, Builder builder)
    {
        for (final String attrName : config.getAttributeNames())
        {
            int idx = attrName.indexOf("factory.feature.");
            if (idx != -1)
            {
                final String value = config.getAttribute(attrName);
                final String name = attrName.substring(idx + "factory.feature.".length());
                builder.feature(name, Boolean.valueOf(value));
            }
        }
    }

    private Object getPayload(final Message message) throws ActionProcessingException
    {
        try
        {
            return payloadProxy.getPayload(message);
        }
        catch (MessageDeliverException e)
        {
            throw new ActionProcessingException(e.getMessage(), e);
        }
    }
   
    private Message setPayload(final Message message, final Object payload) throws ActionProcessingException
    {
        try
        {
            payloadProxy.setPayload(message, payload);
        }
        catch (MessageDeliverException e)
        {
            throw new ActionProcessingException(e.getMessage(), e);
        }
        return message;
    }
   
    public TransformerFactoryConfig getTranformerConfig()
    {
        return transformerConfig;
    }

    @Override
    public String toString()
    {
        return String.format("%s templateFile=%s, validation=%b, schemaFile=%s, schemaLanguage=%s, failOnWarning=%b, features=%s, attributes=%s", getClass().getSimpleName(), transformerConfig.getTemplateFile(), validation, schemaFile, schemaLanguage, failOnWarning, transformerConfig.getFeatures(), transformerConfig.getAttributes());
    }
   
    private static class TransformerListener implements ErrorListener
    {
        private final boolean failOnWarning;

        public TransformerListener(boolean failOnWarning)
        {
            this.failOnWarning = failOnWarning;
        }

        public void warning(TransformerException exception) throws TransformerException
        {
            if (failOnWarning)
            {
                throw exception;
            }
            else
            {
                log.warn("Transformation Warning.", exception);
            }
        }

        public void error(TransformerException exception) throws TransformerException
        {
            throw exception;
        }

        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;
      }
    }

    public int getNumberOfPooledTransfomers ()
    {
        if (transformers == null)
            throw new IllegalStateException("The transformers have not been initialized yet. Please make sure that initialize has bee called prior to calling this method.");
       
        return transformers.size();
    }
}
TOP

Related Classes of org.jboss.soa.esb.actions.transformation.xslt.XsltAction$ValidationHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.