001: /* *****************************************************************************
002: * HTTPData.java
003: * ****************************************************************************/
004:
005: /* J_LZ_COPYRIGHT_BEGIN *******************************************************
006: * Copyright 2001-2007 Laszlo Systems, Inc. All Rights Reserved. *
007: * Use is subject to license terms. *
008: * J_LZ_COPYRIGHT_END *********************************************************/
009:
010: package org.openlaszlo.data;
011:
012: import java.util.Enumeration;
013: import java.util.Hashtable;
014: import java.util.StringTokenizer;
015: import java.net.URL;
016: import java.net.URLDecoder;
017: import java.net.MalformedURLException;
018: import java.net.UnknownHostException;
019: import java.io.*;
020: import javax.servlet.http.HttpServletRequest;
021: import javax.servlet.http.HttpServletResponse;
022:
023: import org.apache.commons.httpclient.*;
024: import org.apache.commons.httpclient.methods.*;
025: import org.apache.commons.httpclient.util.*;
026: import org.apache.log4j.*;
027:
028: import org.openlaszlo.xml.internal.XMLUtils;
029: import org.openlaszlo.utils.LZHttpUtils;
030: import org.openlaszlo.utils.LZGetMethod;
031: import org.openlaszlo.utils.LZPostMethod;
032: import org.openlaszlo.utils.LZPutMethod;
033: import org.openlaszlo.utils.LZDeleteMethod;
034: import org.openlaszlo.utils.FileUtils;
035: import org.openlaszlo.server.LPS;
036: import org.apache.oro.text.regex.*;
037:
038: /**
039: * A class for holding on to results of an Http fetch.
040: *
041: * @author <a href="mailto:bloch@laszlosystems.com">Eric Bloch</a>
042: */
043:
044: public class HttpData extends Data {
045:
046: /** response code */
047: public final int code;
048:
049: /** Http request */
050: public final HttpMethodBase request;
051:
052: HttpMethodBase getRequest() {
053: return this .request;
054: }
055:
056: private PatternMatcher pMatcher = new Perl5Matcher();
057: private static final Pattern charsetPattern;
058: private static final Pattern declEncodingPattern;
059: static {
060: try {
061: Perl5Compiler compiler = new Perl5Compiler();
062: charsetPattern = compiler.compile(";charset=([^ ]*)");
063: declEncodingPattern = compiler
064: .compile("[ \t\r\n]*<[?]xml .*encoding=[\"']([^ \"']*)[\"'] .*[?]>");
065: } catch (MalformedPatternException e) {
066: throw new RuntimeException(e.getMessage());
067: }
068: }
069:
070: /**
071: * @param r filled request
072: * @param c response code
073: */
074: public HttpData(HttpMethodBase r, int c) {
075: code = c;
076: request = r;
077: }
078:
079: /**
080: * @return true if the data was "not modified"
081: */
082: public boolean notModified() {
083: return code == HttpServletResponse.SC_NOT_MODIFIED;
084: }
085:
086: /**
087: * @return the lastModified time of the data
088: */
089: public long lastModified() {
090:
091: Header lastModifiedHdr = request
092: .getResponseHeader(LZHttpUtils.LAST_MODIFIED);
093:
094: if (lastModifiedHdr != null) {
095: String lm = lastModifiedHdr.getValue();
096: long l = LZHttpUtils.getDate(lm);
097: // Truncate to nearest second
098: return ((l) / 1000L) * 1000L;
099: } else {
100: return -1;
101: }
102: }
103:
104: /**
105: * append response headers
106: */
107: /**
108: * release any resources associated with this data
109: */
110: public void release() {
111: request.releaseConnection();
112: }
113:
114: /**
115: * @return mime type
116: */
117: public String getMimeType() {
118: Header hdr = request
119: .getResponseHeader(LZHttpUtils.CONTENT_TYPE);
120: String contentType = "";
121: if (hdr != null) {
122: contentType = hdr.getValue();
123: }
124: return contentType;
125: }
126:
127: /**
128: * @return string
129: */
130: public String getAsString() throws IOException {
131: byte rawbytes[] = request.getResponseBody();
132: if (rawbytes == null || rawbytes.length == 0) {
133: throw new InterruptedIOException("null http response body");
134: }
135: String encoding = "UTF-8";
136: String content = getMimeType();
137: // search for ;charset=XXXX in Content-Type header
138: if (pMatcher.matches(content, charsetPattern)) {
139: encoding = pMatcher.getMatch().group(1);
140: }
141: // search for 'encoding' attribute in xml declaration, e.g.,
142: // <?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
143:
144: String decl = getXMLDeclaration(rawbytes);
145: if (pMatcher.matches(decl, declEncodingPattern)) {
146: encoding = pMatcher.getMatch().group(1);
147: }
148:
149: return new String(rawbytes, encoding);
150: }
151:
152: /** Returns the first non-whitespace line.
153: *
154: */
155: String getXMLDeclaration(byte buf[]) {
156: String str = new String(buf);
157: BufferedReader br = new BufferedReader(new StringReader(str));
158: String line;
159: while (true) {
160: try {
161: line = br.readLine();
162: } catch (IOException e) {
163: return "";
164: }
165: if (line == null) {
166: return "";
167: }
168: if (line.length() == 0)
169: continue;
170: if (line.startsWith("<?xml ")) {
171: return line;
172: } else {
173: return "";
174: }
175: }
176: }
177:
178: /**
179: * @return input stream
180: */
181: public InputStream getInputStream() throws IOException {
182: InputStream str = request.getResponseBodyAsStream();
183: if (str == null) {
184: throw new IOException(
185: /* (non-Javadoc)
186: * @i18n.test
187: * @org-mes="http response body is null"
188: */
189: org.openlaszlo.i18n.LaszloMessages.getMessage(
190: HTTPDataSource.class.getName(), "051018-774"));
191: }
192: return str;
193: }
194:
195: /**
196: * @return size, if known
197: */
198: public long size() {
199: Header hdr = request
200: .getResponseHeader(LZHttpUtils.CONTENT_LENGTH);
201: if (hdr != null) {
202: String contentLength = hdr.getValue();
203: if (contentLength != null) {
204: int cl = Integer.parseInt(contentLength);
205: return cl;
206: }
207: }
208: return -1;
209: }
210: }
|