groovyclassloadertest.groovy

来自「Groovy动态语言 运行在JVM中的动态语言 可以方便的处理业务逻辑变化大的业」· GROOVY 代码 · 共 189 行

GROOVY
189
字号
/*
 * $Id: GroovyClassLoaderTest.groovy 3812 2006-06-06 15:06:04Z blackdrag $
 *
 * 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) {
        assert ncdfe.message.indexOf("TestCase")>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
  }    
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?