001: /* RequestXelResolver.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Tue Mar 29 18:45:46 2005, Created by tomyeh
010: }}IS_NOTE
011:
012: Copyright (C) 2005 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.web.servlet.xel;
020:
021: import java.util.List;
022: import java.util.LinkedList;
023: import java.util.Set;
024: import java.util.AbstractSet;
025: import java.util.Map;
026: import java.util.HashMap;
027: import java.util.AbstractMap;
028: import java.util.Collections;
029: import java.util.Iterator;
030: import java.util.Enumeration;
031:
032: import javax.servlet.Servlet;
033: import javax.servlet.ServletConfig;
034: import javax.servlet.ServletContext;
035: import javax.servlet.ServletRequest;
036: import javax.servlet.ServletResponse;
037: import javax.servlet.http.HttpServletRequest;
038: import javax.servlet.http.HttpSession;
039: import javax.servlet.http.Cookie;
040:
041: import org.zkoss.xel.ExpressionFactory;
042: import org.zkoss.xel.VariableResolver;
043: import org.zkoss.xel.XelException;
044:
045: /**
046: * A XEL variable resolver that is based on Servlet request, response,
047: * and EL.
048: *
049: * @author tomyeh
050: * @since 3.0.0
051: */
052: abstract public class RequestXelResolver implements VariableResolver {
053: private final ServletContext _ctx;
054: private final ServletRequest _request;
055: private final ServletResponse _response;
056: private HttpSession _sess;
057: private Map _reqScope, _sessScope, _appScope;
058: /** A fake page context implementation. */
059: private PageContext _pc;
060: /** cached cookies. */
061: private Map _cookies;
062:
063: /** Request-based resolver.
064: * @param ctx the context; which might be null
065: * @param request the request. It cannot be null.
066: * @param response the response, which might bell.
067: * @exception IllegalArgumentException if request is null.
068: */
069: public RequestXelResolver(ServletContext ctx,
070: ServletRequest request, ServletResponse response) {
071: if (request == null)
072: throw new IllegalArgumentException();
073: _ctx = ctx;
074: _request = request;
075: _response = response;
076: }
077:
078: public RequestXelResolver(ServletContext ctx, ServletRequest request) {
079: this (ctx, request, null);
080: }
081:
082: public RequestXelResolver(ServletRequest request) {
083: this (null, request, null);
084: }
085:
086: //-- extra --//
087: /** Returns the expression factory (never null).
088: * <p>The deriving class must override it.
089: */
090: abstract public ExpressionFactory getExpressionFactory();
091:
092: /** Returns the page context. */
093: public PageContext getPageContext() {
094: if (_pc == null)
095: _pc = new PageContextImpl();
096: return _pc;
097: }
098:
099: /** Returns the request. */
100: public ServletRequest getRequest() {
101: return _request;
102: }
103:
104: /** Returns the response. */
105: public ServletResponse getResponse() {
106: return _response;
107: }
108:
109: /** Returns the context. */
110: public ServletContext getServletContext() {
111: return _ctx;
112: }
113:
114: //-- VariableResovler --//
115: public Object resolveVariable(String name) throws XelException {
116: if ("pageContext".equals(name)) {
117: return getPageContext();
118: } else if ("pageScope".equals(name)) {
119: return Collections.EMPTY_MAP;
120: } else if ("requestScope".equals(name)) {
121: return getRequestScope();
122: } else if ("sessionScope".equals(name)) {
123: return getSessionScope();
124: } else if ("applicationScope".equals(name)) {
125: return getApplicationScope();
126: } else if ("param".equals(name)) {
127: return new ParamMap();
128: } else if ("paramValues".equals(name)) {
129: return _request.getParameterMap();
130: } else if ("header".equals(name)) {
131: if (!(_request instanceof HttpServletRequest))
132: return Collections.EMPTY_MAP;
133:
134: final HttpServletRequest hreq = (HttpServletRequest) _request;
135: return new AttributesMap() {
136: protected Enumeration getKeys() {
137: return hreq.getHeaderNames();
138: }
139:
140: protected Object getValue(String key) {
141: return hreq.getHeader(key);
142: }
143:
144: protected void setValue(String key, Object val) {
145: throw new UnsupportedOperationException("readonly");
146: }
147:
148: protected void removeValue(String key) {
149: throw new UnsupportedOperationException("readonly");
150: }
151: };
152: } else if ("headerValues".equals(name)) {
153: if (!(_request instanceof HttpServletRequest))
154: return Collections.EMPTY_MAP;
155:
156: final HttpServletRequest hreq = (HttpServletRequest) _request;
157: return new AttributesMap() {
158: //It is OK to cache because it is readonly
159: private final Map _values = new HashMap();
160:
161: protected Enumeration getKeys() {
162: return hreq.getHeaderNames();
163: }
164:
165: protected Object getValue(String key) {
166: Object o = _values.get(key);
167: if (o == null) {
168: final Enumeration e = hreq.getHeaders(key);
169: if (e == null || !e.hasMoreElements())
170: return null;
171:
172: final List l = new LinkedList();
173: do {
174: l.add(e.nextElement());
175: } while (e.hasMoreElements());
176: o = l.toArray(new String[l.size()]);
177: _values.put(key, o);
178: }
179: return o;
180: }
181:
182: protected void setValue(String key, Object val) {
183: throw new UnsupportedOperationException("readonly");
184: }
185:
186: protected void removeValue(String key) {
187: throw new UnsupportedOperationException("readonly");
188: }
189: };
190: } else if ("initParam".equals(name)) {
191: if (_ctx == null)
192: return Collections.EMPTY_MAP;
193:
194: return new AttributesMap() {
195: protected Enumeration getKeys() {
196: return _ctx.getInitParameterNames();
197: }
198:
199: protected Object getValue(String key) {
200: return _ctx.getInitParameter(key);
201: }
202:
203: protected void setValue(String key, Object val) {
204: throw new UnsupportedOperationException("readonly");
205: }
206:
207: protected void removeValue(String key) {
208: throw new UnsupportedOperationException("readonly");
209: }
210: };
211: } else if ("cookie".equals(name)) {
212: if (_cookies != null)
213: return _cookies;
214:
215: final Cookie[] cookies;
216: if (!(_request instanceof HttpServletRequest)
217: || (cookies = ((HttpServletRequest) _request)
218: .getCookies()) == null
219: || cookies.length == 0)
220: return Collections.EMPTY_MAP;
221:
222: _cookies = new HashMap();
223: for (int j = cookies.length; --j >= 0;)
224: _cookies.put(cookies[j].getName(), cookies[j]);
225: }
226:
227: return findAttribute(name);
228: //according EL spec, we have to search attribute
229: }
230:
231: private HttpSession getSession() {
232: if (_sess != null)
233: return _sess;
234:
235: if (!(_request instanceof HttpServletRequest))
236: return null;
237: return _sess = ((HttpServletRequest) _request)
238: .getSession(false);
239: }
240:
241: private Object findAttribute(String name) {
242: Object o = getRequestScope().get(name);
243: if (o != null)
244: return o;
245: o = getSessionScope().get(name);
246: return o != null ? o : getApplicationScope().get(name);
247: }
248:
249: private Map getRequestScope() {
250: if (_reqScope != null)
251: return _reqScope;
252: return _reqScope = new AttributesMap() {
253: protected Enumeration getKeys() {
254: return _request.getAttributeNames();
255: }
256:
257: protected Object getValue(String key) {
258: return _request.getAttribute(key);
259: }
260:
261: protected void setValue(String key, Object val) {
262: _request.setAttribute(key, val);
263: }
264:
265: protected void removeValue(String key) {
266: _request.removeAttribute(key);
267: }
268: };
269: }
270:
271: private Map getSessionScope() {
272: if (_sessScope != null)
273: return _sessScope;
274: final HttpSession sess = getSession();
275: if (sess == null)
276: return _sessScope = Collections.EMPTY_MAP;
277: return _sessScope = new AttributesMap() {
278: protected Enumeration getKeys() {
279: return sess.getAttributeNames();
280: }
281:
282: protected Object getValue(String key) {
283: return sess.getAttribute(key);
284: }
285:
286: protected void setValue(String key, Object val) {
287: sess.setAttribute(key, val);
288: }
289:
290: protected void removeValue(String key) {
291: sess.removeAttribute(key);
292: }
293: };
294: }
295:
296: private Map getApplicationScope() {
297: if (_appScope != null)
298: return _appScope;
299: if (_ctx == null)
300: return _appScope = Collections.EMPTY_MAP;
301: return _appScope = new AttributesMap() {
302: protected Enumeration getKeys() {
303: return _ctx.getAttributeNames();
304: }
305:
306: protected Object getValue(String key) {
307: return _ctx.getAttribute(key);
308: }
309:
310: protected void setValue(String key, Object val) {
311: _ctx.setAttribute(key, val);
312: }
313:
314: protected void removeValue(String key) {
315: _ctx.removeAttribute(key);
316: }
317: };
318: }
319:
320: /** Used to access attributes of request, session and context. */
321: private class ParamMap extends StringKeysMap {
322: private Set _entries;
323:
324: public Set entrySet() {
325: if (_entries == null) {
326: _entries = new AbstractSet() {
327: public int size() {
328: return ParamMap.this .size();
329: }
330:
331: public boolean contains(Object o) {
332: return ParamMap.this .containsKey(o);
333: }
334:
335: public Iterator iterator() {
336: return new EntryIter();
337: }
338: };
339: }
340: return _entries;
341: }
342:
343: public int size() {
344: return _request.getParameterMap().size();
345: }
346:
347: public boolean containsKey(Object key) {
348: return _request.getParameterMap().containsKey(key);
349: }
350:
351: protected Object getValue(String key) {
352: return _request.getParameter(key);
353: }
354:
355: protected Enumeration getKeys() {
356: return _request.getParameterNames();
357: }
358:
359: protected void setValue(String key, Object value) {
360: throw new UnsupportedOperationException("readonly");
361: }
362:
363: protected void removeValue(String key) {
364: throw new UnsupportedOperationException("readonly");
365: }
366: } //ParamMap
367:
368: /** An implemnetation of PageContext. */
369: private class PageContextImpl implements PageContext {
370: public ServletRequest getRequest() {
371: return _request;
372: }
373:
374: public ServletResponse getResponse() {
375: return _response;
376: }
377:
378: public ServletConfig getServletConfig() {
379: return null;
380: }
381:
382: public ServletContext getServletContext() {
383: return _ctx;
384: }
385:
386: public HttpSession getSession() {
387: return RequestXelResolver.this .getSession();
388: }
389:
390: public VariableResolver getVariableResolver() {
391: return RequestXelResolver.this;
392: }
393: }
394: }
|