Author: dpillot
Date: Thu Jun 28 17:17:07 2007
New Revision: 17825

URL: https://svndev.jahia.net/websvn/listing.php?sc=3D1&rev=3D17825&repname=
=3Djahia
Log:
http://www.jahia.net/jira/browse/JAHIA-1988:
added new JahiaGroovy engine extending the groovy engine with dependecies c=
heck control

Added:
    branches/JAHIA-5-0-SP-BRANCH/core/src/java/org/jahia/services/events/Ja=
hiaGroovyEngine.java
Modified:
    branches/JAHIA-5-0-SP-BRANCH/core/src/java/org/jahia/services/events/Gr=
oovyEventListener.java
    branches/JAHIA-5-0-SP-BRANCH/core/src/webapp/WEB-INF/etc/spring/applica=
tioncontext-basejahiaconfig.xml

Modified: branches/JAHIA-5-0-SP-BRANCH/core/src/java/org/jahia/services/eve=
nts/GroovyEventListener.java
URL: https://svndev.jahia.net/websvn/diff.php?path=3D/branches/JAHIA-5-0-SP=
-BRANCH/core/src/java/org/jahia/services/events/GroovyEventListener.java&re=
v=3D17825&repname=3Djahia
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
--- branches/JAHIA-5-0-SP-BRANCH/core/src/java/org/jahia/services/events/Gr=
oovyEventListener.java (original)
+++ branches/JAHIA-5-0-SP-BRANCH/core/src/java/org/jahia/services/events/Gr=
oovyEventListener.java Thu Jun 28 17:17:07 2007
@@ -18,7 +18,8 @@
 package org.jahia.services.events;
 =

 import groovy.lang.Binding;
-import groovy.util.GroovyScriptEngine;
+import org.apache.commons.collections.FastHashMap;
+import org.jahia.bin.Jahia;
 import org.jahia.content.events.ContentActivationEvent;
 import org.jahia.content.events.ContentObjectDeleteEvent;
 import org.jahia.content.events.ContentObjectRestoreVersionEvent;
@@ -29,7 +30,6 @@
 import org.jahia.params.ProcessingContext;
 import org.jahia.services.timebasedpublishing.RetentionRuleEvent;
 import org.jahia.services.workflow.WorkflowEvent;
-import org.apache.commons.collections.FastHashMap;
 =

 import java.io.File;
 import java.util.Map;
@@ -59,8 +59,8 @@
             "events/EventListener.groovy";
     private static final String GROOVY_FILE_NAME =3D "EventListener.groovy=
";
 =

-    private GroovyScriptEngine groovyScriptEngine;
-
+    private JahiaGroovyEngine jahiaScriptEngine;
+    private static long lastCall=3D0;// used for performance mode
     private boolean checkConfig (ProcessingContext processingContext) {
         if (configLoaded)
             return configLoaded;
@@ -82,7 +82,7 @@
 =

         defaultPathToGroovy =3D GroovyEventListener.DEFAULT_PATH_TO_GROOVY;
         groovyFileName =3D GroovyEventListener.GROOVY_FILE_NAME;
-        groovyScriptEngine =3D (GroovyScriptEngine) SpringContextSingleton=
.getInstance().getContext().getBean("groovyScriptEngine");
+        jahiaScriptEngine =3D (JahiaGroovyEngine) SpringContextSingleton.g=
etInstance().getContext().getBean("groovyScriptEngine");
 =

         configLoaded =3D true;
     }
@@ -96,12 +96,23 @@
             try {
                 String groovyFileName =3D resolveGroovyFullFileName(proces=
singContext);
 =

+                // Developement mode flag
+                boolean checkDependances=3DJahia.getSettings().isDevelopme=
ntMode();
                 long startTime =3D System.currentTimeMillis();
-                synchronized (groovyScriptEngine) {
+
+                //performance mode
+                if(startTime-lastCall<1500 && checkDependances && enabledP=
erformanceMode){
+                    //under heavy load we avoid the checking bottleneck re=
peatedly, assuming script unchanged and dependencies too
+                     checkDependances=3Dfalse;
+                    logger.debug("lapse between 2 dependency checks too cl=
ose: no checks");
+                }
+                if(lastCall=3D=3D0) checkDependances=3Dtrue;//only the fir=
st time
+                lastCall=3DstartTime;
+                synchronized (jahiaScriptEngine) {
                     Binding binding =3D new Binding();
                     binding.setVariable("eventName", eventName);
                     binding.setVariable("jahiaEvent", je);
-                    groovyScriptEngine.run(groovyFileName, binding);
+                    jahiaScriptEngine.run(groovyFileName, binding, checkDe=
pendances);
                 }
                 long endTime =3D System.currentTimeMillis();
                 long executionTime =3D endTime - startTime;
@@ -323,4 +334,6 @@
             }
         }
     }
+    // this flag could be use to control the repeated dependencies check f=
rom groovy script
+    public static boolean enabledPerformanceMode=3Dtrue;
 }

Added: branches/JAHIA-5-0-SP-BRANCH/core/src/java/org/jahia/services/events=
/JahiaGroovyEngine.java
URL: https://svndev.jahia.net/websvn/filedetails.php?path=3D/branches/JAHIA=
-5-0-SP-BRANCH/core/src/java/org/jahia/services/events/JahiaGroovyEngine.ja=
va&rev=3D17825&repname=3Djahia
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
--- branches/JAHIA-5-0-SP-BRANCH/core/src/java/org/jahia/services/events/Ja=
hiaGroovyEngine.java (added)
+++ branches/JAHIA-5-0-SP-BRANCH/core/src/java/org/jahia/services/events/Ja=
hiaGroovyEngine.java Thu Jun 28 17:17:07 2007
@@ -0,0 +1,182 @@
+package org.jahia.services.events;
+
+import groovy.lang.Binding;
+import groovy.lang.GroovyClassLoader;
+import groovy.lang.Script;
+import groovy.util.GroovyScriptEngine;
+import groovy.util.ResourceConnector;
+import groovy.util.ResourceException;
+import groovy.util.ScriptException;
+import org.codehaus.groovy.control.CompilationFailedException;
+import org.codehaus.groovy.runtime.InvokerHelper;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Jahia groovy script engine
+ *
+ */
+public class JahiaGroovyEngine extends GroovyScriptEngine {
+
+   private static org.apache.log4j.Logger logger =3D
+            org.apache.log4j.Logger.getLogger (JahiaGroovyEngine.class);
+
+     private static class ScriptCacheEntry {
+        private Class scriptClass;
+        private long lastModified;
+        private Map dependencies =3D new HashMap();
+    }
+
+    //private URL[] roots;
+    private Map scriptCache =3D Collections.synchronizedMap(new HashMap());
+    private ResourceConnector rc;
+
+    /**
+     * The groovy script engine will run groovy scripts and reload them and
+     * their dependencies when they are modified. This is useful for embed=
ding
+     * groovy in other containers like games and application servers.
+     *
+     * @param roots This an array of URLs where Groovy scripts will be sto=
red. They should
+     *              be layed out using their package structure like Java c=
lasses
+     */
+    public JahiaGroovyEngine(URL[] roots) {
+        super(roots);
+        this.rc=3Dthis;
+        logger.debug("length URLS:"+roots.length);
+        for(int i=3D0;i<roots.length;i++){
+            logger.debug(i+" "+roots[i].getFile());
+        }
+
+    }
+
+     /**
+     * Run a script identified by name with dependencies control.
+     *
+     * @param scriptName name of the script to run
+     * @param binding binding to pass to the script
+     * @param DependenciesCheck boolean to control dependency check
+     * @return an object
+     * @throws groovy.util.ResourceException resource issue
+     * @throws groovy.util.ScriptException script parsing issue
+     */
+    public Object run(String scriptName, Binding binding,boolean Dependenc=
iesCheck) throws ResourceException, ScriptException {
+        ScriptCacheEntry entry =3D updateCacheEntry(scriptName, getParentC=
lassLoader(),DependenciesCheck);
+        Script scriptObject =3D InvokerHelper.createScript(entry.scriptCla=
ss, binding);
+        return scriptObject.run();
+    }
+
+    /**
+     * Locate the class and reload it or any of its dependencies
+     * (from private method of parent class)
+     * @param scriptName
+     * @param parentClassLoader
+     * @return the scriptName cache entry
+     * @throws ResourceException
+     * @throws ScriptException
+     */
+    private ScriptCacheEntry updateCacheEntry(String scriptName, final Cla=
ssLoader parentClassLoader, boolean dependenciesCheck)
+            throws ResourceException, ScriptException
+    {
+        ScriptCacheEntry entry;
+
+        scriptName =3D scriptName.intern();
+        synchronized (scriptName) {
+
+            URLConnection groovyScriptConn =3D rc.getResourceConnection(sc=
riptName);
+
+            // URL last modified
+            long lastModified =3D groovyScriptConn.getLastModified();
+            // Check the cache for the scriptName
+            entry =3D (ScriptCacheEntry) scriptCache.get(scriptName);
+            // If the entry isn't null check all the dependencies
+
+            boolean dependencyOutOfDate =3D false;
+
+            //checks only if dependenciesCheck is requested by caller or s=
cript is modified
+            if ((entry !=3D null && dependenciesCheck)||(entry !=3D null &=
& entry.lastModified < lastModified)) {
+
+                logger.debug("checking "+entry.dependencies.keySet().size(=
)+" dependencies");
+                for (Iterator i =3D entry.dependencies.keySet().iterator()=
; i.hasNext();) {
+                    URLConnection urlc =3D null;
+                    URL url =3D (URL) i.next();
+                    try {
+                        urlc =3D url.openConnection();
+                        urlc.setDoInput(false);
+                        urlc.setDoOutput(false);
+                        long dependentLastModified =3D urlc.getLastModifie=
d();
+                        if (dependentLastModified > ((Long) entry.dependen=
cies.get(url)).longValue()) {
+                            dependencyOutOfDate =3D true;
+                            break;
+                        }
+                    } catch (IOException ioe) {
+                        dependencyOutOfDate =3D true;
+                        break;
+                    }
+                }
+                =

+            }
+
+            if (entry =3D=3D null || entry.lastModified < lastModified || =
dependencyOutOfDate) {
+                String loggermessage=3D"updating cache entry because ";
+                if(entry =3D=3D null)
+                     loggermessage+=3D"entry is null, creating...";
+                if(entry !=3D null && entry.lastModified < lastModified)
+                     loggermessage+=3D"entry is modified, updating...";
+                if(dependencyOutOfDate)
+                    loggermessage+=3D"dependencies need to be updated";
+                logger.debug(loggermessage);
+                // Make a new entry
+                entry =3D new ScriptCacheEntry();
+
+                // Closure variable
+                final ScriptCacheEntry finalEntry =3D entry;
+
+                // Compile the scriptName into an object
+                GroovyClassLoader groovyLoader =3D
+                        (GroovyClassLoader) AccessController.doPrivileged(=
new PrivilegedAction() {
+                            public Object run() {
+                                return new GroovyClassLoader(parentClassLo=
ader) {
+                                    protected Class findClass(String class=
Name) throws ClassNotFoundException {
+                                        String filename =3D className.repl=
ace('.', File.separatorChar) + ".groovy";
+                                        URLConnection dependentScriptConn =
=3D null;
+                                        try {
+                                            dependentScriptConn =3D rc.get=
ResourceConnection(filename);
+                                            finalEntry.dependencies.put(
+                                                    dependentScriptConn.ge=
tURL(),
+                                                    new Long(dependentScri=
ptConn.getLastModified()));
+                                        } catch (ResourceException e1) {
+                                            throw new ClassNotFoundExcepti=
on("Could not read " + className + ": " + e1);
+                                        }
+                                        try {
+                                            return parseClass(dependentScr=
iptConn.getInputStream(), filename);
+                                        } catch (CompilationFailedExceptio=
n e2) {
+                                            throw new ClassNotFoundExcepti=
on("Syntax error in " + className + ": " + e2);
+                                        } catch (IOException e2) {
+                                            throw new ClassNotFoundExcepti=
on("Problem reading " + className + ": " + e2);
+                                        }
+                                    }
+                                };
+                            }
+                        });
+
+                try {
+                    entry.scriptClass =3D groovyLoader.parseClass(groovySc=
riptConn.getInputStream(), scriptName);
+                } catch (Exception e) {
+                    throw new ScriptException("Could not parse scriptName:=
 " + scriptName, e);
+                }
+                entry.lastModified =3D lastModified;
+                scriptCache.put(scriptName, entry);
+            }
+        }
+        return entry;
+    }
+}

Modified: branches/JAHIA-5-0-SP-BRANCH/core/src/webapp/WEB-INF/etc/spring/a=
pplicationcontext-basejahiaconfig.xml
URL: https://svndev.jahia.net/websvn/diff.php?path=3D/branches/JAHIA-5-0-SP=
-BRANCH/core/src/webapp/WEB-INF/etc/spring/applicationcontext-basejahiaconf=
ig.xml&rev=3D17825&repname=3Djahia
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
--- branches/JAHIA-5-0-SP-BRANCH/core/src/webapp/WEB-INF/etc/spring/applica=
tioncontext-basejahiaconfig.xml (original)
+++ branches/JAHIA-5-0-SP-BRANCH/core/src/webapp/WEB-INF/etc/spring/applica=
tioncontext-basejahiaconfig.xml Thu Jun 28 17:17:07 2007
@@ -159,7 +159,7 @@
         </property>
     </bean>
 =

-    <bean id=3D"groovyScriptEngine" class=3D"groovy.util.GroovyScriptEngin=
e">
+    <bean id=3D"groovyScriptEngine" class=3D"org.jahia.services.events.Jah=
iaGroovyEngine">
         <constructor-arg>
             <list>
                 <value>file:///${jahiaWebAppRoot}/WEB-INF/var/scripts/groo=
vy/</value>

_______________________________________________
cvs_list mailing list
[email protected]
http://lists.jahia.org/cgi-bin/mailman/listinfo/cvs_list

Reply via email to