[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