Search in sources :

Example 1 with FinalModifierException

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;
}
Also used : UnableToProxyException(org.apache.aries.proxy.UnableToProxyException) FinalModifierException(org.apache.aries.proxy.FinalModifierException)

Example 2 with FinalModifierException

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");
}
Also used : ArrayList(java.util.ArrayList) FinalModifierException(org.apache.aries.proxy.FinalModifierException) Method(java.lang.reflect.Method)

Example 3 with FinalModifierException

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;
}
Also used : Type(org.objectweb.asm.Type) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) FinalModifierException(org.apache.aries.proxy.FinalModifierException) Method(org.objectweb.asm.commons.Method) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 4 with FinalModifierException

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));
    }
}
Also used : Bundle(org.osgi.framework.Bundle) ArrayList(java.util.ArrayList) FinalModifierException(org.apache.aries.proxy.FinalModifierException) Test(org.junit.Test)

Example 5 with FinalModifierException

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"));
    }
}
Also used : Bundle(org.osgi.framework.Bundle) ArrayList(java.util.ArrayList) FinalModifierException(org.apache.aries.proxy.FinalModifierException) Test(org.junit.Test)

Aggregations

FinalModifierException (org.apache.aries.proxy.FinalModifierException)7 ArrayList (java.util.ArrayList)4 Test (org.junit.Test)3 Bundle (org.osgi.framework.Bundle)3 UnableToProxyException (org.apache.aries.proxy.UnableToProxyException)2 Method (java.lang.reflect.Method)1 MethodVisitor (org.objectweb.asm.MethodVisitor)1 Type (org.objectweb.asm.Type)1 GeneratorAdapter (org.objectweb.asm.commons.GeneratorAdapter)1 Method (org.objectweb.asm.commons.Method)1 BundleWiring (org.osgi.framework.wiring.BundleWiring)1