View Javadoc

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.struts2.jasper.servlet;
19  
20  import org.apache.struts2.jasper.Constants;
21  
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.net.URL;
25  import java.net.URLClassLoader;
26  import java.security.CodeSource;
27  import java.security.PermissionCollection;
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 ClassLoader parent;
41      private SecurityManager securityManager;
42  
43      public JasperLoader(URL[] urls, ClassLoader parent,
44                          PermissionCollection permissionCollection,
45                          CodeSource codeSource) {
46          super(urls, parent);
47          this.permissionCollection = permissionCollection;
48          this.parent = parent;
49          this.securityManager = System.getSecurityManager();
50      }
51  
52      /***
53       * Load the class with the specified name.  This method searches for
54       * classes in the same manner as <code>loadClass(String, boolean)</code>
55       * with <code>false</code> as the second argument.
56       *
57       * @param name Name of the class to be loaded
58       * @throws ClassNotFoundException if the class was not found
59       */
60      public Class loadClass(String name) throws ClassNotFoundException {
61  
62          return (loadClass(name, false));
63      }
64  
65      /***
66       * Load the class with the specified name, searching using the following
67       * algorithm until it finds and returns the class.  If the class cannot
68       * be found, returns <code>ClassNotFoundException</code>.
69       * <ul>
70       * <li>Call <code>findLoadedClass(String)</code> to check if the
71       * class has already been loaded.  If it has, the same
72       * <code>Class</code> object is returned.</li>
73       * <li>If the <code>delegate</code> property is set to <code>true</code>,
74       * call the <code>loadClass()</code> method of the parent class
75       * loader, if any.</li>
76       * <li>Call <code>findClass()</code> to find this class in our locally
77       * defined repositories.</li>
78       * <li>Call the <code>loadClass()</code> method of our parent
79       * class loader, if any.</li>
80       * </ul>
81       * If the class was found using the above steps, and the
82       * <code>resolve</code> flag is <code>true</code>, this method will then
83       * call <code>resolveClass(Class)</code> on the resulting Class object.
84       *
85       * @param name    Name of the class to be loaded
86       * @param resolve If <code>true</code> then resolve the class
87       * @throws ClassNotFoundException if the class was not found
88       */
89      public Class loadClass(final String name, boolean resolve)
90              throws ClassNotFoundException {
91  
92          Class clazz = null;
93  
94          // (0) Check our previously loaded class cache
95          clazz = findLoadedClass(name);
96          if (clazz != null) {
97              if (resolve)
98                  resolveClass(clazz);
99              return (clazz);
100         }
101 
102         // (.5) Permission to access this class when using a SecurityManager
103         if (securityManager != null) {
104             int dot = name.lastIndexOf('.');
105             if (dot >= 0) {
106                 try {
107                     // Do not call the security manager since by default, we grant that package.
108                     if (!"org.apache.struts2.jasper.runtime".equalsIgnoreCase(name.substring(0, dot))) {
109                         securityManager.checkPackageAccess(name.substring(0, dot));
110                     }
111                 } catch (SecurityException se) {
112                     String error = "Security Violation, attempt to use " +
113                             "Restricted Class: " + name;
114                     se.printStackTrace();
115                     throw new ClassNotFoundException(error);
116                 }
117             }
118         }
119 
120         if (!name.startsWith(Constants.JSP_PACKAGE_NAME)) {
121             // Class is not in org.apache.jsp, therefore, have our
122             // parent load it
123             clazz = parent.loadClass(name);
124             if (resolve)
125                 resolveClass(clazz);
126             return clazz;
127         }
128 
129         return findClass(name);
130     }
131 
132 
133     /***
134      * Delegate to parent
135      *
136      * @see java.lang.ClassLoader#getResourceAsStream(java.lang.String)
137      */
138     public InputStream getResourceAsStream(String name) {
139         InputStream is = parent.getResourceAsStream(name);
140         if (is == null) {
141             URL url = findResource(name);
142             if (url != null) {
143                 try {
144                     is = url.openStream();
145                 } catch (IOException e) {
146                     is = null;
147                 }
148             }
149         }
150         return is;
151     }
152 
153 
154     /***
155      * Get the Permissions for a CodeSource.
156      * <p/>
157      * Since this ClassLoader is only used for a JSP page in
158      * a web application context, we just return our preset
159      * PermissionCollection for the web app context.
160      *
161      * @param codeSource Code source where the code was loaded from
162      * @return PermissionCollection for CodeSource
163      */
164     public final PermissionCollection getPermissions(CodeSource codeSource) {
165         return permissionCollection;
166     }
167 }