+ redone the JBossLTW (no dependency on the JBoss API)
- removed JBoss jars
- removed JBoss imports (Spring code doesn't rely on it)
This commit is contained in:
Costin Leau 2009-11-12 01:25:39 +00:00
parent d0b6891275
commit 846c7f6000
11 changed files with 227 additions and 466 deletions

View File

@ -46,8 +46,10 @@
<dependency org="org.aspectj" name="com.springsource.org.aspectj.weaver" rev="1.6.5.RELEASE" conf="optional, aspectj->compile"/>
<dependency org="org.beanshell" name="com.springsource.bsh" rev="2.0.0.b4" conf="optional, beanshell->compile"/>
<dependency org="org.codehaus.groovy" name="com.springsource.org.codehaus.groovy" rev="1.6.3" conf="optional, groovy->compile"/>
<!--
<dependency org="org.jboss.cl" name="com.springsource.org.jboss.classloader" rev="2.0.5.GA" conf="provided->compile"/>
<dependency org="org.jboss.util" name="com.springsource.org.jboss.util" rev="2.2.13.GA" conf="provided, runtime->compile"/>
-->
<dependency org="org.joda" name="com.springsource.org.joda.time" rev="1.6.0" conf="optional->compile"/>
<dependency org="org.jruby" name="com.springsource.org.jruby" rev="1.2.0" conf="optional, jruby->compile"/>
<dependency org="org.springframework" name="org.springframework.asm" rev="latest.integration" conf="compile->compile"/>

View File

@ -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) {
}
}

View File

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

View File

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

View File

@ -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;
}
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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());
}
}

View File

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

View File

@ -0,0 +1,8 @@
/**
*
* Support for class instrumentation on JBoss AS 5.x / JBoss MC 2.0.x.
*
*/
package org.springframework.instrument.classloading.jboss;

View File

@ -30,8 +30,6 @@ Import-Template:
org.aspectj.weaver.*;version="[1.5.4, 2.0.0)";resolution:=optional,
org.codehaus.groovy.*;version="[1.5.0, 2.0.0)";resolution:=optional,
org.joda.*;version="[1.6.0, 2.0.0)";resolution:=optional,
org.jboss.classloader.*;version="[2.0.5, 3.0.0)";resolution:=optional,
org.jboss.util.*;version="[2.2.13, 3.0.0)";resolution:=optional,
org.jruby.*;version="[1.1.0, 2.0.0)";resolution:=optional,
org.omg.CORBA.*;version="0";resolution:=optional,
org.springframework.aop.*;version="[3.0.0, 3.0.1)";resolution:=optional,