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