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;
}
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;
}
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);
}
}
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);
}
}
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);
}
}
}
Aggregations