Author: aparfonov
Date: 2011-01-20 09:21:42 -0500 (Thu, 20 Jan 2011)
New Revision: 3822
Modified:
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/script/groovy/JcrGroovyClassLoaderProvider.java
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/script/groovy/JcrGroovyCompiler.java
Log:
EXOJCR-1164
Modified:
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/script/groovy/JcrGroovyClassLoaderProvider.java
===================================================================
---
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/script/groovy/JcrGroovyClassLoaderProvider.java 2011-01-20
11:20:33 UTC (rev 3821)
+++
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/script/groovy/JcrGroovyClassLoaderProvider.java 2011-01-20
14:21:42 UTC (rev 3822)
@@ -19,7 +19,10 @@
package org.exoplatform.services.jcr.ext.script.groovy;
import groovy.lang.GroovyClassLoader;
+import groovy.lang.GroovyResourceLoader;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.ModuleNode;
import org.codehaus.groovy.control.CompilationUnit;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.control.ErrorCollector;
@@ -33,17 +36,15 @@
import org.exoplatform.services.rest.ext.groovy.SourceFolder;
import java.io.File;
+import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.AccessController;
import java.security.CodeSource;
import java.security.PrivilegedAction;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import java.util.Set;
/**
* @author <a href="mailto:andrey.parfonov@exoplatform.com">Andrey
Parfonov</a>
@@ -74,56 +75,57 @@
return new JcrCompilationUnit(config, cs, this);
}
- @SuppressWarnings("rawtypes")
- public Class[] parseClasses(SourceFile[] files, boolean includeLoadedClasses)
+ public URL[] findDependencies(final SourceFolder[] sources, final SourceFile[]
files) throws IOException
{
- return doParseClasses(files, Phases.CLASS_GENERATION, null,
includeLoadedClasses);
+ return findDependencies(sources, files, Phases.SEMANTIC_ANALYSIS, null);
}
@SuppressWarnings("rawtypes")
- private Class[] doParseClasses(SourceFile[] sources, int phase,
CompilerConfiguration config,
- boolean includeLoadedClasses)
+ private URL[] findDependencies(SourceFolder[] sources, SourceFile[] files, int
phase, CompilerConfiguration config)
+ throws IOException
{
- synchronized (classCache)
+ CodeSource cs = new CodeSource(getCodeSource(),
(java.security.cert.Certificate[])null);
+ JcrGroovyResourceLoader actualLoader = null;
+ URL[] roots = null;
+ if (sources != null && sources.length > 0)
{
- CodeSource cs = new CodeSource(getCodeSource(),
(java.security.cert.Certificate[])null);
- CompilationUnit cunit = createCompilationUnit(config, cs);
- Set<SourceUnit> setSunit = new HashSet<SourceUnit>();
+ roots = new URL[sources.length];
for (int i = 0; i < sources.length; i++)
- setSunit.add(cunit.addSource(sources[i].getPath()));
- MultipleClassCollector collector = createMultipleCollector(cunit, setSunit);
- cunit.setClassgenCallback(collector);
- cunit.compile(phase);
+ roots[i] = sources[i].getPath();
+ actualLoader = new JcrGroovyResourceLoader(roots);
+ }
- for (Iterator iter = collector.getLoadedClasses().iterator();
iter.hasNext();)
- {
- Class clazz = (Class)iter.next();
- String classname = clazz.getName();
- int i = classname.lastIndexOf('.');
- if (i != -1)
+ final HierarchicalResourceLoader loader =
+ new HierarchicalResourceLoader(actualLoader,
JcrGroovyClassLoader.this.getResourceLoader());
+
+ CompilationUnit cunit =
+ new JcrCompilationUnit(config, cs, new JcrGroovyClassLoader(
+ JcrGroovyClassLoaderProvider.class.getClassLoader()) {
+ public GroovyResourceLoader getResourceLoader()
{
- String pkgname = classname.substring(0, i);
- Package pkg = getPackage(pkgname);
- if (pkg == null)
- definePackage(pkgname, null, null, null, null, null, null, null);
+ return loader;
}
- setClassCacheEntry(clazz);
- }
- List<Class> compiledClasses;
- if (includeLoadedClasses)
+ });
+
+ for (int i = 0; i < files.length; i++)
+ cunit.addSource(files[i].getPath());
+ cunit.compile(phase);
+
+ List classNodes = cunit.getAST().getClasses();
+ List<URL> dependencies = new ArrayList<URL>(classNodes.size());
+ for (Iterator iter = classNodes.iterator(); iter.hasNext();)
+ {
+ ClassNode classNode = (ClassNode)iter.next();
+ ModuleNode module = classNode.getModule();
+ if (module != null)
{
-System.out.println("+++++++++++++++++++++++++ " + cunit.getClasses());
- Collection loadedClasses = collector.getLoadedClasses();
- compiledClasses = new ArrayList<Class>(loadedClasses.size());
- for (Iterator iter = loadedClasses.iterator(); iter.hasNext();)
- compiledClasses.add((Class)iter.next());
+ SourceUnit currentSunit = module.getContext();
+ if (currentSunit instanceof JcrSourceUnit)
+ dependencies.add(((JcrSourceUnit)currentSunit).getUrl());
}
- else
- {
- compiledClasses = collector.getCompiledClasses();
- }
- return compiledClasses.toArray(new Class[compiledClasses.size()]);
}
+
+ return dependencies.toArray(new URL[dependencies.size()]);
}
}
@@ -169,6 +171,8 @@
/** Adapter for JCR like URLs. */
public static class JcrSourceUnit extends SourceUnit
{
+ private URL url;
+
public JcrSourceUnit(File source, CompilerConfiguration configuration,
GroovyClassLoader loader, ErrorCollector er)
{
super(source, configuration, loader, er);
@@ -192,9 +196,40 @@
* jcr://repository/workspace#/path */
super("jcr".equals(source.getProtocol()) ? source.getRef() :
source.getPath(), new URLReaderSource(source,
configuration), configuration, loader, er);
+ this.url = source;
}
+
+ public URL getUrl()
+ {
+ return url;
+ }
}
+ private static class HierarchicalResourceLoader implements GroovyResourceLoader
+ {
+ private final GroovyResourceLoader actual;
+ private final GroovyResourceLoader parent;
+
+ HierarchicalResourceLoader(GroovyResourceLoader actual, GroovyResourceLoader
parent)
+ throws MalformedURLException
+ {
+ this.actual = actual;
+ this.parent = parent;
+ }
+
+ public URL loadGroovySource(String filename) throws MalformedURLException
+ {
+ URL resource = null;
+ if (actual != null)
+ resource = actual.loadGroovySource(filename);
+ if (resource == null && parent != null)
+ resource = parent.loadGroovySource(filename);
+ return resource;
+ }
+ }
+
+ /* ========================================================================== */
+
public JcrGroovyClassLoaderProvider()
{
super(AccessController.doPrivileged(new
PrivilegedAction<JcrGroovyClassLoader>() {
Modified:
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/script/groovy/JcrGroovyCompiler.java
===================================================================
---
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/script/groovy/JcrGroovyCompiler.java 2011-01-20
11:20:33 UTC (rev 3821)
+++
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/script/groovy/JcrGroovyCompiler.java 2011-01-20
14:21:42 UTC (rev 3822)
@@ -36,6 +36,8 @@
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -77,30 +79,12 @@
*/
public Class<?>[] compile(UnifiedNodeReference... sourceReferences) throws
IOException
{
- return compile(false, sourceReferences);
+ return compile(null, sourceReferences);
}
/**
* Compile Groovy source that located in <code>sourceReferences</code>.
* Compiled sources can be dependent to each other and dependent to Groovy
- * sources that are accessible for this compiler.
- *
- * @param includeLoadedClasses if <code>true</code> then array of classes
- * which method method return contains all loaded classes. If
- * <code>false</code> then only classes created from
- * <code>sourceReferences</code> included in result array
- * @param sourceReferences references to Groovy sources to be compiled
- * @return result of compilation
- * @throws IOException if any i/o errors occurs
- */
- public Class<?>[] compile(boolean includeLoadedClasses, UnifiedNodeReference...
sourceReferences) throws IOException
- {
- return compile(includeLoadedClasses, null, sourceReferences);
- }
-
- /**
- * Compile Groovy source that located in <code>sourceReferences</code>.
- * Compiled sources can be dependent to each other and dependent to Groovy
* sources that are accessible for this compiler and with additional Groovy
* sources <code>src</code>. <b>NOTE</b> To be able load
Groovy source files
* from specified folders the following rules must be observed:
@@ -138,58 +122,10 @@
*/
public Class<?>[] compile(SourceFolder[] src, UnifiedNodeReference...
sourceReferences) throws IOException
{
- return compile(false, src, sourceReferences);
- }
-
- /**
- * Compile Groovy source that located in <code>sourceReferences</code>.
- * Compiled sources can be dependent to each other and dependent to Groovy
- * sources that are accessible for this compiler and with additional Groovy
- * sources <code>src</code>. <b>NOTE</b> To be able load
Groovy source files
- * from specified folders the following rules must be observed:
- * <ul>
- * <li>Groovy source files must be located in folder with respect to package
- * structure</li>
- * <li>Name of Groovy source files must be the same as name of class located
- * in file</li>
- * <li>Groovy source file must have extension '.groovy'</li>
- * </ul>
- * <br/>
- * Example: If source stream that we want compile contains the following
- * code:
- *
- * <pre>
- * package c.b.a
- *
- * import a.b.c.A
- *
- * class B extends A {
- * // Do something.
- * }
- * </pre>
- *
- * Assume we store dependencies in JCR then URL of folder with Groovy sources
- * may be like this:
<code>jcr://repository/workspace#/groovy-library</code>.
- * Then absolute path to JCR node that contains Groovy source must be as
- * following: <code>/groovy-library/a/b/c/A.groovy</code>
- *
- * @param includeLoadedClasses if <code>true</code> then array of classes
- * which method method return contains all loaded classes. If
- * <code>false</code> then only classes created from
- * <code>sourceReferences</code> included in result array
- * @param src additional Groovy source location that should be added in
- * class-path when compile <code>sourceReferences</code>
- * @param sourceReferences references to Groovy sources to be compiled
- * @return result of compilation
- * @throws IOException if any i/o errors occurs
- */
- public Class<?>[] compile(boolean includeLoadedClasses, SourceFolder[] src,
UnifiedNodeReference... sourceReferences)
- throws IOException
- {
SourceFile[] files = new SourceFile[sourceReferences.length];
for (int i = 0; i < sourceReferences.length; i++)
files[i] = new SourceFile(sourceReferences[i].getURL());
- return
doCompile((JcrGroovyClassLoader)classLoaderProvider.getGroovyClassLoader(src), files,
includeLoadedClasses);
+ return
doCompile((JcrGroovyClassLoader)classLoaderProvider.getGroovyClassLoader(src), files);
}
/**
@@ -214,41 +150,12 @@
*/
public Class<?>[] compile(SourceFolder[] src, SourceFile[] files) throws
IOException
{
- return compile(false, src, files);
+ return
doCompile((JcrGroovyClassLoader)classLoaderProvider.getGroovyClassLoader(src), files);
}
/**
* Compile Groovy source that located in <code>files</code>. Compiled
sources
* can be dependent to each other and dependent to Groovy sources that are
- * accessible for this compiler and with additional Groovy sources
- * <code>src</code>. <b>NOTE</b> To be able load Groovy source
files from
- * specified folders the following rules must be observed:
- * <ul>
- * <li>Groovy source files must be located in folder with respect to package
- * structure</li>
- * <li>Name of Groovy source files must be the same as name of class located
- * in file</li>
- * <li>Groovy source file must have extension '.groovy'</li>
- * </ul>
- *
- * @param includeLoadedClasses if <code>true</code> then array of classes
- * which method method return contains all loaded classes. If
- * <code>false</code> then only classes created from
- * <code>sourceReferences</code> included in result array
- * @param src additional Groovy source location that should be added in
- * class-path when compile <code>files</code>
- * @param files Groovy sources to be compiled
- * @return result of compilation
- * @throws IOException if any i/o errors occurs
- */
- public Class<?>[] compile(boolean includeLoadedClasses, SourceFolder[] src,
SourceFile[] files) throws IOException
- {
- return
doCompile((JcrGroovyClassLoader)classLoaderProvider.getGroovyClassLoader(src), files,
includeLoadedClasses);
- }
-
- /**
- * Compile Groovy source that located in <code>files</code>. Compiled
sources
- * can be dependent to each other and dependent to Groovy sources that are
* accessible for this compiler.
*
* @param files Groovy sources to be compiled
@@ -257,40 +164,40 @@
*/
public Class<?>[] compile(SourceFile[] files) throws IOException
{
- return compile(false, files);
+ return doCompile((JcrGroovyClassLoader)classLoaderProvider.getGroovyClassLoader(),
files);
}
- /**
- * Compile Groovy source that located in <code>files</code>. Compiled
sources
- * can be dependent to each other and dependent to Groovy sources that are
- * accessible for this compiler.
- *
- * @param includeLoadedClasses if <code>true</code> then array of classes
- * which method method return contains all loaded classes. If
- * <code>false</code> then only classes created from
- * <code>sourceReferences</code> included in result array
- * @param files Groovy sources to be compiled
- * @return result of compilation
- * @throws IOException if any i/o errors occurs
- */
- public Class<?>[] compile(boolean includeLoadedClasses, SourceFile[] files)
throws IOException
- {
- return doCompile((JcrGroovyClassLoader)classLoaderProvider.getGroovyClassLoader(),
files, includeLoadedClasses);
- }
-
@SuppressWarnings("rawtypes")
- private Class<?>[] doCompile(final JcrGroovyClassLoader cl, final SourceFile[]
files,
- final boolean includeLoadedClasses) throws IOException
+ private Class<?>[] doCompile(final JcrGroovyClassLoader cl, final SourceFile[]
files) throws IOException
{
Class[] classes = AccessController.doPrivileged(new
PrivilegedAction<Class[]>() {
public Class[] run()
{
- return cl.parseClasses(files, includeLoadedClasses);
+ return cl.parseClasses(files);
}
});
return classes;
}
+ public URL[] getDependencies(final SourceFolder[] sources, final SourceFile[] files)
throws IOException
+ {
+ try
+ {
+ return AccessController.doPrivileged(new
PrivilegedExceptionAction<URL[]>() {
+ public URL[] run() throws IOException
+ {
+ return
((JcrGroovyClassLoader)classLoaderProvider.getGroovyClassLoader()).findDependencies(sources,
+ files);
+ }
+ });
+ }
+ catch (PrivilegedActionException e)
+ {
+ Throwable cause = e.getCause();
+ throw (IOException)cause;
+ }
+ }
+
/**
* @return get underling groovy class loader
*/