LoadTimeWeaver.getThrowawayClassLoader() decorated for exclude support (if necessary)
Issue: SPR-13886
This commit is contained in:
parent
448621ac58
commit
b82df144e4
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
@ -22,6 +22,8 @@ import java.lang.reflect.Method;
|
|||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.DecoratingClassLoader;
|
||||
import org.springframework.core.OverridingClassLoader;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
@ -97,15 +99,14 @@ public class ReflectiveLoadTimeWeaver implements LoadTimeWeaver {
|
|||
Assert.notNull(classLoader, "ClassLoader must not be null");
|
||||
this.classLoader = classLoader;
|
||||
this.addTransformerMethod = ClassUtils.getMethodIfAvailable(
|
||||
this.classLoader.getClass(), ADD_TRANSFORMER_METHOD_NAME,
|
||||
new Class<?>[] {ClassFileTransformer.class});
|
||||
this.classLoader.getClass(), ADD_TRANSFORMER_METHOD_NAME, ClassFileTransformer.class);
|
||||
if (this.addTransformerMethod == null) {
|
||||
throw new IllegalStateException(
|
||||
"ClassLoader [" + classLoader.getClass().getName() + "] does NOT provide an " +
|
||||
"'addTransformer(ClassFileTransformer)' method.");
|
||||
}
|
||||
this.getThrowawayClassLoaderMethod = ClassUtils.getMethodIfAvailable(
|
||||
this.classLoader.getClass(), GET_THROWAWAY_CLASS_LOADER_METHOD_NAME, new Class<?>[0]);
|
||||
this.classLoader.getClass(), GET_THROWAWAY_CLASS_LOADER_METHOD_NAME);
|
||||
// getThrowawayClassLoader method is optional
|
||||
if (this.getThrowawayClassLoaderMethod == null) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
|
@ -130,7 +131,10 @@ public class ReflectiveLoadTimeWeaver implements LoadTimeWeaver {
|
|||
@Override
|
||||
public ClassLoader getThrowawayClassLoader() {
|
||||
if (this.getThrowawayClassLoaderMethod != null) {
|
||||
return (ClassLoader) ReflectionUtils.invokeMethod(this.getThrowawayClassLoaderMethod, this.classLoader);
|
||||
ClassLoader target = (ClassLoader)
|
||||
ReflectionUtils.invokeMethod(this.getThrowawayClassLoaderMethod, this.classLoader);
|
||||
return (target instanceof DecoratingClassLoader ? target :
|
||||
new OverridingClassLoader(this.classLoader, target));
|
||||
}
|
||||
else {
|
||||
return new SimpleThrowawayClassLoader(this.classLoader);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
@ -20,6 +20,7 @@ import java.lang.instrument.ClassFileTransformer;
|
|||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.core.OverridingClassLoader;
|
||||
import org.springframework.instrument.classloading.LoadTimeWeaver;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
@ -109,7 +110,7 @@ public class GlassFishLoadTimeWeaver implements LoadTimeWeaver {
|
|||
@Override
|
||||
public ClassLoader getThrowawayClassLoader() {
|
||||
try {
|
||||
return (ClassLoader) this.copyMethod.invoke(this.classLoader);
|
||||
return new OverridingClassLoader(this.classLoader, (ClassLoader) this.copyMethod.invoke(this.classLoader));
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw new IllegalStateException("GlassFish copy method threw exception", ex.getCause());
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
@ -20,6 +20,7 @@ import java.lang.instrument.ClassFileTransformer;
|
|||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.core.OverridingClassLoader;
|
||||
import org.springframework.instrument.classloading.LoadTimeWeaver;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
@ -103,7 +104,7 @@ public class TomcatLoadTimeWeaver implements LoadTimeWeaver {
|
|||
@Override
|
||||
public ClassLoader getThrowawayClassLoader() {
|
||||
try {
|
||||
return (ClassLoader) this.copyMethod.invoke(this.classLoader);
|
||||
return new OverridingClassLoader(this.classLoader, (ClassLoader) this.copyMethod.invoke(this.classLoader));
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw new IllegalStateException("Tomcat copy method threw exception", ex.getCause());
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
@ -18,6 +18,7 @@ package org.springframework.instrument.classloading.weblogic;
|
|||
|
||||
import java.lang.instrument.ClassFileTransformer;
|
||||
|
||||
import org.springframework.core.OverridingClassLoader;
|
||||
import org.springframework.instrument.classloading.LoadTimeWeaver;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
@ -70,6 +71,8 @@ public class WebLogicLoadTimeWeaver implements LoadTimeWeaver {
|
|||
|
||||
@Override
|
||||
public ClassLoader getThrowawayClassLoader() {
|
||||
return this.classLoader.getThrowawayClassLoader();
|
||||
return new OverridingClassLoader(this.classLoader.getClassLoader(),
|
||||
this.classLoader.getThrowawayClassLoader());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
@ -29,47 +29,57 @@ import org.springframework.util.Assert;
|
|||
|
||||
/**
|
||||
*
|
||||
* Reflective wrapper around a WebSphere 7 class loader. Used to
|
||||
* 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
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
*/
|
||||
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;
|
||||
Class<?> wsCompoundClassLoaderClass;
|
||||
try {
|
||||
wsCompoundClassLoaderClass = classLoader.loadClass(COMPOUND_CLASS_LOADER_NAME);
|
||||
cloneConstructor = classLoader.getClass().getDeclaredConstructor(wsCompoundClassLoaderClass);
|
||||
cloneConstructor.setAccessible(true);
|
||||
this.cloneConstructor = classLoader.getClass().getDeclaredConstructor(wsCompoundClassLoaderClass);
|
||||
this.cloneConstructor.setAccessible(true);
|
||||
|
||||
wsPreProcessorClass = classLoader.loadClass(CLASS_PRE_PROCESSOR_NAME);
|
||||
addPreDefinePlugin = classLoader.getClass().getMethod("addPreDefinePlugin", wsPreProcessorClass);
|
||||
transformerList = wsCompoundClassLoaderClass.getDeclaredField(PLUGINS_FIELD);
|
||||
transformerList.setAccessible(true);
|
||||
this.wsPreProcessorClass = classLoader.loadClass(CLASS_PRE_PROCESSOR_NAME);
|
||||
this.addPreDefinePlugin = classLoader.getClass().getMethod("addPreDefinePlugin", this.wsPreProcessorClass);
|
||||
this.transformerList = wsCompoundClassLoaderClass.getDeclaredField(PLUGINS_FIELD);
|
||||
this.transformerList.setAccessible(true);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException(
|
||||
"Could not initialize WebSphere LoadTimeWeaver because WebSphere 7 API classes are not available",
|
||||
ex);
|
||||
"Could not initialize WebSphere LoadTimeWeaver because WebSphere API classes are not available", ex);
|
||||
}
|
||||
|
||||
if (!wsCompoundClassLoaderClass.isInstance(classLoader)) {
|
||||
throw new IllegalArgumentException("ClassLoader must be instance of [" + COMPOUND_CLASS_LOADER_NAME + "]");
|
||||
}
|
||||
Assert.isInstanceOf(wsCompoundClassLoaderClass, classLoader,
|
||||
"ClassLoader must be instance of [" + COMPOUND_CLASS_LOADER_NAME + "]");
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
|
||||
public ClassLoader getClassLoader() {
|
||||
return this.classLoader;
|
||||
}
|
||||
|
@ -79,9 +89,8 @@ class WebSphereClassLoaderAdapter {
|
|||
try {
|
||||
InvocationHandler adapter = new WebSphereClassPreDefinePlugin(transformer);
|
||||
Object adapterInstance = Proxy.newProxyInstance(this.wsPreProcessorClass.getClassLoader(),
|
||||
new Class<?>[] { this.wsPreProcessorClass }, adapter);
|
||||
new Class<?>[] {this.wsPreProcessorClass}, adapter);
|
||||
this.addPreDefinePlugin.invoke(this.classLoader, adapterInstance);
|
||||
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
throw new IllegalStateException("WebSphere addPreDefinePlugin method threw exception", ex.getCause());
|
||||
|
@ -93,9 +102,9 @@ class WebSphereClassLoaderAdapter {
|
|||
|
||||
public ClassLoader getThrowawayClassLoader() {
|
||||
try {
|
||||
ClassLoader loader = cloneConstructor.newInstance(getClassLoader());
|
||||
// clear out the transformers (copied as well)
|
||||
List<?> list = (List<?>) transformerList.get(loader);
|
||||
ClassLoader loader = this.cloneConstructor.newInstance(getClassLoader());
|
||||
// Clear out the transformers (copied as well)
|
||||
List<?> list = (List<?>) this.transformerList.get(loader);
|
||||
list.clear();
|
||||
return loader;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
@ -18,6 +18,7 @@ package org.springframework.instrument.classloading.websphere;
|
|||
|
||||
import java.lang.instrument.ClassFileTransformer;
|
||||
|
||||
import org.springframework.core.OverridingClassLoader;
|
||||
import org.springframework.instrument.classloading.LoadTimeWeaver;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
@ -67,7 +68,8 @@ public class WebSphereLoadTimeWeaver implements LoadTimeWeaver {
|
|||
|
||||
@Override
|
||||
public ClassLoader getThrowawayClassLoader() {
|
||||
return this.classLoader.getThrowawayClassLoader();
|
||||
return new OverridingClassLoader(this.classLoader.getClassLoader(),
|
||||
this.classLoader.getThrowawayClassLoader());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
@ -16,8 +16,9 @@
|
|||
|
||||
package org.springframework.core;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.lang.UsesJava7;
|
||||
import org.springframework.util.Assert;
|
||||
|
@ -49,11 +50,11 @@ public abstract class DecoratingClassLoader extends ClassLoader {
|
|||
}
|
||||
|
||||
|
||||
private final Set<String> excludedPackages = new HashSet<String>();
|
||||
private final Set<String> excludedPackages =
|
||||
Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(8));
|
||||
|
||||
private final Set<String> excludedClasses = new HashSet<String>();
|
||||
|
||||
private final Object exclusionMonitor = new Object();
|
||||
private final Set<String> excludedClasses =
|
||||
Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(8));
|
||||
|
||||
|
||||
/**
|
||||
|
@ -79,10 +80,8 @@ public abstract class DecoratingClassLoader extends ClassLoader {
|
|||
*/
|
||||
public void excludePackage(String packageName) {
|
||||
Assert.notNull(packageName, "Package name must not be null");
|
||||
synchronized (this.exclusionMonitor) {
|
||||
this.excludedPackages.add(packageName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a class name to exclude from decoration (e.g. overriding).
|
||||
|
@ -92,10 +91,8 @@ public abstract class DecoratingClassLoader extends ClassLoader {
|
|||
*/
|
||||
public void excludeClass(String className) {
|
||||
Assert.notNull(className, "Class name must not be null");
|
||||
synchronized (this.exclusionMonitor) {
|
||||
this.excludedClasses.add(className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the specified class is excluded from decoration
|
||||
|
@ -107,7 +104,6 @@ public abstract class DecoratingClassLoader extends ClassLoader {
|
|||
* @see #excludeClass
|
||||
*/
|
||||
protected boolean isExcluded(String className) {
|
||||
synchronized (this.exclusionMonitor) {
|
||||
if (this.excludedClasses.contains(className)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -116,7 +112,6 @@ public abstract class DecoratingClassLoader extends ClassLoader {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
@ -38,7 +38,8 @@ import org.springframework.util.FileCopyUtils;
|
|||
public class OverridingClassLoader extends DecoratingClassLoader {
|
||||
|
||||
/** Packages that are excluded by default */
|
||||
public static final String[] DEFAULT_EXCLUDED_PACKAGES = new String[] {"java.", "javax.", "sun.", "oracle."};
|
||||
public static final String[] DEFAULT_EXCLUDED_PACKAGES = new String[]
|
||||
{"java.", "javax.", "sun.", "oracle.", "javassist.", "org.springframework.core."};
|
||||
|
||||
private static final String CLASS_FILE_SUFFIX = ".class";
|
||||
|
||||
|
@ -49,12 +50,26 @@ public class OverridingClassLoader extends DecoratingClassLoader {
|
|||
}
|
||||
|
||||
|
||||
private final ClassLoader overrideDelegate;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new OverridingClassLoader for the given ClassLoader.
|
||||
* @param parent the ClassLoader to build an overriding ClassLoader for
|
||||
*/
|
||||
public OverridingClassLoader(ClassLoader parent) {
|
||||
this(parent, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new OverridingClassLoader for the given ClassLoader.
|
||||
* @param parent the ClassLoader to build an overriding ClassLoader for
|
||||
* @param overrideDelegate the ClassLoader to delegate to for overriding
|
||||
* @since 4.3
|
||||
*/
|
||||
public OverridingClassLoader(ClassLoader parent, ClassLoader overrideDelegate) {
|
||||
super(parent);
|
||||
this.overrideDelegate = overrideDelegate;
|
||||
for (String packageName : DEFAULT_EXCLUDED_PACKAGES) {
|
||||
excludePackage(packageName);
|
||||
}
|
||||
|
@ -62,20 +77,25 @@ public class OverridingClassLoader extends DecoratingClassLoader {
|
|||
|
||||
|
||||
@Override
|
||||
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||
Class<?> result = null;
|
||||
if (isEligibleForOverriding(name)) {
|
||||
result = loadClassForOverriding(name);
|
||||
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
||||
if (this.overrideDelegate != null && isEligibleForOverriding(name)) {
|
||||
return this.overrideDelegate.loadClass(name);
|
||||
}
|
||||
return super.loadClass(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||
if (isEligibleForOverriding(name)) {
|
||||
Class<?> result = loadClassForOverriding(name);
|
||||
if (result != null) {
|
||||
if (resolve) {
|
||||
resolveClass(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return super.loadClass(name, resolve);
|
||||
}
|
||||
return super.loadClass(name, resolve);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue