Search in sources :

Example 1 with UnableToProxyException

use of org.apache.aries.proxy.UnableToProxyException 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 UnableToProxyException

use of org.apache.aries.proxy.UnableToProxyException in project aries by apache.

the class AsmProxyManager method getLowestSubclass.

private Class<?> getLowestSubclass(Set<Class<?>> notInterfaces) throws UnableToProxyException {
    Iterator<Class<?>> it = notInterfaces.iterator();
    Class<?> classToProxy = it.next();
    while (it.hasNext()) {
        Class<?> potential = it.next();
        if (classToProxy.isAssignableFrom(potential)) {
            //potential can be widened to classToProxy, and is therefore
            //a lower subclass
            classToProxy = potential;
        } else if (!!!potential.isAssignableFrom(classToProxy)) {
            //an error, we can't be part of two hierarchies at once!
            throw new UnableToProxyException(classToProxy, "The requested classes " + classToProxy + " and " + potential + " are not in the same type hierarchy");
        }
    }
    return classToProxy;
}
Also used : UnableToProxyException(org.apache.aries.proxy.UnableToProxyException)

Example 3 with UnableToProxyException

use of org.apache.aries.proxy.UnableToProxyException in project aries by apache.

the class OSGiFriendlyClassWriter method getCommonSuperClass.

/**
   * We provide an implementation that doesn't cause class loads to occur. It may
   * not be sufficient because it expects to find the common parent using a single
   * classloader, though in fact the common parent may only be loadable by another
   * bundle from which an intermediate class is loaded
   *
   * precondition: arg0 and arg1 are not equal. (checked before this method is called)
   */
@Override
protected final String getCommonSuperClass(String arg0, String arg1) {
    //If either is Object, then Object must be the answer
    if (arg0.equals(OBJECT_INTERNAL_NAME) || arg1.equals(OBJECT_INTERNAL_NAME)) {
        return OBJECT_INTERNAL_NAME;
    }
    Set<String> names = new HashSet<String>();
    names.add(arg0);
    names.add(arg1);
    //Try loading the class (in ASM not for real)
    try {
        boolean bRunning = true;
        boolean aRunning = true;
        InputStream is;
        String arg00 = arg0;
        String arg11 = arg1;
        String unable = null;
        while (aRunning || bRunning) {
            if (aRunning) {
                is = loader.getResourceAsStream(arg00 + ".class");
                if (is != null) {
                    ClassReader cr = new ClassReader(is);
                    arg00 = cr.getSuperName();
                    if (arg00 == null) {
                        if (names.size() == 2) {
                            //arg0 is an interface
                            return OBJECT_INTERNAL_NAME;
                        }
                        //old arg00 was java.lang.Object
                        aRunning = false;
                    } else if (!!!names.add(arg00)) {
                        return arg00;
                    }
                } else {
                    //The class file isn't visible on this ClassLoader
                    unable = arg0;
                    aRunning = false;
                }
            }
            if (bRunning) {
                is = loader.getResourceAsStream(arg11 + ".class");
                if (is != null) {
                    ClassReader cr = new ClassReader(is);
                    arg11 = cr.getSuperName();
                    if (arg11 == null) {
                        if (names.size() == 3) {
                            //arg1 is an interface
                            return OBJECT_INTERNAL_NAME;
                        }
                        //old arg11 was java.lang.Object
                        bRunning = false;
                    } else if (!!!names.add(arg11)) {
                        return arg11;
                    }
                } else {
                    unable = arg1;
                    bRunning = false;
                }
            }
        }
        String msg = String.format("The class %s and %s do not have a common super class.", arg0, arg1);
        if (unable == null) {
            throw new RuntimeException(msg);
        } else {
            throw new RuntimeException(new UnableToProxyException(unable, msg));
        }
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
Also used : InputStream(java.io.InputStream) ClassReader(org.objectweb.asm.ClassReader) UnableToProxyException(org.apache.aries.proxy.UnableToProxyException) IOException(java.io.IOException) HashSet(java.util.HashSet)

Example 4 with UnableToProxyException

use of org.apache.aries.proxy.UnableToProxyException in project aries by apache.

the class AbstractWovenProxyAdapter method visit.

public final void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
    LOGGER.debug(Constants.LOG_ENTRY, "visit", new Object[] { version, access, name, signature, superName, interfaces });
    // always update to the most recent version of the JVM
    version = JAVA_CLASS_VERSION;
    superType = Type.getType("L" + superName + ";");
    try {
        // we only want to implement WovenProxy once in the hierarchy.
        // It's best to do this as high up as possible so we check the
        // super. By loading it we may end up weaving it, but that's a good thing!
        Class<?> superClass = Class.forName(superName.replace('/', '.'), false, loader);
        isSerializable = Serializable.class.isAssignableFrom(superClass) || Arrays.asList(interfaces).contains(Type.getInternalName(Serializable.class)) || checkInterfacesForSerializability(interfaces);
        if (!!!WovenProxy.class.isAssignableFrom(superClass)) {
            // We have found a type we need to add WovenProxy information to
            implementWovenProxy = true;
            if (superClass != Object.class) {
                //If our superclass isn't Object, it means we didn't weave all the way
                //to the top of the hierarchy. This means we need to override all the
                //methods defined on our parent so that they can be intercepted!
                nonObjectSupers.add(superClass);
                Class<?> nextSuper = superClass.getSuperclass();
                while (nextSuper != Object.class) {
                    nonObjectSupers.add(nextSuper);
                    nextSuper = nextSuper.getSuperclass();
                }
                //Don't use reflection - it can be dangerous
                superHasNoArgsConstructor = superHasNoArgsConstructor(superName, name);
            } else {
                superHasNoArgsConstructor = true;
            }
            // re-work the interfaces list to include WovenProxy
            String[] interfacesPlusWovenProxy = new String[interfaces.length + 1];
            System.arraycopy(interfaces, 0, interfacesPlusWovenProxy, 0, interfaces.length);
            interfacesPlusWovenProxy[interfaces.length] = WOVEN_PROXY_IFACE_TYPE.getInternalName();
            // Write the class header including WovenProxy.
            cv.visit(version, access, name, signature, superName, interfacesPlusWovenProxy);
        } else {
            // Already has a woven proxy parent, but we still need to write the
            // header!
            cv.visit(version, access, name, signature, superName, interfaces);
        }
    } catch (ClassNotFoundException e) {
        // If this happens we're about to hit bigger trouble on verify, so we
        // should stop weaving and fail. Make sure we don't cause the hook to
        // throw an error though.
        UnableToProxyException u = new UnableToProxyException(name, e);
        cannotLoadSuperClassException(superName, u);
    }
}
Also used : Serializable(java.io.Serializable) WovenProxy(org.apache.aries.proxy.weaving.WovenProxy) UnableToProxyException(org.apache.aries.proxy.UnableToProxyException)

Example 5 with UnableToProxyException

use of org.apache.aries.proxy.UnableToProxyException in project aries by apache.

the class ProxyWeavingHook method weave.

public final void weave(WovenClass wovenClass) {
    BundleWiring bw = wovenClass.getBundleWiring();
    if (bw != null) {
        Bundle b = bw.getBundle();
        if (b.getBundleId() == 0 || b.getSymbolicName().startsWith("org.apache.aries.proxy") || b.getSymbolicName().startsWith("org.apache.aries.util")) {
            return;
        }
    }
    if (!isEnabled(wovenClass.getClassName()) || isDisabled(wovenClass.getClassName())) {
        return;
    }
    if (shouldWeave(wovenClass)) {
        byte[] bytes = null;
        try {
            bytes = WovenProxyGenerator.getWovenProxy(wovenClass.getBytes(), wovenClass.getBundleWiring().getClassLoader());
        } catch (Exception e) {
            if (e instanceof RuntimeException && e.getCause() instanceof UnableToProxyException) {
                //This is a weaving failure that should be logged, but the class
                //can still be loaded
                LOGGER.trace(String.format("The class %s cannot be woven, it may not be possible for the runtime to proxy this class.", wovenClass.getClassName()), e);
            } else {
                throw weavingException(wovenClass, e);
            }
        }
        if (bytes != null && bytes.length != 0) {
            wovenClass.setBytes(bytes);
            List<String> imports = wovenClass.getDynamicImports();
            imports.add(IMPORT_A);
            imports.add(IMPORT_B);
        }
    }
}
Also used : Bundle(org.osgi.framework.Bundle) BundleWiring(org.osgi.framework.wiring.BundleWiring) UnableToProxyException(org.apache.aries.proxy.UnableToProxyException) WeavingException(org.osgi.framework.hooks.weaving.WeavingException) UnableToProxyException(org.apache.aries.proxy.UnableToProxyException)

Aggregations

UnableToProxyException (org.apache.aries.proxy.UnableToProxyException)12 IOException (java.io.IOException)3 InputStream (java.io.InputStream)2 FinalModifierException (org.apache.aries.proxy.FinalModifierException)2 ClassReader (org.objectweb.asm.ClassReader)2 Bundle (org.osgi.framework.Bundle)2 BundleWiring (org.osgi.framework.wiring.BundleWiring)2 Serializable (java.io.Serializable)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 LinkedHashSet (java.util.LinkedHashSet)1 Lock (java.util.concurrent.locks.Lock)1 ReadWriteLock (java.util.concurrent.locks.ReadWriteLock)1 ReentrantReadWriteLock (java.util.concurrent.locks.ReentrantReadWriteLock)1 ProxyManager (org.apache.aries.proxy.ProxyManager)1 WovenProxy (org.apache.aries.proxy.weaving.WovenProxy)1 Label (org.objectweb.asm.Label)1 GeneratorAdapter (org.objectweb.asm.commons.GeneratorAdapter)1 Method (org.objectweb.asm.commons.Method)1 WeavingException (org.osgi.framework.hooks.weaving.WeavingException)1