001: /*
002: * $Id: ServletRequestPropertyReader.java,v 1.28 2007/09/18 08:45:14 agoubard Exp $
003: *
004: * Copyright 2003-2007 Orange Nederland Breedband B.V.
005: * See the COPYRIGHT file for redistribution and use restrictions.
006: */
007: package org.xins.common.servlet;
008:
009: import java.util.HashMap;
010: import java.util.Map;
011: import java.util.StringTokenizer;
012:
013: import javax.servlet.ServletRequest;
014: import javax.servlet.http.HttpServletRequest;
015:
016: import org.xins.common.MandatoryArgumentChecker;
017: import org.xins.common.collections.AbstractPropertyReader;
018: import org.xins.common.text.ParseException;
019: import org.xins.common.text.TextUtils;
020: import org.xins.common.text.URLEncoding;
021:
022: /**
023: * Implementation of a <code>PropertyReader</code> that returns the
024: * request parameters from a <code>ServletRequest</code> object.
025: *
026: * @version $Revision: 1.28 $ $Date: 2007/09/18 08:45:14 $
027: * @author <a href="mailto:ernst@ernstdehaan.com">Ernst de Haan</a>
028: * @author <a href="mailto:anthony.goubard@japplis.com">Anthony Goubard</a>
029: *
030: * @since XINS 1.0.0
031: */
032: public final class ServletRequestPropertyReader extends
033: AbstractPropertyReader {
034:
035: /**
036: * Constructs a new <code>ServletRequestPropertyReader</code> for a
037: * <code>ServletRequest</code>.
038: *
039: * @param request
040: * the {@link ServletRequest} object, cannot be <code>null</code>.
041: *
042: * @throws NullPointerException
043: * if <code>request == null</code>.
044: */
045: public ServletRequestPropertyReader(ServletRequest request)
046: throws NullPointerException {
047: super (request.getParameterMap());
048: }
049:
050: /**
051: * Constructs a new <code>ServletRequestPropertyReader</code> for an
052: * <code>HttpServletRequest</code>.
053: *
054: * @param request
055: * the {@link HttpServletRequest} object, cannot be <code>null</code>.
056: *
057: * @throws IllegalArgumentException
058: * if <code>request == null</code>.
059: *
060: * @throws ParseException
061: * if the query string in the specified servlet request cannot be
062: * parsed.
063: *
064: * @since XINS 1.4.0
065: */
066: public ServletRequestPropertyReader(HttpServletRequest request)
067: throws IllegalArgumentException, ParseException {
068:
069: // Initially allocate a complete HashMap already
070: super (new HashMap(20));
071:
072: // Check preconditions
073: MandatoryArgumentChecker.check("request", request);
074:
075: Map properties = getPropertiesMap();
076:
077: // Get the HTTP query string
078: String query = request.getQueryString();
079:
080: // Short-circuit if the query string is empty
081: if (TextUtils.isEmpty(query)) {
082: return;
083: }
084:
085: // Parse the parameters in the HTTP query string
086: try {
087: StringTokenizer st = new StringTokenizer(query, "&");
088: while (st.hasMoreTokens()) {
089: String token = st.nextToken();
090: int equalsPos = token.indexOf('=');
091: if (equalsPos != -1) {
092: String parameterKey = URLEncoding.decode(token
093: .substring(0, equalsPos));
094: String parameterValue = URLEncoding.decode(token
095: .substring(equalsPos + 1));
096: add(properties, parameterKey, parameterValue);
097: } else {
098: add(properties, token, "");
099: }
100: }
101:
102: // URLEncoder.decode(String url, String enc) may throw an UnsupportedEncodingException
103: // or an IllegalArgumentException
104: } catch (Exception cause) {
105: throw new ParseException(
106: "Failed to parse HTTP query string.", cause,
107: "URL decoding failed.");
108: }
109: }
110:
111: /**
112: * Sets a parameter to the specified value. If the parameter is already set
113: * to a different value, then an exception is thrown.
114: *
115: * <p>This function is used during parsing of a HTTP query string, which is
116: * why a {@link ParseException} is thrown in case of conflicting values.
117: *
118: * @param properties
119: * the set of parameters, should not be <code>null</code>.
120: *
121: * @param key
122: * the parameter key, should not be <code>null</code>.
123: *
124: * @param value
125: * the parameter value, should not be <code>null</code>.
126: *
127: * @throws NullPointerException
128: * if <code>properties == null</code>.
129: *
130: * @throws ParseException
131: * if a conflicting value is found for a certain parameter.
132: */
133: private static void add(Map properties, String key, String value)
134: throws NullPointerException, ParseException {
135:
136: Object existingValue = properties.get(key);
137: if (existingValue != null && !existingValue.equals(value)) {
138: String detail = "Conflicting values found for parameter \""
139: + key + "\": \"" + (String) existingValue
140: + "\" versus \"" + value + "\".";
141: throw new ParseException(
142: "Failed to parse HTTP query string.",
143: (Throwable) null, detail);
144: }
145:
146: properties.put(key, value);
147: }
148: }
|