Browse Source
+ redone the JBossLTW (no dependency on the JBoss API) - removed JBoss jars - removed JBoss imports (Spring code doesn't rely on it) git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@2364 50f2f4bb-b051-0410-bef5-90022cba6387pull/1/head
11 changed files with 227 additions and 466 deletions
@ -1,50 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
package org.springframework.instrument.classloading.jboss; |
|
||||||
|
|
||||||
import java.security.ProtectionDomain; |
|
||||||
import java.lang.instrument.ClassFileTransformer; |
|
||||||
|
|
||||||
import org.jboss.util.loading.Translator; |
|
||||||
|
|
||||||
/** |
|
||||||
* ClassFileTransfomer to Translator bridge. |
|
||||||
* |
|
||||||
* @author Ales Justin |
|
||||||
*/ |
|
||||||
public class ClassFileTransformer2Translator implements Translator { |
|
||||||
|
|
||||||
private ClassFileTransformer transformer; |
|
||||||
|
|
||||||
public ClassFileTransformer2Translator(ClassFileTransformer transformer) { |
|
||||||
if (transformer == null) { |
|
||||||
throw new IllegalArgumentException("Null transformer"); |
|
||||||
} |
|
||||||
|
|
||||||
this.transformer = transformer; |
|
||||||
} |
|
||||||
|
|
||||||
public byte[] transform(ClassLoader loader, |
|
||||||
String className, |
|
||||||
Class<?> classBeingRedefined, |
|
||||||
ProtectionDomain protectionDomain, |
|
||||||
byte[] classfileBuffer) throws Exception { |
|
||||||
return transformer.transform(loader, className, classBeingRedefined, protectionDomain, classfileBuffer); |
|
||||||
} |
|
||||||
|
|
||||||
public void unregisterClassLoader(ClassLoader loader) { |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,78 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
package org.springframework.instrument.classloading.jboss; |
|
||||||
|
|
||||||
import java.lang.reflect.Method; |
|
||||||
|
|
||||||
import org.jboss.classloader.spi.ClassLoaderSystem; |
|
||||||
import org.jboss.classloader.spi.base.BaseClassLoader; |
|
||||||
import org.jboss.classloader.spi.base.BaseClassLoaderDomain; |
|
||||||
import org.jboss.classloader.spi.base.BaseClassLoaderPolicy; |
|
||||||
import org.jboss.classloader.spi.base.BaseClassLoaderSystem; |
|
||||||
import org.jboss.util.loading.Translator; |
|
||||||
|
|
||||||
/** |
|
||||||
* Reflective wrapper around a JBoss_5.0.x class loader. Used to encapsulate the classloader-specific methods |
|
||||||
* (discovered and called through reflection) from the load-time weaver. |
|
||||||
* |
|
||||||
* @author Ales Justin |
|
||||||
*/ |
|
||||||
public class JBoss50ClassLoader extends JBoss5ClassLoader { |
|
||||||
|
|
||||||
private Method addTranslator; |
|
||||||
|
|
||||||
private ClassLoaderSystem system; |
|
||||||
|
|
||||||
public JBoss50ClassLoader(BaseClassLoader classLoader) { |
|
||||||
super(classLoader); |
|
||||||
} |
|
||||||
|
|
||||||
protected void fallbackStrategy() throws Exception { |
|
||||||
try { |
|
||||||
// let's check if we have a patched policy, with translator per policy
|
|
||||||
addTranslator = getMethod(BaseClassLoaderPolicy.class, "addTranslator"); |
|
||||||
} |
|
||||||
catch (Exception ignored) { |
|
||||||
//log.info("Policy doesn't have addTranslator, falling back to ClassLoaderSystem.");
|
|
||||||
|
|
||||||
Method getClassLoaderDomain = getMethod(BaseClassLoaderPolicy.class, "getClassLoaderDomain"); |
|
||||||
BaseClassLoaderDomain domain = invokeMethod(getClassLoaderDomain, getPolicy(), BaseClassLoaderDomain.class); |
|
||||||
Method getClassLoaderSystem = getMethod(BaseClassLoaderDomain.class, "getClassLoaderSystem"); |
|
||||||
BaseClassLoaderSystem system = invokeMethod(getClassLoaderSystem, domain, BaseClassLoaderSystem.class); |
|
||||||
if (system instanceof ClassLoaderSystem) { |
|
||||||
this.system = ClassLoaderSystem.class.cast(system); |
|
||||||
} |
|
||||||
else { |
|
||||||
throw new IllegalArgumentException( |
|
||||||
"ClassLoaderSystem must be instance of [" + ClassLoaderSystem.class.getName() + "]"); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected void addTranslator(Translator translator) { |
|
||||||
if (addTranslator != null) { |
|
||||||
try { |
|
||||||
addTranslator.invoke(translator); |
|
||||||
} |
|
||||||
catch (Exception e) { |
|
||||||
throw new IllegalArgumentException(e); |
|
||||||
} |
|
||||||
} |
|
||||||
else { |
|
||||||
system.setTranslator(translator); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,37 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
package org.springframework.instrument.classloading.jboss; |
|
||||||
|
|
||||||
import org.jboss.classloader.spi.base.BaseClassLoader; |
|
||||||
import org.jboss.util.loading.Translator; |
|
||||||
|
|
||||||
/** |
|
||||||
* Reflective wrapper around a JBoss_5.1.x class loader. Used to encapsulate the classloader-specific methods |
|
||||||
* (discovered and called through reflection) from the load-time weaver. |
|
||||||
* |
|
||||||
* @author <a href="mailto:ales.justin@jboss.org">Ales Justin</a> |
|
||||||
*/ |
|
||||||
public class JBoss51ClassLoader extends JBoss5ClassLoader { |
|
||||||
|
|
||||||
public JBoss51ClassLoader(BaseClassLoader classLoader) { |
|
||||||
super(classLoader); |
|
||||||
} |
|
||||||
|
|
||||||
protected void addTranslator(Translator translator) { |
|
||||||
|
|
||||||
getPolicy().addTranslator(translator); |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,120 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* 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; |
|
||||||
import java.lang.reflect.Method; |
|
||||||
import java.security.AccessController; |
|
||||||
import java.security.PrivilegedExceptionAction; |
|
||||||
|
|
||||||
import org.jboss.classloader.spi.ClassLoaderPolicy; |
|
||||||
import org.jboss.classloader.spi.base.BaseClassLoader; |
|
||||||
import org.jboss.util.loading.Translator; |
|
||||||
|
|
||||||
import org.springframework.util.Assert; |
|
||||||
import org.springframework.instrument.classloading.SimpleThrowawayClassLoader; |
|
||||||
|
|
||||||
/** |
|
||||||
* Reflective wrapper around a JBoss5 class loader. Used to encapsulate the classloader-specific methods (discovered and |
|
||||||
* called through reflection) from the load-time weaver. |
|
||||||
* |
|
||||||
* @author Ales Justin |
|
||||||
* @author Marius Bogoevici |
|
||||||
*/ |
|
||||||
public abstract class JBoss5ClassLoader extends ReflectionHelper { |
|
||||||
|
|
||||||
private final BaseClassLoader classLoader; |
|
||||||
|
|
||||||
private ClassLoaderPolicy policy; |
|
||||||
|
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
protected JBoss5ClassLoader(BaseClassLoader classLoader) { |
|
||||||
Assert.notNull(classLoader, "ClassLoader must not be null"); |
|
||||||
this.classLoader = classLoader; |
|
||||||
|
|
||||||
try { |
|
||||||
SecurityManager sm = System.getSecurityManager(); |
|
||||||
if (sm != null) { |
|
||||||
AccessController.doPrivileged(new InstantiationAction()); |
|
||||||
} |
|
||||||
else { |
|
||||||
doInstantiate(); |
|
||||||
} |
|
||||||
} |
|
||||||
catch (Exception e) { |
|
||||||
throw new IllegalStateException( |
|
||||||
"Could not initialize JBoss ClassLoader because JBoss5 API classes are not available", e); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get the policy. |
|
||||||
* |
|
||||||
* @return the policy |
|
||||||
*/ |
|
||||||
protected ClassLoaderPolicy getPolicy() { |
|
||||||
return policy; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Do instantiate method, variables. |
|
||||||
* |
|
||||||
* @throws Exception for any error |
|
||||||
*/ |
|
||||||
private void doInstantiate() throws Exception { |
|
||||||
Method getPolicy = getMethod(BaseClassLoader.class, "getPolicy"); |
|
||||||
policy = invokeMethod(getPolicy, classLoader, ClassLoaderPolicy.class); |
|
||||||
fallbackStrategy(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* The fallback strategy. |
|
||||||
* |
|
||||||
* @throws Exception for any error |
|
||||||
*/ |
|
||||||
protected void fallbackStrategy() throws Exception { |
|
||||||
} |
|
||||||
|
|
||||||
public void addTransformer(ClassFileTransformer transformer) { |
|
||||||
Assert.notNull(transformer, "ClassFileTransformer must not be null"); |
|
||||||
Translator translator = new ClassFileTransformer2Translator(transformer); |
|
||||||
addTranslator(translator); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Add the translator. |
|
||||||
* |
|
||||||
* @param translator the translator |
|
||||||
*/ |
|
||||||
protected abstract void addTranslator(Translator translator); |
|
||||||
|
|
||||||
public ClassLoader getInternalClassLoader() { |
|
||||||
return classLoader; |
|
||||||
} |
|
||||||
|
|
||||||
public ClassLoader getThrowawayClassLoader() { |
|
||||||
return new SimpleThrowawayClassLoader(classLoader); |
|
||||||
} |
|
||||||
|
|
||||||
/** Instantiation action. */ |
|
||||||
private class InstantiationAction implements PrivilegedExceptionAction { |
|
||||||
|
|
||||||
public Object run() throws Exception { |
|
||||||
doInstantiate(); |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,120 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* 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; |
|
||||||
import java.lang.reflect.Method; |
|
||||||
|
|
||||||
import org.jboss.classloader.spi.base.BaseClassLoader; |
|
||||||
|
|
||||||
import org.springframework.instrument.classloading.LoadTimeWeaver; |
|
||||||
import org.springframework.util.Assert; |
|
||||||
import org.springframework.util.ClassUtils; |
|
||||||
|
|
||||||
/** |
|
||||||
* {@link LoadTimeWeaver} implementation for JBoss5's instrumentable ClassLoader. |
|
||||||
* |
|
||||||
* @author Ales Justin |
|
||||||
*/ |
|
||||||
public class JBoss5LoadTimeWeaver extends ReflectionHelper implements LoadTimeWeaver { |
|
||||||
|
|
||||||
private JBoss5ClassLoader classLoader; |
|
||||||
|
|
||||||
public JBoss5LoadTimeWeaver() { |
|
||||||
this(ClassUtils.getDefaultClassLoader()); |
|
||||||
} |
|
||||||
|
|
||||||
public JBoss5LoadTimeWeaver(ClassLoader classLoader) { |
|
||||||
Assert.notNull(classLoader, "ClassLoader must not be null"); |
|
||||||
BaseClassLoader bcl = determineClassLoader(classLoader); |
|
||||||
if (bcl == null) { |
|
||||||
throw new IllegalArgumentException( |
|
||||||
classLoader + " and its parents are not suitable ClassLoaders: " + "An [" + |
|
||||||
BaseClassLoader.class.getName() + "] implementation is required."); |
|
||||||
} |
|
||||||
this.classLoader = createClassLoaderWrapper(bcl); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Create a JBoss5 classloader wrapper based on the underlying JBossAS version. |
|
||||||
* |
|
||||||
* @param bcl the base classloader |
|
||||||
* @return new JBoss5 classloader wrapper |
|
||||||
*/ |
|
||||||
protected JBoss5ClassLoader createClassLoaderWrapper(BaseClassLoader bcl) { |
|
||||||
int versionNumber = 0; |
|
||||||
String tag; |
|
||||||
|
|
||||||
try { |
|
||||||
// BCL should see Version class
|
|
||||||
Class<?> versionClass = bcl.loadClass("org.jboss.Version"); |
|
||||||
Method getInstance = getMethod(versionClass, "getInstance"); |
|
||||||
Object version = getInstance.invoke(null); // static method
|
|
||||||
|
|
||||||
Method getMajor = getMethod(versionClass, "getMajor"); |
|
||||||
versionNumber += 100 * invokeMethod(getMajor, version, Integer.class); |
|
||||||
Method getMinor = getMethod(versionClass, "getMinor"); |
|
||||||
versionNumber += 10 * invokeMethod(getMinor, version, Integer.class); |
|
||||||
Method getRevision = getMethod(versionClass, "getRevision"); |
|
||||||
versionNumber += invokeMethod(getRevision, version, Integer.class); |
|
||||||
Method getTag = getMethod(versionClass, "getTag"); |
|
||||||
tag = invokeMethod(getTag, version, String.class); |
|
||||||
} |
|
||||||
catch (Exception e) { |
|
||||||
//log.warn("Exception creating JBoss5 CL wrapper: " + e + ", falling back to JBoss50ClassLoader wrapper.");
|
|
||||||
return new JBoss50ClassLoader(bcl); |
|
||||||
} |
|
||||||
|
|
||||||
if (versionNumber < 500) // this only works on new MC code
|
|
||||||
{ |
|
||||||
throw new IllegalArgumentException( |
|
||||||
"JBoss5LoadTimeWeaver can only be used on new JBoss Microcontainer ClassLoader."); |
|
||||||
} |
|
||||||
else if (versionNumber <= 501 || (versionNumber == 510 && "Beta1".equals(tag))) { |
|
||||||
return new JBoss50ClassLoader(bcl); |
|
||||||
} |
|
||||||
else { |
|
||||||
return new JBoss51ClassLoader(bcl); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Find first BaseClassLoader implementation. |
|
||||||
* |
|
||||||
* @param classLoader the classloader |
|
||||||
* @return BaseClassLoader instance or null if not found |
|
||||||
*/ |
|
||||||
private BaseClassLoader determineClassLoader(ClassLoader classLoader) { |
|
||||||
for (ClassLoader cl = classLoader; cl != null; cl = cl.getParent()) { |
|
||||||
if (cl instanceof BaseClassLoader) { |
|
||||||
return (BaseClassLoader) cl; |
|
||||||
} |
|
||||||
} |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
public void addTransformer(ClassFileTransformer transformer) { |
|
||||||
classLoader.addTransformer(transformer); |
|
||||||
} |
|
||||||
|
|
||||||
public ClassLoader getInstrumentableClassLoader() { |
|
||||||
return classLoader.getInternalClassLoader(); |
|
||||||
} |
|
||||||
|
|
||||||
public ClassLoader getThrowawayClassLoader() { |
|
||||||
return classLoader.getThrowawayClassLoader(); |
|
||||||
} |
|
||||||
} |
|
||||||
@ -0,0 +1,148 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2006-2009 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. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* 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; |
||||||
|
import java.lang.reflect.Constructor; |
||||||
|
import java.lang.reflect.Method; |
||||||
|
|
||||||
|
import org.springframework.util.Assert; |
||||||
|
import org.springframework.util.ReflectionUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* Reflective wrapper around a JBoss 5 class loader methods (discovered and called |
||||||
|
* through reflection) for load time weaving. |
||||||
|
* |
||||||
|
* @author Costin Leau |
||||||
|
*/ |
||||||
|
class JBossClassLoaderAdapter { |
||||||
|
|
||||||
|
private static final String TRANSLATOR_ADAPTER_NAME = "org.jboss.classloader.spi.translator.ClassFileTransformer2Translator"; |
||||||
|
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 final ClassLoader classLoader; |
||||||
|
private final Constructor<?> constructor; |
||||||
|
private final Method addTranslator; |
||||||
|
private final Object target; |
||||||
|
|
||||||
|
JBossClassLoaderAdapter(ClassLoader classLoader) { |
||||||
|
Class<?> clazzLoaderType = null; |
||||||
|
try { |
||||||
|
// resolve BaseClassLoader.class
|
||||||
|
clazzLoaderType = classLoader.loadClass(LOADER_NAME); |
||||||
|
|
||||||
|
ClassLoader clazzLoader = null; |
||||||
|
// 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; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (clazzLoader == null) { |
||||||
|
throw new IllegalArgumentException(classLoader + " and its parents are not suitable ClassLoaders: " |
||||||
|
+ "A [" + LOADER_NAME + "] implementation is required."); |
||||||
|
} |
||||||
|
|
||||||
|
this.classLoader = clazzLoader; |
||||||
|
|
||||||
|
// BaseClassLoader#getPolicy
|
||||||
|
Method method = clazzLoaderType.getDeclaredMethod(GET_POLICY); |
||||||
|
ReflectionUtils.makeAccessible(method); |
||||||
|
Object policy = method.invoke(this.classLoader); |
||||||
|
|
||||||
|
Object addTarget = null; |
||||||
|
Method addMethod = null; |
||||||
|
|
||||||
|
// try the 5.1.x hooks
|
||||||
|
// check existence of BaseClassLoaderPolicy#addTranslator(Translator)
|
||||||
|
Class<?> 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); |
||||||
|
addTarget = system; |
||||||
|
|
||||||
|
// 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); |
||||||
|
} |
||||||
|
|
||||||
|
this.addTranslator = addMethod; |
||||||
|
this.target = addTarget; |
||||||
|
|
||||||
|
// resolve Transformer2TranslatorUtil constructor
|
||||||
|
clazz = classLoader.loadClass(TRANSLATOR_ADAPTER_NAME); |
||||||
|
this.constructor = clazz.getDeclaredConstructor(ClassFileTransformer.class); |
||||||
|
|
||||||
|
} catch (Exception ex) { |
||||||
|
throw new IllegalStateException( |
||||||
|
"Could not initialize JBoss LoadTimeWeaver because the JBoss 5 API classes are not available", ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void addTransformer(ClassFileTransformer transformer) { |
||||||
|
Object translator = null; |
||||||
|
try { |
||||||
|
translator = this.constructor.newInstance(transformer); |
||||||
|
} catch (Exception ex) { |
||||||
|
throw new IllegalStateException("Could not instantiate a JBoss class translator", ex); |
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
addTranslator.invoke(target, translator); |
||||||
|
} catch (Exception ex) { |
||||||
|
throw new IllegalStateException("Could not add transformer on JBoss classloader " + classLoader, ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public ClassLoader getClassLoader() { |
||||||
|
return classLoader; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,69 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2009 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. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* 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; |
||||||
|
|
||||||
|
import org.springframework.instrument.classloading.LoadTimeWeaver; |
||||||
|
import org.springframework.instrument.classloading.SimpleThrowawayClassLoader; |
||||||
|
import org.springframework.util.Assert; |
||||||
|
import org.springframework.util.ClassUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* {@link LoadTimeWeaver} implementation for JBoss's instrumentable ClassLoader. |
||||||
|
* |
||||||
|
* <p><b>NOTE:</b> Requires JBoss AS version 5.0.0 or higher. |
||||||
|
* |
||||||
|
* <p>Thanks to Ales Justin and Marius Bogoevici for the initial prototype.</p> |
||||||
|
* |
||||||
|
* @author Costin Leau |
||||||
|
*/ |
||||||
|
public class JBossLoadTimeWeaver implements LoadTimeWeaver { |
||||||
|
|
||||||
|
private final JBossClassLoaderAdapter classLoader; |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates a new instance of the {@link JBossLoadTimeWeaver} class using |
||||||
|
* the default {@link ClassLoader class loader}. |
||||||
|
* @see org.springframework.util.ClassUtils#getDefaultClassLoader() |
||||||
|
*/ |
||||||
|
public JBossLoadTimeWeaver() { |
||||||
|
this(ClassUtils.getDefaultClassLoader()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates a new instance of the {@link JBossLoadTimeWeaver} class using |
||||||
|
* the supplied {@link ClassLoader}. |
||||||
|
* @param classLoader the <code>ClassLoader</code> to delegate to for |
||||||
|
* weaving (must not be <code>null</code>) |
||||||
|
*/ |
||||||
|
public JBossLoadTimeWeaver(ClassLoader classLoader) { |
||||||
|
Assert.notNull(classLoader, "ClassLoader must not be null"); |
||||||
|
this.classLoader = new JBossClassLoaderAdapter(classLoader); |
||||||
|
} |
||||||
|
|
||||||
|
public void addTransformer(ClassFileTransformer transformer) { |
||||||
|
this.classLoader.addTransformer(transformer); |
||||||
|
} |
||||||
|
|
||||||
|
public ClassLoader getInstrumentableClassLoader() { |
||||||
|
return this.classLoader.getClassLoader(); |
||||||
|
} |
||||||
|
|
||||||
|
public ClassLoader getThrowawayClassLoader() { |
||||||
|
return new SimpleThrowawayClassLoader(getInstrumentableClassLoader()); |
||||||
|
} |
||||||
|
} |
||||||
@ -1,59 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
package org.springframework.instrument.classloading.jboss; |
|
||||||
|
|
||||||
import java.lang.reflect.Method; |
|
||||||
|
|
||||||
/** |
|
||||||
* Reflection helper. |
|
||||||
* |
|
||||||
* @author Ales Justin |
|
||||||
*/ |
|
||||||
public abstract class ReflectionHelper { |
|
||||||
|
|
||||||
/** |
|
||||||
* Get method from class. |
|
||||||
* |
|
||||||
* @param clazz the owner class
|
|
||||||
* @param name the method name |
|
||||||
* @return declared method |
|
||||||
* @throws Exception for any error |
|
||||||
*/ |
|
||||||
protected static Method getMethod(Class<?> clazz, String name) throws Exception { |
|
||||||
Method method = clazz.getDeclaredMethod(name); |
|
||||||
method.setAccessible(true); |
|
||||||
return method; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Invoke method and check the result. |
|
||||||
* |
|
||||||
* @param method the method |
|
||||||
* @param target the target |
|
||||||
* @param expectedType the expected type |
|
||||||
* @param <T> the exact type |
|
||||||
* @return invocation's result |
|
||||||
* @throws Exception for any error |
|
||||||
*/ |
|
||||||
protected static <T> T invokeMethod(Method method, Object target, Class<T> expectedType) throws Exception { |
|
||||||
Object result = method.invoke(target); |
|
||||||
if (expectedType.isInstance(result) == false) { |
|
||||||
throw new IllegalArgumentException("Returned result must be instance of [" + expectedType.getName() + "]"); |
|
||||||
} |
|
||||||
|
|
||||||
return expectedType.cast(result); |
|
||||||
} |
|
||||||
} |
|
||||||
@ -0,0 +1,8 @@ |
|||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* Support for class instrumentation on JBoss AS 5.x / JBoss MC 2.0.x. |
||||||
|
* |
||||||
|
*/ |
||||||
|
package org.springframework.instrument.classloading.jboss; |
||||||
|
|
||||||
Loading…
Reference in new issue