KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > core > OverridingClassLoader


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.core;
18
19 import java.io.IOException JavaDoc;
20 import java.io.InputStream JavaDoc;
21 import java.util.Collections JavaDoc;
22 import java.util.HashSet JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.Set JavaDoc;
25
26 import org.springframework.util.Assert;
27 import org.springframework.util.FileCopyUtils;
28
29 /**
30  * <code>ClassLoader</code> that does <i>not</i> always delegate to the
31  * parent loader, as normal class loaders do. This enables, for example,
32  * instrumentation to be forced in the overriding ClassLoader, or a
33  * "throwaway" class loading behavior, where selected classes are
34  * temporarily loaded in the overriding ClassLoader, in order to be load
35  * an instrumented version of the class in the parent ClassLoader later on.
36  *
37  * @author Rod Johnson
38  * @author Juergen Hoeller
39  * @since 2.0.1
40  */

41 public class OverridingClassLoader extends ClassLoader JavaDoc {
42
43     private static final String JavaDoc CLASS_FILE_SUFFIX = ".class";
44
45
46     private final Set JavaDoc excludedPackages = Collections.synchronizedSet(new HashSet JavaDoc());
47
48     private final Set JavaDoc excludedClasses = Collections.synchronizedSet(new HashSet JavaDoc());
49
50
51     /**
52      * Create a new OverridingClassLoader for the given class loader.
53      * @param parent the ClassLoader to build an overriding ClassLoader for
54      */

55     public OverridingClassLoader(ClassLoader JavaDoc parent) {
56         super(parent);
57         this.excludedPackages.add("java.");
58         this.excludedPackages.add("javax.");
59     }
60
61
62     /**
63      * Add a package name to exclude from overriding.
64      * <p>Any class whose fully-qualified name starts with the name registered
65      * here will be handled by the parent ClassLoader in the usual fashion.
66      * @param packageName the package name to exclude
67      */

68     public void excludePackage(String JavaDoc packageName) {
69         Assert.notNull(packageName, "Package name must not be null");
70         this.excludedPackages.add(packageName);
71     }
72
73     /**
74      * Add a class name to exclude from overriding.
75      * <p>Any class name registered here will be handled by
76      * the parent ClassLoader in the usual fashion.
77      * @param className the class name to exclude
78      */

79     public void excludeClass(String JavaDoc className) {
80         Assert.notNull(className, "Class name must not be null");
81         this.excludedClasses.add(className);
82     }
83
84
85     protected Class JavaDoc loadClass(String JavaDoc name, boolean resolve) throws ClassNotFoundException JavaDoc {
86         Class JavaDoc result = null;
87
88         if (isEligibleForOverriding(name)) {
89             result = findLoadedClass(name);
90             if (result == null) {
91                 String JavaDoc internalName = name.replace('.', '/') + CLASS_FILE_SUFFIX;
92                 InputStream JavaDoc is = getParent().getResourceAsStream(internalName);
93                 if (is != null) {
94                     try {
95                         // Load the raw bytes.
96
byte[] bytes = FileCopyUtils.copyToByteArray(is);
97                         // Transform if necessary and use the potentially transformed bytes.
98
byte[] transformed = transformIfNecessary(name, bytes);
99                         result = defineClass(name, transformed, 0, transformed.length);
100                     }
101                     catch (IOException JavaDoc ex) {
102                         throw new ClassNotFoundException JavaDoc("Cannot load resource for class [" + name + "]", ex);
103                     }
104                 }
105             }
106         }
107
108         if (result != null) {
109             if (resolve) {
110                 resolveClass(result);
111             }
112             return result;
113         }
114         else {
115             return super.loadClass(name, resolve);
116         }
117     }
118
119     /**
120      * Determine whether the specified class is eligible for overriding
121      * by this class loader.
122      * <p>The default implementation checks against excluded packages and classes.
123      * @param className the class name to check
124      * @return whether the specified class is eligible
125      * @see #excludePackage
126      * @see #excludeClass
127      */

128     protected boolean isEligibleForOverriding(String JavaDoc className) {
129         if (this.excludedClasses.contains(className)) {
130             return false;
131         }
132         for (Iterator JavaDoc it = this.excludedPackages.iterator(); it.hasNext();) {
133             String JavaDoc packageName = (String JavaDoc) it.next();
134             if (className.startsWith(packageName)) {
135                 return false;
136             }
137         }
138         return true;
139     }
140
141
142     /**
143      * Transformation hook to be implemented by subclasses.
144      * <p>The default implementation simply returns the given bytes as-is.
145      * @param name the fully-qualified name of the class being transformed
146      * @param bytes the raw bytes of the class
147      * @return the transformed bytes (never <code>null</code>;
148      * same as the input bytes if the transformation produced no changes)
149      */

150     protected byte[] transformIfNecessary(String JavaDoc name, byte[] bytes) {
151         return bytes;
152     }
153
154 }
155
Popular Tags