KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > j > HttpLoadProcess


1 /*
2  * HttpLoadProcess.java
3  *
4  * Copyright (C) 2000-2003 Peter Graves
5  * $Id: HttpLoadProcess.java,v 1.2 2003/06/28 01:20:47 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.j;
23
24 import java.io.InputStream JavaDoc;
25 import java.io.OutputStream JavaDoc;
26 import java.io.OutputStreamWriter JavaDoc;
27 import java.net.Socket JavaDoc;
28 import java.net.URL JavaDoc;
29 import java.security.Provider JavaDoc;
30 import java.security.Security JavaDoc;
31 import java.util.List JavaDoc;
32 import javax.swing.SwingUtilities JavaDoc;
33
34 public final class HttpLoadProcess extends LoadProcess implements BackgroundProcess,
35     Runnable JavaDoc, Cancellable
36 {
37     private Socket JavaDoc socket;
38     private boolean render = true;
39
40     private String JavaDoc request;
41     private String JavaDoc responseHeaders;
42     private String JavaDoc contentType;
43
44     private int redirectionCount;
45
46     private FastStringBuffer sbHeaders = new FastStringBuffer();
47
48     public HttpLoadProcess(Buffer buffer, HttpFile file)
49     {
50         super(buffer, file);
51     }
52
53     public final String JavaDoc getRequest()
54     {
55         return request;
56     }
57
58     public final String JavaDoc getResponseHeaders()
59     {
60         return responseHeaders;
61     }
62
63     public final String JavaDoc getContentType()
64     {
65         return contentType;
66     }
67
68     private final void setContentType(String JavaDoc s)
69     {
70         contentType = s;
71     }
72
73     public void run()
74     {
75         if (buffer != null) {
76             buffer.setBusy(true);
77             buffer.setBackgroundProcess(this);
78         }
79         load();
80         if (buffer != null && buffer.getBackgroundProcess() == this) {
81             Log.debug("calling setBackgroundProcess(null)");
82             buffer.setBackgroundProcess(null);
83             buffer.setBusy(false);
84         }
85     }
86
87     private void load()
88     {
89         boolean usingProxy = false;
90         if (file.getProtocol() == File.PROTOCOL_HTTPS) {
91             if (!findProvider()) {
92                 error("No SSL provider found");
93                 return;
94             }
95         }
96         cache = Utilities.getTempFile();
97         if (cache == null) {
98             Log.error("HttpLoadProcess.load cache is null");
99             return; // Report error!
100
}
101         Debug.assertTrue(socket == null);
102         String JavaDoc hostName = file.getHostName();
103         int port = file.getPort();
104         if (file.getProtocol() == File.PROTOCOL_HTTPS) {
105             socket = createSSLSocket(hostName, port);
106             if (socket == null) {
107                 if (!cancelled)
108                     error("Can't create SSL socket");
109                 return;
110             }
111         } else {
112             String JavaDoc httpProxy = Editor.preferences().getStringProperty("httpProxy");
113             if (httpProxy != null) {
114                 if (httpProxy.startsWith("http://"))
115                     httpProxy = httpProxy.substring(7);
116                 int index = httpProxy.indexOf(':');
117                 if (index >= 0) {
118                     try {
119                         port = Integer.parseInt(httpProxy.substring(index + 1));
120                         hostName = httpProxy.substring(0, index);
121                         usingProxy = true;
122                     }
123                     catch (NumberFormatException JavaDoc e) {
124                         Log.error(e);
125                     }
126                 }
127             }
128             connect(hostName, port);
129         }
130         if (cancelled) {
131             Log.debug("cancelled!!");
132             if (cancelRunnable != null)
133                 SwingUtilities.invokeLater(cancelRunnable);
134             return;
135         }
136         if (socket == null) {
137             if (errorRunnable != null)
138                 SwingUtilities.invokeLater(errorRunnable);
139             return;
140         }
141         String JavaDoc location = null;
142         boolean redirected = false;
143         String JavaDoc encoding = null;
144         try {
145             InputStream JavaDoc in = socket.getInputStream();
146             OutputStreamWriter JavaDoc writer = new OutputStreamWriter JavaDoc(socket.getOutputStream());
147             FastStringBuffer sb = new FastStringBuffer(1024);
148             sb.append("GET ");
149             sb.append(usingProxy ? file.netPath() : file.canonicalPath());
150             sb.append(" HTTP/1.0\r\n");
151             sb.append("Host: ");
152             sb.append(file.getHostName());
153             sb.append("\r\n");
154             String JavaDoc userAgent = Editor.preferences().getStringProperty(Property.HTTP_USER_AGENT);
155             if (userAgent != null && userAgent.length() > 0) {
156                 sb.append("User-Agent: ");
157                 sb.append(userAgent);
158                 sb.append("\r\n");
159             }
160             if (Editor.preferences().getBooleanProperty(Property.HTTP_ENABLE_COOKIES)) {
161                 String JavaDoc cookie = Cookie.getCookie(new URL JavaDoc(file.netPath()));
162                 if (cookie != null) {
163                     sb.append("Cookie: ");
164                     sb.append(cookie);
165                     sb.append("\r\n");
166                 }
167             }
168             sb.append("\r\n");
169             request = sb.toString();
170             writer.write(request);
171             writer.flush();
172             sb.setLength(0);
173             sbHeaders.append(request);
174             OutputStream JavaDoc out = cache.getOutputStream();
175             byte[] buf = new byte[16384];
176             long totalBytes = 0;
177             int totalLength = 0; // Includes length of response headers.
178
if (progressNotifier != null)
179                 progressNotifier.progressStart();
180             while (!cancelled) {
181                 int bytesRead = 0;
182                 try {
183                     // We may get an exception here if the user cancels.
184
bytesRead = in.read(buf);
185                 }
186                 catch (Exception JavaDoc e) {
187                     if (!cancelled)
188                         Log.error(e);
189                 }
190                 if (bytesRead <= 0)
191                     break;
192                 if (sb != null) {
193                     int oldLength = sb.length();
194                     sb.append(new String JavaDoc(buf, 0, bytesRead, "ISO8859_1"));
195                     String JavaDoc s = sb.toString();
196                     int skip = 4; // "\r\n\r\n"
197
int index = s.indexOf("\r\n\r\n");
198                     if (index < 0) {
199                         index = s.indexOf("\n\n");
200                         skip = 2; // "\n\n"
201
}
202                     if (index >= 0) {
203                         // We've got the headers.
204
sb = null;
205                         responseHeaders = s.substring(0, index + skip);
206                         sbHeaders.append(responseHeaders);
207                         int statusCode = getStatusCode(responseHeaders);
208                         Log.debug("statusCode = " + statusCode);
209                         if (statusCode == 301 || statusCode == 302) {
210                             // "Moved Permanently", "Moved Temporarily"
211
location = getLocation(responseHeaders);
212                             redirected = true;
213                             Log.debug("redirected to |" + location + "|");
214                             Log.debug(request);
215                             Log.debug(responseHeaders);
216                         }
217                         // Remove status line.
218
int end = responseHeaders.indexOf('\n');
219                         if (end >= 0)
220                             responseHeaders = responseHeaders.substring(end + 1);
221                         int contentLength = getContentLength(responseHeaders);
222                         if (contentLength != 0)
223                             totalLength = responseHeaders.length() + contentLength;
224                         Log.debug("responseHeaders = |" + responseHeaders + "|");
225                         Headers headers = Headers.parse(responseHeaders);
226                         setContentType(headers.getValue(Headers.CONTENT_TYPE));
227                         Log.debug("content-type = |" + contentType + "|");
228                         String JavaDoc charset =
229                             Utilities.getCharsetFromContentType(contentType);
230                         Log.debug("charset = |" + charset + "|");
231                         if (charset != null)
232                             encoding = Utilities.getEncodingFromCharset(charset);
233                         Log.debug("encoding = |" + encoding + "|");
234                         if (Editor.preferences().getBooleanProperty(Property.HTTP_ENABLE_COOKIES)) {
235                             String JavaDoc cookie = headers.getValue(Headers.SET_COOKIE);
236                             if (cookie != null)
237                                 Cookie.setCookie(new URL JavaDoc(file.netPath()), cookie);
238                         }
239                         int offset = index - oldLength + skip;
240                         int length = bytesRead - offset;
241                         out.write(buf, offset, length);
242                     }
243                 } else
244                     out.write(buf, 0, bytesRead);
245                 totalBytes += bytesRead;
246                 if (progressNotifier != null)
247                     progressNotifier.progress("Received ", totalBytes, totalLength);
248             }
249             if (progressNotifier != null)
250                 progressNotifier.progressStop();
251             out.close();
252             in.close();
253             socket.close();
254             socket = null;
255         }
256         catch (Exception JavaDoc e) {
257             Log.error(e);
258         }
259         if (cancelled)
260             cache.delete();
261         if (!cache.isFile())
262             cache = null;
263         if (!cancelled && render && redirected && redirectionCount < 5) {
264             if (cache != null) {
265                 if (cache.isFile())
266                     cache.delete();
267                 cache = null;
268             }
269             File parent = file.getParentFile();
270             if (parent != null) {
271                 // Recurse.
272
file = HttpFile.getHttpFile((HttpFile)parent, location);
273                 ++redirectionCount;
274                 load();
275                 return;
276             }
277         }
278         if (cache != null) {
279             // Success!
280
final HttpFile httpFile = (HttpFile) file;
281             httpFile.setCache(cache);
282             httpFile.setHeaders(sbHeaders.toString());
283             httpFile.setContentType(contentType);
284             httpFile.setEncoding(encoding);
285             cache.setEncoding(encoding);
286             if (successRunnable != null)
287                 SwingUtilities.invokeLater(successRunnable);
288         } else if (cancelled) {
289             if (cancelRunnable != null)
290                 SwingUtilities.invokeLater(cancelRunnable);
291         } else if (errorRunnable != null)
292             SwingUtilities.invokeLater(errorRunnable);
293     }
294
295     private void connect(final String JavaDoc hostName, final int port)
296     {
297         Debug.assertTrue(socket == null);
298         Log.debug("Connecting to " + hostName + " on port " + port + "...");
299         if (progressNotifier != null)
300             progressNotifier.setText("Connecting to " + hostName + " on port " + port + "...");
301         SocketConnection sc = new SocketConnection(hostName, port, 30000, 200, this);
302         socket = sc.connect();
303         if (socket != null) {
304             if (progressNotifier != null)
305                 progressNotifier.setText("Connected to " + hostName);
306         } else
307             setErrorText(sc.getErrorText());
308     }
309
310     private boolean findProvider()
311     {
312         Provider JavaDoc provider = null;
313         try {
314             provider =
315                 (Provider JavaDoc) Class.forName("com.sun.net.ssl.internal.ssl.Provider").newInstance();
316         }
317         catch (Exception JavaDoc e) {}
318         if (provider != null) {
319             Security.addProvider(provider);
320             System.setProperty("java.protocol.handler.pkgs",
321                 "com.sun.net.ssl.internal.www.protocol");
322             return true;
323         }
324         return false;
325     }
326
327     private Socket JavaDoc createSSLSocket(String JavaDoc hostName, int port)
328     {
329         try {
330             // SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
331
Class JavaDoc SSLSocketFactory = Class.forName("javax.net.ssl.SSLSocketFactory");
332             java.lang.reflect.Method JavaDoc getDefault = SSLSocketFactory.getMethod("getDefault", new Class JavaDoc[0]);
333             Object JavaDoc factory = getDefault.invoke(null, new Object JavaDoc[0]);
334
335             // Socket socket = factory.createSocket(hostName, port);
336
Class JavaDoc[] parameterTypes = new Class JavaDoc[2];
337             parameterTypes[0] = String JavaDoc.class;
338             parameterTypes[1] = Integer.TYPE;
339             java.lang.reflect.Method JavaDoc createSocket = factory.getClass().getMethod("createSocket", parameterTypes);
340             Object JavaDoc[] args = new Object JavaDoc[2];
341             args[0] = hostName;
342             args[1] = new Integer JavaDoc(port);
343             Socket JavaDoc socket = (Socket JavaDoc) createSocket.invoke(factory, args);
344             return socket;
345         }
346         catch (Throwable JavaDoc t) {
347             Log.error(t);
348             return null;
349         }
350     }
351
352     private static int getStatusCode(String JavaDoc responseHeaders)
353     {
354         int begin = responseHeaders.indexOf(' ') + 1;
355         if (begin == 0)
356             return -1;
357         int end = responseHeaders.indexOf(' ', begin);
358         if (end < 0)
359             return -1;
360         try {
361             return Utilities.parseInt(responseHeaders.substring(begin, end));
362         }
363         catch (NumberFormatException JavaDoc e) {
364             return -1;
365         }
366     }
367
368     private static String JavaDoc getLocation(String JavaDoc responseHeaders)
369     {
370         final String JavaDoc lookFor = "\nlocation:";
371         final int index = responseHeaders.toLowerCase().indexOf(lookFor);
372         if (index < 0)
373             return null;
374         final int begin = index + lookFor.length();
375         final int end = responseHeaders.indexOf('\n', begin);
376         if (end < 0)
377             return null;
378         String JavaDoc location = responseHeaders.substring(begin, end).trim();
379         if (location.startsWith("http:/") && !location.startsWith("http://")) {
380             // Be permissive in what we accept.
381
location = "http://".concat(location.substring(6));
382         }
383         return location;
384     }
385
386     private static int getContentLength(String JavaDoc responseHeaders)
387     {
388         final String JavaDoc lookFor = "\r\ncontent-length:";
389         final int index = responseHeaders.toLowerCase().indexOf(lookFor);
390         if (index < 0)
391             return 0; // No content length header.
392
final String JavaDoc value = responseHeaders.substring(index + lookFor.length()).trim();
393         try {
394             return Utilities.parseInt(value);
395         }
396         catch (NumberFormatException JavaDoc e) {
397             return 0;
398         }
399     }
400
401     private void error(String JavaDoc errorText)
402     {
403         Log.error(errorText);
404         if (errorRunnable != null) {
405             errorRunnable.setMessage(errorText);
406             SwingUtilities.invokeLater(errorRunnable);
407         }
408     }
409
410     public static void httpShowHeaders()
411     {
412         final Editor editor = Editor.currentEditor();
413         final Buffer buffer = editor.getBuffer();
414         final File file = buffer.getFile();
415         if (file instanceof HttpFile) {
416             editor.setWaitCursor();
417             final String JavaDoc title = "httpShowHeaders ".concat(file.netPath());
418             Buffer buf = null;
419             for (BufferIterator it = new BufferIterator(); it.hasNext();) {
420                 Buffer b = it.nextBuffer();
421                 if (b instanceof OutputBuffer && b.getParentBuffer() == buffer) {
422                     if (title.equals(b.getTitle())) {
423                         buf = b;
424                         break;
425                     }
426                 }
427             }
428             if (buf == null) {
429                 buf = OutputBuffer.getOutputBuffer(((HttpFile)file).getHeaders());
430                 buf.setParentBuffer(buffer);
431                 buf.setTitle(title);
432             }
433             editor.makeNext(buf);
434             editor.activateInOtherWindow(buf);
435             editor.setDefaultCursor();
436         }
437     }
438 }
439
Popular Tags