[jbpm-commits] JBoss JBPM SVN: r5942 - in jbpm4/trunk/modules: bpmn/src/main/resources/META-INF/services and 1 other directories.
do-not-reply at jboss.org
do-not-reply at jboss.org
Thu Dec 10 06:15:52 EST 2009
Author: jbarrez
Date: 2009-12-10 06:15:51 -0500 (Thu, 10 Dec 2009)
New Revision: 5942
Added:
jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/script/XPathScriptEngine.java
jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/script/XPathScriptEngineFactory.java
Removed:
jbpm4/trunk/modules/bpmn/src/main/java/com/sun/script/xpath/
Modified:
jbpm4/trunk/modules/bpmn/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
Log:
JBPM-2632: move XpathScriptEngine
Modified: jbpm4/trunk/modules/bpmn/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
===================================================================
--- jbpm4/trunk/modules/bpmn/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory 2009-12-10 09:09:01 UTC (rev 5941)
+++ jbpm4/trunk/modules/bpmn/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory 2009-12-10 11:15:51 UTC (rev 5942)
@@ -1 +1 @@
-com.sun.script.xpath.XPathScriptEngineFactory
\ No newline at end of file
+org.jbpm.pvm.internal.script.XPathScriptEngineFactory
\ No newline at end of file
Copied: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/script/XPathScriptEngine.java (from rev 5938, jbpm4/trunk/modules/bpmn/src/main/java/com/sun/script/xpath/XPathScriptEngine.java)
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/script/XPathScriptEngine.java (rev 0)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/script/XPathScriptEngine.java 2009-12-10 11:15:51 UTC (rev 5942)
@@ -0,0 +1,458 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met: Redistributions of source code
+ * must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution. Neither the name of the Sun Microsystems nor the names of
+ * is contributors may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * XPathScriptEngine.java
+ * @author A. Sundararajan
+ */
+
+package org.jbpm.pvm.internal.script;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.script.AbstractScriptEngine;
+import javax.script.Bindings;
+import javax.script.Compilable;
+import javax.script.CompiledScript;
+import javax.script.Invocable;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptException;
+import javax.script.SimpleBindings;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathFactory;
+import javax.xml.xpath.XPathFunction;
+import javax.xml.xpath.XPathFunctionResolver;
+import javax.xml.xpath.XPathVariableResolver;
+
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+
+public class XPathScriptEngine extends AbstractScriptEngine implements Compilable {
+
+ // my factory, may be null
+ private ScriptEngineFactory factory;
+ private XPathFactory xpathFactory;
+
+ // special context variables for XPath result type and input
+ public static final String XPATH_RESULT_TYPE = "com.sun.script.xpath.resultType";
+ public static final String XPATH_INPUT_SRC = "com.sun.script.xpath.inputSource";
+
+ // XML namespace prefixes and URIs.
+ public static final String XMLNS_COLON = "xmlns:";
+ public static final String XPATH_CONTEXT_PREFIX = "context";
+ public static final String XPATH_CONTEXT_URI = "http://www.sun.com/java/jsr223/xpath/context";
+
+ private Document objectData;
+
+ public XPathScriptEngine() {
+ xpathFactory = XPathFactory.newInstance();
+ }
+
+ // my implementation for CompiledScript
+ private class XPathCompiledScript extends CompiledScript {
+
+ private XPathExpression expr;
+
+ XPathCompiledScript(XPathExpression expr) {
+ this.expr = expr;
+ }
+
+ public ScriptEngine getEngine() {
+ return XPathScriptEngine.this;
+ }
+
+ public Object eval(ScriptContext ctx) throws ScriptException {
+ return evalXPath(expr, ctx);
+ }
+ }
+
+ public CompiledScript compile(String script) throws ScriptException {
+ XPathExpression expr = compileXPath(script, context);
+ return new XPathCompiledScript(expr);
+ }
+
+ public CompiledScript compile(Reader reader) throws ScriptException {
+ return compile(readFully(reader));
+ }
+
+ public Object eval(String str, ScriptContext ctx) throws ScriptException {
+ XPathExpression expr = compileXPath(str, ctx);
+ return evalXPath(expr, ctx);
+ }
+
+ public Object eval(Reader reader, ScriptContext ctx) throws ScriptException {
+ return eval(readFully(reader), ctx);
+ }
+
+ public ScriptEngineFactory getFactory() {
+ synchronized (this) {
+ if (factory == null) {
+ factory = new XPathScriptEngineFactory();
+ }
+ }
+ return factory;
+ }
+
+ public Bindings createBindings() {
+ return new SimpleBindings();
+ }
+
+ void setFactory(ScriptEngineFactory factory) {
+ this.factory = factory;
+ }
+
+ // Internals only below this point
+
+ // find a variable of given qname in given context
+ private static Object findVariable(QName qname, ScriptContext ctx) {
+ String name;
+ int scope;
+
+ if (XPATH_CONTEXT_URI.equals(qname.getNamespaceURI())) {
+ name = qname.getLocalPart();
+ synchronized (ctx) {
+ scope = ctx.getAttributesScope(name);
+ if (scope != -1) {
+ return ctx.getAttribute(name, scope);
+ } // else fallthru
+ }
+ }
+ if (qname.getPrefix() == null || "".equals(qname.getPrefix())) {
+ name = qname.getLocalPart();
+ } else {
+ name = qname.getPrefix() + ":" + qname.getLocalPart();
+ }
+ synchronized (ctx) {
+ scope = ctx.getAttributesScope(name);
+ if (scope != -1) {
+ return ctx.getAttribute(name, scope);
+ } // else fallthru
+ }
+ return null;
+ }
+
+ private static void collectNamespaces(Map<String, String> map, Bindings scope) {
+ for (String key : scope.keySet()) {
+ if (key.startsWith(XMLNS_COLON)) {
+ Object uri = scope.get(key);
+ // collect all variables starting with "xmlns:" and
+ // collect the prefix to URI mappings.
+ String prefix = key.substring(XMLNS_COLON.length());
+ if (uri instanceof String) {
+ String tmp = (String) uri;
+ if (tmp.length() != 0) {
+ map.put(prefix, tmp);
+ }
+ }
+ }
+ }
+ }
+
+ private static NamespaceContext makeNamespaceContext(ScriptContext ctx) {
+ // namespace prefix-to-URI mappings
+ final Map<String, String> namespaces = new HashMap<String, String>();
+ for (int scope : ctx.getScopes()) {
+ Bindings bind = ctx.getBindings(scope);
+ if (bind != null) {
+ // TODO: See what needs to be done....
+ // collectNamespaces(namespaces, bind);
+ }
+ }
+
+ // look for mapping for default XML namespace
+ Object def = ctx.getAttribute(XMLConstants.XMLNS_ATTRIBUTE);
+ if (def instanceof String) {
+ namespaces.put(XMLConstants.DEFAULT_NS_PREFIX, (String) def);
+ }
+
+ // standard required mappings by XPath standard
+ namespaces.put(XMLConstants.XML_NS_PREFIX, XMLConstants.XML_NS_URI);
+ namespaces.put(XMLConstants.XMLNS_ATTRIBUTE, XMLConstants.XMLNS_ATTRIBUTE_NS_URI);
+
+ // add prefix mapping for XPATH_CONTEXT_PREFIX
+ namespaces.put(XPATH_CONTEXT_PREFIX, XPATH_CONTEXT_URI);
+
+ return new NamespaceContext() {
+
+ public String getNamespaceURI(String prefix) {
+ if (prefix == null) {
+ throw new IllegalArgumentException();
+ }
+ String uri = namespaces.get(prefix);
+ if (uri == null) {
+ return XMLConstants.NULL_NS_URI;
+ } else {
+ return uri;
+ }
+ }
+
+ public String getPrefix(String namespaceURI) {
+ if (namespaceURI == null) {
+ throw new IllegalArgumentException();
+ }
+ for (String prefix : namespaces.keySet()) {
+ String uri = namespaces.get(prefix);
+ if (namespaceURI.equals(uri)) {
+ return prefix;
+ }
+ }
+ return null;
+ }
+
+ public Iterator getPrefixes(String namespaceURI) {
+ if (namespaceURI == null) {
+ throw new IllegalArgumentException();
+ }
+ List list = new ArrayList();
+ for (String prefix : namespaces.keySet()) {
+ String uri = namespaces.get(prefix);
+ if (namespaceURI.equals(uri)) {
+ list.add(prefix);
+ }
+ }
+ return Collections.unmodifiableList(list).iterator();
+ }
+ };
+ }
+
+ private static XPathFunction makeXPathFunction(final Constructor ctr, int arity) {
+ if (ctr.getParameterTypes().length != arity) {
+ return null;
+ }
+ return new XPathFunction() {
+
+ public Object evaluate(List args) {
+ try {
+ return ctr.newInstance(args.toArray());
+ } catch (Exception exp) {
+ throw new RuntimeException(exp);
+ }
+ }
+ };
+ }
+
+ private static XPathFunction makeXPathFunction(final Method method, int arity) {
+ int modifiers = method.getModifiers();
+ int numArgs = method.getParameterTypes().length;
+ if (Modifier.isStatic(modifiers) && numArgs == arity) {
+ // static method. expose "as is".
+ return new XPathFunction() {
+
+ public Object evaluate(List args) {
+ try {
+ return method.invoke(null, args.toArray());
+ } catch (Exception exp) {
+ throw new RuntimeException(exp);
+ }
+ }
+ };
+ } else if ((numArgs + 1) == arity) {
+ // instance method. treat the first arg as 'this'
+ return new XPathFunction() {
+
+ public Object evaluate(List args) {
+ List tmp = args.subList(1, args.size());
+ try {
+ return method.invoke(args.get(0), tmp.toArray());
+ } catch (Exception exp) {
+ throw new RuntimeException(exp);
+ }
+ }
+ };
+ } else {
+ return null;
+ }
+ }
+
+ private static XPathFunction makeXPathFunction(final String funcName, final Invocable invocable) {
+ return new XPathFunction() {
+
+ public Object evaluate(List args) {
+ try {
+ return invocable.invokeFunction(funcName, args.toArray());
+ } catch (Exception exp) {
+ throw new RuntimeException(exp);
+ }
+ }
+ };
+ }
+
+ // make a XPathFunction from given object
+ private static XPathFunction makeXPathFunction(QName qname, Object obj, int arity) {
+ if (obj == null) {
+ return null;
+ } else if (obj instanceof XPathFunction) {
+ // already XPathFunction - just return
+ return (XPathFunction) obj;
+ } else if (obj instanceof Method) {
+ // a Method object. wrap as XPathFunction
+ return makeXPathFunction((Method) obj, arity);
+ } else if (obj instanceof Constructor) {
+ // a Constructor object. wrap as XPathFunction
+ return makeXPathFunction((Constructor) obj, arity);
+ } else if (obj instanceof Invocable) {
+ // wrap a script function as XPathFunction. Using this,
+ // scripts from other languages (for eg. JavaScript) can use
+ // this engine and pass script functions as XPathFunction extensions
+
+ return makeXPathFunction(qname.getLocalPart(), (Invocable) obj);
+ } else {
+ // can't map the object as XPathFunction.
+ return null;
+ }
+ }
+
+ // Internals only below this point
+ private XPathExpression compileXPath(String str, final ScriptContext ctx) throws ScriptException {
+ // JSR-223 requirement
+ ctx.setAttribute("context", ctx, ScriptContext.ENGINE_SCOPE);
+ try {
+ XPath xpath = xpathFactory.newXPath();
+ xpath.setXPathVariableResolver(new XPathVariableResolver() {
+
+ public Object resolveVariable(QName qname) {
+ return findVariable(qname, ctx);
+ }
+ });
+
+ xpath.setXPathFunctionResolver(new XPathFunctionResolver() {
+
+ public XPathFunction resolveFunction(QName qname, int arity) {
+ Object obj = findVariable(qname, ctx);
+ return makeXPathFunction(qname, obj, arity);
+ }
+ });
+ xpath.setNamespaceContext(makeNamespaceContext(ctx));
+ // xpath.setNamespaceContext(new BpmnFunctionResolver());
+ // xpath.setXPathFunctionResolver(new BpmnFunctionResolver());
+ int begin = str.indexOf("getObjectData") > -1 ? 14 : 0;
+ if (begin > 0) {
+ String objectDataRef = str.substring(begin + 1, str.indexOf(")") - 1);
+
+ objectData = (Document) ctx.getAttribute(objectDataRef);
+ // ctx.setAttribute(XPATH_INPUT_SRC, objectData , 100);
+
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ Source xmlSource = new DOMSource(objectData);
+ Result outputTarget = new StreamResult(outputStream);
+ TransformerFactory.newInstance().newTransformer().transform(xmlSource, outputTarget);
+ InputStream is = new ByteArrayInputStream(outputStream.toByteArray());
+ ctx.setReader(new InputStreamReader(is));
+
+ str = str.substring(str.indexOf(")") + 1);
+ }
+ XPathExpression xpe = xpath.compile(str);
+ return xpe;
+ } catch (Exception exp) {
+ throw new ScriptException(exp);
+ }
+ }
+
+ private Object getVariable(ScriptContext ctx, String name) {
+ synchronized (ctx) {
+ int scope = ctx.getAttributesScope(name);
+ if (scope != -1) {
+ return ctx.getAttribute(name, scope);
+ }
+ }
+ return null;
+ }
+ private Object evalXPath(XPathExpression expr, final ScriptContext ctx) throws ScriptException {
+
+ try {
+ Object resultType = getVariable(ctx, XPATH_RESULT_TYPE);
+ Object input = getVariable(ctx, XPATH_INPUT_SRC);
+
+ InputSource src;
+ if (input == null) {
+ // no input specified, use context reader
+ src = new InputSource(ctx.getReader());
+ } else {
+ // explicit InputSource specified
+ if (input instanceof InputSource) {
+ src = (InputSource) input;
+ } else if (input instanceof String) {
+ src = new InputSource((String) input);
+ } else if (input instanceof Reader) {
+ src = new InputSource((Reader) input);
+ } else if (input instanceof InputStream) {
+ src = new InputSource((InputStream) input);
+ } else {
+ // some other object input type specified (Node/NodeList)
+ src = null;
+ }
+ }
+
+ resultType = XPathConstants.BOOLEAN;
+
+ if (resultType instanceof QName) {
+ return (src != null) ? expr.evaluate(src, (QName) resultType) : expr.evaluate(input, (QName) resultType);
+ } else {
+ return (src != null) ? expr.evaluate(src) : expr.evaluate(input);
+ }
+ } catch (Exception exp) {
+ throw new ScriptException(exp);
+ }
+ }
+
+ private String readFully(Reader reader) throws ScriptException {
+ char[] arr = new char[8 * 1024]; // 8K at a time
+ StringBuilder buf = new StringBuilder();
+ int numChars;
+ try {
+ while ((numChars = reader.read(arr, 0, arr.length)) > 0) {
+ buf.append(arr, 0, numChars);
+ }
+ } catch (IOException exp) {
+ throw new ScriptException(exp);
+ }
+ return buf.toString();
+ }
+}
Copied: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/script/XPathScriptEngineFactory.java (from rev 5938, jbpm4/trunk/modules/bpmn/src/main/java/com/sun/script/xpath/XPathScriptEngineFactory.java)
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/script/XPathScriptEngineFactory.java (rev 0)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/script/XPathScriptEngineFactory.java 2009-12-10 11:15:51 UTC (rev 5942)
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met: Redistributions of source code
+ * must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution. Neither the name of the Sun Microsystems nor the names of
+ * is contributors may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * XPathScriptEngineFactory.java
+ * @author A. Sundararajan
+ */
+
+package org.jbpm.pvm.internal.script;
+
+import javax.script.*;
+import java.util.*;
+
+public class XPathScriptEngineFactory implements ScriptEngineFactory {
+ public String getEngineName() {
+ return "xpath";
+ }
+
+ public String getEngineVersion() {
+ return "1.0";
+ }
+
+ public List<String> getExtensions() {
+ return extensions;
+ }
+
+ public String getLanguageName() {
+ return "jaxp";
+ }
+
+ public String getLanguageVersion() {
+ return "1.4";
+ }
+
+ public String getMethodCallSyntax(String obj, String m, String... args) {
+ throw new UnsupportedOperationException("getMethodCallSyntax");
+ }
+
+ public List<String> getMimeTypes() {
+ return mimeTypes;
+ }
+
+ public List<String> getNames() {
+ return names;
+ }
+
+ public String getOutputStatement(String str) {
+ throw new UnsupportedOperationException("getOutputStatement");
+ }
+
+ public String getParameter(String key) {
+ if (key.equals(ScriptEngine.ENGINE)) {
+ return getEngineName();
+ } else if (key.equals(ScriptEngine.ENGINE_VERSION)) {
+ return getEngineVersion();
+ } else if (key.equals(ScriptEngine.NAME)) {
+ return getEngineName();
+ } else if (key.equals(ScriptEngine.LANGUAGE)) {
+ return getLanguageName();
+ } else if (key.equals(ScriptEngine.LANGUAGE_VERSION)) {
+ return getLanguageVersion();
+ } else if (key.equals("THREADING")) {
+ return "MULTITHREADED";
+ } else {
+ return null;
+ }
+ }
+
+ public String getProgram(String... statements) {
+ throw new UnsupportedOperationException("getProgram");
+ }
+
+ public ScriptEngine getScriptEngine() {
+ XPathScriptEngine engine = new XPathScriptEngine();
+ engine.setFactory(this);
+ return engine;
+ }
+
+ private static List<String> names;
+ private static List<String> extensions;
+ private static List<String> mimeTypes;
+ static {
+ names = new ArrayList<String>(1);
+ names.add("xpath");
+ names = Collections.unmodifiableList(names);
+ extensions = names;
+ mimeTypes = new ArrayList<String>(0);
+ mimeTypes = Collections.unmodifiableList(mimeTypes);
+ }
+}
More information about the jbpm-commits
mailing list