You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by ad...@apache.org on 2010/03/23 22:05:56 UTC

svn commit: r926780 - in /ofbiz/trunk/framework: base/src/org/ofbiz/base/util/GroovyUtil.java service/src/org/ofbiz/service/engine/GroovyEngine.java

Author: adrianc
Date: Tue Mar 23 21:05:56 2010
New Revision: 926780

URL: http://svn.apache.org/viewvc?rev=926780&view=rev
Log:
Added the ability for services to invoke Groovy script methods. Groovy service methods do not have parameters; parameters are passed in the context - just like simple method services.

Removed long comment (unused cache testing code) in GroovyUtil.java.

Modified:
    ofbiz/trunk/framework/base/src/org/ofbiz/base/util/GroovyUtil.java
    ofbiz/trunk/framework/service/src/org/ofbiz/service/engine/GroovyEngine.java

Modified: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/GroovyUtil.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/GroovyUtil.java?rev=926780&r1=926779&r2=926780&view=diff
==============================================================================
--- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/GroovyUtil.java (original)
+++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/GroovyUtil.java Tue Mar 23 21:05:56 2010
@@ -18,21 +18,20 @@
  */
 package org.ofbiz.base.util;
 
-import java.io.InputStream;
 import java.io.IOException;
-import java.net.MalformedURLException;
+import java.io.InputStream;
 import java.net.URL;
 import java.util.Map;
 import java.util.Set;
 
-import org.ofbiz.base.location.FlexibleLocation;
-import org.ofbiz.base.util.cache.UtilCache;
-
 import groovy.lang.Binding;
 import groovy.lang.GroovyClassLoader;
 import groovy.lang.GroovyShell;
+
 import org.codehaus.groovy.control.CompilationFailedException;
 import org.codehaus.groovy.runtime.InvokerHelper;
+import org.ofbiz.base.location.FlexibleLocation;
+import org.ofbiz.base.util.cache.UtilCache;
 
 /**
  * GroovyUtil - Groovy Utilities
@@ -131,83 +130,27 @@ public class GroovyUtil {
         }
     }
 
-    @SuppressWarnings("unchecked")
-    public static Object runScriptAtLocation(String location, Map<String, Object> context) throws GeneralException {
+    public static Class<?> getScriptClassFromLocation(String location) throws GeneralException {
         try {
-            Class scriptClass = parsedScripts.get(location);
+            Class<?> scriptClass = parsedScripts.get(location);
             if (scriptClass == null) {
                 URL scriptUrl = FlexibleLocation.resolveLocation(location);
                 if (scriptUrl == null) {
                     throw new GeneralException("Script not found at location [" + location + "]");
                 }
-
                 scriptClass = parseClass(scriptUrl.openStream(), location);
-                if (Debug.verboseOn()) Debug.logVerbose("Caching Groovy script at: " + location, module);
-                parsedScripts.put(location, scriptClass);
-            }
-
-            return InvokerHelper.createScript(scriptClass, getBinding(context)).run();
-
-            /* This code is just to test performance of the parsed versus unparsed approaches
-            long startTimeParsed = System.currentTimeMillis();
-            InvokerHelper.createScript(scriptClass, getBinding(context)).run();
-            if (Debug.timingOn()) Debug.logTiming("Ran parsed groovy script in [" + (System.currentTimeMillis() - startTimeParsed) + "]ms at: " + location, module);
-            */
-
-            /* NOTE DEJ20080526: this approach uses a pre-parsed script but it is not thread safe
-             *
-             * the groovy Script object contains both the parsed script AND the context, which is weird when trying to run a cached Script
-             * there is no available clone() method on the Script object, so we can't clone and set the context/binding to get around thread-safe issues
-            Script script = parsedScripts.get(location);
-            if (script == null) {
-                URL scriptUrl = FlexibleLocation.resolveLocation(location);
-                if (scriptUrl == null) {
-                    throw new GeneralException("Script not found at location [" + location + "]");
+                if (Debug.verboseOn()) {
+                    Debug.logVerbose("Caching Groovy script at: " + location, module);
                 }
-
-                script = emptyGroovyShell.parse(scriptUrl.openStream(), scriptUrl.getFile());
-                if (Debug.verboseOn()) Debug.logVerbose("Caching Groovy script at: " + location, module);
-                parsedScripts.put(location, script);
-            }
-
-            script.setBinding(getBinding(context));
-            return script.run();
-             */
-
-            /* NOTE DEJ20080527: this approach works but only caches script text, not the parsed script
-            public static UtilCache<String, String> sourceScripts = UtilCache.createUtilCache("script.GroovyLocationSourceCache", 0, 0, false);
-
-            public static GroovyShell emptyGroovyShell = new GroovyShell();
-            String scriptString = sourceScripts.get(location);
-            if (scriptString == null) {
-                URL scriptUrl = FlexibleLocation.resolveLocation(location);
-                if (scriptUrl == null) {
-                    throw new GeneralException("Script not found at location [" + location + "]");
-                }
-
-                scriptString = UtilURL.readUrlText(scriptUrl);
-
-                if (Debug.verboseOn()) Debug.logVerbose("Caching Groovy script source at: " + location, module);
-                sourceScripts.put(location, scriptString);
+                parsedScripts.put(location, scriptClass);
             }
-
-            long startTime = System.currentTimeMillis();
-            Script script = emptyGroovyShell.parse(scriptString, location);
-            script.setBinding(getBinding(context));
-            Object scriptResult = script.run();
-            if (Debug.timingOn()) Debug.logTiming("Parsed and ran groovy script in [" + (System.currentTimeMillis() - startTime) + "]ms at: " + location, module);
-
-            return scriptResult;
-             */
-        } catch (MalformedURLException e) {
-            String errMsg = "Error loading Groovy script at [" + location + "]: " + e.toString();
-            throw new GeneralException(errMsg, e);
-        } catch (IOException e) {
-            String errMsg = "Error loading Groovy script at [" + location + "]: " + e.toString();
-            throw new GeneralException(errMsg, e);
-        } catch (CompilationFailedException e) {
-            String errMsg = "Error loading Groovy script at [" + location + "]: " + e.toString();
-            throw new GeneralException(errMsg, e);
+            return scriptClass;
+        } catch (Exception e) {
+            throw new GeneralException("Error loading Groovy script at [" + location + "]: ", e);
         }
     }
+
+    public static Object runScriptAtLocation(String location, Map<String, Object> context) throws GeneralException {
+        return InvokerHelper.createScript(getScriptClassFromLocation(location), getBinding(context)).run();
+    }
 }

Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/engine/GroovyEngine.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/engine/GroovyEngine.java?rev=926780&r1=926779&r2=926780&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/engine/GroovyEngine.java (original)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/engine/GroovyEngine.java Tue Mar 23 21:05:56 2010
@@ -20,6 +20,9 @@ package org.ofbiz.service.engine;
 
 import java.util.Map;
 
+import org.codehaus.groovy.runtime.InvokerHelper;
+import groovy.lang.Binding;
+import groovy.lang.Script;
 import org.ofbiz.base.util.GeneralException;
 import org.ofbiz.base.util.GroovyUtil;
 import static org.ofbiz.base.util.UtilGenerics.cast;
@@ -34,6 +37,8 @@ import org.ofbiz.service.ServiceUtil;
  */
 public final class GroovyEngine extends GenericAsyncEngine {
 
+    protected static final Object[] EMPTY_ARGS = {};
+
     public GroovyEngine(ServiceDispatcher dispatcher) {
         super(dispatcher);
     }
@@ -58,22 +63,23 @@ public final class GroovyEngine extends 
         if (UtilValidate.isEmpty(modelService.location)) {
             throw new GenericServiceException("Cannot run Groovy service with empty location");
         }
-
-        String location = this.getLocation(modelService);
         context.put("dctx", dispatcher.getLocalContext(localName));
-
         try {
-            Object resultObj = GroovyUtil.runScriptAtLocation(location, context);
-
-            if (resultObj != null && resultObj instanceof Map) {
+            Script script = InvokerHelper.createScript(GroovyUtil.getScriptClassFromLocation(this.getLocation(modelService)), new Binding(context));
+            Object resultObj = null;
+            if (UtilValidate.isEmpty(modelService.invoke)) {
+                resultObj = script.run();
+            } else {
+                resultObj = script.invokeMethod(modelService.invoke, EMPTY_ARGS);
+            }
+            if (resultObj != null && resultObj instanceof Map<?, ?>) {
                 return cast(resultObj);
-            } else if (context.get("result") != null && context.get("result") instanceof Map) {
+            } else if (context.get("result") != null && context.get("result") instanceof Map<?, ?>) {
                 return cast(context.get("result"));
             }
         } catch (GeneralException e) {
             throw new GenericServiceException(e);
         }
-
         return ServiceUtil.returnSuccess();
     }
 }



Re: svn commit: r926780 - in /ofbiz/trunk/framework: base/src/org/ofbiz/base/util/GroovyUtil.java service/src/org/ofbiz/service/engine/GroovyEngine.java

Posted by Adam Heath <do...@brainfood.com>.
adrianc@apache.org wrote:
> Author: adrianc
> Date: Tue Mar 23 21:05:56 2010
> New Revision: 926780
> 
> URL: http://svn.apache.org/viewvc?rev=926780&view=rev
> Log:
> Added the ability for services to invoke Groovy script methods. Groovy service methods do not have parameters; parameters are passed in the context - just like simple method services.
> 
> Removed long comment (unused cache testing code) in GroovyUtil.java.
> 
> Modified:
>     ofbiz/trunk/framework/base/src/org/ofbiz/base/util/GroovyUtil.java
>     ofbiz/trunk/framework/service/src/org/ofbiz/service/engine/GroovyEngine.java
> 
> Modified: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/GroovyUtil.java
> URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/GroovyUtil.java?rev=926780&r1=926779&r2=926780&view=diff
> ==============================================================================
> --- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/GroovyUtil.java (original)
> +++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/GroovyUtil.java Tue Mar 23 21:05:56 2010
> @@ -18,21 +18,20 @@
>   */
>  package org.ofbiz.base.util;
>  
> -import java.io.InputStream;
>  import java.io.IOException;
> -import java.net.MalformedURLException;
> +import java.io.InputStream;
>  import java.net.URL;
>  import java.util.Map;
>  import java.util.Set;
>  
> -import org.ofbiz.base.location.FlexibleLocation;
> -import org.ofbiz.base.util.cache.UtilCache;
> -
>  import groovy.lang.Binding;
>  import groovy.lang.GroovyClassLoader;
>  import groovy.lang.GroovyShell;
> +
>  import org.codehaus.groovy.control.CompilationFailedException;
>  import org.codehaus.groovy.runtime.InvokerHelper;
> +import org.ofbiz.base.location.FlexibleLocation;
> +import org.ofbiz.base.util.cache.UtilCache;
>  
>  /**
>   * GroovyUtil - Groovy Utilities
> @@ -131,83 +130,27 @@ public class GroovyUtil {
>          }
>      }
>  
> -    @SuppressWarnings("unchecked")
> -    public static Object runScriptAtLocation(String location, Map<String, Object> context) throws GeneralException {
> +    public static Class<?> getScriptClassFromLocation(String location) throws GeneralException {

This change should have really been a separate commit, as it was
making the code reusable.

Anytime a bunch of code is removed, to use some already existing code,
means it might be possible that a bug could be introduced just with
the removing of the original code.

>          try {
> -            Class scriptClass = parsedScripts.get(location);
> +            Class<?> scriptClass = parsedScripts.get(location);
>              if (scriptClass == null) {
>                  URL scriptUrl = FlexibleLocation.resolveLocation(location);
>                  if (scriptUrl == null) {
>                      throw new GeneralException("Script not found at location [" + location + "]");
>                  }
> -
>                  scriptClass = parseClass(scriptUrl.openStream(), location);
> -                if (Debug.verboseOn()) Debug.logVerbose("Caching Groovy script at: " + location, module);
> -                parsedScripts.put(location, scriptClass);
> -            }
> -
> -            return InvokerHelper.createScript(scriptClass, getBinding(context)).run();
> -
> -            /* This code is just to test performance of the parsed versus unparsed approaches
> -            long startTimeParsed = System.currentTimeMillis();
> -            InvokerHelper.createScript(scriptClass, getBinding(context)).run();
> -            if (Debug.timingOn()) Debug.logTiming("Ran parsed groovy script in [" + (System.currentTimeMillis() - startTimeParsed) + "]ms at: " + location, module);
> -            */
> -
> -            /* NOTE DEJ20080526: this approach uses a pre-parsed script but it is not thread safe
> -             *
> -             * the groovy Script object contains both the parsed script AND the context, which is weird when trying to run a cached Script
> -             * there is no available clone() method on the Script object, so we can't clone and set the context/binding to get around thread-safe issues
> -            Script script = parsedScripts.get(location);
> -            if (script == null) {
> -                URL scriptUrl = FlexibleLocation.resolveLocation(location);
> -                if (scriptUrl == null) {
> -                    throw new GeneralException("Script not found at location [" + location + "]");
> +                if (Debug.verboseOn()) {
> +                    Debug.logVerbose("Caching Groovy script at: " + location, module);
>                  }

This particular change reformatted the code; it used to have the
verboseOn call on the same line as the logVerbose call.

> -
> -                script = emptyGroovyShell.parse(scriptUrl.openStream(), scriptUrl.getFile());
> -                if (Debug.verboseOn()) Debug.logVerbose("Caching Groovy script at: " + location, module);
> -                parsedScripts.put(location, script);
> -            }
> -
> -            script.setBinding(getBinding(context));
> -            return script.run();
> -             */
> -
> -            /* NOTE DEJ20080527: this approach works but only caches script text, not the parsed script
> -            public static UtilCache<String, String> sourceScripts = UtilCache.createUtilCache("script.GroovyLocationSourceCache", 0, 0, false);
> -
> -            public static GroovyShell emptyGroovyShell = new GroovyShell();
> -            String scriptString = sourceScripts.get(location);
> -            if (scriptString == null) {
> -                URL scriptUrl = FlexibleLocation.resolveLocation(location);
> -                if (scriptUrl == null) {
> -                    throw new GeneralException("Script not found at location [" + location + "]");
> -                }
> -
> -                scriptString = UtilURL.readUrlText(scriptUrl);
> -
> -                if (Debug.verboseOn()) Debug.logVerbose("Caching Groovy script source at: " + location, module);
> -                sourceScripts.put(location, scriptString);
> +                parsedScripts.put(location, scriptClass);
>              }
> -
> -            long startTime = System.currentTimeMillis();
> -            Script script = emptyGroovyShell.parse(scriptString, location);
> -            script.setBinding(getBinding(context));
> -            Object scriptResult = script.run();
> -            if (Debug.timingOn()) Debug.logTiming("Parsed and ran groovy script in [" + (System.currentTimeMillis() - startTime) + "]ms at: " + location, module);
> -
> -            return scriptResult;
> -             */
> -        } catch (MalformedURLException e) {
> -            String errMsg = "Error loading Groovy script at [" + location + "]: " + e.toString();
> -            throw new GeneralException(errMsg, e);
> -        } catch (IOException e) {
> -            String errMsg = "Error loading Groovy script at [" + location + "]: " + e.toString();
> -            throw new GeneralException(errMsg, e);
> -        } catch (CompilationFailedException e) {
> -            String errMsg = "Error loading Groovy script at [" + location + "]: " + e.toString();
> -            throw new GeneralException(errMsg, e);
> +            return scriptClass;
> +        } catch (Exception e) {
> +            throw new GeneralException("Error loading Groovy script at [" + location + "]: ", e);
>          }
>      }
> +
> +    public static Object runScriptAtLocation(String location, Map<String, Object> context) throws GeneralException {
> +        return InvokerHelper.createScript(getScriptClassFromLocation(location), getBinding(context)).run();
> +    }
>  }
> 
> Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/engine/GroovyEngine.java
> URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/engine/GroovyEngine.java?rev=926780&r1=926779&r2=926780&view=diff
> ==============================================================================
> --- ofbiz/trunk/framework/service/src/org/ofbiz/service/engine/GroovyEngine.java (original)
> +++ ofbiz/trunk/framework/service/src/org/ofbiz/service/engine/GroovyEngine.java Tue Mar 23 21:05:56 2010
> @@ -20,6 +20,9 @@ package org.ofbiz.service.engine;
>  
>  import java.util.Map;
>  
> +import org.codehaus.groovy.runtime.InvokerHelper;
> +import groovy.lang.Binding;
> +import groovy.lang.Script;
>  import org.ofbiz.base.util.GeneralException;
>  import org.ofbiz.base.util.GroovyUtil;
>  import static org.ofbiz.base.util.UtilGenerics.cast;
> @@ -34,6 +37,8 @@ import org.ofbiz.service.ServiceUtil;
>   */
>  public final class GroovyEngine extends GenericAsyncEngine {
>  
> +    protected static final Object[] EMPTY_ARGS = {};
> +
>      public GroovyEngine(ServiceDispatcher dispatcher) {
>          super(dispatcher);
>      }
> @@ -58,22 +63,23 @@ public final class GroovyEngine extends 
>          if (UtilValidate.isEmpty(modelService.location)) {
>              throw new GenericServiceException("Cannot run Groovy service with empty location");
>          }
> -
> -        String location = this.getLocation(modelService);
>          context.put("dctx", dispatcher.getLocalContext(localName));
> -
>          try {
> -            Object resultObj = GroovyUtil.runScriptAtLocation(location, context);
> -
> -            if (resultObj != null && resultObj instanceof Map) {
> +            Script script = InvokerHelper.createScript(GroovyUtil.getScriptClassFromLocation(this.getLocation(modelService)), new Binding(context));
> +            Object resultObj = null;
> +            if (UtilValidate.isEmpty(modelService.invoke)) {
> +                resultObj = script.run();
> +            } else {
> +                resultObj = script.invokeMethod(modelService.invoke, EMPTY_ARGS);
> +            }
> +            if (resultObj != null && resultObj instanceof Map<?, ?>) {
>                  return cast(resultObj);

Actually, the resultObj != null is not needed.  But that's how the
code was originally.

> -            } else if (context.get("result") != null && context.get("result") instanceof Map) {
> +            } else if (context.get("result") != null && context.get("result") instanceof Map<?, ?>) {
>                  return cast(context.get("result"));

The comparison against null is not needed here.

>              }
>          } catch (GeneralException e) {
>              throw new GenericServiceException(e);
>          }
> -
>          return ServiceUtil.returnSuccess();
>      }
>  }
> 
>