Skip to contentMethod: getValue(Object)
1: /*
2: * Copyright (c) 1997, 2020 Oracle and/or its affiliates and others.
3: * All rights reserved.
4: * Copyright 2004 The Apache Software Foundation
5: *
6: * Licensed under the Apache License, Version 2.0 (the "License");
7: * you may not use this file except in compliance with the License.
8: * You may obtain a copy of the License at
9: *
10: * http://www.apache.org/licenses/LICENSE-2.0
11: *
12: * Unless required by applicable law or agreed to in writing, software
13: * distributed under the License is distributed on an "AS IS" BASIS,
14: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15: * See the License for the specific language governing permissions and
16: * limitations under the License.
17: */
18:
19: package jakarta.servlet.jsp.el;
20:
21: import java.beans.FeatureDescriptor;
22: import java.util.Iterator;
23: import java.util.ArrayList;
24: import java.util.Collection;
25: import java.util.Enumeration;
26: import java.util.HashMap;
27: import java.util.List;
28: import java.util.Map;
29: import java.util.Set;
30:
31: import jakarta.servlet.ServletContext;
32: import jakarta.servlet.http.Cookie;
33: import jakarta.servlet.http.HttpServletRequest;
34: import jakarta.servlet.jsp.PageContext;
35: import jakarta.servlet.jsp.JspContext;
36:
37: import jakarta.el.PropertyNotWritableException;
38: import jakarta.el.ELContext;
39: import jakarta.el.ELResolver;
40:
41: /**
42: * Defines variable resolution behavior for the EL implicit objects defined in the JSP specification.
43: *
44: * <p>
45: * The following variables are resolved by this <code>ELResolver</code>, as per the JSP specification:
46: * </p>
47: * <ul>
48: * <li><code>pageContext</code> - the <code>PageContext</code> object.</li>
49: * <li><code>pageScope</code> - a <code>Map</code> that maps page-scoped attribute names to their values.</li>
50: * <li><code>requestScope</code> - a <code>Map</code> that maps request-scoped attribute names to their values.</li>
51: * <li><code>sessionScope</code> - a <code>Map</code> that maps session-scoped attribute names to their values.</li>
52: * <li><code>applicationScope</code> - a <code>Map</code> that maps application-scoped attribute names to their
53: * values.</li>
54: * <li><code>param</code> - a <code>Map</code> that maps parameter names to a single String parameter value (obtained by
55: * calling <code>ServletRequest.getParameter(String name)</code>).</li>
56: * <li><code>paramValues</code> - a <code>Map</code> that maps parameter names to a <code>String[]</code> of all
57: * values for that parameter (obtained by calling <code>ServletRequest.getParameterValues(String name))</code>.</li>
58: * <li><code>header</code> - a <code>Map</code> that maps header names to a single String header value (obtained by
59: * calling <code>HttpServletRequest.getHeader(String name))</code>.</li>
60: * <li><code>headerValues</code> - a <code>Map</code> that maps header names to a <code>String[]</code> of all values
61: * for that header (obtained by calling <code>HttpServletRequest.getHeaders(String))</code>.</li>
62: * <li><code>cookie</code> - a <code>Map</code> that maps cookie names to a single <code>Cookie</code> object. Cookies
63: * are retrieved according to the semantics of <code>HttpServletRequest.getCookies()</code>. If the same name is shared
64: * by multiple cookies, an implementation must use the first one encountered in the array of <code>Cookie</code> objects
65: * returned by the <code>getCookies()</code> method. However, users of the cookie implicit object must be aware that the
66: * ordering of cookies is currently unspecified in the servlet specification.</li>
67: * <li><code>initParam</code> - a <code>Map</code> that maps context initialization parameter names to their String
68: * parameter value (obtained by calling <code>ServletContext.getInitParameter(String name))</code>.</li>
69: * </ul>
70: *
71: * @see jakarta.el.ELResolver
72: * @since JSP 2.1
73: */
74: public class ImplicitObjectELResolver extends ELResolver {
75:
76: /**
77: * If the base object is <code>null</code>, and the property matches the name of a JSP implicit object, returns the
78: * implicit object.
79: *
80: * <p>
81: * The <code>propertyResolved</code> property of the <code>ELContext</code> object must be set to <code>true</code>
82: * by this resolver before returning if an implicit object is matched. If this property is not <code>true</code>
83: * after this method is called, the caller should ignore the return value.
84: * </p>
85: *
86: * @param context The context of this evaluation.
87: * @param base Only <code>null</code> is handled by this resolver. Other values will result in an immediate
88: * return.
89: * @param property The name of the implicit object to resolve.
90: * @return If the <code>propertyResolved</code> property of <code>ELContext</code> was set to <code>true</code>,
91: * then the implicit object; otherwise undefined.
92: * @throws NullPointerException if context is <code>null</code>
93: */
94: @Override
95: public Object getValue(ELContext context, Object base, Object property) {
96:
97: if (context == null) {
98: throw new NullPointerException();
99: }
100:
101: if (base != null) {
102: return null;
103: }
104:
105: PageContext ctxt = (PageContext) context.getContext(JspContext.class);
106:
107: if ("pageContext".equals(property)) {
108: context.setPropertyResolved(true);
109: return ctxt;
110: }
111: ImplicitObjects implicitObjects = ImplicitObjects.getImplicitObjects(ctxt);
112: if ("pageScope".equals(property)) {
113: context.setPropertyResolved(true);
114: return implicitObjects.getPageScopeMap();
115: }
116: if ("requestScope".equals(property)) {
117: context.setPropertyResolved(true);
118: return implicitObjects.getRequestScopeMap();
119: }
120: if ("sessionScope".equals(property)) {
121: context.setPropertyResolved(true);
122: return implicitObjects.getSessionScopeMap();
123: }
124: if ("applicationScope".equals(property)) {
125: context.setPropertyResolved(true);
126: return implicitObjects.getApplicationScopeMap();
127: }
128: if ("param".equals(property)) {
129: context.setPropertyResolved(true);
130: return implicitObjects.getParamMap();
131: }
132: if ("paramValues".equals(property)) {
133: context.setPropertyResolved(true);
134: return implicitObjects.getParamsMap();
135: }
136: if ("header".equals(property)) {
137: context.setPropertyResolved(true);
138: return implicitObjects.getHeaderMap();
139: }
140: if ("headerValues".equals(property)) {
141: context.setPropertyResolved(true);
142: return implicitObjects.getHeadersMap();
143: }
144: if ("initParam".equals(property)) {
145: context.setPropertyResolved(true);
146: return implicitObjects.getInitParamMap();
147: }
148: if ("cookie".equals(property)) {
149: context.setPropertyResolved(true);
150: return implicitObjects.getCookieMap();
151: }
152: return null;
153: }
154:
155: /**
156: * If the base object is <code>null</code>, and the property matches the name of a JSP implicit object, returns
157: * <code>null</code> to indicate that no types are ever accepted to <code>setValue()</code>.
158: *
159: * <p>
160: * The <code>propertyResolved</code> property of the <code>ELContext</code> object must be set to <code>true</code>
161: * by this resolver before returning if an implicit object is matched. If this property is not <code>true</code>
162: * after this method is called, the caller should ignore the return value.
163: * </p>
164: *
165: * @param context The context of this evaluation.
166: * @param base Only <code>null</code> is handled by this resolver. Other values will result in an immediate
167: * return.
168: * @param property The name of the implicit object to resolve.
169: * @return If the <code>propertyResolved</code> property of <code>ELContext</code> was set to <code>true</code>,
170: * then <code>null</code> otherwise undefined.
171: * @throws NullPointerException if context is <code>null</code>
172: */
173: @Override
174: public Class<?> getType(ELContext context, Object base, Object property) {
175:
176: if (context == null) {
177: throw new NullPointerException();
178: }
179:
180: if ((base == null) && ("pageContext".equals(property) || "pageScope".equals(property))
181: || "requestScope".equals(property) || "sessionScope".equals(property)
182: || "applicationScope".equals(property) || "param".equals(property) || "paramValues".equals(property)
183: || "header".equals(property) || "headerValues".equals(property) || "initParam".equals(property)
184: || "cookie".equals(property)) {
185: context.setPropertyResolved(true);
186: }
187: return null;
188: }
189:
190: /**
191: * If the base object is <code>null</code>, and the property matches the name of a JSP implicit object, throws
192: * <code>PropertyNotWritableException</code> to indicate that implicit objects cannot be overwritten.
193: *
194: * <p>
195: * The <code>propertyResolved</code> property of the <code>ELContext</code> object must be set to <code>true</code>
196: * by this resolver before returning if an implicit object is matched. If this property is not <code>true</code>
197: * after this method is called, the caller should ignore the return value.
198: * </p>
199: *
200: * @param context The context of this evaluation.
201: * @param base Only <code>null</code> is handled by this resolver. Other values will result in an immediate
202: * return.
203: * @param property The name of the implicit object.
204: * @param val The value to be associated with the implicit object.
205: * @throws NullPointerException if context is <code>null</code>.
206: * @throws PropertyNotWritableException always thrown, if the implicit object name is recognized by this resolver.
207: */
208: @Override
209: public void setValue(ELContext context, Object base, Object property, Object val) {
210:
211: if (context == null) {
212: throw new NullPointerException();
213: }
214:
215: if ((base == null) && ("pageContext".equals(property) || "pageScope".equals(property))
216: || "requestScope".equals(property) || "sessionScope".equals(property)
217: || "applicationScope".equals(property) || "param".equals(property) || "paramValues".equals(property)
218: || "header".equals(property) || "headerValues".equals(property) || "initParam".equals(property)
219: || "cookie".equals(property)) {
220: throw new PropertyNotWritableException();
221: }
222: }
223:
224: /**
225: * If the base object is <code>null</code>, and the property matches the name of a JSP implicit object, returns
226: * <code>true</code> to indicate that implicit objects cannot be overwritten.
227: *
228: * <p>
229: * The <code>propertyResolved</code> property of the <code>ELContext</code> object must be set to <code>true</code>
230: * by this resolver before returning if an implicit object is matched. If this property is not <code>true</code>
231: * after this method is called, the caller should ignore the return value.
232: * </p>
233: *
234: * @param context The context of this evaluation.
235: * @param base Only <code>null</code> is handled by this resolver. Other values will result in an immediate
236: * return.
237: * @param property The name of the implicit object.
238: * @return If the <code>propertyResolved</code> property of <code>ELContext</code> was set to <code>true</code>,
239: * then <code>true</code> otherwise undefined.
240: * @throws NullPointerException if context is <code>null</code>.
241: */
242: @Override
243: public boolean isReadOnly(ELContext context, Object base, Object property) {
244: if (context == null) {
245: throw new NullPointerException();
246: }
247:
248: if ((base == null) && ("pageContext".equals(property) || "pageScope".equals(property))
249: || "requestScope".equals(property) || "sessionScope".equals(property)
250: || "applicationScope".equals(property) || "param".equals(property) || "paramValues".equals(property)
251: || "header".equals(property) || "headerValues".equals(property) || "initParam".equals(property)
252: || "cookie".equals(property)) {
253: context.setPropertyResolved(true);
254: return true;
255: }
256: return false; // Doesn't matter
257: }
258:
259: /**
260: * If the base object is <code>null</code>, and the property matches the name of a JSP implicit object, returns an
261: * <code>Iterator</code> containing <code>FeatureDescriptor</code> objects with information about each JSP implicit
262: * object resolved by this resolver. Otherwise, returns <code>null</code>.
263: *
264: * <p>
265: * The <code>Iterator</code> returned must contain one instance of {@link java.beans.FeatureDescriptor} for each of
266: * the EL implicit objects defined by the JSP spec. Each info object contains information about a single implicit
267: * object, and is initialized as follows:
268: * </p>
269: * <dl>
270: * <dt>displayName</dt><dd>- The name of the implicit object.</dd>
271: * <dt>name</dt><dd>- Same as displayName property.</dd>
272: * <dt>shortDescription</dt><dd>- A suitable description for the implicit object. Will vary by implementation.</dd>
273: * <dt>expert</dt><dd>- <code>false</code></dd>
274: * <dt>hidden</dt><dd>- <code>false</code></dd>
275: * <dt>preferred</dt><dd>- <code>true</code></dd>
276: * </dl>
277: * In addition, the following named attributes must be set in the returned <code>FeatureDescriptor</code>s:
278: * <dl>
279: * <dt>{@link ELResolver#TYPE}</dt><dd>- The runtime type of the implicit object.</dd>
280: * <dt>{@link ELResolver#RESOLVABLE_AT_DESIGN_TIME}</dt><dd>- <code>true</code>.</dd>
281: * </dl>
282: *
283: * @param context The context of this evaluation.
284: * @param base Only <code>null</code> is handled by this resolver. Other values will result in a
285: * <code>null</code> return value.
286: * @return An <code>Iterator</code> containing one <code>FeatureDescriptor</code> object for each implicit object,
287: * or <code>null</code> if <code>base</code> is not <code>null</code>.
288: *
289: * @deprecated This method is deprecated as of EL 5.0 and will be removed in EL 6.0 (Jakarta EE 11). Therefore it
290: * will be removed here in JSP 4.0.
291: */
292: @Deprecated(forRemoval = true, since = "JSP 3.1")
293: @Override
294: public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
295:
296: ArrayList<FeatureDescriptor> list = new ArrayList<>(11);
297:
298: // pageContext
299: FeatureDescriptor descriptor = new FeatureDescriptor();
300: descriptor.setName("pageContext");
301: descriptor.setDisplayName("pageContext");
302: // descriptor.setShortDescription("");
303: descriptor.setExpert(false);
304: descriptor.setHidden(false);
305: descriptor.setPreferred(true);
306: descriptor.setValue("type", PageContext.class);
307: descriptor.setValue("resolvableAtDesignTime", Boolean.TRUE);
308: list.add(descriptor);
309:
310: // pageScope
311: descriptor = new FeatureDescriptor();
312: descriptor.setName("pageScope");
313: descriptor.setDisplayName("pageScope");
314: // descriptor.setShortDescription("");
315: descriptor.setExpert(false);
316: descriptor.setHidden(false);
317: descriptor.setPreferred(true);
318: descriptor.setValue("type", Map.class);
319: descriptor.setValue("resolvableAtDesignTime", Boolean.TRUE);
320: list.add(descriptor);
321:
322: // requestScope
323: descriptor = new FeatureDescriptor();
324: descriptor.setName("requestScope");
325: descriptor.setDisplayName("requestScope");
326: // descriptor.setShortDescription("");
327: descriptor.setExpert(false);
328: descriptor.setHidden(false);
329: descriptor.setPreferred(true);
330: descriptor.setValue("type", Map.class);
331: descriptor.setValue("resolvableAtDesignTime", Boolean.TRUE);
332: list.add(descriptor);
333:
334: // sessionScope
335: descriptor = new FeatureDescriptor();
336: descriptor.setName("sessionScope");
337: descriptor.setDisplayName("sessionScope");
338: // descriptor.setShortDescription("");
339: descriptor.setExpert(false);
340: descriptor.setHidden(false);
341: descriptor.setPreferred(true);
342: descriptor.setValue("type", Map.class);
343: descriptor.setValue("resolvableAtDesignTime", Boolean.TRUE);
344: list.add(descriptor);
345:
346: // applicationScope
347: descriptor = new FeatureDescriptor();
348: descriptor.setName("applicationScope");
349: descriptor.setDisplayName("applicationScope");
350: // descriptor.setShortDescription("");
351: descriptor.setExpert(false);
352: descriptor.setHidden(false);
353: descriptor.setPreferred(true);
354: descriptor.setValue("type", Map.class);
355: descriptor.setValue("resolvableAtDesignTime", Boolean.TRUE);
356: list.add(descriptor);
357:
358: // param
359: descriptor = new FeatureDescriptor();
360: descriptor.setName("param");
361: descriptor.setDisplayName("param");
362: // descriptor.setShortDescription("");
363: descriptor.setExpert(false);
364: descriptor.setHidden(false);
365: descriptor.setPreferred(true);
366: descriptor.setValue("type", Map.class);
367: descriptor.setValue("resolvableAtDesignTime", Boolean.TRUE);
368: list.add(descriptor);
369:
370: // paramValues
371: descriptor = new FeatureDescriptor();
372: descriptor.setName("paramValues");
373: descriptor.setDisplayName("paramValues");
374: // descriptor.setShortDescription("");
375: descriptor.setExpert(false);
376: descriptor.setHidden(false);
377: descriptor.setPreferred(true);
378: descriptor.setValue("type", Map.class);
379: descriptor.setValue("resolvableAtDesignTime", Boolean.TRUE);
380: list.add(descriptor);
381:
382: // header
383: descriptor = new FeatureDescriptor();
384: descriptor.setName("header");
385: descriptor.setDisplayName("header");
386: // descriptor.setShortDescription("");
387: descriptor.setExpert(false);
388: descriptor.setHidden(false);
389: descriptor.setPreferred(true);
390: descriptor.setValue("type", Map.class);
391: descriptor.setValue("resolvableAtDesignTime", Boolean.TRUE);
392: list.add(descriptor);
393:
394: // headerValues
395: descriptor = new FeatureDescriptor();
396: descriptor.setName("headerValues");
397: descriptor.setDisplayName("headerValues");
398: // descriptor.setShortDescription("");
399: descriptor.setExpert(false);
400: descriptor.setHidden(false);
401: descriptor.setPreferred(true);
402: descriptor.setValue("type", Map.class);
403: descriptor.setValue("resolvableAtDesignTime", Boolean.TRUE);
404: list.add(descriptor);
405:
406: // cookie
407: descriptor = new FeatureDescriptor();
408: descriptor.setName("cookie");
409: descriptor.setDisplayName("cookie");
410: // descriptor.setShortDescription("");
411: descriptor.setExpert(false);
412: descriptor.setHidden(false);
413: descriptor.setPreferred(true);
414: descriptor.setValue("type", Map.class);
415: descriptor.setValue("resolvableAtDesignTime", Boolean.TRUE);
416: list.add(descriptor);
417:
418: // initParam
419: descriptor = new FeatureDescriptor();
420: descriptor.setName("initParam");
421: descriptor.setDisplayName("initParam");
422: // descriptor.setShortDescription("");
423: descriptor.setExpert(false);
424: descriptor.setHidden(false);
425: descriptor.setPreferred(true);
426: descriptor.setValue("type", Map.class);
427: descriptor.setValue("resolvableAtDesignTime", Boolean.TRUE);
428: list.add(descriptor);
429:
430: return list.iterator();
431: }
432:
433: /**
434: * If the base object is <code>null</code>, returns <code>String.class</code>. Otherwise, returns <code>null</code>.
435: *
436: * @param context The context of this evaluation.
437: * @param base Only <code>null</code> is handled by this resolver. Other values will result in a
438: * <code>null</code> return value.
439: * @return <code>null</code> if base is not <code>null</code> otherwise <code>String.class</code>.
440: */
441: @Override
442: public Class<String> getCommonPropertyType(ELContext context, Object base) {
443: if (base == null) {
444: return String.class;
445: }
446: return null;
447: }
448:
449: // XXX - I moved this class from commons-el to an inner class here
450: // so that we do not have a dependency from the JSP APIs into commons-el.
451: // There might be a better way to do this.
452: /**
453: * <p>
454: * This class is used to generate the implicit Map and List objects that wrap various elements of the PageContext.
455: * It also returns the correct implicit object for a given implicit object name.
456: *
457: * @author Nathan Abramson - Art Technology Group
458: */
459: private static class ImplicitObjects {
460: // -------------------------------------
461: // Constants
462: // -------------------------------------
463:
464: // XXX - This probably needs to change, now that this is in a
465: // standard pkg.
466: static final String sAttributeName = "org.apache.taglibs.standard.ImplicitObjects";
467:
468: // -------------------------------------
469: // Member variables
470: // -------------------------------------
471:
472: PageContext mContext;
473: Map<String, Object> mPage;
474: Map<String, Object> mRequest;
475: Map<String, Object> mSession;
476: Map<String, Object> mApplication;
477: Map<String, String> mParam;
478: Map<String, String[]> mParams;
479: Map<String, String> mHeader;
480: Map<String, String[]> mHeaders;
481: Map<String, String> mInitParam;
482: Map<String, Cookie> mCookie;
483:
484:
485: /**
486: *
487: * Constructor
488: *
489: * @param pContext The PageContext for which this instance is to be constructed
490: */
491: public ImplicitObjects(PageContext pContext) {
492: mContext = pContext;
493: }
494:
495:
496: /**
497: *
498: * @param pContext The PageContext for which the ImplicitObjects instance is required
499: * @return the ImplicitObjects associated with the PageContext, creating it if it doesn't yet exist.
500: */
501: public static ImplicitObjects getImplicitObjects(PageContext pContext) {
502: ImplicitObjects objs = (ImplicitObjects) pContext.getAttribute(sAttributeName, PageContext.PAGE_SCOPE);
503: if (objs == null) {
504: objs = new ImplicitObjects(pContext);
505: pContext.setAttribute(sAttributeName, objs, PageContext.PAGE_SCOPE);
506: }
507: return objs;
508: }
509:
510:
511: /**
512: *
513: * @return the Map that "wraps" page-scoped attributes
514: */
515: public Map<String, Object> getPageScopeMap() {
516: if (mPage == null) {
517: mPage = createPageScopeMap(mContext);
518: }
519: return mPage;
520: }
521:
522:
523: /**
524: *
525: * @return the Map that "wraps" request-scoped attributes
526: */
527: public Map<String, Object> getRequestScopeMap() {
528: if (mRequest == null) {
529: mRequest = createRequestScopeMap(mContext);
530: }
531: return mRequest;
532: }
533:
534:
535: /**
536: *
537: * @return the Map that "wraps" session-scoped attributes
538: */
539: public Map<String, Object> getSessionScopeMap() {
540: if (mSession == null) {
541: mSession = createSessionScopeMap(mContext);
542: }
543: return mSession;
544: }
545:
546:
547: /**
548: *
549: * @return the Map that "wraps" application-scoped attributes
550: */
551: public Map<String, Object> getApplicationScopeMap() {
552: if (mApplication == null) {
553: mApplication = createApplicationScopeMap(mContext);
554: }
555: return mApplication;
556: }
557:
558:
559: /**
560: *
561: * @return the Map that maps parameter name to a single parameter values.
562: */
563: public Map<String, String> getParamMap() {
564: if (mParam == null) {
565: mParam = createParamMap(mContext);
566: }
567: return mParam;
568: }
569:
570:
571: /**
572: *
573: * @return the Map that maps parameter name to an array of parameter values.
574: */
575: public Map<String, String[]> getParamsMap() {
576: if (mParams == null) {
577: mParams = createParamsMap(mContext);
578: }
579: return mParams;
580: }
581:
582:
583: /**
584: *
585: * @return the Map that maps header name to a single header values.
586: */
587: public Map<String, String> getHeaderMap() {
588: if (mHeader == null) {
589: mHeader = createHeaderMap(mContext);
590: }
591: return mHeader;
592: }
593:
594:
595: /**
596: *
597: * @return the Map that maps header name to an array of header values.
598: */
599: public Map<String, String[]> getHeadersMap() {
600: if (mHeaders == null) {
601: mHeaders = createHeadersMap(mContext);
602: }
603: return mHeaders;
604: }
605:
606:
607: /**
608: *
609: * @return the Map that maps init parameter name to a single init parameter values.
610: */
611: public Map<String, String> getInitParamMap() {
612: if (mInitParam == null) {
613: mInitParam = createInitParamMap(mContext);
614: }
615: return mInitParam;
616: }
617:
618:
619: /**
620: *
621: * @return the Map that maps cookie name to the first matching Cookie in request.getCookies().
622: */
623: public Map<String, Cookie> getCookieMap() {
624: if (mCookie == null) {
625: mCookie = createCookieMap(mContext);
626: }
627: return mCookie;
628: }
629:
630: // -------------------------------------
631: // Methods for generating wrapper maps
632: // -------------------------------------
633: /**
634: *
635: * Creates the Map that "wraps" page-scoped attributes
636: *
637: * @param pContext The PageContext for which the Map should be produced
638: *
639: * @return the Map that "wraps" page-scoped attributes
640: */
641: public static Map<String, Object> createPageScopeMap(PageContext pContext) {
642: final PageContext context = pContext;
643: return new EnumeratedMap<>() {
644: @Override
645: public Enumeration<String> enumerateKeys() {
646: return context.getAttributeNamesInScope(PageContext.PAGE_SCOPE);
647: }
648:
649: @Override
650: public Object getValue(Object pKey) {
651:• if (pKey instanceof String) {
652: return context.getAttribute((String) pKey, PageContext.PAGE_SCOPE);
653: } else {
654: return null;
655: }
656: }
657:
658: @Override
659: public boolean isMutable() {
660: return true;
661: }
662: };
663: }
664:
665:
666: /**
667: *
668: * Creates the Map that "wraps" request-scoped attributes
669: *
670: * @param pContext The PageContext for which the Map should be produced
671: *
672: * @return the Map that "wraps" request-scoped attributes
673: */
674: public static Map<String, Object> createRequestScopeMap(PageContext pContext) {
675: final PageContext context = pContext;
676: return new EnumeratedMap<>() {
677: @Override
678: public Enumeration<String> enumerateKeys() {
679: return context.getAttributeNamesInScope(PageContext.REQUEST_SCOPE);
680: }
681:
682: @Override
683: public Object getValue(Object pKey) {
684: if (pKey instanceof String) {
685: return context.getAttribute((String) pKey, PageContext.REQUEST_SCOPE);
686: } else {
687: return null;
688: }
689: }
690:
691: @Override
692: public boolean isMutable() {
693: return true;
694: }
695: };
696: }
697:
698:
699: /**
700: *
701: * Creates the Map that "wraps" session-scoped attributes
702: *
703: * @param pContext The PageContext for which the Map should be produced
704: *
705: * @return the Map that "wraps" session-scoped attributes
706: */
707: public static Map<String, Object> createSessionScopeMap(PageContext pContext) {
708: final PageContext context = pContext;
709: return new EnumeratedMap<>() {
710: @Override
711: public Enumeration<String> enumerateKeys() {
712: return context.getAttributeNamesInScope(PageContext.SESSION_SCOPE);
713: }
714:
715: @Override
716: public Object getValue(Object pKey) {
717: if (pKey instanceof String) {
718: return context.getAttribute((String) pKey, PageContext.SESSION_SCOPE);
719: } else {
720: return null;
721: }
722: }
723:
724: @Override
725: public boolean isMutable() {
726: return true;
727: }
728: };
729: }
730:
731:
732: /**
733: *
734: * Creates the Map that "wraps" application-scoped attributes
735: *
736: * @param pContext The PageContext for which the Map should be produced
737: *
738: * @return the Map that "wraps" application-scoped attributes
739: */
740: public static Map<String, Object> createApplicationScopeMap(PageContext pContext) {
741: final PageContext context = pContext;
742: return new EnumeratedMap<>() {
743: @Override
744: public Enumeration<String> enumerateKeys() {
745: return context.getAttributeNamesInScope(PageContext.APPLICATION_SCOPE);
746: }
747:
748: @Override
749: public Object getValue(Object pKey) {
750: if (pKey instanceof String) {
751: return context.getAttribute((String) pKey, PageContext.APPLICATION_SCOPE);
752: } else {
753: return null;
754: }
755: }
756:
757: @Override
758: public boolean isMutable() {
759: return true;
760: }
761: };
762: }
763:
764:
765: /**
766: *
767: * Creates the Map that maps parameter name to single parameter value.
768: *
769: * @param pContext The PageContext for which the Map should be produced
770: *
771: * @return the Map that maps parameter name to single parameter value
772: */
773: public static Map<String, String> createParamMap(PageContext pContext) {
774: final HttpServletRequest request = (HttpServletRequest) pContext.getRequest();
775: return new EnumeratedMap<>() {
776: @Override
777: public Enumeration<String> enumerateKeys() {
778: return request.getParameterNames();
779: }
780:
781: @Override
782: public String getValue(Object pKey) {
783: if (pKey instanceof String) {
784: return request.getParameter((String) pKey);
785: } else {
786: return null;
787: }
788: }
789:
790: @Override
791: public boolean isMutable() {
792: return false;
793: }
794: };
795: }
796:
797:
798: /**
799: *
800: * Creates the Map that maps parameter name to an array of parameter values.
801: *
802: * @param pContext The PageContext for which the Map should be produced
803: *
804: * @return the Map that maps parameter name to an array of parameter values.
805: */
806: public static Map<String, String[]> createParamsMap(PageContext pContext) {
807: final HttpServletRequest request = (HttpServletRequest) pContext.getRequest();
808: return new EnumeratedMap<>() {
809: @Override
810: public Enumeration<String> enumerateKeys() {
811: return request.getParameterNames();
812: }
813:
814: @Override
815: public String[] getValue(Object pKey) {
816: if (pKey instanceof String) {
817: return request.getParameterValues((String) pKey);
818: } else {
819: return null;
820: }
821: }
822:
823: @Override
824: public boolean isMutable() {
825: return false;
826: }
827: };
828: }
829:
830:
831: /**
832: *
833: * Creates the Map that maps header name to single header value.
834: *
835: * @param pContext The PageContext for which the Map should be produced
836: *
837: * @return the Map that maps header name to single header value
838: */
839: public static Map<String, String> createHeaderMap(PageContext pContext) {
840: final HttpServletRequest request = (HttpServletRequest) pContext.getRequest();
841: return new EnumeratedMap<>() {
842: @Override
843: public Enumeration<String> enumerateKeys() {
844: return request.getHeaderNames();
845: }
846:
847: @Override
848: public String getValue(Object pKey) {
849: if (pKey instanceof String) {
850: return request.getHeader((String) pKey);
851: } else {
852: return null;
853: }
854: }
855:
856: @Override
857: public boolean isMutable() {
858: return false;
859: }
860: };
861: }
862:
863:
864: /**
865: *
866: * Creates the Map that maps header name to an array of header values.
867: *
868: * @param pContext The PageContext for which the Map should be produced
869: *
870: * @return the Map that maps header name to an array of header values
871: */
872: public static Map<String, String[]> createHeadersMap(PageContext pContext) {
873: final HttpServletRequest request = (HttpServletRequest) pContext.getRequest();
874: return new EnumeratedMap<>() {
875: @Override
876: public Enumeration<String> enumerateKeys() {
877: return request.getHeaderNames();
878: }
879:
880: @Override
881: public String[] getValue(Object pKey) {
882: if (pKey instanceof String) {
883: // Drain the header enumeration
884: List<String> l = new ArrayList<>();
885: Enumeration<String> e = request.getHeaders((String) pKey);
886: if (e != null) {
887: while (e.hasMoreElements()) {
888: l.add(e.nextElement());
889: }
890: }
891: return l.toArray(new String[l.size()]);
892: } else {
893: return null;
894: }
895: }
896:
897: @Override
898: public boolean isMutable() {
899: return false;
900: }
901: };
902: }
903:
904:
905: /**
906: *
907: * Creates the Map that maps init parameter name to single init parameter value.
908: *
909: * @param pContext The PageContext for which the Map should be produced
910: *
911: * @return the Map that maps init parameter name to single init parameter value.
912: */
913: public static Map<String, String> createInitParamMap(PageContext pContext) {
914: final ServletContext context = pContext.getServletContext();
915: return new EnumeratedMap<>() {
916: @Override
917: public Enumeration<String> enumerateKeys() {
918: return context.getInitParameterNames();
919: }
920:
921: @Override
922: public String getValue(Object pKey) {
923: if (pKey instanceof String) {
924: return context.getInitParameter((String) pKey);
925: } else {
926: return null;
927: }
928: }
929:
930: @Override
931: public boolean isMutable() {
932: return false;
933: }
934: };
935: }
936:
937:
938: /**
939: *
940: * Creates the Map that maps cookie name to the first matching Cookie in request.getCookies().
941: *
942: * @param pContext The PageContext for which the Map should be produced
943: *
944: * @return the Map that maps cookie name to the first matching Cookie in request.getCookies().
945: */
946: public static Map<String, Cookie> createCookieMap(PageContext pContext) {
947: // Read all the cookies and construct the entire map
948: HttpServletRequest request = (HttpServletRequest) pContext.getRequest();
949: Cookie[] cookies = request.getCookies();
950: Map<String, Cookie> ret = new HashMap<>();
951: for (int i = 0; cookies != null && i < cookies.length; i++) {
952: Cookie cookie = cookies[i];
953: if (cookie != null) {
954: String name = cookie.getName();
955: if (!ret.containsKey(name)) {
956: ret.put(name, cookie);
957: }
958: }
959: }
960: return ret;
961: }
962: }
963:
964: // XXX - I moved this class from commons-el to an inner class here
965: // so that we do not have a dependency from the JSP APIs into commons-el.
966: // There might be a better way to do this.
967: /**
968: * <p>
969: * This is a Map implementation driven by a data source that only provides an enumeration of keys and a
970: * getValue(key) method. This class must be subclassed to implement those methods.
971: *
972: * <p>
973: * Some of the methods may incur a performance penalty that involves enumerating the entire data source. In these
974: * cases, the Map will try to save the results of that enumeration, but only if the underlying data source is
975: * immutable.
976: *
977: * @author Nathan Abramson - Art Technology Group
978: */
979: private static abstract class EnumeratedMap<K, V> implements Map<K, V> {
980: // -------------------------------------
981: // Member variables
982: // -------------------------------------
983:
984: Map<K, V> mMap;
985:
986:
987: @Override
988: public void clear() {
989: throw new UnsupportedOperationException();
990: }
991:
992:
993: @Override
994: public boolean containsKey(Object pKey) {
995: return getValue(pKey) != null;
996: }
997:
998:
999: @Override
1000: public boolean containsValue(Object pValue) {
1001: return getAsMap().containsValue(pValue);
1002: }
1003:
1004:
1005: @Override
1006: public Set<Map.Entry<K, V>> entrySet() {
1007: return getAsMap().entrySet();
1008: }
1009:
1010:
1011: @Override
1012: public V get(Object pKey) {
1013: return getValue(pKey);
1014: }
1015:
1016:
1017: @Override
1018: public boolean isEmpty() {
1019: return !enumerateKeys().hasMoreElements();
1020: }
1021:
1022:
1023: @Override
1024: public Set<K> keySet() {
1025: return getAsMap().keySet();
1026: }
1027:
1028:
1029: @Override
1030: public V put(K pKey, V pValue) {
1031: throw new UnsupportedOperationException();
1032: }
1033:
1034:
1035: @Override
1036: public void putAll(Map<? extends K, ? extends V> pMap) {
1037: throw new UnsupportedOperationException();
1038: }
1039:
1040:
1041: @Override
1042: public V remove(Object pKey) {
1043: throw new UnsupportedOperationException();
1044: }
1045:
1046:
1047: @Override
1048: public int size() {
1049: return getAsMap().size();
1050: }
1051:
1052:
1053: @Override
1054: public Collection<V> values() {
1055: return getAsMap().values();
1056: }
1057:
1058: // -------------------------------------
1059: // Abstract methods
1060: // -------------------------------------
1061: /**
1062: *
1063: * @return an enumeration of the keys
1064: */
1065: public abstract Enumeration<K> enumerateKeys();
1066:
1067:
1068: /**
1069: *
1070: * @return true if it is possible for this data source to change
1071: */
1072: public abstract boolean isMutable();
1073:
1074:
1075: /**
1076: *
1077: * @param pKey The key for which the value should be obtained
1078: * @return the value associated with the given key, or null if not found.
1079: */
1080: public abstract V getValue(Object pKey);
1081:
1082:
1083: /**
1084: *
1085: * Converts the MapSource to a Map. If the map is not mutable, this is cached
1086: *
1087: * @return A Map created from the source Enumeration
1088: */
1089: public Map<K, V> getAsMap() {
1090: if (mMap != null) {
1091: return mMap;
1092: } else {
1093: Map<K, V> m = convertToMap();
1094: if (!isMutable()) {
1095: mMap = m;
1096: }
1097: return m;
1098: }
1099: }
1100:
1101:
1102: /**
1103: *
1104: * Converts to a Map
1105: */
1106: Map<K, V> convertToMap() {
1107: Map<K, V> ret = new HashMap<>();
1108: for (Enumeration<K> e = enumerateKeys(); e.hasMoreElements();) {
1109: K key = e.nextElement();
1110: V value = getValue(key);
1111: ret.put(key, value);
1112: }
1113: return ret;
1114: }
1115: }
1116: }