11/*
2- * Copyright 2002-2012 the original author or authors.
2+ * Copyright 2002-2013 the original author or authors.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
2222
2323import org .apache .catalina .loader .ResourceEntry ;
2424import org .apache .catalina .loader .WebappClassLoader ;
25+
2526import org .springframework .instrument .classloading .WeavingTransformer ;
2627
2728/**
3132 * <p>To be registered using a
3233 * {@code <a href="http://tomcat.apache.org/tomcat-5.5-doc/config/loader.html">Loader</a>} tag
3334 * in Tomcat's {@code <a href="http://tomcat.apache.org/tomcat-5.5-doc/config/context.html">Context</a>}
34- * definition in the {@code server.xml} file, with the Spring-provided
35- * "spring-tomcat-weaver.jar" file deployed into Tomcat's "server/lib" (for Tomcat 5.x) or "lib" (for Tomcat 6.x) directory.
35+ * definition in the {@code server.xml} file, with the Spring-provided "spring-instrument-tomcat.jar"
36+ * file deployed into Tomcat's "server/lib" (for Tomcat 5.x) or "lib" (for Tomcat 6.x) directory.
3637 * The required configuration tag looks as follows:
3738 *
3839 * <pre class="code"><Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/></pre>
5859public class TomcatInstrumentableClassLoader extends WebappClassLoader {
5960
6061private static final String CLASS_SUFFIX = ".class" ;
62+
6163/** Use an internal WeavingTransformer */
6264private final WeavingTransformer weavingTransformer ;
6365
@@ -101,8 +103,7 @@ public void addTransformer(ClassFileTransformer transformer) {
101103 */
102104public ClassLoader getThrowawayClassLoader () {
103105WebappClassLoader tempLoader = new WebappClassLoader ();
104- // Use reflection to copy all the fields since most of them are private
105- // on pre-5.5 Tomcat.
106+ // Use reflection to copy all the fields since most of them are private on pre-5.5 Tomcat.
106107shallowCopyFieldState (this , tempLoader );
107108return tempLoader ;
108109}
@@ -111,65 +112,41 @@ public ClassLoader getThrowawayClassLoader() {
111112@ Override
112113protected ResourceEntry findResourceInternal (String name , String path ) {
113114ResourceEntry entry = super .findResourceInternal (name , path );
114- // Postpone String parsing as much as possible (it is slow).
115115if (entry != null && entry .binaryContent != null && path .endsWith (CLASS_SUFFIX )) {
116- String className = (name .endsWith (CLASS_SUFFIX ) ? name .substring (0 , name .length () - CLASS_SUFFIX .length ())
117- : name );
118- byte [] transformed = this .weavingTransformer .transformIfNecessary (className , entry .binaryContent );
119- entry .binaryContent = transformed ;
116+ String className = (name .endsWith (CLASS_SUFFIX ) ? name .substring (0 , name .length () - CLASS_SUFFIX .length ()) : name );
117+ entry .binaryContent = this .weavingTransformer .transformIfNecessary (className , entry .binaryContent );
120118}
121119return entry ;
122120}
123121
124122@ Override
125123public String toString () {
126124StringBuilder sb = new StringBuilder (getClass ().getName ());
127- sb .append ("\r \n " );
128- sb .append (super .toString ());
125+ sb .append ("\r \n " ).append (super .toString ());
129126return sb .toString ();
130127}
131128
132129
133130// The code below is originally taken from ReflectionUtils and optimized for
134131// local usage. There is no dependency on ReflectionUtils to keep this class
135132// self-contained (since it gets deployed into Tomcat's server class loader).
136-
137- /**
138- * Given the source object and the destination, which must be the same class
139- * or a subclass, copy all fields, including inherited fields. Designed to
140- * work on objects with public no-arg constructors.
141- * @throws IllegalArgumentException if arguments are incompatible or either
142- * is {@code null}
143- */
144- private static void shallowCopyFieldState (final Object src , final Object dest ) throws IllegalArgumentException {
145- if (src == null ) {
146- throw new IllegalArgumentException ("Source for field copy cannot be null" );
147- }
148- if (dest == null ) {
149- throw new IllegalArgumentException ("Destination for field copy cannot be null" );
150- }
151- Class targetClass = findCommonAncestor (src .getClass (), dest .getClass ());
152-
133+ private static void shallowCopyFieldState (final WebappClassLoader src , final WebappClassLoader dest ) {
134+ Class <?> targetClass = WebappClassLoader .class ;
153135// Keep backing up the inheritance hierarchy.
154136do {
155- // Copy each field declared on this class unless it's static or
156- // file.
157137Field [] fields = targetClass .getDeclaredFields ();
158- for (int i = 0 ; i < fields .length ; i ++) {
159- Field field = fields [i ];
160- // Skip static and final fields (the old FieldFilter)
161- // do not copy resourceEntries - it's a cache that holds class entries.
138+ for (Field field : fields ) {
139+ // Do not copy resourceEntries - it's a cache that holds class entries.
162140if (!(Modifier .isStatic (field .getModifiers ()) || Modifier .isFinal (field .getModifiers ()) ||
163141field .getName ().equals ("resourceEntries" ))) {
164142try {
165- // copy the field (the old FieldCallback)
166143field .setAccessible (true );
167144Object srcValue = field .get (src );
168145field .set (dest , srcValue );
169146}
170147catch (IllegalAccessException ex ) {
171148throw new IllegalStateException (
172- "Shouldn't be illegal to access field '" + fields [ i ] .getName () + "': " + ex );
149+ "Shouldn't be illegal to access field '" + field .getName () + "': " + ex );
173150}
174151}
175152}
@@ -178,23 +155,4 @@ private static void shallowCopyFieldState(final Object src, final Object dest) t
178155while (targetClass != null && targetClass != Object .class );
179156}
180157
181- private static Class findCommonAncestor (Class one , Class two ) throws IllegalArgumentException {
182- Class ancestor = one ;
183- while (ancestor != Object .class || ancestor != null ) {
184- if (ancestor .isAssignableFrom (two )) {
185- return ancestor ;
186- }
187- ancestor = ancestor .getSuperclass ();
188- }
189- // try the other class hierarchy
190- ancestor = two ;
191- while (ancestor != Object .class || ancestor != null ) {
192- if (ancestor .isAssignableFrom (one )) {
193- return ancestor ;
194- }
195- ancestor = ancestor .getSuperclass ();
196- }
197- return null ;
198- }
199-
200158}
0 commit comments