pier 01/08/05 11:33:42
Modified: webapp/java WarpRequestHandler.java
Log:
Compliancy patch:
- Now values of URL-encoded sessions are correctly handled (Thanks to
Eryq <[EMAIL PROTECTED]> for reporting this bug.
- Locales are set correctly in the request object, parsing the
Accept-Languages header as done in the HTTP/1.1 connector.
- The query string is now set to null if there are no query parameters.
With this patch, mod_webapp using WARP runs all WatchDog compliancy tests
just fine.
Revision Changes Path
1.15 +165 -15 jakarta-tomcat-connectors/webapp/java/WarpRequestHandler.java
Index: WarpRequestHandler.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat-connectors/webapp/java/WarpRequestHandler.java,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- WarpRequestHandler.java 2001/07/25 22:32:05 1.14
+++ WarpRequestHandler.java 2001/08/05 18:33:42 1.15
@@ -59,7 +59,12 @@
import java.io.File;
import java.io.IOException;
import java.net.URL;
+import java.util.*;
+import java.util.Locale;
+import java.util.TreeMap;
+
import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
import org.apache.catalina.Container;
import org.apache.catalina.Context;
@@ -68,9 +73,13 @@
import org.apache.catalina.Host;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.util.RequestUtil;
+import org.apache.catalina.util.StringParser;
public class WarpRequestHandler {
+ private StringParser parser = new StringParser();
+ private static final String match=";"+Globals.SESSION_PARAMETER_NAME+"=";
+
/* ==================================================================== */
/* Constructor */
/* ==================================================================== */
@@ -118,8 +127,9 @@
response.setPacket(packet);
request.setMethod(meth);
- request.setRequestURI(ruri);
- request.setQueryString(args);
+ this.processUri(logger,request,ruri);
+ if (args.length()>0) request.setQueryString(args);
+ else request.setQueryString(null);
request.setProtocol(prot);
request.setConnection(connection);
Context ctx=connector.applicationContext(id);
@@ -163,10 +173,7 @@
case Constants.TYPE_REQ_HEADER: {
String hnam=packet.readString();
String hval=packet.readString();
- if (Constants.DEBUG)
- logger.debug("Request header "+hnam+": "+hval);
- request.addHeader(hnam,hval);
- this.processHeader(request,hnam,hval);
+ this.processHeader(logger,request,hnam,hval);
break;
}
@@ -220,9 +227,43 @@
}
}
}
+ }
+
+ private void processUri(WarpLogger logger, WarpRequest req, String uri) {
+
+ // Parse any requested session ID out of the request URI
+ int semicolon = uri.indexOf(match);
+ if (semicolon >= 0) {
+ String rest = uri.substring(semicolon + match.length());
+ int semicolon2 = rest.indexOf(';');
+ if (semicolon2 >= 0) {
+ req.setRequestedSessionId(rest.substring(0, semicolon2));
+ rest = rest.substring(semicolon2);
+ } else {
+ req.setRequestedSessionId(rest);
+ rest = "";
+ }
+ req.setRequestedSessionURL(true);
+ uri = uri.substring(0, semicolon) + rest;
+ if (Constants.DEBUG) {
+ logger.log("Requested URL session id is " +
+ ((HttpServletRequest) req.getRequest())
+ .getRequestedSessionId());
+ }
+ } else {
+ req.setRequestedSessionId(null);
+ req.setRequestedSessionURL(false);
+ }
+
+ req.setRequestURI(uri);
}
-
- private void processHeader(WarpRequest req, String name, String value) {
+
+ private void processHeader(WarpLogger logger, WarpRequest req,
+ String name, String value) {
+
+ if (Constants.DEBUG)
+ logger.debug("Request header "+name+": "+value);
+
if ("cookie".equalsIgnoreCase(name)) {
Cookie cookies[] = RequestUtil.parseCookieHeader(value);
for (int i = 0; i < cookies.length; i++) {
@@ -235,17 +276,126 @@
(cookies[i].getValue());
req.setRequestedSessionCookie(true);
req.setRequestedSessionURL(false);
-/* if (Constants.DEBUG)
- logger.debug(" Requested cookie session id is " +
- ((HttpServletRequest) request.getRequest())
+ if (Constants.DEBUG) {
+ logger.debug("Requested cookie session id is " +
+ ((HttpServletRequest) req.getRequest())
.getRequestedSessionId());
-*/ }
+ }
+ }
}
-/* if (Constants.DEBUG)
- logger.debug(" Adding cookie " + cookies[i].getName() + "=" +
+ if (Constants.DEBUG) {
+ logger.debug("Adding cookie "+cookies[i].getName()+"="+
cookies[i].getValue());
-*/ req.addCookie(cookies[i]);
+ }
+ req.addCookie(cookies[i]);
+ }
+ }
+ if (name.equalsIgnoreCase("Accept-Language"))
+ parseAcceptLanguage(logger,req,value);
+ req.addHeader(name,value);
+ }
+
+ /**
+ * Parse the value of an <code>Accept-Language</code> header, and add
+ * the corresponding Locales to the current request.
+ *
+ * @param value The value of the <code>Accept-Language</code> header.
+ */
+ private void parseAcceptLanguage(WarpLogger logger, WarpRequest request,
+ String value) {
+
+ // Store the accumulated languages that have been requested in
+ // a local collection, sorted by the quality value (so we can
+ // add Locales in descending order). The values will be ArrayLists
+ // containing the corresponding Locales to be added
+ TreeMap locales = new TreeMap();
+
+ // Preprocess the value to remove all whitespace
+ int white = value.indexOf(' ');
+ if (white < 0)
+ white = value.indexOf('\t');
+ if (white >= 0) {
+ StringBuffer sb = new StringBuffer();
+ int len = value.length();
+ for (int i = 0; i < len; i++) {
+ char ch = value.charAt(i);
+ if ((ch != ' ') && (ch != '\t'))
+ sb.append(ch);
+ }
+ value = sb.toString();
+ }
+
+ // Process each comma-delimited language specification
+ parser.setString(value); // ASSERT: parser is available to us
+ int length = parser.getLength();
+ while (true) {
+
+ // Extract the next comma-delimited entry
+ int start = parser.getIndex();
+ if (start >= length)
+ break;
+ int end = parser.findChar(',');
+ String entry = parser.extract(start, end).trim();
+ parser.advance(); // For the following entry
+
+ // Extract the quality factor for this entry
+ double quality = 1.0;
+ int semi = entry.indexOf(";q=");
+ if (semi >= 0) {
+ try {
+ quality = Double.parseDouble(entry.substring(semi + 3));
+ } catch (NumberFormatException e) {
+ quality = 0.0;
+ }
+ entry = entry.substring(0, semi);
+ }
+
+ // Skip entries we are not going to keep track of
+ if (quality < 0.00005)
+ continue; // Zero (or effectively zero) quality factors
+ if ("*".equals(entry))
+ continue; // FIXME - "*" entries are not handled
+
+ // Extract the language and country for this entry
+ String language = null;
+ String country = null;
+ int dash = entry.indexOf('-');
+ if (dash < 0) {
+ language = entry;
+ country = "";
+ } else {
+ language = entry.substring(0, dash);
+ country = entry.substring(dash + 1);
}
+
+ // Add a new Locale to the list of Locales for this quality level
+ Locale locale = new Locale(language, country);
+ Double key = new Double(-quality); // Reverse the order
+ ArrayList values = (ArrayList) locales.get(key);
+ if (values == null) {
+ values = new ArrayList();
+ locales.put(key, values);
+ }
+ values.add(locale);
+
}
+
+ // Process the quality values in highest->lowest order (due to
+ // negating the Double value when creating the key)
+ Iterator keys = locales.keySet().iterator();
+ while (keys.hasNext()) {
+ Double key = (Double) keys.next();
+ ArrayList list = (ArrayList) locales.get(key);
+ Iterator values = list.iterator();
+ while (values.hasNext()) {
+ Locale locale = (Locale) values.next();
+ if (Constants.DEBUG) {
+ logger.debug("Adding locale '" + locale + "'");
+ }
+ request.addLocale(locale);
+ }
+ }
}
+
+
}