blob: a0bd2b259e1b9943fbaf23903f4b21c2f972c973 [file] [log] [blame]
/*
* 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!
}
}