001: /* *****************************************************************************
002: * ContentEncoding.java
003: * ****************************************************************************/
004:
005: /* J_LZ_COPYRIGHT_BEGIN *******************************************************
006: * Copyright 2001-2004 Laszlo Systems, Inc. All Rights Reserved. *
007: * Use is subject to license terms. *
008: * J_LZ_COPYRIGHT_END *********************************************************/
009:
010: package org.openlaszlo.utils;
011:
012: import org.openlaszlo.server.LPS;
013:
014: import javax.servlet.*;
015: import javax.servlet.http.*;
016:
017: import java.util.StringTokenizer;
018: import java.util.List;
019: import java.util.ArrayList;
020: import java.util.Iterator;
021:
022: import org.apache.log4j.*;
023:
024: /**
025: * ContentEncoding is representation of an HTTP 1.1 Content Encoding
026: * according to RFC 2616:
027: * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html"
028: * >http://www.w3.org/Protocols/rfc2616/rfc2616.html</a>
029: * This spec is less than perfect.
030: *
031: * @author <a href="mailto:bloch@laszlosystems.com">bloch@laszlosystems.com</a>
032: */
033: public class ContentEncoding {
034:
035: private static Logger mLogger = Logger
036: .getLogger(ContentEncoding.class);
037:
038: public String name = null;
039: public float q = 0;
040:
041: /**
042: * @param req an HTTP request
043: * @return ContentEncoding [] an array of encodings acceptable by
044: * client making this request
045: */
046: private static List parseEncodings(HttpServletRequest req) {
047:
048: String acceptHeader = req.getHeader("Accept-Encoding");
049: if (acceptHeader == null) {
050: return null;
051: }
052:
053: StringTokenizer toker = new StringTokenizer(acceptHeader, ",");
054:
055: int numEncodings = toker.countTokens();
056:
057: ArrayList encs = new ArrayList(numEncodings);
058: int i = 0;
059:
060: while (toker.hasMoreElements()) {
061: String token = toker.nextToken();
062: StringTokenizer t = new StringTokenizer(token, ";");
063: ContentEncoding enc = new ContentEncoding();
064: enc.name = t.nextToken().trim();
065: if (t.countTokens() > 1) {
066: enc.q = Float.parseFloat(t.nextToken().trim());
067: } else {
068: enc.q = 1;
069: }
070: encs.add(enc);
071: }
072:
073: return encs;
074: }
075:
076: /**
077: * @return the encoding that is "best" among the array for
078: * a response. We support gzip and deflate. Some user agents
079: * say they do gzip, but don't.
080: * @param req HttpServlet request
081: */
082: public static String chooseEncoding(HttpServletRequest req) {
083:
084: // This case is annoying
085: String ua = req.getHeader(LZHttpUtils.USER_AGENT);
086: if (ua == null) {
087: mLogger.warn(
088: /* (non-Javadoc)
089: * @i18n.test
090: * @org-mes="request has no user-agent header"
091: */
092: org.openlaszlo.i18n.LaszloMessages.getMessage(
093: ContentEncoding.class.getName(), "051018-91"));
094: return null;
095: }
096:
097: if (!LPS.configuration.optionAllows(
098: "content-encoding-user-agent", ua)) {
099: return null;
100: }
101:
102: List encs = parseEncodings(req);
103: if (encs == null) {
104: return null;
105: }
106:
107: // First try gzip(transduce x-gzip to gzip) and then
108: // try deflate. Otherwise try null.
109: //
110: // FIXME: [2002-12-17] The spec says we should use a more complicated
111: // algorithm but this will probably work in general. Time will tell.
112:
113: Iterator iter;
114:
115: iter = encs.iterator();
116: while (iter.hasNext()) {
117: ContentEncoding e = (ContentEncoding) iter.next();
118: if (e.name.equals("gzip") || e.name.equals("x-gzip")) {
119: return "gzip";
120: }
121: }
122:
123: // FIXME: [2002-12-17 bloch]deflate as used in CompilationManager
124: // doesn't seem to produce bits that mozilla or ie can cope with. Hmmm...
125: /*
126: iter = encs.iterator();
127: while (iter.hasNext()) {
128: ContentEncoding e = (ContentEncoding)iter.next();
129: if (e.name.equals("deflate")) {
130: return "deflate";
131: }
132: }
133: */
134:
135: return null;
136: }
137: }
|