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