[jboss-svn-commits] JBL Code SVN: r21360 - in labs/jbossesb/trunk/product: rosetta/src/org/jboss/soa/esb/actions/scripting and 1 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Tue Aug 5 07:04:16 EDT 2008
Author: kevin.conner at jboss.com
Date: 2008-08-05 07:04:16 -0400 (Tue, 05 Aug 2008)
New Revision: 21360
Added:
labs/jbossesb/trunk/product/rosetta/src/org/jboss/soa/esb/actions/scripting/ScriptingAction.java
labs/jbossesb/trunk/product/rosetta/tests/src/org/jboss/soa/esb/actions/scripting/ScriptingActionUnitTest.java
labs/jbossesb/trunk/product/rosetta/tests/src/org/jboss/soa/esb/actions/scripting/test.bsh
Modified:
labs/jbossesb/trunk/product/docs/ProgrammersGuide.odt
Log:
Added scripting action: JBESB-1683
Modified: labs/jbossesb/trunk/product/docs/ProgrammersGuide.odt
===================================================================
(Binary files differ)
Added: labs/jbossesb/trunk/product/rosetta/src/org/jboss/soa/esb/actions/scripting/ScriptingAction.java
===================================================================
--- labs/jbossesb/trunk/product/rosetta/src/org/jboss/soa/esb/actions/scripting/ScriptingAction.java (rev 0)
+++ labs/jbossesb/trunk/product/rosetta/src/org/jboss/soa/esb/actions/scripting/ScriptingAction.java 2008-08-05 11:04:16 UTC (rev 21360)
@@ -0,0 +1,272 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, 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-2007,
+ */
+
+package org.jboss.soa.esb.actions.scripting;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+import org.apache.bsf.BSFException;
+import org.apache.bsf.BSFManager;
+import org.apache.log4j.Logger;
+import org.jboss.internal.soa.esb.util.StreamUtils;
+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.util.ClassUtil;
+
+/**
+ * <a href="http://jakarta.apache.org/bsf/">BSF</a> Scripting action pipeline processor.
+ * <p/>
+ * Based on {@link GroovyActionProcessor} by Gregory Pierce and Tom Fennelly.
+ * <p>
+ * <pre>
+ * <action name="helloWorld" class="org.jboss.soa.esb.actions.scripting.ScriptingAction">
+ * <property name="script" value="/scripts/helloWorld.bsh"/>
+ * <-- The language property is not required; it is deduced via the script extension but can be overridden -->
+ * <property name="language" value="beanshell"/>
+ * </action>
+ * </pre>
+ * </p>
+ * The {@link Message} is bound on the script under the name "message".
+ * The {@link ConfigTree} is bound under the name "config".
+ * The {@link MessagePayloadProxy} is bound under the name "payloadProxy".
+ * <p/>
+ * The script can also be supplied to this action as the message payload,
+ * allowing you to dynamically supply the action with a script.
+ * <p/>
+ * The following are the supported scripting languages, although the developer
+ * is responsible for including the appropriate 3rd party libraries (from bsf.jar's
+ * org/apache/bsf/Languages.properties):
+ *
+ * <pre>
+ * # List of script types and their associated scripting engines
+ * #
+ * # languageDescriptor = engineClass, ext1|ext2|... {, codebaseURL, ...}
+ * #
+ * # where exti are extensions for the language. Note that we leave
+ * # all the engines enabled now and allow them to fail at load time.
+ * # This way engines can be added by just adding to the classpath
+ * # without having to edit this file. Cheating, really, but it works.
+ * #
+ * javascript = org.apache.bsf.engines.javascript.JavaScriptEngine, js
+ * jacl = org.apache.bsf.engines.jacl.JaclEngine, jacl
+ * netrexx = org.apache.bsf.engines.netrexx.NetRexxEngine, nrx
+ * java = org.apache.bsf.engines.java.JavaEngine, java
+ * javaclass = org.apache.bsf.engines.javaclass.JavaClassEngine, class
+ * bml = org.apache.bml.ext.BMLEngine, bml
+ * vbscript = org.apache.bsf.engines.activescript.ActiveScriptEngine, vbs
+ * jscript = org.apache.bsf.engines.activescript.ActiveScriptEngine, jss
+ * perlscript = org.apache.bsf.engines.activescript.ActiveScriptEngine, pls
+ * perl = org.apache.bsf.engines.perl.PerlEngine, pl
+ * jpython = org.apache.bsf.engines.jpython.JPythonEngine, py
+ * jython = org.apache.bsf.engines.jython.JythonEngine, py
+ * lotusscript = org.apache.bsf.engines.lotusscript.LsEngine, lss
+ * xslt = org.apache.bsf.engines.xslt.XSLTEngine, xslt
+ * pnuts = pnuts.ext.PnutsBSFEngine, pnut
+ * beanbasic = org.apache.bsf.engines.beanbasic.BeanBasicEngine, bb
+ * beanshell = bsh.util.BeanShellBSFEngine, bsh
+ * ruby = org.jruby.javasupport.bsf.JRubyEngine, rb
+ * judoscript = com.judoscript.BSFJudoEngine, judo|jud
+ * </pre>
+ *
+ * @author dward at jboss.org
+ */
+public class ScriptingAction extends AbstractActionPipelineProcessor
+{
+
+ private static Logger logger = Logger.getLogger(ScriptingAction.class);
+
+ private static final Map<String,String> LANGUAGES = new HashMap<String,String>();
+
+ static
+ {
+ InputStream is = null;
+ try
+ {
+ is = BSFManager.class.getClassLoader().getResourceAsStream("org/apache/bsf/Languages.properties");
+ is = new BufferedInputStream(is);
+ Properties props = new Properties();
+ props.load(is);
+ for (Enumeration<?> names = props.propertyNames(); names.hasMoreElements();)
+ {
+ String lang = (String)names.nextElement();
+ StringTokenizer st = new StringTokenizer(props.getProperty(lang), ",");
+ st.nextToken(); // throw out the engine class name
+ st = new StringTokenizer(st.nextToken(), "|");
+ while ( st.hasMoreTokens() ) // now get each extension
+ LANGUAGES.put(st.nextToken().trim(), lang);
+ }
+ }
+ catch (IOException ioe) {}
+ finally
+ {
+ try { if (is != null) is.close(); } catch (Throwable t) {}
+ }
+ }
+
+ private ConfigTree config;
+ private MessagePayloadProxy payloadProxy;
+ private String script = null;
+ private String language = null;
+
+ public ScriptingAction(ConfigTree config)
+ {
+ this.config = config;
+ payloadProxy = new MessagePayloadProxy(config);
+ }
+
+ public void initialise() throws ActionLifecycleException
+ {
+ // attempt to get the script
+ String scriptPath = getAttribute("script");
+ if (scriptPath == null)
+ {
+ final boolean supportMessageBasedScripting = config.getBooleanAttribute("supportMessageBasedScripting", false);
+ if(supportMessageBasedScripting)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("No script specified on action config " + config.getAttribute("name")
+ + ". Expecting script to be in message.");
+ }
+ }
+ else
+ {
+ throw new ActionLifecycleException("'script' not configured on the action and message based scripting is not enabled ('supportMessageBasedScripting=false').");
+ }
+ }
+ else
+ {
+ InputStream scriptStream = null;
+ try
+ {
+ scriptStream = ClassUtil.getResourceAsStream(scriptPath, ScriptingAction.class);
+ if (scriptStream != null)
+ {
+ scriptStream = new BufferedInputStream(scriptStream);
+ script = new String( StreamUtils.readStream(scriptStream) );
+ }
+ else
+ {
+ // TODO: i18n
+ throw new ActionLifecycleException(
+ "script '" + scriptPath + "' not found on classpath" );
+ }
+ }
+ catch (Throwable t)
+ {
+ throw new ActionLifecycleException(t);
+ }
+ finally
+ {
+ try { if (scriptStream != null) scriptStream.close(); } catch (Throwable t) {}
+ }
+ }
+ // attempt to get the language
+ language = getAttribute("language");
+ if (language == null && script != null)
+ {
+ // try again via extension
+ int pos = scriptPath.lastIndexOf('.');
+ if (pos > -1 && pos < scriptPath.length()-1)
+ language = scriptPath.substring( pos+1, scriptPath.length() );
+ }
+ if (language != null)
+ {
+ // substitute extension for language if we can
+ if ( LANGUAGES.containsKey(language) )
+ language = LANGUAGES.get(language);
+ }
+ else
+ {
+ // TODO: i18n
+ throw new ActionLifecycleException("language not specified");
+ }
+ }
+
+ public Message process(Message message) throws ActionProcessingException
+ {
+ BSFManager bsf = new BSFManager();
+ try
+ {
+ bsf.declareBean( "message", message, message.getClass() );
+ bsf.declareBean( "config", config, config.getClass() );
+ bsf.declareBean( "payloadProxy", payloadProxy, payloadProxy.getClass() );
+ // NOTE: cannot use eval here since it does not work for all engines (jython in particular)
+ bsf.exec( language, null, 0, 0, getScript(message) );
+ }
+ catch (BSFException bsfe)
+ {
+ throw new ActionProcessingException(bsfe);
+ }
+ return message;
+ }
+
+ private String getScript(Message message) throws ActionProcessingException
+ {
+ if (script != null)
+ return script;
+ else
+ {
+ Object messageScript;
+ try
+ {
+ messageScript = payloadProxy.getPayload(message);
+ }
+ catch (MessageDeliverException mde)
+ {
+ throw new ActionProcessingException(mde);
+ }
+ if (messageScript instanceof String)
+ return (String)messageScript;
+ else if (messageScript instanceof byte[])
+ return new String( (byte[])messageScript );
+ else
+ {
+ // TODO: i18n
+ throw new ActionProcessingException("script not specified in message");
+ }
+ }
+ }
+
+ private String getAttribute(String name)
+ {
+ String value = config.getAttribute(name);
+ if (value != null)
+ {
+ value = value.trim();
+ if (value.length() == 0)
+ value = null;
+ }
+ return value;
+ }
+
+}
Property changes on: labs/jbossesb/trunk/product/rosetta/src/org/jboss/soa/esb/actions/scripting/ScriptingAction.java
___________________________________________________________________
Name: svn:keywords
+ Rev Date
Name: svn:eol-style
+ native
Added: labs/jbossesb/trunk/product/rosetta/tests/src/org/jboss/soa/esb/actions/scripting/ScriptingActionUnitTest.java
===================================================================
--- labs/jbossesb/trunk/product/rosetta/tests/src/org/jboss/soa/esb/actions/scripting/ScriptingActionUnitTest.java (rev 0)
+++ labs/jbossesb/trunk/product/rosetta/tests/src/org/jboss/soa/esb/actions/scripting/ScriptingActionUnitTest.java 2008-08-05 11:04:16 UTC (rev 21360)
@@ -0,0 +1,99 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, 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-2007,
+ */
+
+package org.jboss.soa.esb.actions.scripting;
+
+import junit.framework.TestCase;
+
+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.helpers.ConfigTree;
+import org.jboss.soa.esb.message.Message;
+import org.jboss.soa.esb.message.format.MessageFactory;
+
+/**
+ * Unit tests for ScriptingAction.
+ * <p/>
+ * Based on {@link GroovyActionProcessorUnitTest} by Tom Fennelly.
+ *
+ * @author dward at jboss.org
+ */
+public class ScriptingActionUnitTest extends TestCase
+{
+ public void test_bsh_file()
+ throws ConfigurationException, ActionLifecycleException, ActionProcessingException
+ {
+ do_script_file("test.bsh");
+ }
+
+ private void do_script_file(String script)
+ throws ConfigurationException, ActionLifecycleException, ActionProcessingException
+ {
+ ConfigTree config = new ConfigTree("<config/>");
+ config.setAttribute("script", "/org/jboss/soa/esb/actions/scripting/" + script);
+ String messageContents = "Hello World!";
+ config.setAttribute("messageContents", messageContents);
+ ScriptingAction action = new ScriptingAction(config);
+ Message message = MessageFactory.getInstance().getMessage();
+ assertProcessingOK(action, message, messageContents);
+ }
+
+ public void test_bsh_inlined()
+ throws ConfigurationException, ActionLifecycleException, ActionProcessingException
+ {
+ do_script_inlined(
+ "message.getBody().add(config.getAttribute(\"messageContents\").getBytes());",
+ "bsh" );
+ }
+
+ public void test_beanshell_inlined()
+ throws ConfigurationException, ActionLifecycleException, ActionProcessingException
+ {
+ do_script_inlined(
+ "message.getBody().add(config.getAttribute(\"messageContents\").getBytes());",
+ "beanshell" );
+ }
+
+ private void do_script_inlined(String script, String language)
+ throws ConfigurationException, ActionLifecycleException, ActionProcessingException
+ {
+ ConfigTree config = new ConfigTree("<config/>");
+ config.setAttribute("language", language);
+ config.setAttribute("supportMessageBasedScripting", "true") ;
+ String messageContents = "Hello World - Inlined!";
+ config.setAttribute("messageContents", messageContents);
+ ScriptingAction action = new ScriptingAction(config);
+ Message message = MessageFactory.getInstance().getMessage();
+ message.getBody().add(script);
+ assertProcessingOK(action, message, messageContents);
+ }
+
+ private void assertProcessingOK(ScriptingAction action, Message message, String messageContents)
+ throws ActionLifecycleException, ActionProcessingException
+ {
+ action.initialise();
+ action.process(message);
+ byte[] bodyContents = (byte[]) message.getBody().get();
+ assertNotNull("Expected body contents to be set.", bodyContents);
+ assertEquals( messageContents, new String(bodyContents) );
+ }
+
+}
Property changes on: labs/jbossesb/trunk/product/rosetta/tests/src/org/jboss/soa/esb/actions/scripting/ScriptingActionUnitTest.java
___________________________________________________________________
Name: svn:keywords
+ Rev Date
Name: svn:eol-style
+ native
Added: labs/jbossesb/trunk/product/rosetta/tests/src/org/jboss/soa/esb/actions/scripting/test.bsh
===================================================================
--- labs/jbossesb/trunk/product/rosetta/tests/src/org/jboss/soa/esb/actions/scripting/test.bsh (rev 0)
+++ labs/jbossesb/trunk/product/rosetta/tests/src/org/jboss/soa/esb/actions/scripting/test.bsh 2008-08-05 11:04:16 UTC (rev 21360)
@@ -0,0 +1 @@
+message.getBody().add(config.getAttribute("messageContents").getBytes());
\ No newline at end of file
More information about the jboss-svn-commits
mailing list