blob: 420d44f8be65e757f34dcd19b89e95e9fd2681d1 [file] [log] [blame]
/*
* $Id$
*
* Copyright (c) 2005 The Codehaus - http://groovy.codehaus.org
*
* Licensed 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.security.CodeSource
import org.codehaus.groovy.control.*
import org.codehaus.groovy.ast.*
import org.codehaus.groovy.classgen.*
public class GroovyClassLoaderTest extends GroovyTestCase {
private final GroovyClassLoader classLoader = new GroovyClassLoader()
private boolean contains(String[] paths, String eval) {
try {
eval = (new File(eval)).toURI().toURL().getFile();
} catch (MalformedURLException e) {
return false;
}
for (it in paths) {
if(eval.equals(it)) return true;
}
return false;
}
public void testAddsAClasspathEntryOnlyIfItHasNotAlreadyBeenAdded() {
String newClasspathEntry = "/tmp"
int initialNumberOfClasspathEntries = classLoader.getClassPath().length
classLoader.addClasspath(newClasspathEntry)
assert initialNumberOfClasspathEntries + 1 == classLoader.getClassPath().length
assert contains(classLoader.getClassPath(),newClasspathEntry)
classLoader.addClasspath(newClasspathEntry);
assert initialNumberOfClasspathEntries + 1 == classLoader.getClassPath().length
assert contains(classLoader.getClassPath(),newClasspathEntry)
}
def getPaths(URLClassLoader ucl) {
def urls = ucl.getURLs()
return urls.findAll {!it.file.endsWith(".jar")}
}
def getPaths(String path) {
int start = 0, end=0
String sep = File.pathSeparator
def ret = []
while (end<path.length()) {
start = end
end = path.indexOf(sep,end)
if (end==-1) break
def sub = path.substring(start,end)
if (!sub.endsWith(".jar")) {
ret << ((new File(sub)).toURL())
}
end++
}
return ret
}
public void testClassNotFoundIsNotHidden() {
def paths=[]
def loader = this.class.classLoader
while (loader!=null) {
if (loader instanceof URLClassLoader) {
paths += getPaths(loader)
}
loader = loader.parent
}
paths += getPaths(System.getProperty("java.class.path"))
paths=paths.unique()
def file = File.createTempFile("Foo",".groovy")
def name = file.name-".groovy"
def script = """
class $name extends GroovyTestCase{}
"""
file << script
paths << file.parentFile.toURL()
def cl = new URLClassLoader(paths as URL[],null)
def gcl = new GroovyClassLoader(cl)
try {
gcl.loadClass(name)
assert false
} catch (NoClassDefFoundError ncdfe) {
// TODO: hack for running when under coverage - find a better way
assert ncdfe.message.indexOf("TestCase")>0 || ncdfe.message.indexOf("cobertura")>0
}
}
public void testClassPathNotDerived() {
def config = new CompilerConfiguration()
def loader1 = new GroovyClassLoader(null,config)
config = new CompilerConfiguration()
config.setClasspath("foo")
def loader2 = new GroovyClassLoader(loader1,config)
config = new CompilerConfiguration()
def loader3 = new GroovyClassLoader(loader2,config)
def urls = loader1.URLs
assert urls.length == 0
urls = loader2.URLs
assert urls.length == 1
assert urls[0].toString().endsWith("foo")
urls = loader3.URLs
assert urls.length == 0
}
public void testMultithreading() {
def config = new CompilerConfiguration()
config.recompileGroovySource = true;
def loader = new GroovyClassLoaderTestCustomGCL(config)
def ts = new Thread[100]
for (i in 0..<100) {
ts[i] = Thread.start {
if (i%2==1) sleep(100)
assert GroovyClassLoaderTestFoo1==loader.loadClass("Foox")
}
}
sleep(100)
for (i in 0..<100) {ts[i].join()}
assert GroovyClassLoaderTestFoo2==loader.loadClass("Foox")
}
public void testAdditionalPhaseOperation(){
def loader = new GroovyClassLoaderTestCustomPhaseOperation()
def ret = loader.parseClass("""class Foo{}""")
def field = ret.declaredFields.find {it.name=="id" && it.type==Long.TYPE}
assert field != null
}
}
class GroovyClassLoaderTestFoo1{}
class GroovyClassLoaderTestFoo2{}
class GroovyClassLoaderTestCustomGCL extends GroovyClassLoader{
def GroovyClassLoaderTestCustomGCL(config) {
super(null,config);
}
def counter = 0
protected Class recompile(URL source, String name, Class oldClass) {
if (name=="Foox") {
if (counter<100) {
counter++
return GroovyClassLoaderTestFoo1
} else {
return GroovyClassLoaderTestFoo2
}
}
return super.recompile(source,name,oldClass)
}
protected boolean isSourceNewer(URL source, Class cls) {
return true
}
}
class GroovyClassLoaderTestPropertyAdder extends CompilationUnit.PrimaryClassNodeOperation {
void call(SourceUnit source, GeneratorContext context, ClassNode classNode) {
classNode.addProperty("id", ClassNode.ACC_PUBLIC, ClassHelper.long_TYPE,null,null,null);
}
}
class GroovyClassLoaderTestCustomPhaseOperation extends GroovyClassLoader {
CompilationUnit createCompilationUnit(CompilerConfiguration config, CodeSource source) {
def cu = super.createCompilationUnit(config,source)
cu.addPhaseOperation(new GroovyClassLoaderTestPropertyAdder(),Phases.CONVERSION)
return cu
}
}