Package org.jboss.soa.esb.actions.scripting

Source Code of org.jboss.soa.esb.actions.scripting.GroovyActionProcessor

/*
* 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.actions.scripting;

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import groovy.util.GroovyScriptEngine;
import org.apache.log4j.Logger;
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.ActionPipelineProcessor;
import org.jboss.soa.esb.actions.ActionProcessingException;
import org.jboss.soa.esb.actions.ActionUtils;
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.body.content.BytesBody;
import org.jboss.soa.esb.util.ClassUtil;

import java.io.IOException;
import java.io.InputStream;

/**
* <a href="http://groovy.codehaus.org">Groovy</a> Scripting action processor.
* <p/>
* <pre>
* &lt;action name="groovy" class="org.jboss.soa.esb.actions.scripting.GroovyActionProcessor"&gt;
*     &lt;property name="script" value="/scripts/helloWorld.groovy" /&gt;
* &lt;/action&gt;
* </pre>
* <p/>
* The {@link Message} is bound into the script with the name "message".
* The {@link ConfigTree} is bound into the script with the name "config".
* The {@link MessagePayloadProxy} is bound into the script with the name "payloadProxy".
* The {@link Logger} is bound into the script with the name "logger".
* <p/>
* The script can also be supplied to this action as the message payload, allowing you to
* dynamically supply the action script.  For message based scripts to be executable,
* the "script" action property must be omitted and the "supportMessageBasedScripting" property must
* be set to "true".  There are obvious security issues around executing message based scripts,
* so use this feature controlled manner.
*
* @author Gregory Pierce.
* @author <a href="mailto:tom.fennelly@jboss.com">tom.fennelly@jboss.com</a>
*/
public class GroovyActionProcessor implements ActionPipelineProcessor {

    private static Logger logger = Logger.getLogger(GroovyActionProcessor.class);
    protected ConfigTree configTree;
    protected GroovyScriptEngine scriptEngine;
    private String scriptPath;
    private Script script;
    private boolean cacheScript;
    private MessagePayloadProxy payloadProxy;

    public GroovyActionProcessor(ConfigTree config) throws ConfigurationException {
        this.configTree = config;
        payloadProxy = new MessagePayloadProxy(configTree,
                                               new String[] {BytesBody.BYTES_LOCATION, ActionUtils.POST_ACTION_DATA},
                                               new String[] {ActionUtils.POST_ACTION_DATA});
    }

    public void initialise() throws ActionLifecycleException {
        scriptPath = configTree.getAttribute("script");
        cacheScript = configTree.getBooleanAttribute("cacheScript", true);
        if(scriptPath == null) {
            boolean supportMessageBasedScripting = configTree.getBooleanAttribute("supportMessageBasedScripting", false);
            if(supportMessageBasedScripting) {
                logger.info("No Groovy script specified on action config " + configTree.getAttribute("name")
                        + ". Expecting Groovy script to be in message.");
            } else {
                throw new ActionLifecycleException("'script' not configured on the action and message based scripting is not enabled ('supportMessageBasedScripting=false').");
            }
        }
    }

    /**
     * Get the input stream for the Groovy script (from the classpath).
     * @param scriptPath The script classpath.
     * @return An input
     */
    public static String getScriptFromClasspath(String scriptPath) throws IOException {
        InputStream scriptStream;

        scriptStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(scriptPath);
        if(scriptStream == null) {
            scriptStream = ClassUtil.getResourceAsStream(scriptPath, GroovyActionProcessor.class);
            if(scriptStream == null) {
                throw new IOException("Script '" + scriptPath + "' not found on classpath.");
            }
        }

        try {
            return new String(StreamUtils.readStream(scriptStream));
        } finally {
            try {
                if(scriptStream != null) {
                    scriptStream.close();
                }
            } catch (IOException e) {
                throw new IOException("Failed to close script '" + scriptPath + "' stream.");
            }
        }
    }

    public void destroy() throws ActionLifecycleException {
    }
   
    /**
     * Processes an ESB message. Configuration is via two properties of this ESB element
     * scriptPath - The path to the script that will be run
     * script - the name of the script that will be run (include .groovy exception)
     */
    public synchronized Message process(Message message) throws ActionProcessingException {
        try {
          Script execScript = getScript(message);
            // create a Java/Groovy binding for the message object
            //
            Binding binding = new Binding();

            // binds the message object to the script with a variable name of 'message'
            //
            binding.setVariable("message", message);
            binding.setVariable("config", configTree);
            binding.setVariable("payloadProxy", payloadProxy);
            binding.setVariable("logger", logger);

            execScript.setBinding(binding);

            Object returnVal = execScript.run();

            if(returnVal instanceof Message) {
                return (Message) returnVal;
            } else {
                return message;
            }
        }
        catch (Exception e) {
            logger.error("Error executing Groovy script.", e);
           
            throw new ActionProcessingException("Error executing Groovy script.", e);
    }
  }

    protected Script getScript(Message message) throws ActionProcessingException {
        if(scriptPath != null) {
            if(script == null || !cacheScript) {
                try {
                    String scriptText = GroovyActionProcessor.getScriptFromClasspath(scriptPath);
                    script = constructScriptInstance(scriptText);
                } catch (IOException e) {
                    throw new ActionProcessingException("Error reading script '" + scriptPath + "' stream.");
                }
            }
           
            return script;
        } else {
            // So, the script is being passed in in the message...
            Object messageScript;

            try {
                messageScript = payloadProxy.getPayload(message);
            } catch (MessageDeliverException e) {
                throw new ActionProcessingException(e);
            }

            if(messageScript instanceof String) {
                return constructScriptInstance((String)messageScript);
            } else if(messageScript instanceof byte[]) {
                return constructScriptInstance(new String((byte[])messageScript));
            } else {
                throw new ActionProcessingException("Groovy script not specified in message.");
            }
        }
    }

    private Script constructScriptInstance(String scriptText) {
        GroovyShell shell = new GroovyShell(Thread.currentThread().getContextClassLoader());
        return shell.parse(scriptText);
    }

    public void processException(final Message message, final Throwable th) {
    }

    public void processSuccess(final Message message) {
    }
}
TOP

Related Classes of org.jboss.soa.esb.actions.scripting.GroovyActionProcessor

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.