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
19 package org.apache.catalina.core;
20
21
22 import java.io.InputStream;
23 import java.lang.reflect.InvocationTargetException;
24 import java.lang.reflect.Method;
25 import java.net.MalformedURLException;
26 import java.net.URL;
27 import java.security.AccessController;
28 import java.security.PrivilegedActionException;
29 import java.security.PrivilegedExceptionAction;
30 import java.util.Enumeration;
31 import java.util.HashMap;
32 import java.util.Set;
33
34 import javax.servlet.RequestDispatcher;
35 import javax.servlet.Servlet;
36 import javax.servlet.ServletContext;
37 import javax.servlet.ServletException;
38
39 import org.apache.catalina.Globals;
40 import org.apache.catalina.security.SecurityUtil;
41
42
43 /**
44 * Facade object which masks the internal <code>ApplicationContext</code>
45 * object from the web application.
46 *
47 * @author Remy Maucherat
48 * @author Jean-Francois Arcand
49 * @version $Revision: 505593 $ $Date: 2007-02-10 01:54:56 +0100 (sam., 10 févr. 2007) $
50 */
51
52 public final class ApplicationContextFacade
53 implements ServletContext {
54
55 // ---------------------------------------------------------- Attributes
56 /**
57 * Cache Class object used for reflection.
58 */
59 private HashMap classCache;
60
61
62 /**
63 * Cache method object.
64 */
65 private HashMap objectCache;
66
67
68 // ----------------------------------------------------------- Constructors
69
70
71 /**
72 * Construct a new instance of this class, associated with the specified
73 * Context instance.
74 *
75 * @param context The associated Context instance
76 */
77 public ApplicationContextFacade(ApplicationContext context) {
78 super();
79 this.context = context;
80
81 classCache = new HashMap();
82 objectCache = new HashMap();
83 initClassCache();
84 }
85
86
87 private void initClassCache(){
88 Class[] clazz = new Class[]{String.class};
89 classCache.put("getContext", clazz);
90 classCache.put("getMimeType", clazz);
91 classCache.put("getResourcePaths", clazz);
92 classCache.put("getResource", clazz);
93 classCache.put("getResourceAsStream", clazz);
94 classCache.put("getRequestDispatcher", clazz);
95 classCache.put("getNamedDispatcher", clazz);
96 classCache.put("getServlet", clazz);
97 classCache.put("getInitParameter", clazz);
98 classCache.put("setAttribute", new Class[]{String.class, Object.class});
99 classCache.put("removeAttribute", clazz);
100 classCache.put("getRealPath", clazz);
101 classCache.put("getAttribute", clazz);
102 classCache.put("log", clazz);
103 }
104
105
106 // ----------------------------------------------------- Instance Variables
107
108
109 /**
110 * Wrapped application context.
111 */
112 private ApplicationContext context = null;
113
114
115
116 // ------------------------------------------------- ServletContext Methods
117
118
119 public ServletContext getContext(String uripath) {
120 ServletContext theContext = null;
121 if (SecurityUtil.isPackageProtectionEnabled()) {
122 theContext = (ServletContext)
123 doPrivileged("getContext", new Object[]{uripath});
124 } else {
125 theContext = context.getContext(uripath);
126 }
127 if ((theContext != null) &&
128 (theContext instanceof ApplicationContext)){
129 theContext = ((ApplicationContext)theContext).getFacade();
130 }
131 return (theContext);
132 }
133
134
135 public int getMajorVersion() {
136 return context.getMajorVersion();
137 }
138
139
140 public int getMinorVersion() {
141 return context.getMinorVersion();
142 }
143
144
145 public String getMimeType(String file) {
146 if (SecurityUtil.isPackageProtectionEnabled()) {
147 return (String)doPrivileged("getMimeType", new Object[]{file});
148 } else {
149 return context.getMimeType(file);
150 }
151 }
152
153
154 public Set getResourcePaths(String path) {
155 if (SecurityUtil.isPackageProtectionEnabled()){
156 return (Set)doPrivileged("getResourcePaths", new Object[]{path});
157 } else {
158 return context.getResourcePaths(path);
159 }
160 }
161
162
163 public URL getResource(String path)
164 throws MalformedURLException {
165 if (Globals.IS_SECURITY_ENABLED) {
166 try {
167 return (URL) invokeMethod(context, "getResource",
168 new Object[]{path});
169 } catch(Throwable t) {
170 if (t instanceof MalformedURLException){
171 throw (MalformedURLException)t;
172 }
173 return null;
174 }
175 } else {
176 return context.getResource(path);
177 }
178 }
179
180
181 public InputStream getResourceAsStream(String path) {
182 if (SecurityUtil.isPackageProtectionEnabled()) {
183 return (InputStream) doPrivileged("getResourceAsStream",
184 new Object[]{path});
185 } else {
186 return context.getResourceAsStream(path);
187 }
188 }
189
190
191 public RequestDispatcher getRequestDispatcher(final String path) {
192 if (SecurityUtil.isPackageProtectionEnabled()) {
193 return (RequestDispatcher) doPrivileged("getRequestDispatcher",
194 new Object[]{path});
195 } else {
196 return context.getRequestDispatcher(path);
197 }
198 }
199
200
201 public RequestDispatcher getNamedDispatcher(String name) {
202 if (SecurityUtil.isPackageProtectionEnabled()) {
203 return (RequestDispatcher) doPrivileged("getNamedDispatcher",
204 new Object[]{name});
205 } else {
206 return context.getNamedDispatcher(name);
207 }
208 }
209
210
211 public Servlet getServlet(String name)
212 throws ServletException {
213 if (SecurityUtil.isPackageProtectionEnabled()) {
214 try {
215 return (Servlet) invokeMethod(context, "getServlet",
216 new Object[]{name});
217 } catch (Throwable t) {
218 if (t instanceof ServletException) {
219 throw (ServletException) t;
220 }
221 return null;
222 }
223 } else {
224 return context.getServlet(name);
225 }
226 }
227
228
229 public Enumeration getServlets() {
230 if (SecurityUtil.isPackageProtectionEnabled()) {
231 return (Enumeration) doPrivileged("getServlets", null);
232 } else {
233 return context.getServlets();
234 }
235 }
236
237
238 public Enumeration getServletNames() {
239 if (SecurityUtil.isPackageProtectionEnabled()) {
240 return (Enumeration) doPrivileged("getServletNames", null);
241 } else {
242 return context.getServletNames();
243 }
244 }
245
246
247 public void log(String msg) {
248 if (SecurityUtil.isPackageProtectionEnabled()) {
249 doPrivileged("log", new Object[]{msg} );
250 } else {
251 context.log(msg);
252 }
253 }
254
255
256 public void log(Exception exception, String msg) {
257 if (SecurityUtil.isPackageProtectionEnabled()) {
258 doPrivileged("log", new Class[]{Exception.class, String.class},
259 new Object[]{exception,msg});
260 } else {
261 context.log(exception, msg);
262 }
263 }
264
265
266 public void log(String message, Throwable throwable) {
267 if (SecurityUtil.isPackageProtectionEnabled()) {
268 doPrivileged("log", new Class[]{String.class, Throwable.class},
269 new Object[]{message, throwable});
270 } else {
271 context.log(message, throwable);
272 }
273 }
274
275
276 public String getRealPath(String path) {
277 if (SecurityUtil.isPackageProtectionEnabled()) {
278 return (String) doPrivileged("getRealPath", new Object[]{path});
279 } else {
280 return context.getRealPath(path);
281 }
282 }
283
284
285 public String getServerInfo() {
286 if (SecurityUtil.isPackageProtectionEnabled()) {
287 return (String) doPrivileged("getServerInfo", null);
288 } else {
289 return context.getServerInfo();
290 }
291 }
292
293
294 public String getInitParameter(String name) {
295 if (SecurityUtil.isPackageProtectionEnabled()) {
296 return (String) doPrivileged("getInitParameter",
297 new Object[]{name});
298 } else {
299 return context.getInitParameter(name);
300 }
301 }
302
303
304 public Enumeration getInitParameterNames() {
305 if (SecurityUtil.isPackageProtectionEnabled()) {
306 return (Enumeration) doPrivileged("getInitParameterNames", null);
307 } else {
308 return context.getInitParameterNames();
309 }
310 }
311
312
313 public Object getAttribute(String name) {
314 if (SecurityUtil.isPackageProtectionEnabled()) {
315 return doPrivileged("getAttribute", new Object[]{name});
316 } else {
317 return context.getAttribute(name);
318 }
319 }
320
321
322 public Enumeration getAttributeNames() {
323 if (SecurityUtil.isPackageProtectionEnabled()) {
324 return (Enumeration) doPrivileged("getAttributeNames", null);
325 } else {
326 return context.getAttributeNames();
327 }
328 }
329
330
331 public void setAttribute(String name, Object object) {
332 if (SecurityUtil.isPackageProtectionEnabled()) {
333 doPrivileged("setAttribute", new Object[]{name,object});
334 } else {
335 context.setAttribute(name, object);
336 }
337 }
338
339
340 public void removeAttribute(String name) {
341 if (SecurityUtil.isPackageProtectionEnabled()) {
342 doPrivileged("removeAttribute", new Object[]{name});
343 } else {
344 context.removeAttribute(name);
345 }
346 }
347
348
349 public String getServletContextName() {
350 if (SecurityUtil.isPackageProtectionEnabled()) {
351 return (String) doPrivileged("getServletContextName", null);
352 } else {
353 return context.getServletContextName();
354 }
355 }
356
357
358 public String getContextPath() {
359 if (SecurityUtil.isPackageProtectionEnabled()) {
360 return (String) doPrivileged("getContextPath", null);
361 } else {
362 return context.getContextPath();
363 }
364 }
365
366
367 /**
368 * Use reflection to invoke the requested method. Cache the method object
369 * to speed up the process
370 * @param appContext The AppliationContext object on which the method
371 * will be invoked
372 * @param methodName The method to call.
373 * @param params The arguments passed to the called method.
374 */
375 private Object doPrivileged(ApplicationContext appContext,
376 final String methodName,
377 final Object[] params) {
378 try{
379 return invokeMethod(appContext, methodName, params );
380 } catch (Throwable t){
381 throw new RuntimeException(t.getMessage());
382 }
383
384 }
385
386
387 /**
388 * Use reflection to invoke the requested method. Cache the method object
389 * to speed up the process
390 * will be invoked
391 * @param methodName The method to call.
392 * @param params The arguments passed to the called method.
393 */
394 private Object doPrivileged(final String methodName, final Object[] params){
395 try{
396 return invokeMethod(context, methodName, params);
397 }catch(Throwable t){
398 throw new RuntimeException(t.getMessage());
399 }
400 }
401
402
403 /**
404 * Use reflection to invoke the requested method. Cache the method object
405 * to speed up the process
406 * @param appContext The AppliationContext object on which the method
407 * will be invoked
408 * @param methodName The method to call.
409 * @param params The arguments passed to the called method.
410 */
411 private Object invokeMethod(ApplicationContext appContext,
412 final String methodName,
413 Object[] params)
414 throws Throwable{
415
416 try{
417 Method method = (Method)objectCache.get(methodName);
418 if (method == null){
419 method = appContext.getClass()
420 .getMethod(methodName, (Class[])classCache.get(methodName));
421 objectCache.put(methodName, method);
422 }
423
424 return executeMethod(method,appContext,params);
425 } catch (Exception ex){
426 handleException(ex, methodName);
427 return null;
428 } finally {
429 params = null;
430 }
431 }
432
433 /**
434 * Use reflection to invoke the requested method. Cache the method object
435 * to speed up the process
436 * @param methodName The method to invoke.
437 * @param clazz The class where the method is.
438 * @param params The arguments passed to the called method.
439 */
440 private Object doPrivileged(final String methodName,
441 final Class[] clazz,
442 Object[] params){
443
444 try{
445 Method method = context.getClass()
446 .getMethod(methodName, (Class[])clazz);
447 return executeMethod(method,context,params);
448 } catch (Exception ex){
449 try{
450 handleException(ex, methodName);
451 }catch (Throwable t){
452 throw new RuntimeException(t.getMessage());
453 }
454 return null;
455 } finally {
456 params = null;
457 }
458 }
459
460
461 /**
462 * Executes the method of the specified <code>ApplicationContext</code>
463 * @param method The method object to be invoked.
464 * @param context The AppliationContext object on which the method
465 * will be invoked
466 * @param params The arguments passed to the called method.
467 */
468 private Object executeMethod(final Method method,
469 final ApplicationContext context,
470 final Object[] params)
471 throws PrivilegedActionException,
472 IllegalAccessException,
473 InvocationTargetException {
474
475 if (SecurityUtil.isPackageProtectionEnabled()){
476 return AccessController.doPrivileged(new PrivilegedExceptionAction(){
477 public Object run() throws IllegalAccessException, InvocationTargetException{
478 return method.invoke(context, params);
479 }
480 });
481 } else {
482 return method.invoke(context, params);
483 }
484 }
485
486
487 /**
488 *
489 * Throw the real exception.
490 * @param ex The current exception
491 */
492 private void handleException(Exception ex, String methodName)
493 throws Throwable {
494
495 Throwable realException;
496
497 if (ex instanceof PrivilegedActionException) {
498 ex = ((PrivilegedActionException) ex).getException();
499 }
500
501 if (ex instanceof InvocationTargetException) {
502 realException =
503 ((InvocationTargetException) ex).getTargetException();
504 } else {
505 realException = ex;
506 }
507
508 throw realException;
509 }
510 }