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.runtime;
019:
020: import java.io.IOException;
021: import java.io.Writer;
022: import java.security.AccessController;
023: import java.security.PrivilegedAction;
024: import java.security.PrivilegedActionException;
025: import java.security.PrivilegedExceptionAction;
026: import java.util.Enumeration;
027: import java.util.HashMap;
028:
029: import javax.el.ELContext;
030: import javax.el.ExpressionFactory;
031: import javax.el.ValueExpression;
032: import javax.servlet.Servlet;
033: import javax.servlet.ServletConfig;
034: import javax.servlet.ServletContext;
035: import javax.servlet.ServletException;
036: import javax.servlet.ServletRequest;
037: import javax.servlet.ServletResponse;
038: import javax.servlet.http.HttpServletRequest;
039: import javax.servlet.http.HttpServletResponse;
040: import javax.servlet.http.HttpSession;
041: import javax.servlet.jsp.JspException;
042: import javax.servlet.jsp.JspFactory;
043: import javax.servlet.jsp.JspWriter;
044: import javax.servlet.jsp.PageContext;
045: import javax.servlet.jsp.el.ELException;
046: import javax.servlet.jsp.el.ExpressionEvaluator;
047: import javax.servlet.jsp.el.VariableResolver;
048: import javax.servlet.jsp.tagext.BodyContent;
049:
050: import org.apache.jasper.Constants;
051: import org.apache.jasper.compiler.Localizer;
052: import org.apache.jasper.el.ELContextImpl;
053: import org.apache.jasper.el.ExpressionEvaluatorImpl;
054: import org.apache.jasper.el.FunctionMapperImpl;
055: import org.apache.jasper.el.VariableResolverImpl;
056: import org.apache.jasper.security.SecurityUtil;
057: import org.apache.jasper.util.Enumerator;
058:
059: /**
060: * Implementation of the PageContext class from the JSP spec. Also doubles as a
061: * VariableResolver for the EL.
062: *
063: * @author Anil K. Vijendran
064: * @author Larry Cable
065: * @author Hans Bergsten
066: * @author Pierre Delisle
067: * @author Mark Roth
068: * @author Jan Luehe
069: * @author Jacob Hookom
070: */
071: public class PageContextImpl extends PageContext {
072:
073: private BodyContentImpl[] outs;
074:
075: private int depth;
076:
077: // per-servlet state
078: private Servlet servlet;
079:
080: private ServletConfig config;
081:
082: private ServletContext context;
083:
084: private JspApplicationContextImpl applicationContext;
085:
086: private String errorPageURL;
087:
088: // page-scope attributes
089: private transient HashMap<String, Object> attributes;
090:
091: // per-request state
092: private transient ServletRequest request;
093:
094: private transient ServletResponse response;
095:
096: private transient HttpSession session;
097:
098: private transient ELContextImpl elContext;
099:
100: private boolean isIncluded;
101:
102: // initial output stream
103: private transient JspWriter out;
104:
105: private transient JspWriterImpl baseOut;
106:
107: /*
108: * Constructor.
109: */
110: PageContextImpl() {
111: this .outs = new BodyContentImpl[0];
112: this .attributes = new HashMap<String, Object>(16);
113: this .depth = -1;
114: }
115:
116: public void initialize(Servlet servlet, ServletRequest request,
117: ServletResponse response, String errorPageURL,
118: boolean needsSession, int bufferSize, boolean autoFlush)
119: throws IOException {
120:
121: _initialize(servlet, request, response, errorPageURL,
122: needsSession, bufferSize, autoFlush);
123: }
124:
125: private void _initialize(Servlet servlet, ServletRequest request,
126: ServletResponse response, String errorPageURL,
127: boolean needsSession, int bufferSize, boolean autoFlush)
128: throws IOException {
129:
130: // initialize state
131: this .servlet = servlet;
132: this .config = servlet.getServletConfig();
133: this .context = config.getServletContext();
134: this .errorPageURL = errorPageURL;
135: this .request = request;
136: this .response = response;
137:
138: // initialize application context
139: this .applicationContext = JspApplicationContextImpl
140: .getInstance(context);
141:
142: // Setup session (if required)
143: if (request instanceof HttpServletRequest && needsSession)
144: this .session = ((HttpServletRequest) request).getSession();
145: if (needsSession && session == null)
146: throw new IllegalStateException(
147: "Page needs a session and none is available");
148:
149: // initialize the initial out ...
150: depth = -1;
151: if (this .baseOut == null) {
152: this .baseOut = new JspWriterImpl(response, bufferSize,
153: autoFlush);
154: } else {
155: this .baseOut.init(response, bufferSize, autoFlush);
156: }
157: this .out = baseOut;
158:
159: // register names/values as per spec
160: setAttribute(OUT, this .out);
161: setAttribute(REQUEST, request);
162: setAttribute(RESPONSE, response);
163:
164: if (session != null)
165: setAttribute(SESSION, session);
166:
167: setAttribute(PAGE, servlet);
168: setAttribute(CONFIG, config);
169: setAttribute(PAGECONTEXT, this );
170: setAttribute(APPLICATION, context);
171:
172: isIncluded = request
173: .getAttribute("javax.servlet.include.servlet_path") != null;
174: }
175:
176: public void release() {
177: out = baseOut;
178: try {
179: if (isIncluded) {
180: ((JspWriterImpl) out).flushBuffer();
181: // push it into the including jspWriter
182: } else {
183: // Old code:
184: // out.flush();
185: // Do not flush the buffer even if we're not included (i.e.
186: // we are the main page. The servlet will flush it and close
187: // the stream.
188: ((JspWriterImpl) out).flushBuffer();
189: }
190: } catch (IOException ex) {
191: IllegalStateException ise = new IllegalStateException(
192: Localizer.getMessage("jsp.error.flush"), ex);
193: throw ise;
194: } finally {
195: servlet = null;
196: config = null;
197: context = null;
198: applicationContext = null;
199: elContext = null;
200: errorPageURL = null;
201: request = null;
202: response = null;
203: depth = -1;
204: baseOut.recycle();
205: session = null;
206: attributes.clear();
207: }
208: }
209:
210: public Object getAttribute(final String name) {
211:
212: if (name == null) {
213: throw new NullPointerException(Localizer
214: .getMessage("jsp.error.attribute.null_name"));
215: }
216:
217: if (SecurityUtil.isPackageProtectionEnabled()) {
218: return AccessController
219: .doPrivileged(new PrivilegedAction() {
220: public Object run() {
221: return doGetAttribute(name);
222: }
223: });
224: } else {
225: return doGetAttribute(name);
226: }
227:
228: }
229:
230: private Object doGetAttribute(String name) {
231: return attributes.get(name);
232: }
233:
234: public Object getAttribute(final String name, final int scope) {
235:
236: if (name == null) {
237: throw new NullPointerException(Localizer
238: .getMessage("jsp.error.attribute.null_name"));
239: }
240:
241: if (SecurityUtil.isPackageProtectionEnabled()) {
242: return AccessController
243: .doPrivileged(new PrivilegedAction() {
244: public Object run() {
245: return doGetAttribute(name, scope);
246: }
247: });
248: } else {
249: return doGetAttribute(name, scope);
250: }
251:
252: }
253:
254: private Object doGetAttribute(String name, int scope) {
255: switch (scope) {
256: case PAGE_SCOPE:
257: return attributes.get(name);
258:
259: case REQUEST_SCOPE:
260: return request.getAttribute(name);
261:
262: case SESSION_SCOPE:
263: if (session == null) {
264: throw new IllegalStateException(Localizer
265: .getMessage("jsp.error.page.noSession"));
266: }
267: return session.getAttribute(name);
268:
269: case APPLICATION_SCOPE:
270: return context.getAttribute(name);
271:
272: default:
273: throw new IllegalArgumentException("Invalid scope");
274: }
275: }
276:
277: public void setAttribute(final String name, final Object attribute) {
278:
279: if (name == null) {
280: throw new NullPointerException(Localizer
281: .getMessage("jsp.error.attribute.null_name"));
282: }
283:
284: if (SecurityUtil.isPackageProtectionEnabled()) {
285: AccessController.doPrivileged(new PrivilegedAction() {
286: public Object run() {
287: doSetAttribute(name, attribute);
288: return null;
289: }
290: });
291: } else {
292: doSetAttribute(name, attribute);
293: }
294: }
295:
296: private void doSetAttribute(String name, Object attribute) {
297: if (attribute != null) {
298: attributes.put(name, attribute);
299: } else {
300: removeAttribute(name, PAGE_SCOPE);
301: }
302: }
303:
304: public void setAttribute(final String name, final Object o,
305: final int scope) {
306:
307: if (name == null) {
308: throw new NullPointerException(Localizer
309: .getMessage("jsp.error.attribute.null_name"));
310: }
311:
312: if (SecurityUtil.isPackageProtectionEnabled()) {
313: AccessController.doPrivileged(new PrivilegedAction() {
314: public Object run() {
315: doSetAttribute(name, o, scope);
316: return null;
317: }
318: });
319: } else {
320: doSetAttribute(name, o, scope);
321: }
322:
323: }
324:
325: private void doSetAttribute(String name, Object o, int scope) {
326: if (o != null) {
327: switch (scope) {
328: case PAGE_SCOPE:
329: attributes.put(name, o);
330: break;
331:
332: case REQUEST_SCOPE:
333: request.setAttribute(name, o);
334: break;
335:
336: case SESSION_SCOPE:
337: if (session == null) {
338: throw new IllegalStateException(Localizer
339: .getMessage("jsp.error.page.noSession"));
340: }
341: session.setAttribute(name, o);
342: break;
343:
344: case APPLICATION_SCOPE:
345: context.setAttribute(name, o);
346: break;
347:
348: default:
349: throw new IllegalArgumentException("Invalid scope");
350: }
351: } else {
352: removeAttribute(name, scope);
353: }
354: }
355:
356: public void removeAttribute(final String name, final int scope) {
357:
358: if (name == null) {
359: throw new NullPointerException(Localizer
360: .getMessage("jsp.error.attribute.null_name"));
361: }
362: if (SecurityUtil.isPackageProtectionEnabled()) {
363: AccessController.doPrivileged(new PrivilegedAction() {
364: public Object run() {
365: doRemoveAttribute(name, scope);
366: return null;
367: }
368: });
369: } else {
370: doRemoveAttribute(name, scope);
371: }
372: }
373:
374: private void doRemoveAttribute(String name, int scope) {
375: switch (scope) {
376: case PAGE_SCOPE:
377: attributes.remove(name);
378: break;
379:
380: case REQUEST_SCOPE:
381: request.removeAttribute(name);
382: break;
383:
384: case SESSION_SCOPE:
385: if (session == null) {
386: throw new IllegalStateException(Localizer
387: .getMessage("jsp.error.page.noSession"));
388: }
389: session.removeAttribute(name);
390: break;
391:
392: case APPLICATION_SCOPE:
393: context.removeAttribute(name);
394: break;
395:
396: default:
397: throw new IllegalArgumentException("Invalid scope");
398: }
399: }
400:
401: public int getAttributesScope(final String name) {
402:
403: if (name == null) {
404: throw new NullPointerException(Localizer
405: .getMessage("jsp.error.attribute.null_name"));
406: }
407:
408: if (SecurityUtil.isPackageProtectionEnabled()) {
409: return ((Integer) AccessController
410: .doPrivileged(new PrivilegedAction() {
411: public Object run() {
412: return new Integer(
413: doGetAttributeScope(name));
414: }
415: })).intValue();
416: } else {
417: return doGetAttributeScope(name);
418: }
419: }
420:
421: private int doGetAttributeScope(String name) {
422: if (attributes.get(name) != null)
423: return PAGE_SCOPE;
424:
425: if (request.getAttribute(name) != null)
426: return REQUEST_SCOPE;
427:
428: if (session != null) {
429: if (session.getAttribute(name) != null)
430: return SESSION_SCOPE;
431: }
432:
433: if (context.getAttribute(name) != null)
434: return APPLICATION_SCOPE;
435:
436: return 0;
437: }
438:
439: public Object findAttribute(final String name) {
440: if (SecurityUtil.isPackageProtectionEnabled()) {
441: return AccessController
442: .doPrivileged(new PrivilegedAction() {
443: public Object run() {
444: if (name == null) {
445: throw new NullPointerException(
446: Localizer
447: .getMessage("jsp.error.attribute.null_name"));
448: }
449:
450: return doFindAttribute(name);
451: }
452: });
453: } else {
454: if (name == null) {
455: throw new NullPointerException(Localizer
456: .getMessage("jsp.error.attribute.null_name"));
457: }
458:
459: return doFindAttribute(name);
460: }
461: }
462:
463: private Object doFindAttribute(String name) {
464:
465: Object o = attributes.get(name);
466: if (o != null)
467: return o;
468:
469: o = request.getAttribute(name);
470: if (o != null)
471: return o;
472:
473: if (session != null) {
474: o = session.getAttribute(name);
475: if (o != null)
476: return o;
477: }
478:
479: return context.getAttribute(name);
480: }
481:
482: public Enumeration<String> getAttributeNamesInScope(final int scope) {
483: if (SecurityUtil.isPackageProtectionEnabled()) {
484: return (Enumeration) AccessController
485: .doPrivileged(new PrivilegedAction() {
486: public Object run() {
487: return doGetAttributeNamesInScope(scope);
488: }
489: });
490: } else {
491: return doGetAttributeNamesInScope(scope);
492: }
493: }
494:
495: private Enumeration doGetAttributeNamesInScope(int scope) {
496: switch (scope) {
497: case PAGE_SCOPE:
498: return new Enumerator(attributes.keySet().iterator());
499:
500: case REQUEST_SCOPE:
501: return request.getAttributeNames();
502:
503: case SESSION_SCOPE:
504: if (session == null) {
505: throw new IllegalStateException(Localizer
506: .getMessage("jsp.error.page.noSession"));
507: }
508: return session.getAttributeNames();
509:
510: case APPLICATION_SCOPE:
511: return context.getAttributeNames();
512:
513: default:
514: throw new IllegalArgumentException("Invalid scope");
515: }
516: }
517:
518: public void removeAttribute(final String name) {
519:
520: if (name == null) {
521: throw new NullPointerException(Localizer
522: .getMessage("jsp.error.attribute.null_name"));
523: }
524:
525: if (SecurityUtil.isPackageProtectionEnabled()) {
526: AccessController.doPrivileged(new PrivilegedAction() {
527: public Object run() {
528: doRemoveAttribute(name);
529: return null;
530: }
531: });
532: } else {
533: doRemoveAttribute(name);
534: }
535: }
536:
537: private void doRemoveAttribute(String name) {
538: try {
539: removeAttribute(name, PAGE_SCOPE);
540: removeAttribute(name, REQUEST_SCOPE);
541: if (session != null) {
542: removeAttribute(name, SESSION_SCOPE);
543: }
544: removeAttribute(name, APPLICATION_SCOPE);
545: } catch (Exception ex) {
546: // we remove as much as we can, and
547: // simply ignore possible exceptions
548: }
549: }
550:
551: public JspWriter getOut() {
552: return out;
553: }
554:
555: public HttpSession getSession() {
556: return session;
557: }
558:
559: public Servlet getServlet() {
560: return servlet;
561: }
562:
563: public ServletConfig getServletConfig() {
564: return config;
565: }
566:
567: public ServletContext getServletContext() {
568: return config.getServletContext();
569: }
570:
571: public ServletRequest getRequest() {
572: return request;
573: }
574:
575: public ServletResponse getResponse() {
576: return response;
577: }
578:
579: /**
580: * Returns the exception associated with this page context, if any. <p/>
581: * Added wrapping for Throwables to avoid ClassCastException: see Bugzilla
582: * 31171 for details.
583: *
584: * @return The Exception associated with this page context, if any.
585: */
586: public Exception getException() {
587: Throwable t = JspRuntimeLibrary.getThrowable(request);
588:
589: // Only wrap if needed
590: if ((t != null) && (!(t instanceof Exception))) {
591: t = new JspException(t);
592: }
593:
594: return (Exception) t;
595: }
596:
597: public Object getPage() {
598: return servlet;
599: }
600:
601: private final String getAbsolutePathRelativeToContext(
602: String relativeUrlPath) {
603: String path = relativeUrlPath;
604:
605: if (!path.startsWith("/")) {
606: String uri = (String) request
607: .getAttribute("javax.servlet.include.servlet_path");
608: if (uri == null)
609: uri = ((HttpServletRequest) request).getServletPath();
610: String baseURI = uri.substring(0, uri.lastIndexOf('/'));
611: path = baseURI + '/' + path;
612: }
613:
614: return path;
615: }
616:
617: public void include(String relativeUrlPath)
618: throws ServletException, IOException {
619: JspRuntimeLibrary.include(request, response, relativeUrlPath,
620: out, true);
621: }
622:
623: public void include(final String relativeUrlPath,
624: final boolean flush) throws ServletException, IOException {
625: if (SecurityUtil.isPackageProtectionEnabled()) {
626: try {
627: AccessController
628: .doPrivileged(new PrivilegedExceptionAction() {
629: public Object run() throws Exception {
630: doInclude(relativeUrlPath, flush);
631: return null;
632: }
633: });
634: } catch (PrivilegedActionException e) {
635: Exception ex = e.getException();
636: if (ex instanceof IOException) {
637: throw (IOException) ex;
638: } else {
639: throw (ServletException) ex;
640: }
641: }
642: } else {
643: doInclude(relativeUrlPath, flush);
644: }
645: }
646:
647: private void doInclude(String relativeUrlPath, boolean flush)
648: throws ServletException, IOException {
649: JspRuntimeLibrary.include(request, response, relativeUrlPath,
650: out, flush);
651: }
652:
653: public VariableResolver getVariableResolver() {
654: return new VariableResolverImpl(this .getELContext());
655: }
656:
657: public void forward(final String relativeUrlPath)
658: throws ServletException, IOException {
659: if (SecurityUtil.isPackageProtectionEnabled()) {
660: try {
661: AccessController
662: .doPrivileged(new PrivilegedExceptionAction() {
663: public Object run() throws Exception {
664: doForward(relativeUrlPath);
665: return null;
666: }
667: });
668: } catch (PrivilegedActionException e) {
669: Exception ex = e.getException();
670: if (ex instanceof IOException) {
671: throw (IOException) ex;
672: } else {
673: throw (ServletException) ex;
674: }
675: }
676: } else {
677: doForward(relativeUrlPath);
678: }
679: }
680:
681: private void doForward(String relativeUrlPath)
682: throws ServletException, IOException {
683:
684: // JSP.4.5 If the buffer was flushed, throw IllegalStateException
685: try {
686: out.clear();
687: } catch (IOException ex) {
688: IllegalStateException ise = new IllegalStateException(
689: Localizer
690: .getMessage("jsp.error.attempt_to_clear_flushed_buffer"));
691: ise.initCause(ex);
692: throw ise;
693: }
694:
695: // Make sure that the response object is not the wrapper for include
696: while (response instanceof ServletResponseWrapperInclude) {
697: response = ((ServletResponseWrapperInclude) response)
698: .getResponse();
699: }
700:
701: final String path = getAbsolutePathRelativeToContext(relativeUrlPath);
702: String includeUri = (String) request
703: .getAttribute(Constants.INC_SERVLET_PATH);
704:
705: if (includeUri != null)
706: request.removeAttribute(Constants.INC_SERVLET_PATH);
707: try {
708: context.getRequestDispatcher(path).forward(request,
709: response);
710: } finally {
711: if (includeUri != null)
712: request.setAttribute(Constants.INC_SERVLET_PATH,
713: includeUri);
714: }
715: }
716:
717: public BodyContent pushBody() {
718: return (BodyContent) pushBody(null);
719: }
720:
721: public JspWriter pushBody(Writer writer) {
722: depth++;
723: if (depth >= outs.length) {
724: BodyContentImpl[] newOuts = new BodyContentImpl[depth + 1];
725: for (int i = 0; i < outs.length; i++) {
726: newOuts[i] = outs[i];
727: }
728: newOuts[depth] = new BodyContentImpl(out);
729: outs = newOuts;
730: }
731:
732: outs[depth].setWriter(writer);
733: out = outs[depth];
734:
735: // Update the value of the "out" attribute in the page scope
736: // attribute namespace of this PageContext
737: setAttribute(OUT, out);
738:
739: return outs[depth];
740: }
741:
742: public JspWriter popBody() {
743: depth--;
744: if (depth >= 0) {
745: out = outs[depth];
746: } else {
747: out = baseOut;
748: }
749:
750: // Update the value of the "out" attribute in the page scope
751: // attribute namespace of this PageContext
752: setAttribute(OUT, out);
753:
754: return out;
755: }
756:
757: /**
758: * Provides programmatic access to the ExpressionEvaluator. The JSP
759: * Container must return a valid instance of an ExpressionEvaluator that can
760: * parse EL expressions.
761: */
762: public ExpressionEvaluator getExpressionEvaluator() {
763: return new ExpressionEvaluatorImpl(this .applicationContext
764: .getExpressionFactory());
765: }
766:
767: public void handlePageException(Exception ex) throws IOException,
768: ServletException {
769: // Should never be called since handleException() called with a
770: // Throwable in the generated servlet.
771: handlePageException((Throwable) ex);
772: }
773:
774: public void handlePageException(final Throwable t)
775: throws IOException, ServletException {
776: if (t == null)
777: throw new NullPointerException("null Throwable");
778:
779: if (SecurityUtil.isPackageProtectionEnabled()) {
780: try {
781: AccessController
782: .doPrivileged(new PrivilegedExceptionAction() {
783: public Object run() throws Exception {
784: doHandlePageException(t);
785: return null;
786: }
787: });
788: } catch (PrivilegedActionException e) {
789: Exception ex = e.getException();
790: if (ex instanceof IOException) {
791: throw (IOException) ex;
792: } else {
793: throw (ServletException) ex;
794: }
795: }
796: } else {
797: doHandlePageException(t);
798: }
799:
800: }
801:
802: private void doHandlePageException(Throwable t) throws IOException,
803: ServletException {
804:
805: if (errorPageURL != null && !errorPageURL.equals("")) {
806:
807: /*
808: * Set request attributes. Do not set the
809: * javax.servlet.error.exception attribute here (instead, set in the
810: * generated servlet code for the error page) in order to prevent
811: * the ErrorReportValve, which is invoked as part of forwarding the
812: * request to the error page, from throwing it if the response has
813: * not been committed (the response will have been committed if the
814: * error page is a JSP page).
815: */
816: request.setAttribute("javax.servlet.jsp.jspException", t);
817: request
818: .setAttribute(
819: "javax.servlet.error.status_code",
820: new Integer(
821: HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
822: request.setAttribute("javax.servlet.error.request_uri",
823: ((HttpServletRequest) request).getRequestURI());
824: request.setAttribute("javax.servlet.error.servlet_name",
825: config.getServletName());
826: try {
827: forward(errorPageURL);
828: } catch (IllegalStateException ise) {
829: include(errorPageURL);
830: }
831:
832: // The error page could be inside an include.
833:
834: Object newException = request
835: .getAttribute("javax.servlet.error.exception");
836:
837: // t==null means the attribute was not set.
838: if ((newException != null) && (newException == t)) {
839: request
840: .removeAttribute("javax.servlet.error.exception");
841: }
842:
843: // now clear the error code - to prevent double handling.
844: request.removeAttribute("javax.servlet.error.status_code");
845: request.removeAttribute("javax.servlet.error.request_uri");
846: request.removeAttribute("javax.servlet.error.status_code");
847: request.removeAttribute("javax.servlet.jsp.jspException");
848:
849: } else {
850: // Otherwise throw the exception wrapped inside a ServletException.
851: // Set the exception as the root cause in the ServletException
852: // to get a stack trace for the real problem
853: if (t instanceof IOException)
854: throw (IOException) t;
855: if (t instanceof ServletException)
856: throw (ServletException) t;
857: if (t instanceof RuntimeException)
858: throw (RuntimeException) t;
859:
860: Throwable rootCause = null;
861: if (t instanceof JspException) {
862: rootCause = ((JspException) t).getRootCause();
863: } else if (t instanceof ELException) {
864: rootCause = ((ELException) t).getRootCause();
865: }
866:
867: if (rootCause != null) {
868: throw new ServletException(t.getClass().getName()
869: + ": " + t.getMessage(), rootCause);
870: }
871:
872: throw new ServletException(t);
873: }
874: }
875:
876: private static String XmlEscape(String s) {
877: if (s == null)
878: return null;
879: StringBuffer sb = new StringBuffer();
880: for (int i = 0; i < s.length(); i++) {
881: char c = s.charAt(i);
882: if (c == '<') {
883: sb.append("<");
884: } else if (c == '>') {
885: sb.append(">");
886: } else if (c == '\'') {
887: sb.append("'"); // '
888: } else if (c == '&') {
889: sb.append("&");
890: } else if (c == '"') {
891: sb.append("""); // "
892: } else {
893: sb.append(c);
894: }
895: }
896: return sb.toString();
897: }
898:
899: /**
900: * Proprietary method to evaluate EL expressions. XXX - This method should
901: * go away once the EL interpreter moves out of JSTL and into its own
902: * project. For now, this is necessary because the standard machinery is too
903: * slow.
904: *
905: * @param expression
906: * The expression to be evaluated
907: * @param expectedType
908: * The expected resulting type
909: * @param pageContext
910: * The page context
911: * @param functionMap
912: * Maps prefix and name to Method
913: * @return The result of the evaluation
914: */
915: public static Object proprietaryEvaluate(final String expression,
916: final Class expectedType, final PageContext pageContext,
917: final ProtectedFunctionMapper functionMap,
918: final boolean escape) throws ELException {
919: Object retValue;
920: final ExpressionFactory exprFactory = JspFactory
921: .getDefaultFactory().getJspApplicationContext(
922: pageContext.getServletContext())
923: .getExpressionFactory();
924: if (SecurityUtil.isPackageProtectionEnabled()) {
925: try {
926: retValue = AccessController
927: .doPrivileged(new PrivilegedExceptionAction() {
928:
929: public Object run() throws Exception {
930: ELContextImpl ctx = (ELContextImpl) pageContext
931: .getELContext();
932: ctx
933: .setFunctionMapper(new FunctionMapperImpl(
934: functionMap));
935: ValueExpression ve = exprFactory
936: .createValueExpression(ctx,
937: expression,
938: expectedType);
939: return ve.getValue(ctx);
940: }
941: });
942: } catch (PrivilegedActionException ex) {
943: Exception realEx = ex.getException();
944: if (realEx instanceof ELException) {
945: throw (ELException) realEx;
946: } else {
947: throw new ELException(realEx);
948: }
949: }
950: } else {
951: ELContextImpl ctx = (ELContextImpl) pageContext
952: .getELContext();
953: ctx.setFunctionMapper(new FunctionMapperImpl(functionMap));
954: ValueExpression ve = exprFactory.createValueExpression(ctx,
955: expression, expectedType);
956: retValue = ve.getValue(ctx);
957: }
958: if (escape && retValue != null) {
959: retValue = XmlEscape(retValue.toString());
960: }
961:
962: return retValue;
963: }
964:
965: public ELContext getELContext() {
966: if (this.elContext == null) {
967: this.elContext = this.applicationContext
968: .createELContext(this);
969: }
970: return this.elContext;
971: }
972:
973: }
|