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