|
|
|
@ -1,5 +1,5 @@ |
|
|
|
|
/* |
|
|
|
|
* Copyright 2002-2012 the original author or authors. |
|
|
|
|
* Copyright 2002-2013 the original author or authors. |
|
|
|
|
* |
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
@ -13,6 +13,7 @@ |
|
|
|
|
* See the License for the specific language governing permissions and |
|
|
|
|
* limitations under the License. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
package org.springframework.instrument.classloading.jboss; |
|
|
|
|
|
|
|
|
|
import java.lang.instrument.ClassFileTransformer; |
|
|
|
@ -20,46 +21,39 @@ import java.lang.reflect.InvocationHandler; |
|
|
|
|
import java.lang.reflect.Method; |
|
|
|
|
import java.lang.reflect.Proxy; |
|
|
|
|
|
|
|
|
|
import org.springframework.util.Assert; |
|
|
|
|
import org.springframework.util.ReflectionUtils; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Reflective wrapper around a JBoss 5 and 6 class loader methods (discovered and called |
|
|
|
|
* through reflection) for load time weaving. |
|
|
|
|
* Reflective wrapper around a JBoss 6 class loader methods |
|
|
|
|
* (discovered and called through reflection) for load-time weaving. |
|
|
|
|
* |
|
|
|
|
* @author Costin Leau |
|
|
|
|
* @author Juergen Hoeller |
|
|
|
|
* @since 3.1 |
|
|
|
|
*/ |
|
|
|
|
class JBossMCAdapter implements JBossClassLoaderAdapter { |
|
|
|
|
|
|
|
|
|
private static final String TRANSLATOR_NAME = "org.jboss.util.loading.Translator"; |
|
|
|
|
private static final String POLICY_NAME = "org.jboss.classloader.spi.base.BaseClassLoaderPolicy"; |
|
|
|
|
private static final String DOMAIN_NAME = "org.jboss.classloader.spi.base.BaseClassLoaderDomain"; |
|
|
|
|
private static final String DEDICATED_SYSTEM = "org.jboss.classloader.spi.ClassLoaderSystem"; |
|
|
|
|
private static final String LOADER_NAME = "org.jboss.classloader.spi.base.BaseClassLoader"; |
|
|
|
|
private static final String GET_POLICY = "getPolicy"; |
|
|
|
|
private static final String GET_DOMAIN = "getClassLoaderDomain"; |
|
|
|
|
private static final String GET_SYSTEM = "getClassLoaderSystem"; |
|
|
|
|
|
|
|
|
|
// available since JBoss AS 5.1.0 / MC 2.0.6 (allows multiple transformers to be added)
|
|
|
|
|
private static final String ADD_TRANSLATOR_NAME = "addTranslator"; |
|
|
|
|
// available since JBoss AS 5.0.0 / MC 2.0.1 (allows only one transformer to be added)
|
|
|
|
|
private static final String SET_TRANSLATOR_NAME = "setTranslator"; |
|
|
|
|
private static final String TRANSLATOR_NAME = "org.jboss.util.loading.Translator"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final ClassLoader classLoader; |
|
|
|
|
|
|
|
|
|
private final Object target; |
|
|
|
|
|
|
|
|
|
private final Class<?> translatorClass; |
|
|
|
|
|
|
|
|
|
private final Method addTranslator; |
|
|
|
|
private final Object target; |
|
|
|
|
|
|
|
|
|
JBossMCAdapter(ClassLoader classLoader) { |
|
|
|
|
Class<?> clazzLoaderType = null; |
|
|
|
|
|
|
|
|
|
public JBossMCAdapter(ClassLoader classLoader) { |
|
|
|
|
try { |
|
|
|
|
// resolve BaseClassLoader.class
|
|
|
|
|
clazzLoaderType = classLoader.loadClass(LOADER_NAME); |
|
|
|
|
// Resolve BaseClassLoader.class
|
|
|
|
|
Class<?> clazzLoaderType = classLoader.loadClass(LOADER_NAME); |
|
|
|
|
|
|
|
|
|
ClassLoader clazzLoader = null; |
|
|
|
|
// walk the hierarchy to detect the instrumentation aware classloader
|
|
|
|
|
// Walk the hierarchy to detect the instrumentation aware ClassLoader
|
|
|
|
|
for (ClassLoader cl = classLoader; cl != null && clazzLoader == null; cl = cl.getParent()) { |
|
|
|
|
if (clazzLoaderType.isInstance(cl)) { |
|
|
|
|
clazzLoader = cl; |
|
|
|
@ -67,63 +61,26 @@ class JBossMCAdapter implements JBossClassLoaderAdapter { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (clazzLoader == null) { |
|
|
|
|
throw new IllegalArgumentException(classLoader + " and its parents are not suitable ClassLoaders: " |
|
|
|
|
+ "A [" + LOADER_NAME + "] implementation is required."); |
|
|
|
|
throw new IllegalArgumentException(classLoader + " and its parents are not suitable ClassLoaders: " + |
|
|
|
|
"A [" + LOADER_NAME + "] implementation is required."); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this.classLoader = clazzLoader; |
|
|
|
|
// use the classloader that loaded the classloader to load
|
|
|
|
|
// the types for reflection purposes
|
|
|
|
|
// Use the ClassLoader that loaded the ClassLoader to load the types for reflection purposes
|
|
|
|
|
classLoader = clazzLoader.getClass().getClassLoader(); |
|
|
|
|
|
|
|
|
|
// BaseClassLoader#getPolicy
|
|
|
|
|
Method method = clazzLoaderType.getDeclaredMethod(GET_POLICY); |
|
|
|
|
Method method = clazzLoaderType.getDeclaredMethod("getPolicy"); |
|
|
|
|
ReflectionUtils.makeAccessible(method); |
|
|
|
|
Object policy = method.invoke(this.classLoader); |
|
|
|
|
this.target = method.invoke(this.classLoader); |
|
|
|
|
|
|
|
|
|
Object addTarget = null; |
|
|
|
|
Method addMethod = null; |
|
|
|
|
|
|
|
|
|
// try the 5.1.x hooks
|
|
|
|
|
// check existence of BaseClassLoaderPolicy#addTranslator(Translator)
|
|
|
|
|
// Check existence of BaseClassLoaderPolicy#addTranslator(Translator)
|
|
|
|
|
this.translatorClass = classLoader.loadClass(TRANSLATOR_NAME); |
|
|
|
|
Class<?> clazz = classLoader.loadClass(POLICY_NAME); |
|
|
|
|
try { |
|
|
|
|
addMethod = clazz.getDeclaredMethod(ADD_TRANSLATOR_NAME, translatorClass); |
|
|
|
|
addTarget = policy; |
|
|
|
|
} catch (NoSuchMethodException ex) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// fall back to 5.0.x method
|
|
|
|
|
if (addMethod == null) { |
|
|
|
|
|
|
|
|
|
// BaseClassLoaderPolicy#getClassLoaderDomain
|
|
|
|
|
method = clazz.getDeclaredMethod(GET_DOMAIN); |
|
|
|
|
ReflectionUtils.makeAccessible(method); |
|
|
|
|
Object domain = method.invoke(policy); |
|
|
|
|
|
|
|
|
|
// BaseClassLoaderDomain#getClassLoaderSystem
|
|
|
|
|
clazz = classLoader.loadClass(DOMAIN_NAME); |
|
|
|
|
method = clazz.getDeclaredMethod(GET_SYSTEM); |
|
|
|
|
ReflectionUtils.makeAccessible(method); |
|
|
|
|
Object system = method.invoke(domain); |
|
|
|
|
|
|
|
|
|
// resolve ClassLoaderSystem
|
|
|
|
|
clazz = classLoader.loadClass(DEDICATED_SYSTEM); |
|
|
|
|
Assert.isInstanceOf(clazz, system, "JBoss LoadTimeWeaver requires JBoss loader system of type " |
|
|
|
|
+ clazz.getName() + " on JBoss 5.0.x"); |
|
|
|
|
|
|
|
|
|
// ClassLoaderSystem#setTranslator
|
|
|
|
|
addMethod = clazz.getDeclaredMethod(SET_TRANSLATOR_NAME, translatorClass); |
|
|
|
|
addTarget = system; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this.addTranslator = addMethod; |
|
|
|
|
this.target = addTarget; |
|
|
|
|
|
|
|
|
|
} catch (Exception ex) { |
|
|
|
|
this.addTranslator = this.target.getClass().getMethod("addTranslator", this.translatorClass); |
|
|
|
|
} |
|
|
|
|
catch (Exception ex) { |
|
|
|
|
throw new IllegalStateException( |
|
|
|
|
"Could not initialize JBoss LoadTimeWeaver because the JBoss 5 API classes are not available", ex); |
|
|
|
|
"Could not initialize JBoss LoadTimeWeaver because the JBoss 6 API classes are not available", ex); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -131,17 +88,18 @@ class JBossMCAdapter implements JBossClassLoaderAdapter { |
|
|
|
|
public void addTransformer(ClassFileTransformer transformer) { |
|
|
|
|
InvocationHandler adapter = new JBossMCTranslatorAdapter(transformer); |
|
|
|
|
Object adapterInstance = Proxy.newProxyInstance(this.translatorClass.getClassLoader(), |
|
|
|
|
new Class<?>[] { this.translatorClass }, adapter); |
|
|
|
|
|
|
|
|
|
new Class<?>[] {this.translatorClass}, adapter); |
|
|
|
|
try { |
|
|
|
|
addTranslator.invoke(target, adapterInstance); |
|
|
|
|
} catch (Exception ex) { |
|
|
|
|
throw new IllegalStateException("Could not add transformer on JBoss 5/6 classloader " + classLoader, ex); |
|
|
|
|
this.addTranslator.invoke(this.target, adapterInstance); |
|
|
|
|
} |
|
|
|
|
catch (Exception ex) { |
|
|
|
|
throw new IllegalStateException("Could not add transformer on JBoss 6 ClassLoader " + this.classLoader, ex); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public ClassLoader getInstrumentableClassLoader() { |
|
|
|
|
return classLoader; |
|
|
|
|
return this.classLoader; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|