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