001: /*
002: * Copyright 1999,2004 The Apache Software Foundation.
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.apache.jasper.servlet;
018:
019: import java.net.URL;
020: import java.net.URLClassLoader;
021: import java.security.AccessController;
022: import java.security.CodeSource;
023: import java.security.PermissionCollection;
024: import java.security.PrivilegedAction;
025: import java.security.PrivilegedActionException;
026: import java.security.PrivilegedExceptionAction;
027:
028: import org.apache.jasper.Constants;
029:
030: /**
031: * Class loader for loading servlet class files (corresponding to JSP files)
032: * and tag handler class files (corresponding to tag files).
033: *
034: * @author Anil K. Vijendran
035: * @author Harish Prabandham
036: * @author Jean-Francois Arcand
037: */
038: public class JasperLoader extends URLClassLoader {
039:
040: private PermissionCollection permissionCollection;
041: private CodeSource codeSource;
042: private String className;
043: private ClassLoader parent;
044: private SecurityManager securityManager;
045: private PrivilegedLoadClass privLoadClass;
046:
047: public JasperLoader(URL[] urls, ClassLoader parent,
048: PermissionCollection permissionCollection,
049: CodeSource codeSource) {
050: super (urls, parent);
051: this .permissionCollection = permissionCollection;
052: this .codeSource = codeSource;
053: this .parent = parent;
054: this .privLoadClass = new PrivilegedLoadClass();
055: this .securityManager = System.getSecurityManager();
056: }
057:
058: /**
059: * Load the class with the specified name. This method searches for
060: * classes in the same manner as <code>loadClass(String, boolean)</code>
061: * with <code>false</code> as the second argument.
062: *
063: * @param name Name of the class to be loaded
064: *
065: * @exception ClassNotFoundException if the class was not found
066: */
067: public Class loadClass(String name) throws ClassNotFoundException {
068:
069: return (loadClass(name, false));
070: }
071:
072: /**
073: * Load the class with the specified name, searching using the following
074: * algorithm until it finds and returns the class. If the class cannot
075: * be found, returns <code>ClassNotFoundException</code>.
076: * <ul>
077: * <li>Call <code>findLoadedClass(String)</code> to check if the
078: * class has already been loaded. If it has, the same
079: * <code>Class</code> object is returned.</li>
080: * <li>If the <code>delegate</code> property is set to <code>true</code>,
081: * call the <code>loadClass()</code> method of the parent class
082: * loader, if any.</li>
083: * <li>Call <code>findClass()</code> to find this class in our locally
084: * defined repositories.</li>
085: * <li>Call the <code>loadClass()</code> method of our parent
086: * class loader, if any.</li>
087: * </ul>
088: * If the class was found using the above steps, and the
089: * <code>resolve</code> flag is <code>true</code>, this method will then
090: * call <code>resolveClass(Class)</code> on the resulting Class object.
091: *
092: * @param name Name of the class to be loaded
093: * @param resolve If <code>true</code> then resolve the class
094: *
095: * @exception ClassNotFoundException if the class was not found
096: */
097: public Class loadClass(final String name, boolean resolve)
098: throws ClassNotFoundException {
099:
100: Class clazz = null;
101:
102: // (0) Check our previously loaded class cache
103: clazz = findLoadedClass(name);
104: if (clazz != null) {
105: if (resolve)
106: resolveClass(clazz);
107: return (clazz);
108: }
109:
110: // (.5) Permission to access this class when using a SecurityManager
111: if (securityManager != null) {
112: int dot = name.lastIndexOf('.');
113: if (dot >= 0) {
114: try {
115: // Do not call the security manager since by default, we grant that package.
116: if (!"org.apache.jasper.runtime"
117: .equalsIgnoreCase(name.substring(0, dot))) {
118: securityManager.checkPackageAccess(name
119: .substring(0, dot));
120: }
121: } catch (SecurityException se) {
122: String error = "Security Violation, attempt to use "
123: + "Restricted Class: " + name;
124: se.printStackTrace();
125: throw new ClassNotFoundException(error);
126: }
127: }
128: }
129:
130: // Class is in a package, delegate to thread context class loader
131: if (!name.startsWith(Constants.JSP_PACKAGE_NAME)) {
132: if (securityManager != null) {
133: final ClassLoader classLoader = (ClassLoader) AccessController
134: .doPrivileged(privLoadClass);
135: try {
136: clazz = (Class) AccessController
137: .doPrivileged(new PrivilegedExceptionAction() {
138: public Object run() throws Exception {
139: return classLoader.loadClass(name);
140: }
141: });
142: } catch (PrivilegedActionException ex) {
143: Exception rootCause = ex.getException();
144: if (rootCause instanceof ClassNotFoundException) {
145: throw (ClassNotFoundException) rootCause;
146: } else {
147: throw new ClassNotFoundException(
148: "JasperLoader", rootCause);
149: }
150: }
151: } else {
152: clazz = parent.loadClass(name);
153: }
154:
155: if (resolve)
156: resolveClass(clazz);
157: return clazz;
158: }
159:
160: return findClass(name);
161: }
162:
163: /**
164: * Get the Permissions for a CodeSource.
165: *
166: * Since this ClassLoader is only used for a JSP page in
167: * a web application context, we just return our preset
168: * PermissionCollection for the web app context.
169: *
170: * @param codeSource Code source where the code was loaded from
171: * @return PermissionCollection for CodeSource
172: */
173: public final PermissionCollection getPermissions(
174: CodeSource codeSource) {
175: return permissionCollection;
176: }
177:
178: private class PrivilegedLoadClass implements PrivilegedAction {
179:
180: public Object run() {
181: return Thread.currentThread().getContextClassLoader();
182: }
183: }
184: }
|