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
6061 private static final String CLASS_SUFFIX = ".class" ;
62+
6163 /** Use an internal WeavingTransformer */
6264 private final WeavingTransformer weavingTransformer ;
6365
@@ -101,8 +103,7 @@ public void addTransformer(ClassFileTransformer transformer) {
101103 */
102104 public ClassLoader getThrowawayClassLoader () {
103105 WebappClassLoader 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.
106107 shallowCopyFieldState (this , tempLoader );
107108 return tempLoader ;
108109 }
@@ -111,65 +112,41 @@ public ClassLoader getThrowawayClassLoader() {
111112 @ Override
112113 protected ResourceEntry findResourceInternal (String name , String path ) {
113114 ResourceEntry entry = super .findResourceInternal (name , path );
114- // Postpone String parsing as much as possible (it is slow).
115115 if (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 }
121119 return entry ;
122120 }
123121
124122 @ Override
125123 public String toString () {
126124 StringBuilder sb = new StringBuilder (getClass ().getName ());
127- sb .append ("\r \n " );
128- sb .append (super .toString ());
125+ sb .append ("\r \n " ).append (super .toString ());
129126 return 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.
154136 do {
155- // Copy each field declared on this class unless it's static or
156- // file.
157137 Field [] 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.
162140 if (!(Modifier .isStatic (field .getModifiers ()) || Modifier .isFinal (field .getModifiers ()) ||
163141 field .getName ().equals ("resourceEntries" ))) {
164142 try {
165- // copy the field (the old FieldCallback)
166143 field .setAccessible (true );
167144 Object srcValue = field .get (src );
168145 field .set (dest , srcValue );
169146 }
170147 catch (IllegalAccessException ex ) {
171148 throw 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
178155 while (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