KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > instrument > classloading > ReflectiveLoadTimeWeaver


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.instrument.classloading;
18
19 import java.lang.instrument.ClassFileTransformer JavaDoc;
20 import java.lang.reflect.Method JavaDoc;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24
25 import org.springframework.util.Assert;
26 import org.springframework.util.ClassUtils;
27 import org.springframework.util.ReflectionUtils;
28
29 /**
30  * LoadTimeWeaver which uses reflection to delegate to an underlying ClassLoader
31  * with well-known transformation hooks. The underlying ClassLoader is expected to
32  * support the following weaving methods (as defined in the {@link LoadTimeWeaver}
33  * interface):
34  * <ul>
35  * <li><code>public void addTransformer(java.lang.instrument.ClassFileTransformer)</code>:
36  * for registering the given ClassFileTransformer on this ClassLoader
37  * <li><code>public ClassLoader getThrowawayClassLoader()</code>:
38  * for obtaining a throwaway class loader for this ClassLoader (optional;
39  * ReflectiveLoadTimeWeaver will fall back to a SimpleThrowawayClassLoader if
40  * that method isn't available)
41  * </ul>
42  *
43  * <p>Please note that the above methods <i>must</i> reside in a class that is
44  * publicly accessible, although the class itself does not have to be visible
45  * to the application's class loader.
46  *
47  * <p>The reflective nature of this LoadTimeWeaver is particularly useful when the
48  * underlying class loader implementation is loaded in a different class loader
49  * (such as the application server's class loader which is not visible to the
50  * web application). There is no direct API dependency between this LoadTimeWeaver
51  * adapter and the underlying ClassLoader, just a 'loose' method contract.
52  *
53  * <p>This is the LoadTimeWeaver to use in combination with Spring's
54  * {@link org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader}.
55  *
56  * @author Costin Leau
57  * @author Juergen Hoeller
58  * @since 2.0
59  * @see #addTransformer(java.lang.instrument.ClassFileTransformer)
60  * @see #getThrowawayClassLoader()
61  * @see SimpleThrowawayClassLoader
62  * @see org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader
63  */

64 public class ReflectiveLoadTimeWeaver implements LoadTimeWeaver {
65
66     private static final String JavaDoc ADD_TRANSFORMER_METHOD_NAME = "addTransformer";
67
68     private static final String JavaDoc GET_THROWAWAY_CLASS_LOADER_METHOD_NAME = "getThrowawayClassLoader";
69
70     private static final Log logger = LogFactory.getLog(ReflectiveLoadTimeWeaver.class);
71
72
73     private final ClassLoader JavaDoc classLoader;
74
75     private final Method JavaDoc addTransformerMethod;
76
77     private final Method JavaDoc getThrowawayClassLoaderMethod;
78
79
80     /**
81      * Create a new ReflectiveLoadTimeWeaver for the current context class
82      * loader, <i>which needs to support the required weaving methods</i>.
83      */

84     public ReflectiveLoadTimeWeaver() {
85         this(ClassUtils.getDefaultClassLoader());
86     }
87
88     /**
89      * Create a new SimpleLoadTimeWeaver for the given class loader.
90      * @param classLoader the <code>ClassLoader</code> to delegate to for
91      * weaving (<i>must</i> support the required weaving methods).
92      * @throws IllegalArgumentException if the supplied <code>ClassLoader</code>
93      * is <code>null</code>
94      * @throws IllegalStateException if the supplied <code>ClassLoader</code>
95      * does not support the required weaving methods
96      */

97     public ReflectiveLoadTimeWeaver(ClassLoader JavaDoc classLoader) {
98         Assert.notNull(classLoader, "ClassLoader must not be null");
99         this.classLoader = classLoader;
100         this.addTransformerMethod = ClassUtils.getMethodIfAvailable(
101                 this.classLoader.getClass(), ADD_TRANSFORMER_METHOD_NAME,
102                 new Class JavaDoc [] {ClassFileTransformer JavaDoc.class});
103         if (this.addTransformerMethod == null) {
104             throw new IllegalStateException JavaDoc(
105                     "ClassLoader [" + classLoader.getClass().getName() + "] does NOT provide an " +
106                     "'addTransformer(ClassFileTransformer)' method.");
107         }
108         this.getThrowawayClassLoaderMethod = ClassUtils.getMethodIfAvailable(
109                 this.classLoader.getClass(), GET_THROWAWAY_CLASS_LOADER_METHOD_NAME,
110                 new Class JavaDoc[0]);
111         // getThrowawayClassLoader method is optional
112
if (this.getThrowawayClassLoaderMethod == null) {
113             if (logger.isInfoEnabled()) {
114                 logger.info("The ClassLoader [" + classLoader.getClass().getName() + "] does NOT provide a " +
115                         "'getThrowawayClassLoader()' method; SimpleThrowawayClassLoader will be used instead.");
116             }
117         }
118     }
119
120
121     public void addTransformer(ClassFileTransformer JavaDoc transformer) {
122         Assert.notNull(transformer, "Transformer must not be null");
123         ReflectionUtils.invokeMethod(this.addTransformerMethod, this.classLoader, new Object JavaDoc[] {transformer});
124     }
125
126     public ClassLoader JavaDoc getInstrumentableClassLoader() {
127         return this.classLoader;
128     }
129
130     public ClassLoader JavaDoc getThrowawayClassLoader() {
131         if (this.getThrowawayClassLoaderMethod != null) {
132             return (ClassLoader JavaDoc) ReflectionUtils.invokeMethod(this.getThrowawayClassLoaderMethod, this.classLoader,
133                     new Object JavaDoc[0]);
134         }
135         else {
136             return new SimpleThrowawayClassLoader(this.classLoader);
137         }
138     }
139
140 }
141
Popular Tags