/* | |
* 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.apache.commons.proxy2.javassist; | |
import java.util.HashSet; | |
import java.util.Set; | |
import java.util.concurrent.atomic.AtomicInteger; | |
import javassist.CannotCompileException; | |
import javassist.ClassPool; | |
import javassist.CtClass; | |
import javassist.CtField; | |
import javassist.LoaderClassPath; | |
import javassist.NotFoundException; | |
import org.apache.commons.proxy2.ProxyUtils; | |
import org.apache.commons.proxy2.exception.ObjectProviderException; | |
/** | |
* Some utility methods for dealing with Javassist. This class is not part of the public API! | |
* | |
* @since 1.0 | |
*/ | |
final class JavassistUtils | |
{ | |
//****************************************************************************************************************** | |
// Fields | |
//****************************************************************************************************************** | |
public static final String DEFAULT_BASE_NAME = "JavassistUtilsGenerated"; | |
private static final AtomicInteger CLASS_NUMBER = new AtomicInteger(0); | |
private static final ClassPool CLASS_POOL = new ClassPool(); | |
private static final Set<ClassLoader> CLASS_LOADERS = new HashSet<ClassLoader>(); | |
//****************************************************************************************************************** | |
// Static Methods | |
//****************************************************************************************************************** | |
static | |
{ | |
CLASS_POOL.appendClassPath(new LoaderClassPath(ClassLoader.getSystemClassLoader())); | |
} | |
/** | |
* Adds a field to a class. | |
* | |
* @param fieldType | |
* the field's type | |
* @param fieldName | |
* the field name | |
* @param enclosingClass | |
* the class receiving the new field | |
* @throws CannotCompileException | |
* if a compilation problem occurs | |
*/ | |
public static void addField(Class<?> fieldType, String fieldName, CtClass enclosingClass) | |
throws CannotCompileException | |
{ | |
enclosingClass.addField(new CtField(resolve(fieldType), fieldName, enclosingClass)); | |
} | |
/** | |
* Adds interfaces to a {@link CtClass} | |
* | |
* @param ctClass | |
* the {@link CtClass} | |
* @param proxyClasses | |
* the interfaces | |
*/ | |
public static void addInterfaces(CtClass ctClass, Class<?>[] proxyClasses) | |
{ | |
for (int i = 0; i < proxyClasses.length; i++) | |
{ | |
Class<?> proxyInterface = proxyClasses[i]; | |
ctClass.addInterface(resolve(proxyInterface)); | |
} | |
} | |
/** | |
* Creates a new {@link CtClass} derived from the Java {@link Class} using the default base name. | |
* | |
* @param superclass | |
* the superclass | |
* @return the new derived {@link CtClass} | |
*/ | |
public static CtClass createClass(Class<?> superclass) | |
{ | |
return createClass(DEFAULT_BASE_NAME, superclass); | |
} | |
/** | |
* Creates a new {@link CtClass} derived from the Java {@link Class} using the supplied base name. | |
* | |
* @param baseName | |
* the base name | |
* @param superclass | |
* the superclass | |
* @return the new derived {@link CtClass} | |
*/ | |
public static synchronized CtClass createClass(String baseName, Class<?> superclass) | |
{ | |
return CLASS_POOL.makeClass(baseName + "_" + CLASS_NUMBER.incrementAndGet(), resolve(superclass)); | |
} | |
/** | |
* Finds the {@link CtClass} corresponding to the Java {@link Class} passed in. | |
* | |
* @param clazz | |
* the Java {@link Class} | |
* @return the {@link CtClass} | |
*/ | |
public static CtClass resolve(Class<?> clazz) | |
{ | |
synchronized (CLASS_LOADERS) | |
{ | |
try | |
{ | |
final ClassLoader loader = clazz.getClassLoader(); | |
if (loader != null && !CLASS_LOADERS.contains(loader)) | |
{ | |
CLASS_LOADERS.add(loader); | |
CLASS_POOL.appendClassPath(new LoaderClassPath(loader)); | |
} | |
return CLASS_POOL.get(ProxyUtils.getJavaClassName(clazz)); | |
} | |
catch (NotFoundException e) | |
{ | |
throw new ObjectProviderException("Unable to find class " + clazz.getName() | |
+ " in default Javassist class pool.", e); | |
} | |
} | |
} | |
/** | |
* Resolves an array of Java {@link Class}es to an array of their corresponding {@link CtClass}es. | |
* | |
* @param classes | |
* the Java {@link Class}es | |
* @return the corresponding {@link CtClass}es | |
*/ | |
public static CtClass[] resolve(Class<?>[] classes) | |
{ | |
final CtClass[] ctClasses = new CtClass[classes.length]; | |
for (int i = 0; i < ctClasses.length; ++i) | |
{ | |
ctClasses[i] = resolve(classes[i]); | |
} | |
return ctClasses; | |
} | |
private JavassistUtils() | |
{ | |
// Hiding constructor in utility class! | |
} | |
} |