/* * Copyright (C) 2010 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ 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; import org.codehaus.groovy.control.Phases; import org.codehaus.groovy.control.SourceUnit; import org.codehaus.groovy.control.io.ReaderSource; import org.codehaus.groovy.control.io.URLReaderSource; import org.exoplatform.commons.utils.SecurityHelper; import org.exoplatform.services.rest.ext.groovy.ExtendedGroovyClassLoader; import org.exoplatform.services.rest.ext.groovy.GroovyClassLoaderProvider; import org.exoplatform.services.rest.ext.groovy.SourceFile; 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.CodeSource; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * @author <a href="mailto:andrey.parfonov@exoplatform.com">Andrey Parfonov</a> * @version $Id: JcrGroovyClassLoaderProvider.java 3702 2010-12-22 10:24:13Z * aparfonov $ */ public class JcrGroovyClassLoaderProvider extends GroovyClassLoaderProvider { public static class JcrGroovyClassLoader extends ExtendedGroovyClassLoader { public JcrGroovyClassLoader(ClassLoader classLoader) { super(classLoader); } public JcrGroovyClassLoader(GroovyClassLoader parent) { super(parent); } /** * {@inheritDoc} */ protected CompilationUnit createCompilationUnit(CompilerConfiguration config, CodeSource cs) { return new JcrCompilationUnit(config, cs, this); } public URL[] findDependencies(final SourceFolder[] sources, final SourceFile[] files) throws IOException { return findDependencies(sources, files, Phases.SEMANTIC_ANALYSIS, null); } @SuppressWarnings("rawtypes") private URL[] findDependencies(SourceFolder[] sources, SourceFile[] files, int phase, CompilerConfiguration config) throws IOException { CodeSource cs = new CodeSource(getCodeSource(), (java.security.cert.Certificate[])null); JcrGroovyResourceLoader actualLoader = null; URL[] roots = null; if (sources != null && sources.length > 0) { roots = new URL[sources.length]; for (int i = 0; i < sources.length; i++) roots[i] = sources[i].getPath(); actualLoader = new JcrGroovyResourceLoader(roots); } final HierarchicalResourceLoader loader = new HierarchicalResourceLoader(actualLoader, JcrGroovyClassLoader.this.getResourceLoader()); CompilationUnit cunit = new JcrCompilationUnit(config, cs, new JcrGroovyClassLoader( JcrGroovyClassLoaderProvider.class.getClassLoader()) { public GroovyResourceLoader getResourceLoader() { return loader; } }); 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) { SourceUnit currentSunit = module.getContext(); if (currentSunit instanceof JcrSourceUnit) dependencies.add(((JcrSourceUnit)currentSunit).getUrl()); } } return dependencies.toArray(new URL[dependencies.size()]); } } public static class JcrCompilationUnit extends CompilationUnit { public JcrCompilationUnit() { super(); } public JcrCompilationUnit(CompilerConfiguration configuration, CodeSource security, GroovyClassLoader loader, GroovyClassLoader transformLoader) { super(configuration, security, loader, transformLoader); } public JcrCompilationUnit(CompilerConfiguration configuration, CodeSource security, GroovyClassLoader loader) { super(configuration, security, loader); } public JcrCompilationUnit(CompilerConfiguration configuration) { super(configuration); } public JcrCompilationUnit(GroovyClassLoader loader) { super(loader); } /** * @see org.codehaus.groovy.control.CompilationUnit#addSource(java.net.URL) */ @Override public SourceUnit addSource(URL url) { return addSource(new JcrSourceUnit(url, configuration, classLoader, getErrorCollector())); } } /** 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); } public JcrSourceUnit(String name, ReaderSource source, CompilerConfiguration flags, GroovyClassLoader loader, ErrorCollector er) { super(name, source, flags, loader, er); } public JcrSourceUnit(String name, String source, CompilerConfiguration configuration, GroovyClassLoader loader, ErrorCollector er) { super(name, source, configuration, loader, er); } public JcrSourceUnit(URL source, CompilerConfiguration configuration, GroovyClassLoader loader, ErrorCollector er) { /* jCR path is in fragment of URL: * 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(SecurityHelper.doPrivilegedAction(new PrivilegedAction<JcrGroovyClassLoader>() { public JcrGroovyClassLoader run() { return new JcrGroovyClassLoader(JcrGroovyClassLoaderProvider.class.getClassLoader()); } })); } /** * {@inheritDoc} */ public ExtendedGroovyClassLoader getGroovyClassLoader(SourceFolder[] sources) throws MalformedURLException { if (sources == null || sources.length == 0) return getGroovyClassLoader(); URL[] roots = new URL[sources.length]; for (int i = 0; i < sources.length; i++) roots[i] = sources[i].getPath(); final GroovyClassLoader parent = getGroovyClassLoader(); JcrGroovyClassLoader classLoader = SecurityHelper.doPrivilegedAction(new PrivilegedAction<JcrGroovyClassLoader>() { public JcrGroovyClassLoader run() { return new JcrGroovyClassLoader(parent); } }); classLoader.setResourceLoader(new JcrGroovyResourceLoader(roots)); return classLoader; } }