001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: * $Header:$
018: */
019: package org.apache.beehive.netui.pageflow.scoping.internal;
020:
021: import org.apache.beehive.netui.pageflow.scoping.ScopedRequest;
022: import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
023: import org.apache.beehive.netui.util.logging.Logger;
024:
025: import javax.servlet.http.HttpServletRequest;
026: import javax.servlet.http.HttpSession;
027: import javax.servlet.http.HttpServletRequestWrapper;
028: import javax.servlet.RequestDispatcher;
029: import javax.servlet.ServletRequest;
030: import javax.servlet.ServletContext;
031: import java.util.Enumeration;
032: import java.util.Map;
033: import java.util.Collections;
034: import java.util.ArrayList;
035: import java.util.Iterator;
036: import java.util.HashMap;
037: import java.util.List;
038: import java.util.Set;
039: import java.util.HashSet;
040: import java.io.UnsupportedEncodingException;
041:
042: import org.apache.commons.codec.net.URLCodec;
043: import org.apache.commons.codec.DecoderException;
044:
045: /**
046: * A wrapper around HttpServletRequest, associated with a given scope-key. All calls to setAttribute,
047: * getAttribute, removeAttribute, etc. are scoped to this object, while most other functionality
048: * delegates to the wrapped HttpServletRequest.
049: * Instances of this class also keep track of their own request-URIs, which are independent of the
050: * wrapped request-URIs.
051: */
052: public class ScopedRequestImpl extends HttpServletRequestWrapper
053: implements ScopedRequest {
054: private String _requestURI;
055: private String _servletPath;
056: private String _forwardedURI;
057: private ScopedAttributeContainer _scopedContainer;
058: private List _listenScopes;
059: private String _overridePathInfo = null;
060: private boolean _isActiveRequest = false;
061: private boolean _seeOuterRequestAttributes = false;
062: private Set _visibleOuterRequestAttrs;
063: private Map _additionalParameters;
064:
065: static final String ATTR_PREFIX = "_netui:";
066: private static final String OUR_SESSION_ATTR = ATTR_PREFIX
067: + "scopedSession";
068: private static final String STORED_ATTRS_ATTR = ATTR_PREFIX
069: + "storedAttrs";
070:
071: private static final Logger _log = Logger
072: .getInstance(ScopedRequestImpl.class);
073: private static final URLCodec URL_CODEC = new URLCodec();
074:
075: public ScopedRequestImpl(HttpServletRequest req,
076: String overrideRequestURI, Object scopeKey,
077: ServletContext servletContext,
078: boolean seeOuterRequestAttributes) {
079: super (req);
080:
081: _scopedContainer = new ScopedAttributeContainer(scopeKey);
082: setRequestURI(overrideRequestURI);
083: _seeOuterRequestAttributes = seeOuterRequestAttributes;
084:
085: if (!seeOuterRequestAttributes)
086: _visibleOuterRequestAttrs = new HashSet();
087: }
088:
089: /**
090: * @deprecated Use {@link #ScopedRequestImpl(HttpServletRequest, String, Object, ServletContext, boolean)}.
091: */
092: public ScopedRequestImpl(HttpServletRequest req,
093: String overrideRequestURI, Object scopeKey,
094: ServletContext context) {
095: this (req, overrideRequestURI, scopeKey, context, false);
096: }
097:
098: public String getRequestedSessionId() {
099: return super .getRequestedSessionId();
100: }
101:
102: public String getRequestURI() {
103: return _requestURI;
104: }
105:
106: public void setRequestURI(String uri) {
107: _requestURI = uri;
108:
109: if (uri == null) {
110: _servletPath = null;
111: return;
112: }
113:
114: //
115: // Set the servlet path (decoded)
116: //
117: assert uri.startsWith(getOuterRequest().getContextPath()) : uri;
118: setServletPath(uri.substring(getOuterRequest().getContextPath()
119: .length()));
120: }
121:
122: public void setRequestURI(String contextPath, String servletPath) {
123: _requestURI = contextPath + servletPath;
124: setServletPath(servletPath);
125: }
126:
127: private void setServletPath(String servletPath) {
128: String encoding = getCharacterEncoding();
129:
130: try {
131: if (encoding == null)
132: encoding = "utf-8";
133: servletPath = URL_CODEC.decode(servletPath, encoding);
134: } catch (DecoderException e) {
135: _log.error("error decoding path " + servletPath, e);
136: } catch (UnsupportedEncodingException e) {
137: _log.error("unsupported encoding " + encoding
138: + " while decoding path " + servletPath, e);
139: }
140:
141: _servletPath = ScopedServletUtils.normalizeURI(servletPath);
142: }
143:
144: public StringBuffer getRequestURL() {
145: HttpServletRequest outerRequest = getOuterRequest();
146: StringBuffer url = new StringBuffer(outerRequest.getScheme());
147: url.append("://").append(outerRequest.getServerName());
148: url.append(':').append(outerRequest.getServerPort());
149: url.append(getRequestURI());
150: return url;
151: }
152:
153: public String getServletPath() {
154: return _servletPath;
155: }
156:
157: public String getParameter(String paramName) {
158: String retVal = getLocalParameter(paramName);
159: if (retVal == null) {
160: retVal = getListenScopeParameter(paramName);
161: }
162:
163: return retVal;
164: }
165:
166: /**
167: * Add a parameter to the request.
168: *
169: * @param name the parameter name.
170: * @param value the parameter value.
171: */
172: public void addParameter(String name, String value) {
173: if (_additionalParameters == null) {
174: _additionalParameters = new HashMap();
175: }
176:
177: _additionalParameters.put(name, value);
178: }
179:
180: /**
181: * Get the parameter from the scoped request only (don't check in listen scoped requests)
182: * @param paramName
183: * @return value of the parameter
184: */
185: public String getLocalParameter(String paramName) {
186: if (_additionalParameters != null) {
187: String overrideParam = (String) _additionalParameters
188: .get(paramName);
189:
190: if (overrideParam != null) {
191: return overrideParam;
192: }
193: }
194:
195: ServletRequest request = getRequest();
196: String retVal = request.getParameter(_scopedContainer
197: .getScopedName(paramName));
198:
199: if (retVal == null && _isActiveRequest
200: && paramName.startsWith(AUTOSCOPE_PREFIX)) {
201: retVal = request.getParameter(paramName);
202: }
203:
204: return retVal;
205: }
206:
207: /**
208: * Get the parameter from the listen scoped requests
209: * @param paramName
210: * @return value of the parameter
211: */
212: public String getListenScopeParameter(String paramName) {
213: String retVal = null;
214:
215: if (_listenScopes != null) {
216: for (int i = 0, len = _listenScopes.size(); retVal == null
217: && i < len; ++i) {
218: String key = ScopedServletUtils.getScopedName(
219: paramName, _listenScopes.get(i));
220: retVal = getRequest().getParameter(key);
221: }
222: }
223:
224: return retVal;
225: }
226:
227: public Enumeration getParameterNames() {
228: ArrayList paramNames = new ArrayList();
229:
230: for (Enumeration e = getRequest().getParameterNames(); e
231: .hasMoreElements();) {
232: String scopedParamName = (String) e.nextElement();
233:
234: if (_scopedContainer.isInScope(scopedParamName)) {
235: paramNames.add(_scopedContainer
236: .removeScope(scopedParamName));
237: } else if (_isActiveRequest
238: && scopedParamName.startsWith(AUTOSCOPE_PREFIX)) {
239: paramNames.add(scopedParamName);
240: } else if (_listenScopes != null) {
241: for (int i = 0, len = _listenScopes.size(); i < len; ++i) {
242: Object scope = _listenScopes.get(i);
243:
244: if (ScopedAttributeContainer.isInScope(
245: scopedParamName, scope)) {
246: paramNames.add(ScopedAttributeContainer
247: .removeScope(scopedParamName, scope));
248: }
249: }
250: }
251: }
252:
253: return Collections.enumeration(paramNames);
254: }
255:
256: public String[] getParameterValues(String paramName) {
257: ServletRequest request = getRequest();
258: String[] retVals = request.getParameterValues(_scopedContainer
259: .getScopedName(paramName));
260:
261: if (retVals == null && _isActiveRequest
262: && paramName.startsWith(AUTOSCOPE_PREFIX)) {
263: retVals = request.getParameterValues(paramName);
264: }
265:
266: if (retVals == null && _listenScopes != null) {
267: for (int i = 0, len = _listenScopes.size(); retVals == null
268: && i < len; ++i) {
269: String key = ScopedServletUtils.getScopedName(
270: paramName, _listenScopes.get(i));
271: retVals = request.getParameterValues(key);
272: }
273: }
274:
275: return retVals;
276: }
277:
278: public Map getParameterMap() {
279: return filterParameterMap(getRequest().getParameterMap());
280: }
281:
282: /**
283: * @exclude
284: */
285: public Map filterParameterMap(Map parameterMap) {
286: HashMap map = new HashMap();
287:
288: for (Iterator i = parameterMap.entrySet().iterator(); i
289: .hasNext();) {
290: Map.Entry entry = (Map.Entry) i.next();
291: String scopedParamName = (String) entry.getKey();
292:
293: if (_scopedContainer.isInScope(scopedParamName)) {
294: map.put(_scopedContainer.removeScope(scopedParamName),
295: entry.getValue());
296: } else if (_isActiveRequest
297: && scopedParamName.startsWith(AUTOSCOPE_PREFIX)) {
298: map.put(scopedParamName, entry.getValue());
299: } else if (_listenScopes != null) {
300: for (int j = 0, len = _listenScopes.size(); j < len; ++j) {
301: if (ScopedAttributeContainer.isInScope(
302: scopedParamName, _listenScopes.get(j))) {
303: map.put(ScopedAttributeContainer.removeScope(
304: scopedParamName, _listenScopes.get(j)),
305: entry.getValue());
306: }
307: }
308: }
309: }
310:
311: return map;
312: }
313:
314: /**
315: * Adds a scope to "listen" to. This scope will see all request parameters from a ScopedRequest
316: * of the given scope.
317: */
318: public void addListenScope(Object scopeKey) {
319: assert scopeKey != null;
320:
321: if (_listenScopes == null) {
322: _listenScopes = new ArrayList();
323: }
324:
325: _listenScopes.add(scopeKey);
326: }
327:
328: public RequestDispatcher getRequestDispatcher(String uri) {
329: return new ScopedRequestDispatcher(uri);
330: }
331:
332: public void doForward() {
333: String forwardedURI = _forwardedURI;
334:
335: if (forwardedURI != null) {
336: if (!forwardedURI.startsWith("/")) {
337: int lastSlash = _requestURI.lastIndexOf('/');
338: assert lastSlash != -1 : _requestURI;
339: setRequestURI(_requestURI.substring(0, lastSlash + 1)
340: + forwardedURI);
341: } else {
342: setRequestURI(getOuterRequest().getContextPath(),
343: forwardedURI);
344: }
345:
346: // Parse the query string and add parameters to the internal map
347: parseQueryParameters();
348: } else {
349: setRequestURI(null);
350: }
351: }
352:
353: private void parseQueryParameters() {
354: int queryIndex = _requestURI.indexOf("?");
355: if (queryIndex < 0) {
356: return;
357: }
358:
359: String queryString = _requestURI.substring(queryIndex + 1);
360:
361: // hack off the query string
362: _requestURI = _requestURI.substring(0, queryIndex);
363:
364: if (queryString.length() == 0) {
365: return;
366: }
367:
368: HashMap queryParameters = new HashMap();
369: ParseUtils.parseQueryString(queryString, queryParameters,
370: getCharacterEncoding());
371:
372: Iterator itor = queryParameters.keySet().iterator();
373: while (itor.hasNext()) {
374: Object key = itor.next();
375: addParameter((String) key, (String) queryParameters
376: .get(key));
377: }
378: }
379:
380: /**
381: * Simply stores the URI that was being forwarded to.
382: *
383: * @param uri
384: */
385: public void setForwardedURI(String uri) {
386: _forwardedURI = uri;
387: }
388:
389: public String getForwardedURI() {
390: return _forwardedURI;
391: }
392:
393: /**
394: * @deprecated Use {@link ScopedResponseImpl#didRedirect} instead.
395: */
396: public boolean didRedirect() {
397: return false;
398: }
399:
400: /**
401: * Stores the current map of request attributes in the Session.
402: * @deprecated Moved the persisting of attributes out of the beehive NetUI
403: * layer. Use {@link #getAttributeMap} to get the attributes.
404: */
405: public void persistAttributes() {
406: String attrName = getScopedName(STORED_ATTRS_ATTR);
407: getSession().setAttribute(attrName,
408: _scopedContainer.getSerializableAttrs());
409: }
410:
411: /**
412: * Restores the map of request attributes from a map saved in the Session.
413: * @deprecated Moved the persisting of attributes out of the beehive NetUI
414: * layer. Use {@link #setAttributeMap} to set/merge the attributes.
415: */
416: public void restoreAttributes() {
417: String attrName = getScopedName(STORED_ATTRS_ATTR);
418: Map savedAttrs = (Map) getSession().getAttribute(attrName);
419:
420: if (savedAttrs != null) {
421: setAttributeMap(savedAttrs);
422: }
423: }
424:
425: /**
426: * Get the current map of request attributes.
427: */
428: public Map getAttributeMap() {
429: return _scopedContainer.getAttrMap();
430: }
431:
432: /**
433: * Set/merge the map of request attributes from a given map.
434: * Do not call this method with a null Map.
435: *
436: * @param savedAttrs the Map of attributes to set or merge with
437: * the current map of request attributes
438: */
439: public void setAttributeMap(Map savedAttrs) {
440: assert savedAttrs != null : "Map of attributes must be non-null";
441:
442: Map currentAttrs = _scopedContainer.getAttrMap();
443:
444: Map attrs = new HashMap();
445: attrs.putAll(savedAttrs);
446:
447: if (currentAttrs != null) {
448: attrs.putAll(currentAttrs);
449: }
450:
451: _scopedContainer.setAttrMap(attrs);
452: }
453:
454: public final HttpServletRequest getOuterRequest() {
455: return (HttpServletRequest) getRequest();
456: }
457:
458: public final Object getAttribute(String attrName) {
459: return getAttribute(attrName, true);
460: }
461:
462: public final Object getAttribute(String attrName,
463: boolean allowOuterRequestAttributes) {
464: if (!allowOuterRequestAttributes)
465: return _scopedContainer.getAttribute(attrName);
466:
467: ServletRequest outerRequest = getRequest();
468:
469: if (!_seeOuterRequestAttributes
470: && _visibleOuterRequestAttrs.contains(attrName)) {
471: return outerRequest.getAttribute(attrName);
472: }
473:
474: Object value = _scopedContainer.getAttribute(attrName);
475:
476: if (value == null && _seeOuterRequestAttributes) {
477: value = outerRequest.getAttribute(attrName);
478: }
479:
480: return value;
481: }
482:
483: public final void setAttribute(String attrName, Object o) {
484: if (!_seeOuterRequestAttributes
485: && _visibleOuterRequestAttrs.contains(attrName)) {
486: getRequest().setAttribute(attrName, o);
487: } else {
488: _scopedContainer.setAttribute(attrName, o);
489: }
490: }
491:
492: public final Enumeration getAttributeNames() {
493: Set set = new HashSet();
494:
495: if (!_seeOuterRequestAttributes) {
496: for (Enumeration e = getRequest().getAttributeNames(); e
497: .hasMoreElements();) {
498: Object attrName = e.nextElement();
499: if (_visibleOuterRequestAttrs.contains(attrName))
500: set.add(attrName);
501: }
502: }
503:
504: for (Enumeration e = _scopedContainer.getAttributeNames(); e
505: .hasMoreElements();) {
506: set.add(e.nextElement());
507: }
508:
509: if (_seeOuterRequestAttributes) {
510: for (Enumeration e = getRequest().getAttributeNames(); e
511: .hasMoreElements();) {
512: set.add(e.nextElement());
513: }
514: }
515:
516: return Collections.enumeration(set);
517: }
518:
519: public final void removeAttribute(String attrName) {
520: if (!_seeOuterRequestAttributes
521: && _visibleOuterRequestAttrs.contains(attrName)) {
522: getRequest().removeAttribute(attrName);
523: } else {
524: _scopedContainer.removeAttribute(attrName);
525: }
526: }
527:
528: public void registerOuterAttribute(String attrName) {
529: assert !_seeOuterRequestAttributes : "(attribute "
530: + attrName
531: + ") "
532: + "this method is not valid unless the ScopedRequest is configured not to see outer request attributes";
533:
534: if (_seeOuterRequestAttributes) {
535: _log
536: .error("the ScopedRequest is already configured to see outer request attributes");
537: return;
538: }
539:
540: _visibleOuterRequestAttrs.add(attrName);
541: }
542:
543: public final Object getScopeKey() {
544: return _scopedContainer.getScopeKey();
545: }
546:
547: public void renameScope(Object newScopeKey) {
548: _scopedContainer.renameScope(newScopeKey);
549: }
550:
551: public static void renameSessionScope(Object oldScopeKey,
552: Object newScopeKey, HttpServletRequest outerRequest) {
553: HttpSession realSession = outerRequest.getSession(false);
554:
555: if (realSession != null) {
556: String realSessionAttr = ScopedServletUtils.getScopedName(
557: OUR_SESSION_ATTR, oldScopeKey);
558: Object ourSession = realSession
559: .getAttribute(realSessionAttr);
560: realSessionAttr = ScopedServletUtils.getScopedName(
561: OUR_SESSION_ATTR, newScopeKey);
562: realSession.setAttribute(realSessionAttr, ourSession);
563: }
564: }
565:
566: public String getPathInfo() {
567: return _overridePathInfo;
568: }
569:
570: public void setPathInfo(String pathInfo) {
571: _overridePathInfo = pathInfo;
572: }
573:
574: /**
575: * Makes this request listen to specially-prefixed request parameters.
576: */
577: public void setActiveRequest() {
578: _isActiveRequest = true;
579: }
580:
581: public final String getScopedName(String baseName) {
582: return _scopedContainer.getScopedName(baseName);
583: }
584:
585: /**
586: * see if this scoped request is listening to any other scoped request
587: * @return true if has listen scopes
588: */
589: public boolean hasListenScopes() {
590: return _listenScopes != null && _listenScopes.size() > 0;
591: }
592: }
|