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();
> }
> }
>
>