[jboss-svn-commits] JBL Code SVN: r32099 - labs/jbossesb/workspace/johan.kumps/product/rosetta/src/org/jboss/soa/esb/actions/transformation/xslt.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Mon Mar 15 15:45:14 EDT 2010
Author: johan.kumps
Date: 2010-03-15 15:45:14 -0400 (Mon, 15 Mar 2010)
New Revision: 32099
Added:
labs/jbossesb/workspace/johan.kumps/product/rosetta/src/org/jboss/soa/esb/actions/transformation/xslt/OntologyAction.java
Log:
Initial version
Added: labs/jbossesb/workspace/johan.kumps/product/rosetta/src/org/jboss/soa/esb/actions/transformation/xslt/OntologyAction.java
===================================================================
--- labs/jbossesb/workspace/johan.kumps/product/rosetta/src/org/jboss/soa/esb/actions/transformation/xslt/OntologyAction.java (rev 0)
+++ labs/jbossesb/workspace/johan.kumps/product/rosetta/src/org/jboss/soa/esb/actions/transformation/xslt/OntologyAction.java 2010-03-15 19:45:14 UTC (rev 32099)
@@ -0,0 +1,396 @@
+/*
+ * 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 java.io.IOException;
+import java.io.InputStream;
+import java.util.Hashtable;
+
+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.stream.StreamSource;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+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.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.message.MessageDeliverException;
+import org.jboss.soa.esb.message.Message;
+import org.w3c.dom.Document;
+
+/**
+ * ESB Action that performs lifting tranformation of a message payload towards
+ * the ontology.
+ * <p/>
+ * Example configuration:
+ *
+ * <pre>
+ * @code
+ * <action name="lifting-transform" class="org.jboss.soa.esb.actions.transformation.ontology.LiftingAction">
+ * <property name="failOnWarning" value="true"/>
+ * <property name="resultType" value="STRING"/>
+ * </action>
+ * }
+ *
+ * <pre>
+ *
+ * <h3>Configuration Properties</h3>
+ * <lu>
+ *
+ * <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>uriResolver</i>:
+ * Fully qualified class name of a class that implements {@link URIResolver}.
+ * This will be set on the tranformation factory. Optional</li>
+ *
+ * <li><i>factory.feature.*</i>:
+ * Factory features that will be set for the tranformation 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.
+ * The attribute name should be specified after the 'factory.attribute.' prefix.
+ * For example:
+ * factory.attribute.someVendorAttributename</li>
+ * </lu>
+ *
+ * @author <a href="mailto:johan.kumps at telenet.be">Johan Kumps</a>
+ * @since 4.8
+ */
+public class OntologyAction extends XsltAction {
+
+ /*
+ * The Logging instance for this class.
+ */
+ private static Logger log = Logger.getLogger(OntologyAction.class);
+
+ /*
+ * A Hashtable representing a Templates instance cache
+ */
+ private static Hashtable<String, Templates> templateCache = new Hashtable<String, Templates>();
+
+ /*
+ * The name of the attribute in the XML message containing the lifting
+ * schema mapping location.
+ */
+ private static final String LIFTING_SCHEMA_MAPPING = "liftingSchemaMapping";
+
+ /*
+ * The XPath expression to use to extract the lifting schema attribute
+ */
+ private static XPathExpression XPATH_GETTING_LIFTING_SCHEMA_MAPPING = null;
+
+ /*
+ * The name of the attribute in the XML message containing the lowering
+ * schema mapping location.
+ */
+ private static final String LOWERING_SCHEMA_MAPPING = "loweringSchemaMapping";
+
+ /*
+ * The XPath expression to use to extract the lowering schema attribute
+ */
+ private static XPathExpression XPATH_GETTING_LOWERING_SCHEMA_MAPPING = null;
+
+ /*
+ * Message given when an error occurs during the XPath initialisation
+ */
+ private static final String ERROR_INTIALISING_XPATH = "An error occured while initialising the XPath expressions.";
+
+ /*
+ * Message given when neighter the lifting nor the lowering schema mapping
+ * attribute was found
+ */
+ private static final String NO_ONTOLOGY_MAPPING_SCHEMA = "No ontology mapping schema linked to the incoming message.";
+
+ /*
+ * Message given when both the lifting and the lowering schema mapping
+ * attribute was found
+ */
+ private static final String BOTH_ONTOLOGY_MAPPING_SCHEMAS = "Both ontology mapping schemas linked to the incoming message.";
+
+ /*
+ * Factory used to create an new XSL template instance
+ */
+ private TransformerFactory factory;
+
+ /**
+ * 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 a mandatory attribute has not been set (currently none).
+ */
+ public OntologyAction(final ConfigTree config)
+ throws ConfigurationException {
+ super(config);
+ }
+
+ /**
+ * Initialise the {@link TransformerFactory} and XPath expressions used to
+ * evaluate the messages.
+ *
+ * @throws ActionLifecycleException
+ * if the {@link TransformerFactory} could not be created.
+ *
+ */
+ @Override
+ public void initialise() throws ActionLifecycleException {
+ try {
+ this.factory = TransformerFactory.newInstance();
+ addFeatures(transformerConfig.getFeatures(), factory);
+ addAttributes(transformerConfig.getAttributes(), factory);
+ setResolver(transformerConfig.getUriResolver(), factory);
+ setErrorListener(new TransformerListener(failOnWarning), factory);
+
+ XPathFactory xPathFactory = XPathFactory.newInstance();
+ XPath xpath = xPathFactory.newXPath();
+
+ XPATH_GETTING_LIFTING_SCHEMA_MAPPING = xpath.compile("//@"
+ + LIFTING_SCHEMA_MAPPING);
+
+ XPATH_GETTING_LOWERING_SCHEMA_MAPPING = xpath.compile("//@"
+ + LOWERING_SCHEMA_MAPPING);
+
+ } catch (final TransformerConfigurationException e) {
+ throw new ActionLifecycleException(e.getMessage(), e);
+ } catch (XPathExpressionException e) {
+ throw new ActionLifecycleException(ERROR_INTIALISING_XPATH, e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.jboss.soa.esb.actions.ActionPipelineProcessor#process(org.jboss.soa
+ * .esb.message.Message)
+ */
+ @Override
+ public Message process(Message message) throws ActionProcessingException {
+ AssertArgument.isNotNull(message, "message");
+ Object payload;
+ try {
+ payload = payloadProxy.getPayload(message);
+
+ final Source source;
+ final Result result;
+ // If the payload is of SourceResult that use its source and result.
+ if (payload instanceof SourceResult) {
+ final SourceResult sourceResult = (SourceResult) payload;
+ source = sourceResult.getSource();
+ result = sourceResult.getResult();
+ } else {
+ source = SourceFactory.getInstance().createSource(payload);
+ result = ResultFactory.getInstance().createResult(
+ transformerConfig.getResultType());
+ }
+
+ Document document = DocumentFactory.getInstance().createDocument(
+ payload);
+
+ String liftingSchemaMapping = (String) XPATH_GETTING_LIFTING_SCHEMA_MAPPING
+ .evaluate(document, XPathConstants.STRING);
+ String loweringSchemaMapping = (String) XPATH_GETTING_LOWERING_SCHEMA_MAPPING
+ .evaluate(document, XPathConstants.STRING);
+
+ // If both a lifting and a lowering schema mapping are provided for
+ // the same element, we cannot handle the message
+ if (!isEmpty(liftingSchemaMapping)
+ && !isEmpty(loweringSchemaMapping)) {
+ throw new ActionProcessingException(
+ BOTH_ONTOLOGY_MAPPING_SCHEMAS);
+ }
+
+ String ontologyMappingSchema = null;
+
+ if (!isEmpty(liftingSchemaMapping)) {
+ // We are acting as a lifting action
+ if (OntologyAction.log.isDebugEnabled()) {
+ OntologyAction.log
+ .debug("Acting as a lifting action for message "
+ + message.getHeader().getCall()
+ .getMessageID());
+ }
+ ontologyMappingSchema = liftingSchemaMapping;
+ } else {
+ if (!isEmpty(loweringSchemaMapping)) {
+ // We are acting as a lowering action
+ if (OntologyAction.log.isDebugEnabled()) {
+ OntologyAction.log
+ .debug("Acting as a lowering action for message "
+ + message.getHeader().getCall()
+ .getMessageID());
+ }
+ ontologyMappingSchema = loweringSchemaMapping;
+ }
+ }
+ if (ontologyMappingSchema != null) {
+ final Templates xslTemplate = this
+ .getTemplate(ontologyMappingSchema);
+ final Transformer transformer = xslTemplate.newTransformer();
+ // Perform the transformation.
+ transformer.transform(source, result);
+
+ // Get the result and set on the message object
+ final Object object = ResultFactory.getInstance()
+ .extractResult(result,
+ transformerConfig.getResultType());
+ payloadProxy.setPayload(message, object);
+ return message;
+ } else {
+ // LIFTING_SCHEMA_MAPPING nor LOWERING_SCHEMA_MAPPING attribute
+ // was found in the message payload
+ throw new ActionProcessingException(NO_ONTOLOGY_MAPPING_SCHEMA);
+ }
+
+ } catch (TransformerConfigurationException e) {
+ throw new ActionProcessingException(e);
+ } catch (ActionLifecycleException e) {
+ throw new ActionProcessingException(e);
+ } catch (TransformerException e) {
+ throw new ActionProcessingException(e);
+ } catch (MessageDeliverException e) {
+ throw new ActionProcessingException(e.getMessage(), e);
+ } catch (Exception e) {
+ throw new ActionProcessingException(e);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s failOnWarning=%b, features=%s, attributes=%s",
+ getClass().getSimpleName(), failOnWarning, transformerConfig
+ .getFeatures(), transformerConfig.getAttributes());
+ }
+
+ /**
+ * Parses the passed-in ESB {@link ConfigTree} and populates a
+ * {@link TransformerFactoryConfig}.
+ *
+ * @param config
+ * The ESB {@link ConfigTree}.
+ * @return {@link TransformerFactoryConfig}.
+ * @throws ConfigurationException
+ */
+ protected TransformerFactoryConfig createConfig(final ConfigTree config)
+ throws ConfigurationException {
+ final Builder builder = new TransformerFactoryConfig.Builder();
+ extractFeatures(config, builder);
+ extractAttributes(config, builder);
+ createUrlResolver(config, builder);
+ builder.resultType(ResultFactory.ResultType.valueOf(config
+ .getRequiredAttribute("resultType")));
+ return builder.build();
+ }
+
+ /**
+ * Method implementing a Templates cache. When the Templates object with the
+ * corresponding ontologyMappingSchema key is not found in the cache, a new
+ * instance is created and added to the cache.
+ *
+ * @param ontologyMappingSchema
+ * the key used in the cache
+ * @return the Templates object from the cache.
+ * @throws TransformerConfigurationException
+ * @throws ActionLifecycleException
+ */
+ private Templates getTemplate(String ontologyMappingSchema)
+ throws TransformerConfigurationException, ActionLifecycleException {
+ if (!OntologyAction.templateCache.containsKey(ontologyMappingSchema)) {
+ OntologyAction.templateCache.put(ontologyMappingSchema, this
+ .createTemplate(ontologyMappingSchema));
+ }
+ return OntologyAction.templateCache.get(ontologyMappingSchema);
+ }
+
+ /**
+ *
+ * @param templateFile
+ * @return
+ * @throws ActionLifecycleException
+ * @throws TransformerConfigurationException
+ */
+ private Templates createTemplate(final String templateFile)
+ 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);
+ }
+ }
+ }
+ }
+
+ private boolean isEmpty(String value) {
+ if (value == null) {
+ return true;
+ } else {
+ return value.equals("");
+ }
+ }
+}
More information about the jboss-svn-commits
mailing list