1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.jasper.servlet;
19
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.net.URL;
23 import java.net.URLClassLoader;
24 import java.security.CodeSource;
25 import java.security.PermissionCollection;
26
27 import org.apache.jasper.Constants;
28
29 /**
30 * Class loader for loading servlet class files (corresponding to JSP files)
31 * and tag handler class files (corresponding to tag files).
32 *
33 * @author Anil K. Vijendran
34 * @author Harish Prabandham
35 * @author Jean-Francois Arcand
36 */
37 public class JasperLoader extends URLClassLoader {
38
39 private PermissionCollection permissionCollection;
40 private CodeSource codeSource;
41 private String className;
42 private ClassLoader parent;
43 private SecurityManager securityManager;
44
45 public JasperLoader(URL[] urls, ClassLoader parent,
46 PermissionCollection permissionCollection,
47 CodeSource codeSource) {
48 super(urls, parent);
49 this.permissionCollection = permissionCollection;
50 this.codeSource = codeSource;
51 this.parent = parent;
52 this.securityManager = System.getSecurityManager();
53 }
54
55 /**
56 * Load the class with the specified name. This method searches for
57 * classes in the same manner as <code>loadClass(String, boolean)</code>
58 * with <code>false</code> as the second argument.
59 *
60 * @param name Name of the class to be loaded
61 *
62 * @exception ClassNotFoundException if the class was not found
63 */
64 public Class loadClass(String name) throws ClassNotFoundException {
65
66 return (loadClass(name, false));
67 }
68
69 /**
70 * Load the class with the specified name, searching using the following
71 * algorithm until it finds and returns the class. If the class cannot
72 * be found, returns <code>ClassNotFoundException</code>.
73 * <ul>
74 * <li>Call <code>findLoadedClass(String)</code> to check if the
75 * class has already been loaded. If it has, the same
76 * <code>Class</code> object is returned.</li>
77 * <li>If the <code>delegate</code> property is set to <code>true</code>,
78 * call the <code>loadClass()</code> method of the parent class
79 * loader, if any.</li>
80 * <li>Call <code>findClass()</code> to find this class in our locally
81 * defined repositories.</li>
82 * <li>Call the <code>loadClass()</code> method of our parent
83 * class loader, if any.</li>
84 * </ul>
85 * If the class was found using the above steps, and the
86 * <code>resolve</code> flag is <code>true</code>, this method will then
87 * call <code>resolveClass(Class)</code> on the resulting Class object.
88 *
89 * @param name Name of the class to be loaded
90 * @param resolve If <code>true</code> then resolve the class
91 *
92 * @exception ClassNotFoundException if the class was not found
93 */
94 public Class loadClass(final String name, boolean resolve)
95 throws ClassNotFoundException {
96
97 Class clazz = null;
98
99 // (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".equalsIgnoreCase(name.substring(0,dot))){
114 securityManager.checkPackageAccess(name.substring(0,dot));
115 }
116 } catch (SecurityException se) {
117 String error = "Security Violation, attempt to use " +
118 "Restricted Class: " + name;
119 se.printStackTrace();
120 throw new ClassNotFoundException(error);
121 }
122 }
123 }
124
125 if( !name.startsWith(Constants.JSP_PACKAGE_NAME) ) {
126 // Class is not in org.apache.jsp, therefore, have our
127 // parent load it
128 clazz = parent.loadClass(name);
129 if( resolve )
130 resolveClass(clazz);
131 return clazz;
132 }
133
134 return findClass(name);
135 }
136
137
138 /**
139 * Delegate to parent
140 *
141 * @see java.lang.ClassLoader#getResourceAsStream(java.lang.String)
142 */
143 public InputStream getResourceAsStream(String name) {
144 InputStream is = parent.getResourceAsStream(name);
145 if (is == null) {
146 URL url = findResource(name);
147 if (url != null) {
148 try {
149 is = url.openStream();
150 } catch (IOException e) {
151 is = null;
152 }
153 }
154 }
155 return is;
156 }
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(CodeSource codeSource) {
170 return permissionCollection;
171 }
172 }