KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > soap > util > net > HTTPUtils


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 2000 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "SOAP" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 2000, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package org.apache.soap.util.net;
59
60 import java.net.*;
61 import java.io.*;
62 import java.util.*;
63
64 import org.apache.soap.*;
65 import org.apache.soap.rpc.*;
66 import org.apache.soap.transport.*;
67 import org.apache.soap.util.mime.*;
68 import javax.mail.*;
69 import javax.mail.internet.*;
70 import javax.activation.*;
71 import java.lang.reflect.*;
72
73 /**
74  * A bunch of utility stuff for doing HTTP things.
75  * <p>
76  * 2000/07/30 W. Cloetens added Multipart Mime support
77  *
78  * @author Sanjiva Weerawarana (sanjiva@watson.ibm.com)
79  * @author Matthew J. Duftler (duftler@us.ibm.com)
80  * @author Wouter Cloetens (wcloeten@raleigh.ibm.com)
81  * @author Scott Nichol (snichol@computer.org)
82  */

83 public class HTTPUtils {
84   private static final String JavaDoc HTTP_VERSION = "1.0";
85   private static final int HTTP_DEFAULT_PORT = 80;
86   private static final int HTTPS_DEFAULT_PORT = 443;
87
88   public static final int DEFAULT_OUTPUT_BUFFER_SIZE = 512;
89
90   /**
91    * This method either creates a socket or calls SSLUtils to
92    * create an SSLSocket. It uses reflection to avoid a compile time
93    * dependency on SSL.
94    *
95    * @author Chris Nelson
96    */

97   private static Socket buildSocket(URL url, int targetPort,
98                                     String JavaDoc httpProxyHost, int httpProxyPort,
99                     Boolean JavaDoc tcpNoDelay)
100      throws Exception JavaDoc {
101       Socket s = null;
102       String JavaDoc host = null;
103       int port = targetPort;
104       host = url.getHost();
105
106       if (url.getProtocol().equalsIgnoreCase("HTTPS")) {
107           // Using reflection to avoid compile time dependencies
108
Class JavaDoc SSLUtilsClass =
109               Class.forName("org.apache.soap.util.net.SSLUtils");
110           Class JavaDoc[] paramTypes = new Class JavaDoc[] {String JavaDoc.class, int.class, String JavaDoc.class, int.class};
111           Method buildSSLSocket = SSLUtilsClass.getMethod(
112               "buildSSLSocket", paramTypes);
113           Object JavaDoc[] params = new Object JavaDoc[] {host, new Integer JavaDoc(port),
114               httpProxyHost, new Integer JavaDoc(httpProxyPort)};
115           s = (Socket)buildSSLSocket.invoke(null, params);
116       } else {
117           if (httpProxyHost != null) {
118               host = httpProxyHost;
119               port = httpProxyPort;
120           }
121           s = new Socket(host, port);
122       }
123       
124       if (tcpNoDelay != null)
125       {
126     if (s != null)
127       s.setTcpNoDelay(tcpNoDelay.booleanValue());
128       }
129
130       return s;
131    }
132
133   /**
134    * Utility function to determine port number from URL object.
135    *
136    * @param url URL object from which to determine port number
137    * @return port number
138    */

139   private static int getPort(URL url) throws IOException {
140       int port = url.getPort();
141       if (port < 0) // No port given, use HTTP or HTTPS default
142
if (url.getProtocol().equalsIgnoreCase("HTTPS"))
143               port = HTTPS_DEFAULT_PORT;
144           else
145               port = HTTP_DEFAULT_PORT;
146       return port;
147   }
148
149   /**
150    * POST something to the given URL. The headers are put in as
151    * HTTP headers, the content length is calculated and the content
152    * byte array is sent as the POST content.
153    *
154    * @param url the url to post to
155    * @param request the message
156    * @param timeout the amount of time, in ms, to block on reading data
157    * @param httpProxyHost the HTTP proxy host or null if no proxy
158    * @param httpProxyPort the HTTP proxy port, if the proxy host is not null
159    * @return the response message
160    */

161   public static TransportMessage post(URL url, TransportMessage request,
162                                       int timeout,
163                                       String JavaDoc httpProxyHost, int httpProxyPort)
164       throws IllegalArgumentException JavaDoc, IOException, SOAPException {
165     return post(url,
166                 request,
167                 timeout,
168                 httpProxyHost,
169                 httpProxyPort,
170                 DEFAULT_OUTPUT_BUFFER_SIZE,
171         null);
172   }
173
174   /**
175    * POST something to the given URL. The headers are put in as
176    * HTTP headers, the content length is calculated and the content
177    * byte array is sent as the POST content.
178    *
179    * @param url the url to post to
180    * @param request the message
181    * @param timeout the amount of time, in ms, to block on reading data
182    * @param httpProxyHost the HTTP proxy host or null if no proxy
183    * @param httpProxyPort the HTTP proxy port, if the proxy host is not null
184    * @param outputBufferSize the size of the output buffer on the HTTP stream
185    * @return the response message
186    */

187   public static TransportMessage post(URL url, TransportMessage request,
188                                       int timeout,
189                                       String JavaDoc httpProxyHost, int httpProxyPort,
190                                       int outputBufferSize)
191       throws IllegalArgumentException JavaDoc, IOException, SOAPException {
192     return post(url,
193                 request,
194                 timeout,
195                 httpProxyHost,
196                 httpProxyPort,
197                 outputBufferSize,
198         null);
199   }
200
201   /**
202    * POST something to the given URL. The headers are put in as
203    * HTTP headers, the content length is calculated and the content
204    * byte array is sent as the POST content.
205    *
206    * @param url the url to post to
207    * @param request the message
208    * @param timeout the amount of time, in ms, to block on reading data
209    * @param httpProxyHost the HTTP proxy host or null if no proxy
210    * @param httpProxyPort the HTTP proxy port, if the proxy host is not null
211    * @param outputBufferSize the size of the output buffer on the HTTP stream
212    * @param tcpNoDelay the tcpNoDelay setting for the socket
213    * @return the response message
214    */

215   public static TransportMessage post(URL url, TransportMessage request,
216                                       int timeout,
217                                       String JavaDoc httpProxyHost, int httpProxyPort,
218                                       int outputBufferSize,
219                       Boolean JavaDoc tcpNoDelay)
220       throws IllegalArgumentException JavaDoc, IOException, SOAPException {
221       /* Open the connection */
222       OutputStream outStream = null;
223       InputStream inStream = null;
224       BufferedReader in = null;
225       int port;
226       Socket s;
227       try {
228           port = getPort(url);
229
230           s = buildSocket(url, port, httpProxyHost, httpProxyPort, tcpNoDelay);
231           if (url.getProtocol().equalsIgnoreCase("HTTPS")) {
232              // Ignore proxy from now on. Buildsocket takes handles it
233
httpProxyHost = null;
234           }
235
236           if (timeout > 0) // Should be redundant but not every JVM likes this
237
s.setSoTimeout(timeout);
238
239           outStream = s.getOutputStream ();
240           inStream = s.getInputStream ();
241       }
242       catch (Exception JavaDoc e) {
243         Throwable JavaDoc t = e;
244
245         if (t instanceof InvocationTargetException) {
246           t = ((InvocationTargetException)t).getTargetException();
247         }
248
249         throw new IllegalArgumentException JavaDoc("Error opening socket: " + t);
250       }
251
252       /* Compute the Request URI */
253       String JavaDoc URI = (httpProxyHost == null ? url.getFile() : url.toString());
254       if (URI.length() == 0) URI = "/";
255
256       /* Construct the HTTP header. */
257       StringBuffer JavaDoc headerbuf = new StringBuffer JavaDoc();
258       headerbuf.append(Constants.HEADER_POST).append(' ').append(URI)
259           .append(" HTTP/").append(HTTP_VERSION).append("\r\n")
260           .append(Constants.HEADER_HOST).append(": ").append(url.getHost())
261           .append(':').append(port)
262           .append("\r\n")
263           .append(Constants.HEADER_CONTENT_TYPE).append(": ")
264           .append(request.getContentType()).append("\r\n")
265           .append(Constants.HEADER_CONTENT_LENGTH).append(": ")
266           .append(request.getContentLength()).append("\r\n");
267       for (Enumeration e = request.getHeaderNames(); e.hasMoreElements(); ) {
268           Object JavaDoc key = e.nextElement();
269           headerbuf.append(key).append(": ")
270               .append(request.getHeader((String JavaDoc)key)).append("\r\n");
271       }
272       headerbuf.append("\r\n");
273
274       /* Send the request. */
275       BufferedOutputStream bOutStream = new BufferedOutputStream(outStream, outputBufferSize);
276       bOutStream.write(
277           headerbuf.toString().getBytes(Constants.HEADERVAL_DEFAULT_CHARSET));
278       request.writeTo(bOutStream);
279       //bOutStream.write('\r'); bOutStream.write('\n');
280
//bOutStream.write('\r'); bOutStream.write('\n');
281
bOutStream.flush();
282       outStream.flush();
283
284       BufferedInputStream bInStream = new BufferedInputStream(inStream);
285       /* Read the response status line. */
286       int statusCode = 0;
287       String JavaDoc statusString = null;
288       StringBuffer JavaDoc linebuf = new StringBuffer JavaDoc();
289       int b = 0;
290       while (b != '\n' && b != -1) {
291           b = bInStream.read();
292           if (b != '\n' && b != '\r' && b != -1)
293               linebuf.append((char)b);
294       }
295       String JavaDoc line = linebuf.toString();
296       try {
297           StringTokenizer st = new StringTokenizer(line);
298           st.nextToken(); // ignore version part
299
statusCode = Integer.parseInt (st.nextToken());
300           StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
301           while (st.hasMoreTokens()) {
302               sb.append (st.nextToken());
303               if (st.hasMoreTokens()) {
304                   sb.append(" ");
305               }
306           }
307           statusString = sb.toString();
308       }
309       catch (Exception JavaDoc e) {
310           throw new IllegalArgumentException JavaDoc(
311               "Error parsing HTTP status line \"" + line + "\": " + e);
312       }
313
314       /* Read the entire response (following the status line)
315        * into a byte array. */

316       ByteArrayDataSource ds = new ByteArrayDataSource(bInStream,
317                           Constants.HEADERVAL_DEFAULT_CHARSET);
318
319       /* Extract the headers, content type and content length. */
320       byte[] bytes = ds.toByteArray();
321       Hashtable respHeaders = new Hashtable();
322       int respContentLength = -1;
323       String JavaDoc respContentType = null;
324       StringBuffer JavaDoc namebuf = new StringBuffer JavaDoc();
325       StringBuffer JavaDoc valuebuf = new StringBuffer JavaDoc();
326       boolean parsingName = true;
327       int offset;
328       for (offset = 0; offset < bytes.length; offset++) {
329           if (bytes[offset] == '\n') {
330               if (namebuf.length() == 0)
331                   break;
332               String JavaDoc name = namebuf.toString();
333
334               // Remove trailing ; to prevent ContextType from throwing exception
335
int valueLen = valuebuf.length();
336
337               if (valueLen > 0 && valuebuf.charAt(valueLen - 1) == ';') {
338                   valuebuf.deleteCharAt(valueLen - 1);
339               }
340
341               String JavaDoc value = valuebuf.toString();
342               if (name.equalsIgnoreCase(Constants.HEADER_CONTENT_LENGTH))
343                   respContentLength = Integer.parseInt(value);
344               else if (name.equalsIgnoreCase(Constants.HEADER_CONTENT_TYPE))
345                   respContentType = value;
346               else
347                   respHeaders.put(name, value);
348               namebuf = new StringBuffer JavaDoc();
349               valuebuf = new StringBuffer JavaDoc();
350               parsingName = true;
351           }
352           else if (bytes[offset] != '\r') {
353               if (parsingName) {
354                   if (bytes[offset] == ':') {
355                       parsingName = false;
356                       if ((offset != bytes.length-1) &&
357                           bytes[offset+1] == ' ')
358                         offset++;
359                   }
360                   else
361                       namebuf.append((char)bytes[offset]);
362               }
363               else
364                   valuebuf.append((char)bytes[offset]);
365           }
366       }
367       InputStream is = ds.getInputStream();
368       is.skip(offset + 1);
369       if (respContentLength < 0)
370           respContentLength = ds.getSize() - offset - 1;
371
372       /* Construct the response object. */
373       SOAPContext ctx;
374       TransportMessage response;
375       try {
376           // Create response SOAPContext.
377
ctx = new SOAPContext();
378           // Read content.
379
response = new TransportMessage(is, respContentLength,
380                                           respContentType, ctx, respHeaders);
381           // Extract envelope and SOAPContext
382
response.read();
383       } catch (MessagingException me) {
384           throw new IllegalArgumentException JavaDoc("Error parsing response: " + me);
385       }
386
387       /* All done here! */
388       bOutStream.close();
389       outStream.close();
390       bInStream.close();
391       inStream.close();
392       s.close();
393       return response;
394   }
395 }
396
Popular Tags