001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.jasper.servlet;
019:
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.net.URL;
023: import java.net.URLClassLoader;
024: import java.security.CodeSource;
025: import java.security.PermissionCollection;
026:
027: import org.apache.jasper.Constants;
028:
029: /**
030: * Class loader for loading servlet class files (corresponding to JSP files)
031: * and tag handler class files (corresponding to tag files).
032: *
033: * @author Anil K. Vijendran
034: * @author Harish Prabandham
035: * @author Jean-Francois Arcand
036: */
037: public class JasperLoader extends URLClassLoader {
038:
039: private PermissionCollection permissionCollection;
040: private CodeSource codeSource;
041: private String className;
042: private ClassLoader parent;
043: private SecurityManager securityManager;
044:
045: public JasperLoader(URL[] urls, ClassLoader parent,
046: PermissionCollection permissionCollection,
047: CodeSource codeSource) {
048: super (urls, parent);
049: this .permissionCollection = permissionCollection;
050: this .codeSource = codeSource;
051: this .parent = parent;
052: this .securityManager = System.getSecurityManager();
053: }
054:
055: /**
056: * Load the class with the specified name. This method searches for
057: * classes in the same manner as <code>loadClass(String, boolean)</code>
058: * with <code>false</code> as the second argument.
059: *
060: * @param name Name of the class to be loaded
061: *
062: * @exception ClassNotFoundException if the class was not found
063: */
064: public Class loadClass(String name) throws ClassNotFoundException {
065:
066: return (loadClass(name, false));
067: }
068:
069: /**
070: * Load the class with the specified name, searching using the following
071: * algorithm until it finds and returns the class. If the class cannot
072: * be found, returns <code>ClassNotFoundException</code>.
073: * <ul>
074: * <li>Call <code>findLoadedClass(String)</code> to check if the
075: * class has already been loaded. If it has, the same
076: * <code>Class</code> object is returned.</li>
077: * <li>If the <code>delegate</code> property is set to <code>true</code>,
078: * call the <code>loadClass()</code> method of the parent class
079: * loader, if any.</li>
080: * <li>Call <code>findClass()</code> to find this class in our locally
081: * defined repositories.</li>
082: * <li>Call the <code>loadClass()</code> method of our parent
083: * class loader, if any.</li>
084: * </ul>
085: * If the class was found using the above steps, and the
086: * <code>resolve</code> flag is <code>true</code>, this method will then
087: * call <code>resolveClass(Class)</code> on the resulting Class object.
088: *
089: * @param name Name of the class to be loaded
090: * @param resolve If <code>true</code> then resolve the class
091: *
092: * @exception ClassNotFoundException if the class was not found
093: */
094: public Class loadClass(final String name, boolean resolve)
095: throws ClassNotFoundException {
096:
097: Class clazz = null;
098:
099: // (0) Check our previously loaded class cache
100: clazz = findLoadedClass(name);
101: if (clazz != null) {
102: if (resolve)
103: resolveClass(clazz);
104: return (clazz);
105: }
106:
107: // (.5) Permission to access this class when using a SecurityManager
108: if (securityManager != null) {
109: int dot = name.lastIndexOf('.');
110: if (dot >= 0) {
111: try {
112: // Do not call the security manager since by default, we grant that package.
113: if (!"org.apache.jasper.runtime"
114: .equalsIgnoreCase(name.substring(0, dot))) {
115: securityManager.checkPackageAccess(name
116: .substring(0, dot));
117: }
118: } catch (SecurityException se) {
119: String error = "Security Violation, attempt to use "
120: + "Restricted Class: " + name;
121: se.printStackTrace();
122: throw new ClassNotFoundException(error);
123: }
124: }
125: }
126:
127: if (!name.startsWith(Constants.JSP_PACKAGE_NAME)) {
128: // Class is not in org.apache.jsp, therefore, have our
129: // parent load it
130: clazz = parent.loadClass(name);
131: if (resolve)
132: resolveClass(clazz);
133: return clazz;
134: }
135:
136: return findClass(name);
137: }
138:
139: /**
140: * Delegate to parent
141: *
142: * @see java.lang.ClassLoader#getResourceAsStream(java.lang.String)
143: */
144: public InputStream getResourceAsStream(String name) {
145: InputStream is = parent.getResourceAsStream(name);
146: if (is == null) {
147: URL url = findResource(name);
148: if (url != null) {
149: try {
150: is = url.openStream();
151: } catch (IOException e) {
152: is = null;
153: }
154: }
155: }
156: return is;
157: }
158:
159: /**
160: * Get the Permissions for a CodeSource.
161: *
162: * Since this ClassLoader is only used for a JSP page in
163: * a web application context, we just return our preset
164: * PermissionCollection for the web app context.
165: *
166: * @param codeSource Code source where the code was loaded from
167: * @return PermissionCollection for CodeSource
168: */
169: public final PermissionCollection getPermissions(
170: CodeSource codeSource) {
171: return permissionCollection;
172: }
173: }
|