| /* |
| * 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 org.codehaus.groovy.runtime.metaclass; |
| |
| import org.codehaus.groovy.runtime.Reflector; |
| |
| import java.security.ProtectionDomain; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| /** |
| * Reflector creation helper. This class is used to define the Reflector classes. |
| * For each ClassLoader such a loader will be created by MetaClass. |
| * Special about this loader is, that it knows the classes form the |
| * Groovy Runtime. The Reflector class is resolved in different ways: During |
| * the definition of a class Reflector will resolve to the Reflector class of |
| * the runtime, even if there is another Reflector class in the parent loader. |
| * After the new class is defined Reflector will resolve like other Groovy |
| * classes. This loader is able to resolve all Groovy classes even if the |
| * parent does not know them, but the parent serves first (Reflector during a |
| * class definition is different). |
| * |
| * @author <a href="mailto:blackdrag@gmx.org">Jochen Theodorou</a> |
| */ |
| public class ReflectorLoader extends ClassLoader { |
| private boolean inDefine = false; |
| private final Map loadedClasses = new HashMap(); |
| private final ClassLoader delegatationLoader; |
| |
| private static final String REFLECTOR = Reflector.class.getName(); |
| |
| /** |
| * Tries to find a Groovy class. |
| * |
| * @return the class if found |
| * @throws ClassNotFoundException if not found |
| */ |
| protected Class findClass(String name) throws ClassNotFoundException { |
| if (delegatationLoader==null) return super.findClass(name); |
| return delegatationLoader.loadClass(name); |
| } |
| |
| /** |
| * Loads a class per name. Unlike a normal loadClass this version |
| * behaves different during a class definition. In that case it |
| * checks if the class we want to load is Reflector and returns |
| * class if the check is successful. If it is not during a class |
| * definition it just calls the super class version of loadClass. |
| * |
| * @param name of the class to load |
| * @param resolve is true if the class should be resolved |
| * @see Reflector |
| * @see ClassLoader#loadClass(String, boolean) |
| */ |
| protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { |
| if (inDefine) { |
| if (name.equals(REFLECTOR)) return Reflector.class; |
| } |
| return super.loadClass(name, resolve); |
| } |
| |
| /** |
| * helper method to define Reflector classes. |
| * @param name of the Reflector |
| * @param bytecode the bytecode |
| * @param domain the protection domain |
| * @return the generated class |
| */ |
| public synchronized Class defineClass(String name, byte[] bytecode, ProtectionDomain domain) { |
| inDefine = true; |
| Class c = defineClass(name, bytecode, 0, bytecode.length, domain); |
| loadedClasses.put(name,c); |
| resolveClass(c); |
| inDefine = false; |
| return c; |
| } |
| |
| /** |
| * creates a ReflectorLoader. |
| * @param parent the parent loader. This should never be null! |
| */ |
| public ReflectorLoader(ClassLoader parent) { |
| super(parent); |
| delegatationLoader = getClass().getClassLoader(); |
| } |
| |
| /** |
| * try to load one of the defined Reflector classes by name. |
| * @param name of the Reflector class |
| * @return the Reflector class if defined else null. |
| */ |
| public synchronized Class getLoadedClass(String name) { |
| return (Class)loadedClasses.get(name); |
| } |
| |
| static String getReflectorName(Class theClass) { |
| String className = theClass.getName(); |
| if (className.startsWith("java.")) { |
| String packagePrefix = "gjdk."; |
| String name = packagePrefix + className + "_GroovyReflector"; |
| if (theClass.isArray()) { |
| Class clazz = theClass; |
| name = packagePrefix; |
| int level = 0; |
| while (clazz.isArray()) { |
| clazz = clazz.getComponentType(); |
| level++; |
| } |
| String componentName = clazz.getName(); |
| name = packagePrefix + componentName + "_GroovyReflectorArray"; |
| if (level>1) name += level; |
| } |
| return name; |
| } |
| else { |
| String name = className.replace('$','_') + "_GroovyReflector"; |
| if (theClass.isArray()) { |
| Class clazz = theClass; |
| int level = 0; |
| while (clazz.isArray()) { |
| clazz = clazz.getComponentType(); |
| level++; |
| } |
| String componentName = clazz.getName(); |
| name = componentName.replace('$','_') + "_GroovyReflectorArray"; |
| if (level>1) name += level; |
| } |
| return name; |
| } |
| } |
| } |