001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.instrument.classloading.weblogic;
018:
019: import java.lang.instrument.ClassFileTransformer;
020: import java.lang.reflect.Constructor;
021: import java.lang.reflect.InvocationHandler;
022: import java.lang.reflect.InvocationTargetException;
023: import java.lang.reflect.Method;
024: import java.lang.reflect.Proxy;
025:
026: import org.springframework.util.Assert;
027:
028: /**
029: * Reflective wrapper around a WebLogic 10 class loader. Used to
030: * encapsulate the classloader-specific methods (discovered and
031: * called through reflection) from the load-time weaver.
032: *
033: * @author Costin Leau
034: * @author Juergen Hoeller
035: * @since 2.5
036: */
037: class WebLogicClassLoader {
038:
039: private static final String GENERIC_CLASS_LOADER_NAME = "weblogic.utils.classloaders.GenericClassLoader";
040:
041: private static final String CLASS_PRE_PROCESSOR_NAME = "weblogic.utils.classloaders.ClassPreProcessor";
042:
043: private final ClassLoader internalClassLoader;
044:
045: private final Class wlPreProcessorClass;
046:
047: private final Method addPreProcessorMethod;
048:
049: private final Method getClassFinderMethod;
050:
051: private final Method getParentMethod;
052:
053: private final Constructor wlGenericClassLoaderConstructor;
054:
055: public WebLogicClassLoader(ClassLoader classLoader) {
056: Class wlGenericClassLoaderClass = null;
057: try {
058: wlGenericClassLoaderClass = classLoader
059: .loadClass(GENERIC_CLASS_LOADER_NAME);
060: this .wlPreProcessorClass = classLoader
061: .loadClass(CLASS_PRE_PROCESSOR_NAME);
062: this .addPreProcessorMethod = classLoader.getClass()
063: .getMethod("addInstanceClassPreProcessor",
064: this .wlPreProcessorClass);
065: this .getClassFinderMethod = classLoader.getClass()
066: .getMethod("getClassFinder");
067: this .getParentMethod = classLoader.getClass().getMethod(
068: "getParent");
069: this .wlGenericClassLoaderConstructor = wlGenericClassLoaderClass
070: .getConstructor(this .getClassFinderMethod
071: .getReturnType(), ClassLoader.class);
072: } catch (Exception ex) {
073: throw new IllegalStateException(
074: "Could not initialize WebLogic ClassLoader because WebLogic 10 API classes are not available",
075: ex);
076: }
077: Assert.isInstanceOf(wlGenericClassLoaderClass, classLoader,
078: "ClassLoader must be instance of ["
079: + wlGenericClassLoaderClass.getName() + "]");
080: this .internalClassLoader = classLoader;
081: }
082:
083: public void addTransformer(ClassFileTransformer transformer) {
084: Assert.notNull(transformer,
085: "ClassFileTransformer must not be null");
086: try {
087: InvocationHandler adapter = new WebLogicClassPreProcessorAdapter(
088: transformer, this .internalClassLoader);
089: Object adapterInstance = Proxy.newProxyInstance(
090: this .wlPreProcessorClass.getClassLoader(),
091: new Class[] { this .wlPreProcessorClass }, adapter);
092: this .addPreProcessorMethod.invoke(this .internalClassLoader,
093: adapterInstance);
094: } catch (InvocationTargetException ex) {
095: throw new IllegalStateException(
096: "WebLogic addInstanceClassPreProcessor method threw exception",
097: ex.getCause());
098: } catch (Exception ex) {
099: throw new IllegalStateException(
100: "Could not invoke WebLogic addInstanceClassPreProcessor method",
101: ex);
102: }
103: }
104:
105: public ClassLoader getInternalClassLoader() {
106: return this .internalClassLoader;
107: }
108:
109: public ClassLoader getThrowawayClassLoader() {
110: try {
111: Object classFinder = this .getClassFinderMethod
112: .invoke(this .internalClassLoader);
113: Object parent = this .getParentMethod
114: .invoke(this .internalClassLoader);
115: // arguments for 'clone'-like method
116: return (ClassLoader) this .wlGenericClassLoaderConstructor
117: .newInstance(classFinder, parent);
118: } catch (InvocationTargetException ex) {
119: throw new IllegalStateException(
120: "WebLogic GenericClassLoader constructor failed",
121: ex.getCause());
122: } catch (Exception ex) {
123: throw new IllegalStateException(
124: "Could not construct WebLogic GenericClassLoader",
125: ex);
126: }
127: }
128:
129: }
|