-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
LTW for WebSphere
- Loading branch information
Costin Leau
committed
Feb 1, 2011
1 parent
93de962
commit f191be5
Showing
5 changed files
with
279 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
105 changes: 105 additions & 0 deletions
105
...va/org/springframework/instrument/classloading/websphere/WebSphereClassLoaderAdapter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/* | ||
* Copyright 2011 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.websphere; | ||
|
||
import java.lang.instrument.ClassFileTransformer; | ||
import java.lang.reflect.Constructor; | ||
import java.lang.reflect.Field; | ||
import java.lang.reflect.InvocationHandler; | ||
import java.lang.reflect.InvocationTargetException; | ||
import java.lang.reflect.Method; | ||
import java.lang.reflect.Proxy; | ||
import java.util.List; | ||
|
||
import org.springframework.util.Assert; | ||
|
||
/** | ||
* | ||
* Reflective wrapper around a WebSphere 7 class loader. Used to | ||
* encapsulate the classloader-specific methods (discovered and | ||
* called through reflection) from the load-time weaver. | ||
* | ||
* @author Costin Leau | ||
*/ | ||
class WebSphereClassLoaderAdapter { | ||
|
||
private static final String COMPOUND_CLASS_LOADER_NAME = "com.ibm.ws.classloader.CompoundClassLoader"; | ||
private static final String CLASS_PRE_PROCESSOR_NAME = "com.ibm.websphere.classloader.ClassLoaderInstancePreDefinePlugin"; | ||
private static final String PLUGINS_FIELD = "preDefinePlugins"; | ||
|
||
private ClassLoader classLoader; | ||
private Class<?> wsPreProcessorClass; | ||
private Method addPreDefinePlugin; | ||
private Constructor<? extends ClassLoader> cloneConstructor; | ||
private Field transformerList; | ||
|
||
public WebSphereClassLoaderAdapter(ClassLoader classLoader) { | ||
Class<?> wsCompoundClassLoaderClass = null; | ||
try { | ||
wsCompoundClassLoaderClass = classLoader.loadClass(COMPOUND_CLASS_LOADER_NAME); | ||
cloneConstructor = classLoader.getClass().getDeclaredConstructor(wsCompoundClassLoaderClass); | ||
cloneConstructor.setAccessible(true); | ||
|
||
wsPreProcessorClass = classLoader.loadClass(CLASS_PRE_PROCESSOR_NAME); | ||
addPreDefinePlugin = classLoader.getClass().getMethod("addPreDefinePlugin", wsPreProcessorClass); | ||
transformerList = wsCompoundClassLoaderClass.getDeclaredField(PLUGINS_FIELD); | ||
transformerList.setAccessible(true); | ||
|
||
} catch (Exception ex) { | ||
throw new IllegalStateException( | ||
"Could not initialize WebSphere LoadTimeWeaver because WebSphere 7 API classes are not available", | ||
ex); | ||
} | ||
Assert.isInstanceOf(wsCompoundClassLoaderClass, classLoader, "ClassLoader must be instance of [" | ||
+ COMPOUND_CLASS_LOADER_NAME + "]"); | ||
this.classLoader = classLoader; | ||
} | ||
|
||
public ClassLoader getClassLoader() { | ||
return this.classLoader; | ||
} | ||
|
||
public void addTransformer(ClassFileTransformer transformer) { | ||
Assert.notNull(transformer, "ClassFileTransformer must not be null"); | ||
try { | ||
InvocationHandler adapter = new WebSphereClassPreDefinePlugin(transformer); | ||
Object adapterInstance = Proxy.newProxyInstance(this.wsPreProcessorClass.getClassLoader(), | ||
new Class[] { this.wsPreProcessorClass }, adapter); | ||
this.addPreDefinePlugin.invoke(this.classLoader, adapterInstance); | ||
|
||
} catch (InvocationTargetException ex) { | ||
throw new IllegalStateException("WebSphere addPreDefinePlugin method threw exception", ex.getCause()); | ||
} catch (Exception ex) { | ||
throw new IllegalStateException("Could not invoke WebSphere addPreDefinePlugin method", ex); | ||
} | ||
} | ||
|
||
@SuppressWarnings("unchecked") | ||
public ClassLoader getThrowawayClassLoader() { | ||
try { | ||
ClassLoader loader = (ClassLoader) cloneConstructor.newInstance(getClassLoader()); | ||
// clear out the transformers (copied as well) | ||
List list = (List) transformerList.get(loader); | ||
list.clear(); | ||
return loader; | ||
} catch (InvocationTargetException ex) { | ||
throw new IllegalStateException("WebSphere CompoundClassLoader constructor failed", ex.getCause()); | ||
} catch (Exception ex) { | ||
throw new IllegalStateException("Could not construct WebSphere CompoundClassLoader", ex); | ||
} | ||
} | ||
} |
93 changes: 93 additions & 0 deletions
93
.../org/springframework/instrument/classloading/websphere/WebSphereClassPreDefinePlugin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/* | ||
* Copyright 2011 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.websphere; | ||
|
||
import java.lang.instrument.ClassFileTransformer; | ||
import java.lang.reflect.InvocationHandler; | ||
import java.lang.reflect.Method; | ||
import java.security.CodeSource; | ||
|
||
import org.springframework.util.FileCopyUtils; | ||
|
||
/** | ||
* Adapter that implements WebSphere 7.0 ClassPreProcessPlugin interface, delegating to a | ||
* standard JDK {@link ClassFileTransformer} underneath. | ||
* | ||
* <p>To avoid compile time checks again the vendor API, a dynamic proxy is | ||
* being used. | ||
* | ||
* @author Costin Leau | ||
*/ | ||
class WebSphereClassPreDefinePlugin implements InvocationHandler { | ||
|
||
private final ClassFileTransformer transformer; | ||
|
||
private class Dummy { | ||
} | ||
|
||
/** | ||
* Creates a new {@link WebSphereClassPreDefinePlugin}. | ||
* | ||
* @param transformer the {@link ClassFileTransformer} to be adapted (must | ||
* not be <code>null</code>) | ||
*/ | ||
public WebSphereClassPreDefinePlugin(ClassFileTransformer transformer) { | ||
this.transformer = transformer; | ||
ClassLoader classLoader = transformer.getClass().getClassLoader(); | ||
|
||
// first force the full class loading of the weaver by invoking transformation on a dummy class | ||
try { | ||
String dummyClass = Dummy.class.getName().replace('.', '/'); | ||
byte[] bytes = FileCopyUtils.copyToByteArray(classLoader.getResourceAsStream(dummyClass + ".class")); | ||
transformer.transform(classLoader, dummyClass, null, null, bytes); | ||
} catch (Throwable ex) { | ||
throw new IllegalArgumentException("Cannot load transformer", ex); | ||
} | ||
} | ||
|
||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { | ||
String name = method.getName(); | ||
|
||
if ("equals".equals(name)) { | ||
return (Boolean.valueOf(proxy == args[0])); | ||
} else if ("hashCode".equals(name)) { | ||
return hashCode(); | ||
} else if ("toString".equals(name)) { | ||
return toString(); | ||
} else if ("transformClass".equals(name)) { | ||
return transform((String) args[0], (byte[]) args[1], (CodeSource) args[2], (ClassLoader) args[3]); | ||
} else { | ||
throw new IllegalArgumentException("Unknown method: " + method); | ||
} | ||
} | ||
|
||
public byte[] transform(String className, byte[] classfileBuffer, CodeSource codeSource, ClassLoader classLoader) | ||
throws Exception { | ||
// NB: WebSphere passes className as "." without class while the | ||
// transformer expects a VM, "/" format | ||
byte[] result = transformer.transform(classLoader, className.replace('.', '/'), null, null, classfileBuffer); | ||
|
||
return (result != null ? result : classfileBuffer); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
StringBuilder builder = new StringBuilder(getClass().getName()); | ||
builder.append(" for transformer: "); | ||
builder.append(this.transformer); | ||
return builder.toString(); | ||
} | ||
} |
68 changes: 68 additions & 0 deletions
68
...n/java/org/springframework/instrument/classloading/websphere/WebSphereLoadTimeWeaver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/* | ||
* Copyright 2011 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.websphere; | ||
|
||
import java.lang.instrument.ClassFileTransformer; | ||
|
||
import org.springframework.instrument.classloading.LoadTimeWeaver; | ||
import org.springframework.util.Assert; | ||
import org.springframework.util.ClassUtils; | ||
|
||
/** | ||
* {@link LoadTimeWeaver} implementation for WebSphere instrumentable classloader. | ||
* | ||
* <p><b>NOTE:</b> Requires WebSphere Application Server version 7.0.0 or higher. | ||
* | ||
* @author Costin Leau | ||
* @since 3.1 | ||
*/ | ||
public class WebSphereLoadTimeWeaver implements LoadTimeWeaver { | ||
|
||
private final WebSphereClassLoaderAdapter classLoader; | ||
|
||
/** | ||
* Create a new instance of the {@link WebSphereLoadTimeWeaver} class using | ||
* the default {@link ClassLoader class loader}. | ||
* @see org.springframework.util.ClassUtils#getDefaultClassLoader() | ||
*/ | ||
public WebSphereLoadTimeWeaver() { | ||
this(ClassUtils.getDefaultClassLoader()); | ||
} | ||
|
||
/** | ||
* Create a new instance of the {@link WebSphereLoadTimeWeaver} class using | ||
* the supplied {@link ClassLoader}. | ||
* @param classLoader the <code>ClassLoader</code> to delegate to for | ||
* weaving (must not be <code>null</code>) | ||
*/ | ||
public WebSphereLoadTimeWeaver(ClassLoader classLoader) { | ||
Assert.notNull(classLoader, "ClassLoader must not be null"); | ||
this.classLoader = new WebSphereClassLoaderAdapter(classLoader); | ||
} | ||
|
||
public void addTransformer(ClassFileTransformer transformer) { | ||
this.classLoader.addTransformer(transformer); | ||
} | ||
|
||
public ClassLoader getInstrumentableClassLoader() { | ||
return this.classLoader.getClassLoader(); | ||
} | ||
|
||
public ClassLoader getThrowawayClassLoader() { | ||
return this.classLoader.getThrowawayClassLoader(); | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
...ext/src/main/java/org/springframework/instrument/classloading/websphere/package-info.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
|
||
/** | ||
* | ||
* Support for class instrumentation on IBM WebSphere Application Server 7. | ||
* | ||
*/ | ||
package org.springframework.instrument.classloading.websphere; | ||
|