001: /*
002: * Response.java
003: *
004: *
005: * Copyright (c) 2003 Rimfaxe ApS (www.rimfaxe.com).
006: * All rights reserved.
007: *
008: * This package is written by Lars Andersen <lars@rimfaxe.com>
009: * and licensed by Rimfaxe ApS.
010: *
011: * Redistribution and use in source and binary forms, with or without
012: * modification, are permitted provided that the following conditions
013: * are met:
014: *
015: * 1. Redistributions of source code must retain the above copyright
016: * notice, this list of conditions and the following disclaimer.
017: *
018: * 2. Redistributions in binary form must reproduce the above copyright
019: * notice, this list of conditions and the following disclaimer in
020: * the documentation and/or other materials provided with the
021: * distribution.
022: *
023: * 3. The end-user documentation included with the redistribution, if
024: * any, must include the following acknowlegement:
025: * "This product includes software developed by Rimfaxe ApS
026: (www.rimfaxe.com)"
027: * Alternately, this acknowlegement may appear in the software itself,
028: * if and wherever such third-party acknowlegements normally appear.
029: *
030: * 4. The names "Rimfaxe", "Rimfaxe Software", "Lars Andersen" and
031: * "Rimfaxe WebServer" must not be used to endorse or promote products
032: * derived from this software without prior written permission. For written
033: * permission, please contact info@rimfaxe.com
034: *
035: * 5. Products derived from this software may not be called "Rimfaxe"
036: * nor may "Rimfaxe" appear in their names without prior written
037: * permission of the Rimfaxe ApS.
038: *
039: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
040: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
041: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
042: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
043: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
044: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
045: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
046: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
047: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
048: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
049: * SUCH DAMAGE.
050: *
051: */
052:
053: package com.rimfaxe.http;
054:
055: import java.util.*;
056: import java.io.*;
057:
058: /**
059: *
060: * @author lars
061: */
062: public class Response {
063: Cookie cookie;
064: Vector headers = new Vector();
065:
066: String content = "";
067: String contenttype = "text/plain";
068: String encoding = "binary";
069:
070: String httpline = "HTTP/1.1 200 OK";
071: String location;
072:
073: Integer errorcode = new Integer(0);
074:
075: InputStream stream = null;
076:
077: /** Creates a new instance of Response */
078: public Response(com.rimfaxe.http.Request request, InputStream is) {
079: //BufferedReader d = new BufferedReader(new InputStreamReader(is));
080:
081: System.out.println("Create response from input stream");
082: try {
083: httpline = readLine(is);
084: System.out.println("http line -> " + httpline);
085: parseErrorCode(httpline);
086:
087: String line = readLine(is);
088:
089: while (!line.equalsIgnoreCase("")) {
090: if (line == null) {
091: return;
092: }
093:
094: StringTokenizer tk2 = new StringTokenizer(line, ":",
095: true);
096: String name = tk2.nextToken().trim();
097: tk2.nextToken();
098: String val = tk2.nextToken("\n").trim();
099:
100: boolean addheader = true;
101:
102: if (name.equalsIgnoreCase("Content-Type")) {
103: contenttype = val.trim();
104: }
105: if (name.equalsIgnoreCase("Location")) {
106: location = processLocation(request, val.trim());
107: val = location;
108: }
109:
110: if (name.equalsIgnoreCase("Set-Cookie")) {
111: cookie = new Cookie(val.trim());
112: }
113:
114: if (name.equalsIgnoreCase("Connection")) {
115: addheader = false;
116: }
117:
118: if (addheader) {
119: System.out.println("Adding header in response : "
120: + name + "->" + val);
121: headers.addElement(new Header(name, val));
122: }
123: line = readLine(is);
124:
125: }
126:
127: stream = is;
128: } catch (IOException ex) {
129: // TODO
130: }
131: }
132:
133: /** Creates a new instance of Response */
134: public Response(com.rimfaxe.http.Request request, InputStream is,
135: java.net.HttpURLConnection uc) {
136:
137: try {
138: errorcode = new Integer(uc.getResponseCode());
139:
140: //System.out.println("Error code = "+errorcode);
141:
142: boolean headers_done = false;
143: int idx = 0;
144:
145: while (!headers_done) {
146: idx++;
147: String name = uc.getHeaderFieldKey(idx);
148:
149: if (name == null) {
150:
151: headers_done = true;
152: } else {
153: String val = uc.getHeaderField(idx);
154: boolean addheader = true;
155: if (name.equalsIgnoreCase("Content-Type")) {
156: contenttype = val.trim();
157: }
158: //if (name.equalsIgnoreCase("Location"))
159: //{
160: // location = processLocation(request, val.trim());
161: // val = location;
162: //}
163: if (name.equalsIgnoreCase("Set-Cookie")) {
164: cookie = new Cookie(val.trim());
165: }
166: if (name.equalsIgnoreCase("Connection")) {
167: addheader = false;
168: }
169: if (addheader) {
170: //if (errorcode.intValue()!=200)
171: // System.out.println("Adding header["+idx+"] in response : "+name+"->"+val);
172: headers.addElement(new Header(name, val));
173: }
174:
175: }
176: }
177:
178: stream = is;
179: } catch (IOException ex) {
180: ex.printStackTrace(System.out);
181: }
182: }
183:
184: /** Creates a new instance of Response */
185: public Response(com.rimfaxe.http.Request request, String raw) {
186:
187: StringBuffer buf = new StringBuffer();
188:
189: com.rimfaxe.util.RimfaxeStringTokenizer tkz = new com.rimfaxe.util.RimfaxeStringTokenizer(
190: raw, "\n\r", true);
191: httpline = tkz.nextToken();
192:
193: parseErrorCode(httpline);
194:
195: int countLinefeeds = 0;
196:
197: while ((tkz.hasMoreTokens()) && (countLinefeeds < 4)) {
198: String line = tkz.nextToken();
199:
200: if (line.equalsIgnoreCase("\n"))
201: countLinefeeds++;
202: else if (line.equalsIgnoreCase("\r"))
203: countLinefeeds++;
204: else {
205: //System.out.println("Parsing line in response : "+line);
206: countLinefeeds = 0;
207: com.rimfaxe.util.RimfaxeStringTokenizer tk2 = new com.rimfaxe.util.RimfaxeStringTokenizer(
208: line, ":", true);
209: String name = tk2.nextToken().trim();
210: tk2.nextToken();
211: String val = tk2.nextToken("\n").trim();
212:
213: boolean addheader = true;
214:
215: if (name.equalsIgnoreCase("Content-Type")) {
216: //com.rimfaxe.util.Log.log(""+name+": " + val);
217: contenttype = val.trim();
218: }
219: if (name.equalsIgnoreCase("Location")) {
220: //com.rimfaxe.util.Log.log(""+name+": " + val);
221: location = processLocation(request, val.trim());
222: val = location;
223: }
224: if (name.equalsIgnoreCase("Set-Cookie")) {
225: //System.out.println("Adding header in response : "+name+"->"+val);
226: cookie = new Cookie(val.trim());
227: }
228: if (name.equalsIgnoreCase("Connection")) {
229: addheader = false;
230: // do nothing!
231: }
232:
233: if (addheader) {
234: //System.out.println("Adding header in response : "+name+"->"+val);
235: headers.addElement(new Header(name, val));
236: }
237: }
238: }
239:
240: while (tkz.hasMoreTokens()) {
241: buf.append(tkz.nextToken());
242: }
243:
244: content = "" + buf;
245: }
246:
247: /** Creates a new instance of Response */
248: public Response(String raw, boolean redirect) {
249: StringBuffer buf = new StringBuffer();
250:
251: com.rimfaxe.util.RimfaxeStringTokenizer tkz = new com.rimfaxe.util.RimfaxeStringTokenizer(
252: raw, "\n\r", true);
253: httpline = tkz.nextToken();
254:
255: parseErrorCode(httpline);
256:
257: int countLinefeeds = 0;
258:
259: while ((tkz.hasMoreTokens()) && (countLinefeeds < 4)) {
260: String line = tkz.nextToken();
261:
262: if (line.equalsIgnoreCase("\n"))
263: countLinefeeds++;
264: else if (line.equalsIgnoreCase("\r"))
265: countLinefeeds++;
266: else {
267: countLinefeeds = 0;
268: com.rimfaxe.util.RimfaxeStringTokenizer tk2 = new com.rimfaxe.util.RimfaxeStringTokenizer(
269: line, ":", true);
270: String name = tk2.nextToken().trim();
271: tk2.nextToken();
272: String val = tk2.nextToken("\n").trim();
273:
274: boolean addheader = true;
275:
276: if (name.equalsIgnoreCase("Content-Type")) {
277: //com.rimfaxe.util.Log.log(""+name+": " + val);
278: contenttype = val.trim();
279: }
280: if (name.equalsIgnoreCase("Location")) {
281: //com.rimfaxe.util.Log.log(""+name+": " + val);
282: //location = processLocation(request, val.trim());
283: val = location;
284: }
285: if (name.equalsIgnoreCase("Set-Cookie")) {
286: //com.rimfaxe.util.Log.log("Set-Cookie :"+val);
287: cookie = new Cookie(val.trim());
288: }
289: if (name.equalsIgnoreCase("Connection")) {
290: addheader = false;
291: // do nothing!
292: }
293:
294: if (addheader) {
295: //System.out.println("Adding header in response : "+name+"->"+val);
296: headers.addElement(new Header(name, val));
297: }
298: }
299: }
300:
301: while (tkz.hasMoreTokens()) {
302: buf.append(tkz.nextToken());
303: }
304:
305: content = "" + buf;
306: }
307:
308: public Vector getHeaders() {
309: return headers;
310: }
311:
312: public Cookie getCookie() {
313: return cookie;
314: }
315:
316: public InputStream getStream() {
317: return stream;
318: }
319:
320: public String getContentType() {
321: return contenttype;
322: }
323:
324: public String getLocation() {
325: return location;
326: }
327:
328: public Integer getErrorCode() {
329: return errorcode;
330: }
331:
332: private void parseErrorCode(String line) {
333: //System.out.println("Parse error code from http line :"+ line);
334: com.rimfaxe.util.RimfaxeStringTokenizer tkz = new com.rimfaxe.util.RimfaxeStringTokenizer(
335: line, " ", false);
336: String http = tkz.nextToken();
337: String error = tkz.nextToken();
338: //System.out.println("Status :"+ error);
339: errorcode = new Integer(error);
340: }
341:
342: public String getContent() {
343: StringBuffer buf = new StringBuffer();
344:
345: //System.out.println("Content type = ["+getContentType()+"]");
346: /*if (getContentType().startsWith("text/html")) buf.append("<!-- \n");
347: if (getContentType().startsWith("text/html"))buf.append(""+httpline+"\r\n");
348: Enumeration hl = headers.elements();
349: while (hl.hasMoreElements())
350: {
351: com.rimfaxe.http.Header header = (com.rimfaxe.http.Header) hl.nextElement();
352: String name = header.getName();
353: String val = header.getValue();
354: if (getContentType().startsWith("text/html")) buf.append(name+": "+val+"\r\n");
355: }
356: if (getContentType().startsWith("text/html")) buf.append("\r\n");
357: if (getContentType().startsWith("text/html")) buf.append("-->\n");
358: */
359: buf.append("" + content);
360:
361: return "" + buf;
362: }
363:
364: public String processLocation(com.rimfaxe.http.Request request,
365: String loc) {
366: com.rimfaxe.balancer.RealServer rh = request.getRealHost();
367:
368: if (rh == null)
369: return loc;
370:
371: String ver1 = "http://" + rh.getName();
372: String ver2 = "http://" + rh.getName() + ":" + rh.getPort();
373: String ver3 = "http://" + rh.getIP();
374: String ver4 = "http://" + rh.getIP() + ":" + rh.getPort();
375:
376: boolean replace = false;
377: int chars = 0;
378:
379: if (loc.startsWith(ver4)) {
380: replace = true;
381: chars = ver4.length();
382: } else if (loc.startsWith(ver3)) {
383: replace = true;
384: chars = ver3.length();
385: } else if (loc.startsWith(ver2)) {
386: replace = true;
387: chars = ver2.length();
388: } else if (loc.startsWith(ver1)) {
389: replace = true;
390: chars = ver1.length();
391: }
392:
393: String newloc = "http://" + request.getHost()
394: + loc.substring(chars);
395:
396: //System.out.println("new location -> "+newloc);
397:
398: return newloc;
399: }
400:
401: public String readLine(InputStream is) throws IOException {
402: ByteArrayOutputStream baos = new ByteArrayOutputStream();
403:
404: byte[] buf = new byte[1];
405:
406: while (true) {
407: int read = is.read(buf);
408: if (read == 0)
409: return baos.toString();
410: if (buf[0] == '\r') {
411: } else if (buf[0] == '\n') {
412: return baos.toString();
413: } else {
414: baos.write(buf);
415: }
416: }
417: }
418: }
|