Package org.jboss.soa.esb.smooks

Source Code of org.jboss.soa.esb.smooks.SmooksAction

/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA  02110-1301, USA.
*
* (C) 2005-2006, JBoss Inc.
*/
package org.jboss.soa.esb.smooks;

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.helpers.ConfigTree;
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.message.Properties;
import org.jboss.soa.esb.smooks.resource.SmooksResource;
import org.milyn.Smooks;
import org.milyn.routing.file.FileListAccessor;
import org.milyn.util.CollectionsUtil;
import org.milyn.profile.Profile;
import org.milyn.container.ExecutionContext;
import org.milyn.container.plugin.PayloadProcessor;
import org.milyn.container.plugin.ResultType;
import org.milyn.event.report.HtmlReportGenerator;

import java.io.IOException;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
* <a href="http://milyn.codehaus.org/Smooks">Smooks</a> action pipeline processor.
* <p/>
* Usage:
* <pre>
* &lt;action name="transform" class="org.jboss.soa.esb.smooks.SmooksAction"&gt;
*   &lt;property name="smooksConfig" value="smooks-config.xml" /&gt;
* &lt;/action&gt;
* </pre>
*
* <u>Optional properties:</u>
* <pre>
* &lt;property name="get-payload-location" value="input" /&gt;
* &lt;property name="set-payload-location" value="ouput" /&gt;
* &lt;property name="mappedContextObjects" value="object1,object2" /&gt;
* &lt;property name="resultType" value="STRING" /&gt;
* &lt;property name="reportPath" value="/tmp/smooks-report.html" /&gt;
* &lt;property name="messageProfile" value="fromServiceA" /&gt;
* </pre>
*
* Description of configuration properties:
* <ul>
* <li><i>smooksConfig</i> - the Smooks configuration file. Can be a path on the file system or on the classpath.</li>
* <li><i>get-payload-location</i> - the body location which contains the object to be transformed.  See {@link MessagePayloadProxy}.</li>
* <li><i>set-payload-location</i> - the body location where the transformed object will be placed.  See {@link MessagePayloadProxy}.</li>
* <li><i>mappedContextObjects</i> - comma separated list of Smooks {@link ExecutionContext} objects to be mapped into the {@link #EXECUTION_CONTEXT_ATTR_MAP_KEY} Map on the ESB Message. Default is an empty list.
*                        See <a href="#exposing-smooks-exec">Exposing the Smooks ExecutionContext to other ESB Actions</a>.</li>
* <li><i>resultType</i> - type of result expected from Smooks ("STRING", "BYTES", "JAVA", "NORESULT"). Default is "STRING".  For more
*                         on specifying and controlling the Smooks filtering result, see <a href="#specify-result">Specifying the Source and Result Types</a>.</li>
* <li><i>javaResultBeanId</i> - specifies the Smooks bean context beanId to be mapped as the result when the resultType is "JAVA".  If not specified,
*                               the whole bean context bean Map is mapped as the result.</li>
* <li><i>reportPath</i> - specifies the path and file name for generating a Smooks Execution Report.  This is a development tool.</li>
* <li><i>messageProfile</i> - specifies the default message "profile" name to be used in {@link Smooks#createExecutionContext(String) creation of the Smooks ExecutionContext}.
*                             See <a href="#profiling">Message Profiling</a>.</li>
* </ul>
*
* <h3 id="exposing-smooks-exec">Exposing the Smooks {@link ExecutionContext} to other ESB Actions</h3>
* After Smooks has performed the filtering operation on the message payload, it can map the contents of the
* {@link ExecutionContext} onto a Map on the the ESB message, making it available to other actions in the ESB.
* This Map can be accessed by using the {@link #EXECUTION_CONTEXT_ATTR_MAP_KEY} key as follows:
* <pre>
* message.getBody().get( SmooksAction.EXECUTION_CONTEXT_ATTR_MAP_KEY );
* </pre>
* The {@link ExecutionContext} objects to be mapped must be specified in the "mappedContextObjects" action property.
* The objects must also be {@link Serializable}.
*
* <h3 id="specify-result">Specifying the Source and Result Types</h3>
* From the ESB Message data type, this action is able to automatically determine the type of
* {@link javax.xml.transform.Source} to use (via the Smooks {@link org.milyn.container.plugin.PayloadProcessor}).  The
* {@link javax.xml.transform.Result} type to be used can be specified via the "resultType"
* property, as outlined above.
* <p/>
* It is expected that the above mechanism will be satisfactory for most usecase, but not all.
* For the other usecases, this action supports {@link org.milyn.container.plugin.SourceResult}
* payloads on the ESB Message.  This allows you to manually specify other Source and Result
* types, which is of particular interest with respect to the Result type e.g. for streaming
* the Result to a file etc.
*
* <h3 id="profiling">Message Profiling</h3>
* Smooks Profiling allows you to use a single Smooks instance to transform multiple
* source messages.  As an example, imagine a situation where messages of different formats
* are delivered to a Service.  Before consuming the messages, the Service needs to transform
* these message payloads to a common format.  To accomplish this, you can use profiling.
* <p/>
* The action can have the default profile name configured through the "messageProfile"
* property.  Each incoming ESB message can specify it's profile name through the
* message property of the same name ("messageProfile").  For more on profiling, see
* the <a href="http://milyn.codehaus.org/Smooks+Example+-+profiling">profiling example</a>.
*
* @author <a href="mailto:tom.fennelly@jboss.com">tom.fennelly@jboss.com</a>
* @author <a href="mailto:daniel.bevenius@gmail.com">daniel.bevenius@gmail.com</a>
*/
public class SmooksAction extends AbstractActionPipelineProcessor
{
    public static final String EXECUTION_CONTEXT_ATTR_MAP_KEY = "SmooksExecutionContext";

    private Smooks smooks;

    private String defaultMessageProfile;

    private PayloadProcessor payloadProcessor;

    private MessagePayloadProxy payloadProxy;

    private String reportPath;
   
    private Set<String> mappedContextObjects;

    // public

    public SmooksAction( final ConfigTree configTree ) throws ConfigurationException
    {
        final String smooksConfig = configTree.getRequiredAttribute("smooksConfig");
        try
        {
            smooks = SmooksResource.createSmooksResource(smooksConfig);
        }
        catch (Exception e)
        {
            throw new ConfigurationException("Failed to create Smooks instance for config '" + smooksConfig + "'.", e);
        }

        // Get the default profile from the config...
        defaultMessageProfile = configTree.getAttribute(Properties.MESSAGE_PROFILE, Profile.DEFAULT_PROFILE);
       
        // Create the Smooks PayloadProcessor...
        String resultTypeConfig = configTree.getAttribute("resultType", "STRING");
        ResultType resultType;
        try {
            resultType = ResultType.valueOf(resultTypeConfig);
        } catch(IllegalArgumentException e) {
            throw new ConfigurationException("Invalid 'resultType' config value '" + resultTypeConfig + "'.  Valid values are: " + Arrays.asList(ResultType.values()));
        }
        payloadProcessor = new PayloadProcessor( smooks, resultType );
        if(resultType == ResultType.JAVA) {
            String javaResultBeanId = configTree.getAttribute("javaResultBeanId");
            if(javaResultBeanId != null) {
                payloadProcessor.setJavaResultBeanId(javaResultBeanId);
            }
        }

        payloadProxy = new MessagePayloadProxy( configTree );

        reportPath = configTree.getAttribute("reportPath");

        String mappedContextObjectsConfig = configTree.getAttribute("mappedContextObjects");
        String[] configuredMappedContextObjects;
        if(mappedContextObjectsConfig != null) {
            configuredMappedContextObjects = mappedContextObjectsConfig.split(",");
        } else {
            configuredMappedContextObjects = new String[0];
        }

        // Convert to a Set...
        mappedContextObjects = CollectionsUtil.toSet(configuredMappedContextObjects);

        // Add the default mapped objects to the set...
        mappedContextObjects.add(FileListAccessor.class.getName() + "#allListFileName"); // Constant is private on FileListAccessor (Grrrr!!!)
    }

    /**
     * Executes the actual Smooks tranformation.
     *
     * @param message  The ESB Message object
     *
     * @return      The ESB Message object with the output of the transformation.
     *
     */
  public Message process( final Message message) throws ActionProcessingException
  {
        //  Create Smooks ExecutionContext.
        final String messageProfofile = (String) message.getProperties().getProperty(Properties.MESSAGE_PROFILE, defaultMessageProfile);
        final ExecutionContext executionContext = smooks.createExecutionContext(messageProfofile);

        if(reportPath != null) {
            try {
                executionContext.setEventListener(new HtmlReportGenerator(reportPath));
            } catch (IOException e) {
                throw new ActionProcessingException("Failed to create HtmlReportGenerator instance.", e);
            }
        }

        //  Use the Smooks PayloadProcessor to execute the transformation....
        final Object payload;
        try {
            payload = payloadProxy.getPayload(message);
        } catch (MessageDeliverException e) {
            throw new ActionProcessingException("MessgeDeliveryException while trying to retrieve the message payload:", e);
        }
        final Object newPayload = payloadProcessor.process( payload, executionContext );

        //  Set the ExecutionContext's attributes on the message instance so other actions can access them.
        message.getBody().add( EXECUTION_CONTEXT_ATTR_MAP_KEY, getSerializableObjectsMap( executionContext.getAttributes() ) );

        try {
            payloadProxy.setPayload( message, newPayload );
        } catch (MessageDeliverException e) {
            throw new ActionProcessingException("MessgeDeliveryException while trying to retrieve the message payload:", e);
        }

        return message;
    }

    @Override
    public void destroy() throws ActionLifecycleException
    {
        SmooksResource.closeSmooksResource(smooks);
        super.destroy();
    }

    // protected

    /**
     * Will return a Map containing only the Serializable objects
     * listed in the "mappedContextObjects" action property.
     *
     * @param smooksAttribuesMap   - Map containing attributes from the Smooks ExecutionContext
     * @return Map  - Map containing only the Serializable ExecutionContext objects listed in
     * the "mappedContextObjects" action property.
     */
    @SuppressWarnings( "unchecked" )
  protected Map getSerializableObjectsMap( final Map smooksAttribuesMap )
  {
        Map smooksExecutionContextMap = new HashMap();

        for(String mappedContextObject : mappedContextObjects) {
            Object contextObject = smooksAttribuesMap.get(mappedContextObject);
            if(contextObject instanceof Serializable) {
                smooksExecutionContextMap.put( mappedContextObject, contextObject );
            }
        }

        return smooksExecutionContextMap;
  }

}
TOP

Related Classes of org.jboss.soa.esb.smooks.SmooksAction

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.