http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/lang/GrabExclude.java ---------------------------------------------------------------------- diff --git a/src/main/groovy/lang/GrabExclude.java b/src/main/groovy/lang/GrabExclude.java deleted file mode 100644 index 327cb43..0000000 --- a/src/main/groovy/lang/GrabExclude.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package groovy.lang; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Used to exclude an indirectly referenced artifact (a transitive dependency) from the classpath. - * <p> - * Examples:<br> - * {@code @GrabExclude(group='mysql', module='mysql-connector-java') // group/module form}<br> - * {@code @GrabExclude('mysql:mysql-connector-java') // compact form}<br> - * <p> - * Further information about customising grape behavior can be found on the Grape documentation page: - * <a href="http://groovy-lang.org/grape.html">http://groovy-lang.org/grape.html</a>. - */ -@Retention(RetentionPolicy.SOURCE) -@Target({ - ElementType.CONSTRUCTOR, - ElementType.FIELD, - ElementType.LOCAL_VARIABLE, - ElementType.METHOD, - ElementType.PARAMETER, - ElementType.TYPE}) -public @interface GrabExclude { - - /** - * The organisation or group, e.g.: "org.apache.ant"; required unless the compact form is used. - */ - String group() default ""; - - /** - * The module or artifact, e.g.: "ant-junit"; required unless the compact form is used. - */ - String module() default ""; - - /** - * Allows you to specify the group (organisation) and the module (artifact) in one of two compact convenience formats, - * e.g.: <code>@GrabExclude('org.apache.ant:ant-junit')</code> or <code>@GrabExclude('org.apache.ant#ant-junit')</code> - */ - String value() default ""; -} \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/lang/GrabResolver.java ---------------------------------------------------------------------- diff --git a/src/main/groovy/lang/GrabResolver.java b/src/main/groovy/lang/GrabResolver.java deleted file mode 100644 index 6512cb3..0000000 --- a/src/main/groovy/lang/GrabResolver.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package groovy.lang; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Used to add a repository for resolving Grape dependencies. - * <p> - * For example: - * <pre> - * {@code @GrabResolver}(name='restlet.org', root='http://maven.restlet.org') - * {@code @Grab}(group='org.restlet', module='org.restlet', version='1.1.6') - * class MyRestlet extends org.restlet.Restlet { - * // ... - * } - * </pre> - * By default, the Grapes subsystem uses an Ivy chained resolver. Each resolver - * added using {@code @GrabResolver} is appended to the chain. By default, the grape - * subsystem is shared globally, so added resolvers will become available for any subsequent - * grab calls. Dependency resolution follows Ivy's artifact resolution which tries - * to resolve artifacts in the order specified in the chain of resolvers. - * <p> - * Further information about customising grape behavior can be found on the Grape documentation page: - * <a href="http://groovy-lang.org/grape.html">http://groovy-lang.org/grape.html</a>. - * - * @author Merlyn Albery-Speyer - */ -@Retention(RetentionPolicy.SOURCE) -@Target({ - ElementType.CONSTRUCTOR, - ElementType.FIELD, - ElementType.LOCAL_VARIABLE, - ElementType.METHOD, - ElementType.PARAMETER, - ElementType.TYPE}) -public @interface GrabResolver { - /** - * Allows a shorthand form which sets the name and root to this value. - * Must not be used if name() or root() is non-empty. - */ - String value() default ""; - - /** - * A meaningful name for a repo containing the grape/artifact. - * A non-empty value is required unless value() is used. - */ - String name() default ""; - - /** - * The URL for a repo containing the grape/artifact. - * A non-empty value is required unless value() is used. - */ - String root() default ""; - - /** - * Defaults to Maven2 compatibility. Set false for Ivy only compatibility. - */ - boolean m2Compatible() default true; - - /** - * By default, when a {@code @GrabResolver} annotation is used, a {@code Grape.addResolver()} call is added - * to the static initializers of the class the annotatable node appears in. - * If you wish to disable this, add {@code initClass=false} to the annotation. - */ - boolean initClass() default true; -} http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/lang/Grapes.java ---------------------------------------------------------------------- diff --git a/src/main/groovy/lang/Grapes.java b/src/main/groovy/lang/Grapes.java deleted file mode 100644 index 1255529..0000000 --- a/src/main/groovy/lang/Grapes.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package groovy.lang; - -/** - * Sometimes we will need more than one grab per class, but we can only add - * one annotation type per annotatable node. This class allows for multiple - * grabs to be added. - * <p> - * For example: - * <p> - * <pre> - * {@code @Grapes([@Grab(module='m1'), @Grab(module='m2')])} - * class AnnotatedClass { ... } - * </pre> - * <p> - * You can override an implicit transitive dependency by providing an explicit one. - * E.g. htmlunit 2.6 normally uses xerces 2.9.1 but you can get 2.9.0 as follows: - * <pre> - * {@code @Grapes}([ - * {@code @Grab}('net.sourceforge.htmlunit:htmlunit:2.6'), - * {@code @Grab}('xerces#xercesImpl;2.9.0') - * ]) - * </pre> - * Obviously, only do this if you understand the consequences. - * <p> - * You can also remove transitive dependencies altogether (provided you - * know you don't need them) using {@code @GrabExclude}. - * For example, here is how we would not grab the {@code logkit} and - * {@code avalon-framework} transitive dependencies for Apache POI: - * <pre> - * {@code @Grapes}([ - * {@code @Grab}("org.apache.poi#poi;3.5-beta6"), - * {@code @GrabExclude}("logkit:logkit"), - * {@code @GrabExclude}("avalon-framework#avalon-framework") - * ]) - * import org.apache.poi.hssf.util.CellReference - * assert new CellReference(0, 0, false, false).formatAsString() == 'A1' - * assert new CellReference(1, 3).formatAsString() == '$D$2' - * </pre> - * It is also sometimes also useful to use {@code @GrabConfig} to further adjust how dependencies - * are grabbed. See {@code @GrabConfig} for further information. - */ -public @interface Grapes { - Grab[] value(); - - /** - * This will be pushed into the child grab annotations if the value is not - * set in the child annotation already. - * <p> - * This results in an effective change in the default value, which each @Grab - * can still override - */ - boolean initClass() default true; -} http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/lang/GroovyCallable.java ---------------------------------------------------------------------- diff --git a/src/main/groovy/lang/GroovyCallable.java b/src/main/groovy/lang/GroovyCallable.java deleted file mode 100644 index 1966289..0000000 --- a/src/main/groovy/lang/GroovyCallable.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package groovy.lang; - -import java.util.concurrent.Callable; - -/** - * A special "marker" style interface allowing Groovy classes to implement both - * Runnable and Callable yet give preference to Runnable (for backwards compatibility) - * for APIs having both Runnable and Callable methods. You should generally NOT use this - * method in your own code. - * - * @see java.util.concurrent.Callable - * @since 1.8.0 - */ -public interface GroovyCallable<V> extends Callable<V> { } http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/lang/GroovyClassLoader.java ---------------------------------------------------------------------- diff --git a/src/main/groovy/lang/GroovyClassLoader.java b/src/main/groovy/lang/GroovyClassLoader.java deleted file mode 100644 index 8581879..0000000 --- a/src/main/groovy/lang/GroovyClassLoader.java +++ /dev/null @@ -1,1099 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -/* - * @todo multi threaded compiling of the same class but with different roots - * for compilation... T1 compiles A, which uses B, T2 compiles B... mark A and B - * as parsed and then synchronize compilation. Problems: How to synchronize? - * How to get error messages? - * - */ -package groovy.lang; - -import groovy.util.CharsetToolkit; -import org.codehaus.groovy.ast.ClassHelper; -import org.codehaus.groovy.ast.ClassNode; -import org.codehaus.groovy.ast.FieldNode; -import org.codehaus.groovy.ast.InnerClassNode; -import org.codehaus.groovy.ast.ModuleNode; -import org.codehaus.groovy.ast.expr.ConstantExpression; -import org.codehaus.groovy.classgen.GeneratorContext; -import org.codehaus.groovy.classgen.Verifier; -import org.codehaus.groovy.control.BytecodeProcessor; -import org.codehaus.groovy.control.CompilationFailedException; -import org.codehaus.groovy.control.CompilationUnit; -import org.codehaus.groovy.control.CompilePhase; -import org.codehaus.groovy.control.CompilerConfiguration; -import org.codehaus.groovy.control.Phases; -import org.codehaus.groovy.control.SourceUnit; -import org.codehaus.groovy.runtime.IOGroovyMethods; -import org.codehaus.groovy.runtime.InvokerHelper; -import org.codehaus.groovy.runtime.memoize.ConcurrentCommonCache; -import org.codehaus.groovy.runtime.memoize.EvictableCache; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.Opcodes; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.UnsupportedEncodingException; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.net.URLClassLoader; -import java.net.URLConnection; -import java.net.URLDecoder; -import java.security.AccessController; -import java.security.CodeSource; -import java.security.Permission; -import java.security.PermissionCollection; -import java.security.Permissions; -import java.security.PrivilegedAction; -import java.security.ProtectionDomain; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Enumeration; -import java.util.Map; - -/** - * A ClassLoader which can load Groovy classes. The loaded classes are cached, - * classes from other classloaders should not be cached. To be able to load a - * script that was asked for earlier but was created later it is essential not - * to keep anything like a "class not found" information for that class name. - * This includes possible parent loaders. Classes that are not cached are always - * reloaded. - * - * @author <a href="mailto:[email protected]">James Strachan</a> - * @author Guillaume Laforge - * @author Steve Goetze - * @author Bing Ran - * @author <a href="mailto:[email protected]">Scott Stirling</a> - * @author <a href="mailto:[email protected]">Jochen Theodorou</a> - */ -public class GroovyClassLoader extends URLClassLoader { - private static final URL[] EMPTY_URL_ARRAY = new URL[0]; - private static final Class[] EMPTY_CLASS_ARRAY = new Class[0]; - - /** - * this cache contains the loaded classes or PARSING, if the class is currently parsed - */ - protected final EvictableCache<String, Class> classCache = new ConcurrentCommonCache<String, Class>(); - - /** - * This cache contains mappings of file name to class. It is used - * to bypass compilation. - */ - protected final ConcurrentCommonCache<String, Class> sourceCache = new ConcurrentCommonCache<String, Class>(); - - private final CompilerConfiguration config; - private String sourceEncoding; - private Boolean recompile; - // use 1000000 as offset to avoid conflicts with names form the GroovyShell - private static int scriptNameCounter = 1000000; - - private GroovyResourceLoader resourceLoader = new GroovyResourceLoader() { - public URL loadGroovySource(final String filename) throws MalformedURLException { - return AccessController.doPrivileged(new PrivilegedAction<URL>() { - public URL run() { - for (String extension : config.getScriptExtensions()) { - try { - URL ret = getSourceFile(filename, extension); - if (ret != null) - return ret; - } catch (Throwable t) { // - } - } - return null; - } - }); - } - }; - - /** - * creates a GroovyClassLoader using the current Thread's context - * Class loader as parent. - */ - public GroovyClassLoader() { - this(Thread.currentThread().getContextClassLoader()); - } - - /** - * creates a GroovyClassLoader using the given ClassLoader as parent - */ - public GroovyClassLoader(ClassLoader loader) { - this(loader, null); - } - - /** - * creates a GroovyClassLoader using the given GroovyClassLoader as parent. - * This loader will get the parent's CompilerConfiguration - */ - public GroovyClassLoader(GroovyClassLoader parent) { - this(parent, parent.config, false); - } - - /** - * creates a GroovyClassLoader. - * - * @param parent the parent class loader - * @param config the compiler configuration - * @param useConfigurationClasspath determines if the configurations classpath should be added - */ - public GroovyClassLoader(ClassLoader parent, CompilerConfiguration config, boolean useConfigurationClasspath) { - super(EMPTY_URL_ARRAY, parent); - if (config == null) config = CompilerConfiguration.DEFAULT; - this.config = config; - if (useConfigurationClasspath) { - for (String path : config.getClasspath()) { - this.addClasspath(path); - } - } - - initSourceEncoding(config); - } - - private void initSourceEncoding(CompilerConfiguration config) { - sourceEncoding = config.getSourceEncoding(); - if (null == sourceEncoding) { - // Keep the same default source encoding with the one used by #parseClass(InputStream, String) - // TODO should we use org.codehaus.groovy.control.CompilerConfiguration.DEFAULT_SOURCE_ENCODING instead? - sourceEncoding = CharsetToolkit.getDefaultSystemCharset().name(); - } - } - - /** - * creates a GroovyClassLoader using the given ClassLoader as parent. - */ - public GroovyClassLoader(ClassLoader loader, CompilerConfiguration config) { - this(loader, config, true); - } - - public void setResourceLoader(GroovyResourceLoader resourceLoader) { - if (resourceLoader == null) { - throw new IllegalArgumentException("Resource loader must not be null!"); - } - this.resourceLoader = resourceLoader; - } - - public GroovyResourceLoader getResourceLoader() { - return resourceLoader; - } - - /** - * Loads the given class node returning the implementation Class. - * <p> - * WARNING: this compilation is not synchronized - * - * @param classNode - * @return a class - */ - public Class defineClass(ClassNode classNode, String file, String newCodeBase) { - CodeSource codeSource = null; - try { - codeSource = new CodeSource(new URL("file", "", newCodeBase), (java.security.cert.Certificate[]) null); - } catch (MalformedURLException e) { - //swallow - } - - CompilationUnit unit = createCompilationUnit(config, codeSource); - ClassCollector collector = createCollector(unit, classNode.getModule().getContext()); - try { - unit.addClassNode(classNode); - unit.setClassgenCallback(collector); - unit.compile(Phases.CLASS_GENERATION); - definePackageInternal(collector.generatedClass.getName()); - return collector.generatedClass; - } catch (CompilationFailedException e) { - throw new RuntimeException(e); - } - } - - /** - * Parses the given file into a Java class capable of being run - * - * @param file the file name to parse - * @return the main class defined in the given script - */ - public Class parseClass(File file) throws CompilationFailedException, IOException { - return parseClass(new GroovyCodeSource(file, config.getSourceEncoding())); - } - - /** - * Parses the given text into a Java class capable of being run - * - * @param text the text of the script/class to parse - * @param fileName the file name to use as the name of the class - * @return the main class defined in the given script - */ - public Class parseClass(final String text, final String fileName) throws CompilationFailedException { - GroovyCodeSource gcs = AccessController.doPrivileged(new PrivilegedAction<GroovyCodeSource>() { - public GroovyCodeSource run() { - return new GroovyCodeSource(text, fileName, "/groovy/script"); - } - }); - gcs.setCachable(false); - return parseClass(gcs); - } - - /** - * Parses the given text into a Java class capable of being run - * - * @param text the text of the script/class to parse - * @return the main class defined in the given script - */ - public Class parseClass(String text) throws CompilationFailedException { - return parseClass(text, "script" + System.currentTimeMillis() + - Math.abs(text.hashCode()) + ".groovy"); - } - - public synchronized String generateScriptName() { - scriptNameCounter++; - return "script" + scriptNameCounter + ".groovy"; - } - - public Class parseClass(final Reader reader, final String fileName) throws CompilationFailedException { - GroovyCodeSource gcs = AccessController.doPrivileged(new PrivilegedAction<GroovyCodeSource>() { - public GroovyCodeSource run() { - try { - String scriptText = IOGroovyMethods.getText(reader); - return new GroovyCodeSource(scriptText, fileName, "/groovy/script"); - } catch (IOException e) { - throw new RuntimeException("Impossible to read the content of the reader for file named: " + fileName, e); - } - } - }); - return parseClass(gcs); - } - - /** - * @deprecated Prefer using methods taking a Reader rather than an InputStream to avoid wrong encoding issues. - * Use {@link #parseClass(Reader, String) parseClass} instead - */ - @Deprecated - public Class parseClass(final InputStream in, final String fileName) throws CompilationFailedException { - // For generic input streams, provide a catch-all codebase of GroovyScript - // Security for these classes can be administered via policy grants with - // a codebase of file:groovy.script - GroovyCodeSource gcs = AccessController.doPrivileged(new PrivilegedAction<GroovyCodeSource>() { - public GroovyCodeSource run() { - try { - String scriptText = config.getSourceEncoding() != null ? - IOGroovyMethods.getText(in, config.getSourceEncoding()) : - IOGroovyMethods.getText(in); - return new GroovyCodeSource(scriptText, fileName, "/groovy/script"); - } catch (IOException e) { - throw new RuntimeException("Impossible to read the content of the input stream for file named: " + fileName, e); - } - } - }); - return parseClass(gcs); - } - - public Class parseClass(GroovyCodeSource codeSource) throws CompilationFailedException { - return parseClass(codeSource, codeSource.isCachable()); - } - - /** - * Parses the given code source into a Java class. If there is a class file - * for the given code source, then no parsing is done, instead the cached class is returned. - * - * @param shouldCacheSource if true then the generated class will be stored in the source cache - * @return the main class defined in the given script - */ - public Class parseClass(final GroovyCodeSource codeSource, boolean shouldCacheSource) throws CompilationFailedException { - return sourceCache.getAndPut( - codeSource.getName(), - new EvictableCache.ValueProvider<String, Class>() { - @Override - public Class provide(String key) { - return doParseClass(codeSource); - } - }, - shouldCacheSource - ); - } - - private Class doParseClass(GroovyCodeSource codeSource) { - validate(codeSource); - Class answer; // Was neither already loaded nor compiling, so compile and add to cache. - CompilationUnit unit = createCompilationUnit(config, codeSource.getCodeSource()); - if (recompile!=null && recompile || recompile==null && config.getRecompileGroovySource()) { - unit.addFirstPhaseOperation(TimestampAdder.INSTANCE, CompilePhase.CLASS_GENERATION.getPhaseNumber()); - } - SourceUnit su = null; - File file = codeSource.getFile(); - if (file != null) { - su = unit.addSource(file); - } else { - URL url = codeSource.getURL(); - if (url != null) { - su = unit.addSource(url); - } else { - su = unit.addSource(codeSource.getName(), codeSource.getScriptText()); - } - } - - ClassCollector collector = createCollector(unit, su); - unit.setClassgenCallback(collector); - int goalPhase = Phases.CLASS_GENERATION; - if (config != null && config.getTargetDirectory() != null) goalPhase = Phases.OUTPUT; - unit.compile(goalPhase); - - answer = collector.generatedClass; - String mainClass = su.getAST().getMainClassName(); - for (Object o : collector.getLoadedClasses()) { - Class clazz = (Class) o; - String clazzName = clazz.getName(); - definePackageInternal(clazzName); - setClassCacheEntry(clazz); - if (clazzName.equals(mainClass)) answer = clazz; - } - return answer; - } - - private static void validate(GroovyCodeSource codeSource) { - if (codeSource.getFile() == null) { - if (codeSource.getScriptText() == null) { - throw new IllegalArgumentException("Script text to compile cannot be null!"); - } - } - } - - private void definePackageInternal(String className) { - int i = className.lastIndexOf('.'); - if (i != -1) { - String pkgName = className.substring(0, i); - java.lang.Package pkg = getPackage(pkgName); - if (pkg == null) { - definePackage(pkgName, null, null, null, null, null, null, null); - } - } - } - - /** - * gets the currently used classpath. - * - * @return a String[] containing the file information of the urls - * @see #getURLs() - */ - protected String[] getClassPath() { - //workaround for Groovy-835 - URL[] urls = getURLs(); - String[] ret = new String[urls.length]; - for (int i = 0; i < ret.length; i++) { - ret[i] = urls[i].getFile(); - } - return ret; - } - - protected PermissionCollection getPermissions(CodeSource codeSource) { - PermissionCollection perms; - try { - try { - perms = super.getPermissions(codeSource); - } catch (SecurityException e) { - // We lied about our CodeSource and that makes URLClassLoader unhappy. - perms = new Permissions(); - } - - ProtectionDomain myDomain = AccessController.doPrivileged(new PrivilegedAction<ProtectionDomain>() { - public ProtectionDomain run() { - return getClass().getProtectionDomain(); - } - }); - PermissionCollection myPerms = myDomain.getPermissions(); - if (myPerms != null) { - for (Enumeration<Permission> elements = myPerms.elements(); elements.hasMoreElements();) { - perms.add(elements.nextElement()); - } - } - } catch (Throwable e) { - // We lied about our CodeSource and that makes URLClassLoader unhappy. - perms = new Permissions(); - } - perms.setReadOnly(); - return perms; - } - - public static class InnerLoader extends GroovyClassLoader { - private final GroovyClassLoader delegate; - private final long timeStamp; - - public InnerLoader(GroovyClassLoader delegate) { - super(delegate); - this.delegate = delegate; - timeStamp = System.currentTimeMillis(); - } - - public void addClasspath(String path) { - delegate.addClasspath(path); - } - - public void clearCache() { - delegate.clearCache(); - } - - public URL findResource(String name) { - return delegate.findResource(name); - } - - public Enumeration findResources(String name) throws IOException { - return delegate.findResources(name); - } - - public Class[] getLoadedClasses() { - return delegate.getLoadedClasses(); - } - - public URL getResource(String name) { - return delegate.getResource(name); - } - - public InputStream getResourceAsStream(String name) { - return delegate.getResourceAsStream(name); - } - - public GroovyResourceLoader getResourceLoader() { - return delegate.getResourceLoader(); - } - - public URL[] getURLs() { - return delegate.getURLs(); - } - - public Class loadClass(String name, boolean lookupScriptFiles, boolean preferClassOverScript, boolean resolve) throws ClassNotFoundException, CompilationFailedException { - Class c = findLoadedClass(name); - if (c != null) return c; - return delegate.loadClass(name, lookupScriptFiles, preferClassOverScript, resolve); - } - - public Class parseClass(GroovyCodeSource codeSource, boolean shouldCache) throws CompilationFailedException { - return delegate.parseClass(codeSource, shouldCache); - } - - public void setResourceLoader(GroovyResourceLoader resourceLoader) { - delegate.setResourceLoader(resourceLoader); - } - - public void addURL(URL url) { - delegate.addURL(url); - } - - public long getTimeStamp() { - return timeStamp; - } - } - - /** - * creates a new CompilationUnit. If you want to add additional - * phase operations to the CompilationUnit (for example to inject - * additional methods, variables, fields), then you should overwrite - * this method. - * - * @param config the compiler configuration, usually the same as for this class loader - * @param source the source containing the initial file to compile, more files may follow during compilation - * @return the CompilationUnit - */ - protected CompilationUnit createCompilationUnit(CompilerConfiguration config, CodeSource source) { - return new CompilationUnit(config, source, this); - } - - /** - * creates a ClassCollector for a new compilation. - * - * @param unit the compilationUnit - * @param su the SourceUnit - * @return the ClassCollector - */ - protected ClassCollector createCollector(CompilationUnit unit, SourceUnit su) { - InnerLoader loader = AccessController.doPrivileged(new PrivilegedAction<InnerLoader>() { - public InnerLoader run() { - return new InnerLoader(GroovyClassLoader.this); - } - }); - return new ClassCollector(loader, unit, su); - } - - public static class ClassCollector extends CompilationUnit.ClassgenCallback { - private Class generatedClass; - private final GroovyClassLoader cl; - private final SourceUnit su; - private final CompilationUnit unit; - private final Collection<Class> loadedClasses; - - protected ClassCollector(InnerLoader cl, CompilationUnit unit, SourceUnit su) { - this.cl = cl; - this.unit = unit; - this.loadedClasses = new ArrayList<Class>(); - this.su = su; - } - - public GroovyClassLoader getDefiningClassLoader() { - return cl; - } - - protected Class createClass(byte[] code, ClassNode classNode) { - BytecodeProcessor bytecodePostprocessor = unit.getConfiguration().getBytecodePostprocessor(); - byte[] fcode = code; - if (bytecodePostprocessor!=null) { - fcode = bytecodePostprocessor.processBytecode(classNode.getName(), fcode); - } - GroovyClassLoader cl = getDefiningClassLoader(); - Class theClass = cl.defineClass(classNode.getName(), fcode, 0, fcode.length, unit.getAST().getCodeSource()); - this.loadedClasses.add(theClass); - - if (generatedClass == null) { - ModuleNode mn = classNode.getModule(); - SourceUnit msu = null; - if (mn != null) msu = mn.getContext(); - ClassNode main = null; - if (mn != null) main = (ClassNode) mn.getClasses().get(0); - if (msu == su && main == classNode) generatedClass = theClass; - } - - return theClass; - } - - protected Class onClassNode(ClassWriter classWriter, ClassNode classNode) { - byte[] code = classWriter.toByteArray(); - return createClass(code, classNode); - } - - public void call(ClassVisitor classWriter, ClassNode classNode) { - onClassNode((ClassWriter) classWriter, classNode); - } - - public Collection getLoadedClasses() { - return this.loadedClasses; - } - } - - /** - * open up the super class define that takes raw bytes - */ - public Class defineClass(String name, byte[] b) { - return super.defineClass(name, b, 0, b.length); - } - - /** - * loads a class from a file or a parent classloader. - * This method does call loadClass(String, boolean, boolean, boolean) - * with the last parameter set to false. - * - * @throws CompilationFailedException if compilation was not successful - */ - public Class loadClass(final String name, boolean lookupScriptFiles, boolean preferClassOverScript) - throws ClassNotFoundException, CompilationFailedException { - return loadClass(name, lookupScriptFiles, preferClassOverScript, false); - } - - /** - * gets a class from the class cache. This cache contains only classes loaded through - * this class loader or an InnerLoader instance. If no class is stored for a - * specific name, then the method should return null. - * - * @param name of the class - * @return the class stored for the given name - * @see #removeClassCacheEntry(String) - * @see #setClassCacheEntry(Class) - * @see #clearCache() - */ - protected Class getClassCacheEntry(String name) { - return classCache.get(name); - } - - /** - * sets an entry in the class cache. - * - * @param cls the class - * @see #removeClassCacheEntry(String) - * @see #getClassCacheEntry(String) - * @see #clearCache() - */ - protected void setClassCacheEntry(Class cls) { - classCache.put(cls.getName(), cls); - } - - /** - * removes a class from the class cache. - * - * @param name of the class - * @see #getClassCacheEntry(String) - * @see #setClassCacheEntry(Class) - * @see #clearCache() - */ - protected void removeClassCacheEntry(String name) { - classCache.remove(name); - } - - /** - * adds a URL to the classloader. - * - * @param url the new classpath element - */ - public void addURL(URL url) { - super.addURL(url); - } - - /** - * Indicates if a class is recompilable. Recompilable means, that the classloader - * will try to locate a groovy source file for this class and then compile it again, - * adding the resulting class as entry to the cache. Giving null as class is like a - * recompilation, so the method should always return true here. Only classes that are - * implementing GroovyObject are compilable and only if the timestamp in the class - * is lower than Long.MAX_VALUE. - * <p> - * NOTE: First the parent loaders will be asked and only if they don't return a - * class the recompilation will happen. Recompilation also only happen if the source - * file is newer. - * - * @param cls the class to be tested. If null the method should return true - * @return true if the class should be compiled again - * @see #isSourceNewer(URL, Class) - */ - protected boolean isRecompilable(Class cls) { - if (cls == null) return true; - if (cls.getClassLoader() == this) return false; - if (recompile == null && !config.getRecompileGroovySource()) return false; - if (recompile != null && !recompile) return false; - if (!GroovyObject.class.isAssignableFrom(cls)) return false; - long timestamp = getTimeStamp(cls); - if (timestamp == Long.MAX_VALUE) return false; - return true; - } - - /** - * sets if the recompilation should be enable. There are 3 possible - * values for this. Any value different than null overrides the - * value from the compiler configuration. true means to recompile if needed - * false means to never recompile. - * - * @param mode the recompilation mode - * @see CompilerConfiguration - */ - public void setShouldRecompile(Boolean mode) { - recompile = mode; - } - - /** - * gets the currently set recompilation mode. null means, the - * compiler configuration is used. False means no recompilation and - * true means that recompilation will be done if needed. - * - * @return the recompilation mode - */ - public Boolean isShouldRecompile() { - return recompile; - } - - /** - * loads a class from a file or a parent classloader. - * - * @param name of the class to be loaded - * @param lookupScriptFiles if false no lookup at files is done at all - * @param preferClassOverScript if true the file lookup is only done if there is no class - * @param resolve see {@link java.lang.ClassLoader#loadClass(java.lang.String, boolean)} - * @return the class found or the class created from a file lookup - * @throws ClassNotFoundException if the class could not be found - * @throws CompilationFailedException if the source file could not be compiled - */ - public Class loadClass(final String name, boolean lookupScriptFiles, boolean preferClassOverScript, boolean resolve) - throws ClassNotFoundException, CompilationFailedException { - // look into cache - Class cls = getClassCacheEntry(name); - - // enable recompilation? - boolean recompile = isRecompilable(cls); - if (!recompile) return cls; - - // try parent loader - ClassNotFoundException last = null; - try { - Class parentClassLoaderClass = super.loadClass(name, resolve); - // always return if the parent loader was successful - if (cls != parentClassLoaderClass) return parentClassLoaderClass; - } catch (ClassNotFoundException cnfe) { - last = cnfe; - } catch (NoClassDefFoundError ncdfe) { - if (ncdfe.getMessage().indexOf("wrong name") > 0) { - last = new ClassNotFoundException(name); - } else { - throw ncdfe; - } - } - - // check security manager - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - String className = name.replace('/', '.'); - int i = className.lastIndexOf('.'); - // no checks on the sun.reflect classes for reflection speed-up - // in particular ConstructorAccessorImpl, MethodAccessorImpl, FieldAccessorImpl and SerializationConstructorAccessorImpl - // which are generated at runtime by the JDK - if (i != -1 && !className.startsWith("sun.reflect.")) { - sm.checkPackageAccess(className.substring(0, i)); - } - } - - // prefer class if no recompilation - if (cls != null && preferClassOverScript) return cls; - - // at this point the loading from a parent loader failed - // and we want to recompile if needed. - if (lookupScriptFiles) { - // try groovy file - try { - // check if recompilation already happened. - final Class classCacheEntry = getClassCacheEntry(name); - if (classCacheEntry != cls) return classCacheEntry; - URL source = resourceLoader.loadGroovySource(name); - // if recompilation fails, we want cls==null - Class oldClass = cls; - cls = null; - cls = recompile(source, name, oldClass); - } catch (IOException ioe) { - last = new ClassNotFoundException("IOException while opening groovy source: " + name, ioe); - } finally { - if (cls == null) { - removeClassCacheEntry(name); - } else { - setClassCacheEntry(cls); - } - } - } - - if (cls == null) { - // no class found, there should have been an exception before now - if (last == null) throw new AssertionError(true); - throw last; - } - return cls; - } - - /** - * (Re)Compiles the given source. - * This method starts the compilation of a given source, if - * the source has changed since the class was created. For - * this isSourceNewer is called. - * - * @param source the source pointer for the compilation - * @param className the name of the class to be generated - * @param oldClass a possible former class - * @return the old class if the source wasn't new enough, the new class else - * @throws CompilationFailedException if the compilation failed - * @throws IOException if the source is not readable - * @see #isSourceNewer(URL, Class) - */ - protected Class recompile(URL source, String className, Class oldClass) throws CompilationFailedException, IOException { - if (source != null) { - // found a source, compile it if newer - if ((oldClass != null && isSourceNewer(source, oldClass)) || (oldClass == null)) { - String name = source.toExternalForm(); - - sourceCache.remove(name); - - if (isFile(source)) { - try { - return parseClass(new GroovyCodeSource(new File(source.toURI()), sourceEncoding)); - } catch (URISyntaxException e) { - // do nothing and fall back to the other version - } - } - return parseClass(new InputStreamReader(source.openStream(), sourceEncoding), name); - } - } - return oldClass; - } - - @Override - public Class<?> loadClass(String name) throws ClassNotFoundException { - return loadClass(name, false); - } - - /** - * Implemented here to check package access prior to returning an - * already loaded class. - * - * @throws CompilationFailedException if the compilation failed - * @throws ClassNotFoundException if the class was not found - * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean) - */ - protected Class loadClass(final String name, boolean resolve) throws ClassNotFoundException { - return loadClass(name, true, true, resolve); - } - - /** - * gets the time stamp of a given class. For groovy - * generated classes this usually means to return the value - * of the static field __timeStamp. If the parameter doesn't - * have such a field, then Long.MAX_VALUE is returned - * - * @param cls the class - * @return the time stamp - */ - protected long getTimeStamp(Class cls) { - return Verifier.getTimestamp(cls); - } - - /** - * This method will take a file name and try to "decode" any URL encoded characters. For example - * if the file name contains any spaces this method call will take the resulting %20 encoded values - * and convert them to spaces. - * <p> - * This method was added specifically to fix defect: Groovy-1787. The defect involved a situation - * where two scripts were sitting in a directory with spaces in its name. The code would fail - * when the class loader tried to resolve the file name and would choke on the URLEncoded space values. - */ - private static String decodeFileName(String fileName) { - String decodedFile = fileName; - try { - decodedFile = URLDecoder.decode(fileName, "UTF-8"); - } catch (UnsupportedEncodingException e) { - System.err.println("Encountered an invalid encoding scheme when trying to use URLDecoder.decode() inside of the GroovyClassLoader.decodeFileName() method. Returning the unencoded URL."); - System.err.println("Please note that if you encounter this error and you have spaces in your directory you will run into issues. Refer to GROOVY-1787 for description of this bug."); - } - - return decodedFile; - } - - private static boolean isFile(URL ret) { - return ret != null && ret.getProtocol().equals("file"); - } - - private static File getFileForUrl(URL ret, String filename) { - String fileWithoutPackage = filename; - if (fileWithoutPackage.indexOf('/') != -1) { - int index = fileWithoutPackage.lastIndexOf('/'); - fileWithoutPackage = fileWithoutPackage.substring(index + 1); - } - return fileReallyExists(ret, fileWithoutPackage); - } - - private static File fileReallyExists(URL ret, String fileWithoutPackage) { - File path; - try { - /* fix for GROOVY-5809 */ - path = new File(ret.toURI()); - } catch(URISyntaxException e) { - path = new File(decodeFileName(ret.getFile())); - } - path = path.getParentFile(); - if (path.exists() && path.isDirectory()) { - File file = new File(path, fileWithoutPackage); - if (file.exists()) { - // file.exists() might be case insensitive. Let's do - // case sensitive match for the filename - File parent = file.getParentFile(); - for (String child : parent.list()) { - if (child.equals(fileWithoutPackage)) return file; - } - } - } - //file does not exist! - return null; - } - - private URL getSourceFile(String name, String extension) { - String filename = name.replace('.', '/') + "." + extension; - URL ret = getResource(filename); - if (isFile(ret) && getFileForUrl(ret, filename) == null) return null; - return ret; - } - - /** - * Decides if the given source is newer than a class. - * - * @param source the source we may want to compile - * @param cls the former class - * @return true if the source is newer, false else - * @throws IOException if it is not possible to open an - * connection for the given source - * @see #getTimeStamp(Class) - */ - protected boolean isSourceNewer(URL source, Class cls) throws IOException { - long lastMod; - - // Special handling for file:// protocol, as getLastModified() often reports - // incorrect results (-1) - if (isFile(source)) { - // Coerce the file URL to a File - // See ClassNodeResolver.isSourceNewer for another method that replaces '|' with ':'. - // WTF: Why is this done and where is it documented? - String path = source.getPath().replace('/', File.separatorChar).replace('|', ':'); - File file = new File(path); - lastMod = file.lastModified(); - } else { - URLConnection conn = source.openConnection(); - lastMod = conn.getLastModified(); - conn.getInputStream().close(); - } - long classTime = getTimeStamp(cls); - return classTime + config.getMinimumRecompilationInterval() < lastMod; - } - - /** - * adds a classpath to this classloader. - * - * @param path is a jar file or a directory. - * @see #addURL(URL) - */ - public void addClasspath(final String path) { - AccessController.doPrivileged(new PrivilegedAction<Void>() { - public Void run() { - - URI newURI; - try { - newURI = new URI(path); - // check if we can create a URL from that URI - newURI.toURL(); - } catch (URISyntaxException e) { - // the URI has a false format, so lets try it with files ... - newURI=new File(path).toURI(); - } catch (MalformedURLException e) { - // the URL has a false format, so lets try it with files ... - newURI=new File(path).toURI(); - } catch (IllegalArgumentException e) { - // the URL is not absolute, so lets try it with files ... - newURI=new File(path).toURI(); - } - - URL[] urls = getURLs(); - for (URL url : urls) { - // Do not use URL.equals. It uses the network to resolve names and compares ip addresses! - // That is a violation of RFC and just plain evil. - // http://michaelscharf.blogspot.com/2006/11/javaneturlequals-and-hashcode-make.html - // http://docs.oracle.com/javase/7/docs/api/java/net/URL.html#equals(java.lang.Object) - // "Since hosts comparison requires name resolution, this operation is a blocking operation. - // Note: The defined behavior for equals is known to be inconsistent with virtual hosting in HTTP." - try { - if (newURI.equals(url.toURI())) return null; - } catch (URISyntaxException e) { - // fail fast! if we got a malformed URI the Classloader has to tell it - throw new RuntimeException( e ); - } - } - try { - addURL(newURI.toURL()); - } catch (MalformedURLException e) { - // fail fast! if we got a malformed URL the Classloader has to tell it - throw new RuntimeException( e ); - } - return null; - } - }); - } - - /** - * <p>Returns all Groovy classes loaded by this class loader. - * - * @return all classes loaded by this class loader - */ - public Class[] getLoadedClasses() { - return classCache.values().toArray(EMPTY_CLASS_ARRAY); - } - - /** - * Removes all classes from the class cache. - * <p> - * In addition to internal caches this method also clears any - * previously set MetaClass information for the given set of - * classes being removed. - * - * @see #getClassCacheEntry(String) - * @see #setClassCacheEntry(Class) - * @see #removeClassCacheEntry(String) - */ - public void clearCache() { - Map<String, Class> clearedClasses = classCache.clear(); - - sourceCache.clear(); - - for (Map.Entry<String, Class> entry : clearedClasses.entrySet()) { - // Another Thread may be using an instance of this class - // (for the first time) requiring a ClassInfo lock and - // classloading which would require a lock on classCache. - // The following locks on ClassInfo and to avoid deadlock - // should not be done with a classCache lock. - InvokerHelper.removeClass(entry.getValue()); - } - } - - /** - * Closes this GroovyClassLoader and clears any caches it maintains. - * <p> - * No use should be made of this instance after this method is - * invoked. Any classes that are already loaded are still accessible. - * - * @throws IOException - * @see URLClassLoader#close() - * @see #clearCache() - * @since 2.5.0 - */ - @Override - public void close() throws IOException { - super.close(); - clearCache(); - } - - private static class TimestampAdder extends CompilationUnit.PrimaryClassNodeOperation implements Opcodes { - private static final TimestampAdder INSTANCE = new TimestampAdder(); - - private TimestampAdder() {} - - protected void addTimeStamp(ClassNode node) { - if (node.getDeclaredField(Verifier.__TIMESTAMP) == null) { // in case if verifier visited the call already - FieldNode timeTagField = new FieldNode( - Verifier.__TIMESTAMP, - ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, - ClassHelper.long_TYPE, - //"", - node, - new ConstantExpression(System.currentTimeMillis())); - // alternatively, FieldNode timeTagField = SourceUnit.createFieldNode("public static final long __timeStamp = " + System.currentTimeMillis() + "L"); - timeTagField.setSynthetic(true); - node.addField(timeTagField); - - timeTagField = new FieldNode( - Verifier.__TIMESTAMP__ + String.valueOf(System.currentTimeMillis()), - ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, - ClassHelper.long_TYPE, - //"", - node, - new ConstantExpression((long) 0)); - // alternatively, FieldNode timeTagField = SourceUnit.createFieldNode("public static final long __timeStamp = " + System.currentTimeMillis() + "L"); - timeTagField.setSynthetic(true); - node.addField(timeTagField); - } - } - - @Override - public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException { - if ((classNode.getModifiers() & Opcodes.ACC_INTERFACE) > 0) { - // does not apply on interfaces - return; - } - if (!(classNode instanceof InnerClassNode)) { - addTimeStamp(classNode); - } - } - } -} http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/lang/GroovyCodeSource.java ---------------------------------------------------------------------- diff --git a/src/main/groovy/lang/GroovyCodeSource.java b/src/main/groovy/lang/GroovyCodeSource.java deleted file mode 100644 index a5a2bb1..0000000 --- a/src/main/groovy/lang/GroovyCodeSource.java +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package groovy.lang; - -import groovy.security.GroovyCodeSourcePermission; -import groovy.util.CharsetToolkit; -import org.codehaus.groovy.runtime.IOGroovyMethods; -import org.codehaus.groovy.runtime.ResourceGroovyMethods; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.Reader; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URL; -import java.net.URLConnection; -import java.security.AccessController; -import java.security.CodeSource; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.security.cert.Certificate; -import java.util.Objects; - -/** - * CodeSource wrapper class that allows specific security policies to be associated with a class - * compiled from groovy source. - * - * @author Steve Goetze - * @author Guillaume Laforge - * @author Merlyn Albery-Speyer - */ -public class GroovyCodeSource { - - /** - * The codeSource to be given the generated class. This can be used by policy file - * grants to administer security. - */ - private CodeSource codeSource; - - /** - * The name given to the generated class - */ - private String name; - - /** - * The groovy source to be compiled and turned into a class - */ - private String scriptText; - - /** - * The certificates used to sign the items from the codesource - */ - Certificate[] certs; - - private boolean cachable; - - private File file; - - private URL url; - - public GroovyCodeSource(String script, String name, String codeBase) { - this.name = name; - this.scriptText = script; - this.codeSource = createCodeSource(codeBase); - this.cachable = true; - } - - /** - * Construct a GroovyCodeSource for an inputStream of groovyCode that has an - * unknown provenance -- meaning it didn't come from a File or a URL (e.g. a String). - * The supplied codeBase will be used to construct a File URL that should match up - * with a java Policy entry that determines the grants to be associated with the - * class that will be built from the InputStream. - * <p> - * The permission groovy.security.GroovyCodeSourcePermission will be used to determine if the given codeBase - * may be specified. That is, the current Policy set must have a GroovyCodeSourcePermission that implies - * the codeBase, or an exception will be thrown. This is to prevent callers from hijacking - * existing codeBase policy entries unless explicitly authorized by the user. - */ - public GroovyCodeSource(Reader reader, String name, String codeBase) { - this.name = name; - this.codeSource = createCodeSource(codeBase); - - try { - this.scriptText = IOGroovyMethods.getText(reader); - } catch (IOException e) { - throw new RuntimeException("Impossible to read the text content from that reader, for script: " + name + " with codeBase: " + codeBase, e); - } - } - - public GroovyCodeSource(final File infile, final String encoding) throws IOException { - // avoid files which confuse us like ones with .. in path - final File file = new File(infile.getCanonicalPath()); - if (!file.exists()) { - throw new FileNotFoundException(file.toString() + " (" + file.getAbsolutePath() + ")"); - } - if (file.isDirectory()) { - throw new IllegalArgumentException(file.toString() + " (" + file.getAbsolutePath() + ") is a directory not a Groovy source file."); - } - try { - if (!file.canRead()) - throw new RuntimeException(file.toString() + " can not be read. Check the read permission of the file \"" + file.toString() + "\" (" + file.getAbsolutePath() + ")."); - } - catch (SecurityException e) { - throw e; - } - - this.file = file; - this.cachable = true; - //The calls below require access to user.dir - allow here since getName() and getCodeSource() are - //package private and used only by the GroovyClassLoader. - try { - Object[] info = AccessController.doPrivileged(new PrivilegedExceptionAction<Object[]>() { - public Object[] run() throws IOException { - // retrieve the content of the file using the provided encoding - if (encoding != null) { - scriptText = ResourceGroovyMethods.getText(infile, encoding); - } else { - scriptText = ResourceGroovyMethods.getText(infile); - } - - Object[] info = new Object[2]; - URL url = file.toURI().toURL(); - info[0] = url.toExternalForm(); - //toURI().toURL() will encode, but toURL() will not. - info[1] = new CodeSource(url, (Certificate[]) null); - return info; - } - }); - - this.name = (String) info[0]; - this.codeSource = (CodeSource) info[1]; - } catch (PrivilegedActionException pae) { - Throwable cause = pae.getCause(); - if (cause != null && cause instanceof IOException) { - throw (IOException) cause; - } - throw new RuntimeException("Could not construct CodeSource for file: " + file, cause); - } - } - - /** - * @param infile the file to create a GroovyCodeSource for. - * @throws IOException if an issue arises opening and reading the file. - */ - public GroovyCodeSource(final File infile) throws IOException { - this(infile, CharsetToolkit.getDefaultSystemCharset().name()); - } - - public GroovyCodeSource(URI uri) throws IOException { - this(uri.toURL()); - } - - public GroovyCodeSource(URL url) { - if (url == null) { - throw new RuntimeException("Could not construct a GroovyCodeSource from a null URL"); - } - this.url = url; - // TODO: GROOVY-6561: GroovyMain got the name this way: script.substring(script.lastIndexOf("/") + 1) - this.name = url.toExternalForm(); - this.codeSource = new CodeSource(url, (java.security.cert.Certificate[]) null); - try { - String contentEncoding = getContentEncoding(url); - if (contentEncoding != null) { - this.scriptText = ResourceGroovyMethods.getText(url, contentEncoding); - } else { - this.scriptText = ResourceGroovyMethods.getText(url); // falls-back on default encoding - } - } catch (IOException e) { - throw new RuntimeException("Impossible to read the text content from " + name, e); - } - } - - /** - * TODO(jwagenleitner): remove or fix in future release - * - * According to the spec getContentEncoding() returns the Content-Encoding - * HTTP Header which typically carries values such as 'gzip' or 'deflate' - * and is not the character set encoding. For compatibility in 2.4.x, - * this behavior is retained but should be removed or fixed (parse - * charset from Content-Type header) in future releases. - * - * see GROOVY-8056 and https://github.com/apache/groovy/pull/500 - */ - private static String getContentEncoding(URL url) throws IOException { - URLConnection urlConnection = url.openConnection(); - String encoding = urlConnection.getContentEncoding(); - try { - IOGroovyMethods.closeQuietly(urlConnection.getInputStream()); - } catch (IOException ignore) { - // For compatibility, ignore exceptions from getInputStream() call - } - return encoding; - } - - CodeSource getCodeSource() { - return codeSource; - } - - public String getScriptText() { - return scriptText; - } - - public String getName() { - return name; - } - - public File getFile() { - return file; - } - - public URL getURL() { - return url; - } - - public void setCachable(boolean b) { - cachable = b; - } - - public boolean isCachable() { - return cachable; - } - - private static CodeSource createCodeSource(final String codeBase) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new GroovyCodeSourcePermission(codeBase)); - } - try { - return new CodeSource(new URL("file", "", codeBase), (java.security.cert.Certificate[]) null); - } - catch (MalformedURLException e) { - throw new RuntimeException("A CodeSource file URL cannot be constructed from the supplied codeBase: " + codeBase); - } - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - GroovyCodeSource that = (GroovyCodeSource) o; - return Objects.equals(codeSource, that.codeSource); - } - - @Override - public int hashCode() { - return Objects.hash(codeSource); - } -} http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/lang/GroovyInterceptable.java ---------------------------------------------------------------------- diff --git a/src/main/groovy/lang/GroovyInterceptable.java b/src/main/groovy/lang/GroovyInterceptable.java deleted file mode 100644 index 8f83354..0000000 --- a/src/main/groovy/lang/GroovyInterceptable.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package groovy.lang; - -/** - * Marker interface used to notify that all methods should be intercepted through the <code>invokeMethod</code> mechanism - * of <code>GroovyObject</code>. - * - * @author Guillaume Laforge - */ -public interface GroovyInterceptable extends GroovyObject { -} http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/lang/GroovyObject.java ---------------------------------------------------------------------- diff --git a/src/main/groovy/lang/GroovyObject.java b/src/main/groovy/lang/GroovyObject.java deleted file mode 100644 index 5f271e3..0000000 --- a/src/main/groovy/lang/GroovyObject.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package groovy.lang; - -/** - * The interface implemented by all Groovy objects. - * <p> - * Especially handy for using Groovy objects when in the Java world. - * - * @author <a href="mailto:[email protected]">James Strachan</a> - */ -public interface GroovyObject { - - /** - * Invokes the given method. - * - * @param name the name of the method to call - * @param args the arguments to use for the method call - * @return the result of invoking the method - */ - Object invokeMethod(String name, Object args); - - /** - * Retrieves a property value. - * - * @param propertyName the name of the property of interest - * @return the given property - */ - Object getProperty(String propertyName); - - /** - * Sets the given property to the new value. - * - * @param propertyName the name of the property of interest - * @param newValue the new value for the property - */ - void setProperty(String propertyName, Object newValue); - - /** - * Returns the metaclass for a given class. - * - * @return the metaClass of this instance - */ - MetaClass getMetaClass(); - - /** - * Allows the MetaClass to be replaced with a derived implementation. - * - * @param metaClass the new metaclass - */ - void setMetaClass(MetaClass metaClass); -} http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/lang/GroovyObjectSupport.java ---------------------------------------------------------------------- diff --git a/src/main/groovy/lang/GroovyObjectSupport.java b/src/main/groovy/lang/GroovyObjectSupport.java deleted file mode 100644 index cf7a77f..0000000 --- a/src/main/groovy/lang/GroovyObjectSupport.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package groovy.lang; - -import org.codehaus.groovy.runtime.InvokerHelper; - -/** - * A useful base class for Java objects wishing to be Groovy objects - * - * @author <a href="mailto:[email protected]">James Strachan</a> - */ -public abstract class GroovyObjectSupport implements GroovyObject { - - // never persist the MetaClass - private transient MetaClass metaClass; - - public GroovyObjectSupport() { - this.metaClass = getDefaultMetaClass(); - } - - public Object getProperty(String property) { - return getMetaClass().getProperty(this, property); - } - - public void setProperty(String property, Object newValue) { - getMetaClass().setProperty(this, property, newValue); - } - - public Object invokeMethod(String name, Object args) { - return getMetaClass().invokeMethod(this, name, args); - } - - public MetaClass getMetaClass() { - return this.metaClass; - } - - public void setMetaClass(MetaClass metaClass) { - this.metaClass = - null == metaClass - ? getDefaultMetaClass() - : metaClass; - } - - private MetaClass getDefaultMetaClass() { - return InvokerHelper.getMetaClass(this.getClass()); - } -} http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/lang/GroovyResourceLoader.java ---------------------------------------------------------------------- diff --git a/src/main/groovy/lang/GroovyResourceLoader.java b/src/main/groovy/lang/GroovyResourceLoader.java deleted file mode 100644 index 7abe202..0000000 --- a/src/main/groovy/lang/GroovyResourceLoader.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package groovy.lang; - -import java.net.MalformedURLException; -import java.net.URL; - -/** - * Allows frameworks that integrate with Groovy to determine how Groovy files are resolved. - * - * @author Steven Devijver - */ -public interface GroovyResourceLoader { - - /** - * Loads a Groovy source file given its name. - * - * @param filename name of the file - * @return a URL - * @throws java.net.MalformedURLException if the URL is invalid - */ - URL loadGroovySource(String filename) throws MalformedURLException; -} http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/lang/GroovyRuntimeException.java ---------------------------------------------------------------------- diff --git a/src/main/groovy/lang/GroovyRuntimeException.java b/src/main/groovy/lang/GroovyRuntimeException.java deleted file mode 100644 index 33eb51c..0000000 --- a/src/main/groovy/lang/GroovyRuntimeException.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package groovy.lang; - -import org.codehaus.groovy.ast.ASTNode; -import org.codehaus.groovy.ast.ModuleNode; - -/** - * An exception thrown by the interpreter - * - * @author <a href="mailto:[email protected]">James Strachan</a> - */ -public class GroovyRuntimeException extends RuntimeException { - - private ModuleNode module; - private ASTNode node; - - public GroovyRuntimeException() { - } - - public GroovyRuntimeException(String message) { - super(message); - } - - public GroovyRuntimeException(String message, ASTNode node) { - super(message); - this.node = node; - } - - public GroovyRuntimeException(String message, Throwable cause) { - super(message, cause); - } - - public GroovyRuntimeException(Throwable t) { - super(); - initCause(t); - } - - public void setModule(ModuleNode module) { - this.module = module; - } - - public ModuleNode getModule() { - return module; - } - - public String getMessage() { - return getMessageWithoutLocationText() + getLocationText(); - } - - public ASTNode getNode() { - return node; - } - - public String getMessageWithoutLocationText() { - return super.getMessage(); - } - - protected String getLocationText() { - String answer = ". "; - if (node != null) { - answer += "At [" + node.getLineNumber() + ":" + node.getColumnNumber() + "] "; - } - if (module != null) { - answer += module.getDescription(); - } - if (answer.equals(". ")) { - return ""; - } - return answer; - } -}
