use of org.apache.aries.proxy.FinalModifierException in project aries by apache.
the class ProxySubclassGenerator method getProxySubclass.
public static Class<?> getProxySubclass(Class<?> aClass, ClassLoader loader) throws UnableToProxyException {
LOGGER.debug(Constants.LOG_ENTRY, "getProxySubclass", new Object[] { aClass });
// this is for subclassing java.* or javax.* packages, so that one will do
if (loader == null)
loader = defaultClassLoader;
ConcurrentMap<String, String> proxyMap;
synchronized (loader) {
proxyMap = proxyClassesByClassLoader.get(loader);
if (proxyMap == null) {
proxyMap = new ConcurrentHashMap<String, String>();
proxyClassesByClassLoader.put(loader, proxyMap);
}
}
// check the map to see if we have already generated a subclass for this
// class
// if we have return the mapped class object
// if we haven't generate the subclass and return it
Class<?> classToReturn = null;
synchronized (aClass) {
String key = aClass.getName();
String className = proxyMap.get(key);
if (className != null) {
LOGGER.debug("Found proxy subclass with key {} and name {}.", key, className);
if (className.charAt(0) == FINAL_MODIFIER) {
String[] exceptionParts = className.substring(1).split(":");
if (exceptionParts.length == 1) {
throw new FinalModifierException(aClass);
} else {
throw new FinalModifierException(aClass, exceptionParts[1]);
}
} else if (className.charAt(0) == UNABLE_TO_PROXY) {
throw new UnableToProxyException(aClass);
}
try {
classToReturn = loader.loadClass(className);
} catch (ClassNotFoundException cnfe) {
LOGGER.debug(Constants.LOG_EXCEPTION, cnfe);
throw new UnableToLoadProxyException(className, cnfe);
}
} else {
LOGGER.debug("Need to generate subclass. Using key {}.", key);
try {
scanForFinalModifiers(aClass);
classToReturn = generateAndLoadSubclass(aClass, loader);
if (classToReturn != null) {
proxyMap.put(key, classToReturn.getName());
} else {
proxyMap.put(key, UNABLE_TO_PROXY + aClass.getName());
throw new UnableToProxyException(aClass);
}
} catch (FinalModifierException e) {
if (e.isFinalClass()) {
proxyMap.put(key, FINAL_MODIFIER + e.getClassName());
throw e;
} else {
proxyMap.put(key, FINAL_MODIFIER + e.getClassName() + ':' + e.getFinalMethods());
throw e;
}
}
}
}
LOGGER.debug(Constants.LOG_EXIT, "getProxySubclass", classToReturn);
return classToReturn;
}
use of org.apache.aries.proxy.FinalModifierException in project aries by apache.
the class ProxySubclassGenerator method scanForFinalModifiers.
private static void scanForFinalModifiers(Class<?> clazz) throws FinalModifierException {
LOGGER.debug(Constants.LOG_ENTRY, "scanForFinalModifiers", new Object[] { clazz });
if (isFinal(clazz.getModifiers())) {
throw new FinalModifierException(clazz);
}
List<String> finalMethods = new ArrayList<String>();
// java.lang.Object first)
while (!clazz.getName().startsWith("java.") && !clazz.getName().startsWith("javax.")) {
for (Method m : clazz.getDeclaredMethods()) {
// Static finals are ok, because we won't be overriding them :)
if (isFinal(m.getModifiers()) && !Modifier.isStatic(m.getModifiers())) {
finalMethods.add(m.toGenericString());
}
}
clazz = clazz.getSuperclass();
}
if (!finalMethods.isEmpty()) {
String methodList = finalMethods.toString();
methodList = methodList.substring(1, methodList.length() - 1);
throw new FinalModifierException(clazz, methodList);
}
LOGGER.debug(Constants.LOG_EXIT, "scanForFinalModifiers");
}
use of org.apache.aries.proxy.FinalModifierException in project aries by apache.
the class MethodCopyingClassAdapter method visitMethod.
@Override
public final MethodVisitor visitMethod(final int access, String name, String desc, String sig, String[] exceptions) {
MethodVisitor mv = null;
// abstract ones!.
if (!!!name.equals("<init>") && !!!name.equals("<clinit>") && (access & (ACC_STATIC | ACC_PRIVATE | ACC_SYNTHETIC | ACC_ABSTRACT | ACC_NATIVE | ACC_BRIDGE)) == 0) {
// identify the target method parameters and return type
Method currentTransformMethod = new Method(name, desc);
// We don't want to duplicate a method we already overrode!
if (!!!knownMethods.add(currentTransformMethod))
return null;
// We can't override a final method
if ((access & ACC_FINAL) != 0)
throw new RuntimeException(new FinalModifierException(superToCopy, name));
// package
if ((access & (ACC_PUBLIC | ACC_PROTECTED | ACC_PRIVATE)) == 0) {
if (!!!samePackage) {
methodHiddenException(name);
}
}
// Safe to copy a call to this method!
Type superType = Type.getType(superToCopy);
// identify the target method parameters and return type
String methodStaticFieldName = "methodField" + AbstractWovenProxyAdapter.getSanitizedUUIDString();
transformedMethods.put(methodStaticFieldName, new TypeMethod(superType, currentTransformMethod));
// Remember we need to copy the fake method *and* weave it, use a
// WovenProxyMethodAdapter as well as a CopyingMethodAdapter
MethodVisitor weaver = wovenProxyAdapter.getWeavingMethodVisitor(access, name, desc, sig, exceptions, currentTransformMethod, methodStaticFieldName, superType, false);
if (weaver instanceof AbstractWovenProxyMethodAdapter) {
// gets around the problem, but if not the class will fail verification.
if (!samePackage && (access & ACC_PROTECTED) != 0) {
methodHiddenException(name);
}
mv = new CopyingMethodAdapter((GeneratorAdapter) weaver, superType, currentTransformMethod);
} else {
// For whatever reason we aren't weaving this method. The call to super.xxx() will always work
mv = new CopyingMethodAdapter(new GeneratorAdapter(access, currentTransformMethod, mv), superType, currentTransformMethod);
}
}
return mv;
}
use of org.apache.aries.proxy.FinalModifierException in project aries by apache.
the class BasicProxyTest method checkProxyFinalClass.
/**
* This test does two things. First of all it checks that we throw a FinalModifierException if we
* try to proxy a final class. It also validates that the message and toString in the exception
* works as expected.
*/
@Test
public void checkProxyFinalClass() throws UnableToProxyException {
Bundle b = bundleContext.getBundle();
Callable<Object> c = new TestCallable();
Collection<Class<?>> classes = new ArrayList<Class<?>>();
classes.add(TestCallable.class);
try {
mgr.createDelegatingProxy(b, classes, c, null);
} catch (FinalModifierException e) {
String msg = e.getMessage();
assertEquals("The message didn't look right", "The class " + TestCallable.class.getName() + " is final.", msg);
assertTrue("The message didn't appear in the toString", e.toString().endsWith(msg));
}
}
use of org.apache.aries.proxy.FinalModifierException in project aries by apache.
the class BasicProxyTest method checkProxyFinalMethods.
/**
* This method checks that we correctly fail to proxy a class with final methods.
* It also does a quick validation on the exception message.
*/
@Test
public void checkProxyFinalMethods() throws UnableToProxyException {
Bundle b = bundleContext.getBundle();
Callable<Object> c = new TestCallable();
Collection<Class<?>> classes = new ArrayList<Class<?>>();
Runnable r = new Runnable() {
public final void run() {
}
};
classes.add(r.getClass());
try {
mgr.createDelegatingProxy(b, classes, c, null);
} catch (FinalModifierException e) {
assertTrue("The methods didn't appear in the message", e.getMessage().contains("run"));
}
}
Aggregations