001: /*
002: * @(#)TransferEncodingModule.java 0.3-2 18/06/1999
003: *
004: * This file is part of the HTTPClient package
005: * Copyright (C) 1996-1999 Ronald Tschalär
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free
019: * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
020: * MA 02111-1307, USA
021: *
022: * For questions, suggestions, bug-reports, enhancement-requests etc.
023: * I may be contacted at:
024: *
025: * ronald@innovation.ch
026: *
027: */
028:
029: package HTTPClient;
030:
031: import java.io.IOException;
032: import java.util.Vector;
033: import java.util.zip.InflaterInputStream;
034: import java.util.zip.GZIPInputStream;
035:
036: /**
037: * This module handles the TransferEncoding response header. It currently
038: * handles the "gzip", "deflate", "compress", "chunked" and "identity"
039: * tokens.
040: *
041: * Note: This module requires JDK 1.1 or later.
042: *
043: * @version 0.3-2 18/06/1999
044: * @author Ronald Tschalär
045: */
046:
047: class TransferEncodingModule implements HTTPClientModule,
048: GlobalConstants {
049: static {
050: /* This ensures that the loading of this class is only successful
051: * if we're in JDK 1.1 (or later) and have access to java.util.zip
052: */
053: try {
054: new InflaterInputStream(null);
055: } catch (NullPointerException npe) { /* JDK 1.2 Final started throwing this */
056: }
057: }
058:
059: // Constructors
060:
061: TransferEncodingModule() {
062: }
063:
064: // Methods
065:
066: /**
067: * Invoked by the HTTPClient.
068: */
069: public int requestHandler(Request req, Response[] resp)
070: throws ModuleException {
071: // Parse TE header
072:
073: int idx;
074: NVPair[] hdrs = req.getHeaders();
075: for (idx = 0; idx < hdrs.length; idx++)
076: if (hdrs[idx].getName().equalsIgnoreCase("TE"))
077: break;
078:
079: Vector pte;
080: if (idx == hdrs.length) {
081: hdrs = Util.resizeArray(hdrs, idx + 1);
082: req.setHeaders(hdrs);
083: pte = new Vector();
084: } else {
085: try {
086: pte = Util.parseHeader(hdrs[idx].getValue());
087: } catch (ParseException pe) {
088: throw new ModuleException(pe.toString());
089: }
090: }
091:
092: // done if "*;q=1.0" present
093:
094: HttpHeaderElement all = Util.getElement(pte, "*");
095: if (all != null) {
096: NVPair[] params = all.getParams();
097: for (idx = 0; idx < params.length; idx++)
098: if (params[idx].getName().equalsIgnoreCase("q"))
099: break;
100:
101: if (idx == params.length) // no qvalue, i.e. q=1.0
102: return REQ_CONTINUE;
103:
104: if (params[idx].getValue() == null
105: || params[idx].getValue().length() == 0)
106: throw new ModuleException(
107: "Invalid q value for \"*\" in TE " + "header: ");
108:
109: try {
110: if (Float.valueOf(params[idx].getValue()).floatValue() > 0.)
111: return REQ_CONTINUE;
112: } catch (NumberFormatException nfe) {
113: throw new ModuleException(
114: "Invalid q value for \"*\" in TE " + "header: "
115: + nfe.getMessage());
116: }
117: }
118:
119: // Add gzip, deflate, and compress tokens to the TE header
120:
121: if (!pte.contains(new HttpHeaderElement("deflate")))
122: pte.addElement(new HttpHeaderElement("deflate"));
123: if (!pte.contains(new HttpHeaderElement("gzip")))
124: pte.addElement(new HttpHeaderElement("gzip"));
125: if (!pte.contains(new HttpHeaderElement("compress")))
126: pte.addElement(new HttpHeaderElement("compress"));
127:
128: hdrs[idx] = new NVPair("TE", Util.assembleHeader(pte));
129:
130: return REQ_CONTINUE;
131: }
132:
133: /**
134: * Invoked by the HTTPClient.
135: */
136: public void responsePhase1Handler(Response resp, RoRequest req) {
137: }
138:
139: /**
140: * Invoked by the HTTPClient.
141: */
142: public int responsePhase2Handler(Response resp, Request req) {
143: return RSP_CONTINUE;
144: }
145:
146: /**
147: * Invoked by the HTTPClient.
148: */
149: public void responsePhase3Handler(Response resp, RoRequest req)
150: throws IOException, ModuleException {
151: String te = resp.getHeader("Transfer-Encoding");
152: if (te == null || req.getMethod().equals("HEAD"))
153: return;
154:
155: Vector pte;
156: try {
157: pte = Util.parseHeader(te);
158: } catch (ParseException pe) {
159: throw new ModuleException(pe.toString());
160: }
161:
162: while (pte.size() > 0) {
163: String encoding = ((HttpHeaderElement) pte.lastElement())
164: .getName();
165: if (encoding.equalsIgnoreCase("gzip")) {
166: if (DebugMods)
167: System.err
168: .println("TEM: pushing gzip-input-stream");
169:
170: resp.inp_stream = new GZIPInputStream(resp.inp_stream);
171: } else if (encoding.equalsIgnoreCase("deflate")) {
172: if (DebugMods)
173: System.err
174: .println("TEM: pushing inflater-input-stream");
175:
176: resp.inp_stream = new InflaterInputStream(
177: resp.inp_stream);
178: } else if (encoding.equalsIgnoreCase("compress")) {
179: if (DebugMods)
180: System.err
181: .println("TEM: pushing uncompress-input-stream");
182:
183: resp.inp_stream = new UncompressInputStream(
184: resp.inp_stream);
185: } else if (encoding.equalsIgnoreCase("chunked")) {
186: if (DebugMods)
187: System.err
188: .println("TEM: pushing chunked-input-stream");
189:
190: resp.inp_stream = new ChunkedInputStream(
191: resp.inp_stream);
192: } else if (encoding.equalsIgnoreCase("identity")) {
193: if (DebugMods)
194: System.err
195: .println("TEM: ignoring 'identity' token");
196: } else {
197: if (DebugMods)
198: System.err
199: .println("TEM: Unknown transfer encoding '"
200: + encoding + "'");
201:
202: break;
203: }
204:
205: pte.removeElementAt(pte.size() - 1);
206: }
207:
208: if (pte.size() > 0)
209: resp.setHeader("Transfer-Encoding", Util
210: .assembleHeader(pte));
211: else
212: resp.deleteHeader("Transfer-Encoding");
213: }
214:
215: /**
216: * Invoked by the HTTPClient.
217: */
218: public void trailerHandler(Response resp, RoRequest req) {
219: }
220: }
|