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.catalina.core;
019:
020: import java.io.InputStream;
021: import java.lang.reflect.InvocationTargetException;
022: import java.lang.reflect.Method;
023: import java.net.MalformedURLException;
024: import java.net.URL;
025: import java.security.AccessController;
026: import java.security.PrivilegedActionException;
027: import java.security.PrivilegedExceptionAction;
028: import java.util.Enumeration;
029: import java.util.HashMap;
030: import java.util.Set;
031:
032: import javax.servlet.RequestDispatcher;
033: import javax.servlet.Servlet;
034: import javax.servlet.ServletContext;
035: import javax.servlet.ServletException;
036:
037: import org.apache.catalina.Globals;
038: import org.apache.catalina.security.SecurityUtil;
039:
040: /**
041: * Facade object which masks the internal <code>ApplicationContext</code>
042: * object from the web application.
043: *
044: * @author Remy Maucherat
045: * @author Jean-Francois Arcand
046: * @version $Revision: 505593 $ $Date: 2007-02-10 01:54:56 +0100 (sam., 10 févr. 2007) $
047: */
048:
049: public final class ApplicationContextFacade implements ServletContext {
050:
051: // ---------------------------------------------------------- Attributes
052: /**
053: * Cache Class object used for reflection.
054: */
055: private HashMap classCache;
056:
057: /**
058: * Cache method object.
059: */
060: private HashMap objectCache;
061:
062: // ----------------------------------------------------------- Constructors
063:
064: /**
065: * Construct a new instance of this class, associated with the specified
066: * Context instance.
067: *
068: * @param context The associated Context instance
069: */
070: public ApplicationContextFacade(ApplicationContext context) {
071: super ();
072: this .context = context;
073:
074: classCache = new HashMap();
075: objectCache = new HashMap();
076: initClassCache();
077: }
078:
079: private void initClassCache() {
080: Class[] clazz = new Class[] { String.class };
081: classCache.put("getContext", clazz);
082: classCache.put("getMimeType", clazz);
083: classCache.put("getResourcePaths", clazz);
084: classCache.put("getResource", clazz);
085: classCache.put("getResourceAsStream", clazz);
086: classCache.put("getRequestDispatcher", clazz);
087: classCache.put("getNamedDispatcher", clazz);
088: classCache.put("getServlet", clazz);
089: classCache.put("getInitParameter", clazz);
090: classCache.put("setAttribute", new Class[] { String.class,
091: Object.class });
092: classCache.put("removeAttribute", clazz);
093: classCache.put("getRealPath", clazz);
094: classCache.put("getAttribute", clazz);
095: classCache.put("log", clazz);
096: }
097:
098: // ----------------------------------------------------- Instance Variables
099:
100: /**
101: * Wrapped application context.
102: */
103: private ApplicationContext context = null;
104:
105: // ------------------------------------------------- ServletContext Methods
106:
107: public ServletContext getContext(String uripath) {
108: ServletContext theContext = null;
109: if (SecurityUtil.isPackageProtectionEnabled()) {
110: theContext = (ServletContext) doPrivileged("getContext",
111: new Object[] { uripath });
112: } else {
113: theContext = context.getContext(uripath);
114: }
115: if ((theContext != null)
116: && (theContext instanceof ApplicationContext)) {
117: theContext = ((ApplicationContext) theContext).getFacade();
118: }
119: return (theContext);
120: }
121:
122: public int getMajorVersion() {
123: return context.getMajorVersion();
124: }
125:
126: public int getMinorVersion() {
127: return context.getMinorVersion();
128: }
129:
130: public String getMimeType(String file) {
131: if (SecurityUtil.isPackageProtectionEnabled()) {
132: return (String) doPrivileged("getMimeType",
133: new Object[] { file });
134: } else {
135: return context.getMimeType(file);
136: }
137: }
138:
139: public Set getResourcePaths(String path) {
140: if (SecurityUtil.isPackageProtectionEnabled()) {
141: return (Set) doPrivileged("getResourcePaths",
142: new Object[] { path });
143: } else {
144: return context.getResourcePaths(path);
145: }
146: }
147:
148: public URL getResource(String path) throws MalformedURLException {
149: if (Globals.IS_SECURITY_ENABLED) {
150: try {
151: return (URL) invokeMethod(context, "getResource",
152: new Object[] { path });
153: } catch (Throwable t) {
154: if (t instanceof MalformedURLException) {
155: throw (MalformedURLException) t;
156: }
157: return null;
158: }
159: } else {
160: return context.getResource(path);
161: }
162: }
163:
164: public InputStream getResourceAsStream(String path) {
165: if (SecurityUtil.isPackageProtectionEnabled()) {
166: return (InputStream) doPrivileged("getResourceAsStream",
167: new Object[] { path });
168: } else {
169: return context.getResourceAsStream(path);
170: }
171: }
172:
173: public RequestDispatcher getRequestDispatcher(final String path) {
174: if (SecurityUtil.isPackageProtectionEnabled()) {
175: return (RequestDispatcher) doPrivileged(
176: "getRequestDispatcher", new Object[] { path });
177: } else {
178: return context.getRequestDispatcher(path);
179: }
180: }
181:
182: public RequestDispatcher getNamedDispatcher(String name) {
183: if (SecurityUtil.isPackageProtectionEnabled()) {
184: return (RequestDispatcher) doPrivileged(
185: "getNamedDispatcher", new Object[] { name });
186: } else {
187: return context.getNamedDispatcher(name);
188: }
189: }
190:
191: public Servlet getServlet(String name) throws ServletException {
192: if (SecurityUtil.isPackageProtectionEnabled()) {
193: try {
194: return (Servlet) invokeMethod(context, "getServlet",
195: new Object[] { name });
196: } catch (Throwable t) {
197: if (t instanceof ServletException) {
198: throw (ServletException) t;
199: }
200: return null;
201: }
202: } else {
203: return context.getServlet(name);
204: }
205: }
206:
207: public Enumeration getServlets() {
208: if (SecurityUtil.isPackageProtectionEnabled()) {
209: return (Enumeration) doPrivileged("getServlets", null);
210: } else {
211: return context.getServlets();
212: }
213: }
214:
215: public Enumeration getServletNames() {
216: if (SecurityUtil.isPackageProtectionEnabled()) {
217: return (Enumeration) doPrivileged("getServletNames", null);
218: } else {
219: return context.getServletNames();
220: }
221: }
222:
223: public void log(String msg) {
224: if (SecurityUtil.isPackageProtectionEnabled()) {
225: doPrivileged("log", new Object[] { msg });
226: } else {
227: context.log(msg);
228: }
229: }
230:
231: public void log(Exception exception, String msg) {
232: if (SecurityUtil.isPackageProtectionEnabled()) {
233: doPrivileged("log", new Class[] { Exception.class,
234: String.class }, new Object[] { exception, msg });
235: } else {
236: context.log(exception, msg);
237: }
238: }
239:
240: public void log(String message, Throwable throwable) {
241: if (SecurityUtil.isPackageProtectionEnabled()) {
242: doPrivileged("log", new Class[] { String.class,
243: Throwable.class }, new Object[] { message,
244: throwable });
245: } else {
246: context.log(message, throwable);
247: }
248: }
249:
250: public String getRealPath(String path) {
251: if (SecurityUtil.isPackageProtectionEnabled()) {
252: return (String) doPrivileged("getRealPath",
253: new Object[] { path });
254: } else {
255: return context.getRealPath(path);
256: }
257: }
258:
259: public String getServerInfo() {
260: if (SecurityUtil.isPackageProtectionEnabled()) {
261: return (String) doPrivileged("getServerInfo", null);
262: } else {
263: return context.getServerInfo();
264: }
265: }
266:
267: public String getInitParameter(String name) {
268: if (SecurityUtil.isPackageProtectionEnabled()) {
269: return (String) doPrivileged("getInitParameter",
270: new Object[] { name });
271: } else {
272: return context.getInitParameter(name);
273: }
274: }
275:
276: public Enumeration getInitParameterNames() {
277: if (SecurityUtil.isPackageProtectionEnabled()) {
278: return (Enumeration) doPrivileged("getInitParameterNames",
279: null);
280: } else {
281: return context.getInitParameterNames();
282: }
283: }
284:
285: public Object getAttribute(String name) {
286: if (SecurityUtil.isPackageProtectionEnabled()) {
287: return doPrivileged("getAttribute", new Object[] { name });
288: } else {
289: return context.getAttribute(name);
290: }
291: }
292:
293: public Enumeration getAttributeNames() {
294: if (SecurityUtil.isPackageProtectionEnabled()) {
295: return (Enumeration) doPrivileged("getAttributeNames", null);
296: } else {
297: return context.getAttributeNames();
298: }
299: }
300:
301: public void setAttribute(String name, Object object) {
302: if (SecurityUtil.isPackageProtectionEnabled()) {
303: doPrivileged("setAttribute", new Object[] { name, object });
304: } else {
305: context.setAttribute(name, object);
306: }
307: }
308:
309: public void removeAttribute(String name) {
310: if (SecurityUtil.isPackageProtectionEnabled()) {
311: doPrivileged("removeAttribute", new Object[] { name });
312: } else {
313: context.removeAttribute(name);
314: }
315: }
316:
317: public String getServletContextName() {
318: if (SecurityUtil.isPackageProtectionEnabled()) {
319: return (String) doPrivileged("getServletContextName", null);
320: } else {
321: return context.getServletContextName();
322: }
323: }
324:
325: public String getContextPath() {
326: if (SecurityUtil.isPackageProtectionEnabled()) {
327: return (String) doPrivileged("getContextPath", null);
328: } else {
329: return context.getContextPath();
330: }
331: }
332:
333: /**
334: * Use reflection to invoke the requested method. Cache the method object
335: * to speed up the process
336: * @param appContext The AppliationContext object on which the method
337: * will be invoked
338: * @param methodName The method to call.
339: * @param params The arguments passed to the called method.
340: */
341: private Object doPrivileged(ApplicationContext appContext,
342: final String methodName, final Object[] params) {
343: try {
344: return invokeMethod(appContext, methodName, params);
345: } catch (Throwable t) {
346: throw new RuntimeException(t.getMessage());
347: }
348:
349: }
350:
351: /**
352: * Use reflection to invoke the requested method. Cache the method object
353: * to speed up the process
354: * will be invoked
355: * @param methodName The method to call.
356: * @param params The arguments passed to the called method.
357: */
358: private Object doPrivileged(final String methodName,
359: final Object[] params) {
360: try {
361: return invokeMethod(context, methodName, params);
362: } catch (Throwable t) {
363: throw new RuntimeException(t.getMessage());
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 invokeMethod(ApplicationContext appContext,
376: final String methodName, Object[] params) throws Throwable {
377:
378: try {
379: Method method = (Method) objectCache.get(methodName);
380: if (method == null) {
381: method = appContext.getClass().getMethod(methodName,
382: (Class[]) classCache.get(methodName));
383: objectCache.put(methodName, method);
384: }
385:
386: return executeMethod(method, appContext, params);
387: } catch (Exception ex) {
388: handleException(ex, methodName);
389: return null;
390: } finally {
391: params = null;
392: }
393: }
394:
395: /**
396: * Use reflection to invoke the requested method. Cache the method object
397: * to speed up the process
398: * @param methodName The method to invoke.
399: * @param clazz The class where the method is.
400: * @param params The arguments passed to the called method.
401: */
402: private Object doPrivileged(final String methodName,
403: final Class[] clazz, Object[] params) {
404:
405: try {
406: Method method = context.getClass().getMethod(methodName,
407: (Class[]) clazz);
408: return executeMethod(method, context, params);
409: } catch (Exception ex) {
410: try {
411: handleException(ex, methodName);
412: } catch (Throwable t) {
413: throw new RuntimeException(t.getMessage());
414: }
415: return null;
416: } finally {
417: params = null;
418: }
419: }
420:
421: /**
422: * Executes the method of the specified <code>ApplicationContext</code>
423: * @param method The method object to be invoked.
424: * @param context The AppliationContext object on which the method
425: * will be invoked
426: * @param params The arguments passed to the called method.
427: */
428: private Object executeMethod(final Method method,
429: final ApplicationContext context, final Object[] params)
430: throws PrivilegedActionException, IllegalAccessException,
431: InvocationTargetException {
432:
433: if (SecurityUtil.isPackageProtectionEnabled()) {
434: return AccessController
435: .doPrivileged(new PrivilegedExceptionAction() {
436: public Object run()
437: throws IllegalAccessException,
438: InvocationTargetException {
439: return method.invoke(context, params);
440: }
441: });
442: } else {
443: return method.invoke(context, params);
444: }
445: }
446:
447: /**
448: *
449: * Throw the real exception.
450: * @param ex The current exception
451: */
452: private void handleException(Exception ex, String methodName)
453: throws Throwable {
454:
455: Throwable realException;
456:
457: if (ex instanceof PrivilegedActionException) {
458: ex = ((PrivilegedActionException) ex).getException();
459: }
460:
461: if (ex instanceof InvocationTargetException) {
462: realException = ((InvocationTargetException) ex)
463: .getTargetException();
464: } else {
465: realException = ex;
466: }
467:
468: throw realException;
469: }
470: }
|