KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > soap > transport > http > SOAPHTTPConnection


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.transport.http;
59
60 import java.io.*;
61 import java.net.*;
62 import java.util.*;
63 import org.w3c.dom.*;
64 import org.apache.soap.util.net.*;
65 import org.apache.soap.util.xml.*;
66 import org.apache.soap.util.mime.*;
67 import org.apache.soap.*;
68 import org.apache.soap.encoding.*;
69 import org.apache.soap.encoding.soapenc.Base64;
70 import org.apache.soap.transport.*;
71 import org.apache.soap.rpc.*;
72 import javax.mail.*;
73 import javax.mail.internet.*;
74 import javax.activation.*;
75
76 /**
77  * <code>SOAPHTTPConnection</code> is an implementation of the
78  * <code>SOAPTransport</code> interface for <em>HTTP</em>.
79  *
80  * @author Matthew J. Duftler (duftler@us.ibm.com)
81  * @author Sanjiva Weerawarana (sanjiva@watson.ibm.com)
82  * @author Wouter Cloetens (wcloeten@raleigh.ibm.com)
83  * @author Scott Nichol (snichol@computer.org)
84  */

85 public class SOAPHTTPConnection implements SOAPTransport {
86   private BufferedReader responseReader;
87   private Hashtable responseHeaders;
88   private SOAPContext responseSOAPContext;
89
90   private String httpProxyHost;
91   private int httpProxyPort = 80;
92   private int timeout;
93   private String userName;
94   private String password;
95   private String proxyUserName;
96   private String proxyPassword;
97   private boolean maintainSession = true;
98   private String cookieHeader;
99   private String cookieHeader2;
100   private int outputBufferSize = HTTPUtils.DEFAULT_OUTPUT_BUFFER_SIZE;
101   private Boolean tcpNoDelay = null;
102
103   /**
104    * Set HTTP proxy host.
105    *
106    * @param host the HTTP proxy host or null if no proxy.
107    */

108   public void setProxyHost (String host) {
109       httpProxyHost = host;
110   }
111
112   /**
113    * Set HTTP proxy port.
114    *
115    * @param host the HTTP proxy port.
116    */

117   public void setProxyPort (int port) {
118       httpProxyPort = port;
119   }
120
121   /**
122    * Get HTTP proxy host.
123    *
124    * @return the HTTP proxy host or null if no proxy.
125    */

126   public String getProxyHost () {
127     return httpProxyHost;
128   }
129
130   /**
131    * Get HTTP proxy port.
132    *
133    * @return the HTTP proxy port. Invalid if getProxyHost() returns null.
134    */

135   public int getProxyPort () {
136     return httpProxyPort;
137   }
138
139   /**
140    * Set the username for HTTP Basic authentication.
141    */

142   public void setUserName (String userName) {
143     this.userName = userName;
144   }
145
146   /**
147    * Set the password for HTTP Basic authentication.
148    */

149   public void setPassword (String password) {
150     this.password = password;
151   }
152
153   /**
154    * Set the username for HTTP proxy basic authentication.
155    */

156   public void setProxyUserName (String userName) {
157     this.proxyUserName = userName;
158   }
159
160   /**
161    * Set the password for HTTP proxy basic authentication.
162    */

163   public void setProxyPassword (String password) {
164     this.proxyPassword = password;
165   }
166
167   private static String encodeAuth(String userName, String password)
168     throws SOAPException
169   {
170     try
171     {
172       return Base64.encode((userName + ":" + password).getBytes("8859_1"));
173     }
174     catch (UnsupportedEncodingException e)
175     {
176       throw new SOAPException (Constants.FAULT_CODE_CLIENT, e.getMessage(), e);
177     }
178   }
179
180   /**
181    * Indicate whether to maintain HTTP sessions.
182    */

183   public void setMaintainSession (boolean maintainSession) {
184     this.maintainSession = maintainSession;
185     if (maintainSession == false) {
186       cookieHeader = null;
187       cookieHeader2 = null;
188     }
189   }
190
191   /**
192    * Return session maintanence status.
193    */

194   public boolean getMaintainSession (){
195     return maintainSession;
196   }
197
198   /**
199    * Set the HTTP read timeout.
200    *
201    * @param timeout the amount of time, in ms, to block on reading data.
202    * A zero value indicates an infinite timeout.
203    */

204   public void setTimeout (int timeout) {
205     this.timeout = timeout;
206   }
207
208   /**
209    * Get the HTTP read timeout.
210    *
211    * @return the amount of time, in ms, to block on reading data.
212    */

213   public int getTimeout () {
214     return timeout;
215   }
216
217   /**
218    * Sets the output buffer size (in bytes).
219    *
220    * @param sz The output buffer size (in bytes).
221    */

222   public void setOutputBufferSize(int sz) {
223     outputBufferSize = sz;
224   }
225
226   /**
227    * Gets the output buffer size (in bytes).
228    *
229    * @return The output buffer size (in bytes).
230    */

231   public int getOutputBufferSize() {
232     return outputBufferSize;
233   }
234
235   /**
236    * Get the TCPNoDelay setting.
237    *
238    * @return the TCPNoDelay setting.
239    */

240   public Boolean getTcpNoDelay() {
241     return tcpNoDelay;
242   }
243
244   /**
245    * Set the TCPNoDelay setting. Setting this to true will disable
246    * Nagle's algorithm for TCP. The default is false.
247    */

248   public void setTcpNoDelay(Boolean nodelay) {
249     tcpNoDelay = nodelay;
250   }
251
252   /**
253    * This method is used to request that an envelope be posted to the
254    * given URL. The response (if any) must be gotten by calling the
255    * receive() function.
256    *
257    * @param sendTo the URL to send the envelope to
258    * @param action the SOAPAction header field value
259    * @param headers any other header fields to go to as protocol headers
260    * @param env the envelope to send
261    * @param smr the XML<->Java type mapping registry (passed on)
262    * @param ctx the request SOAPContext
263    *
264    * @exception SOAPException with appropriate reason code if problem
265    */

266   public void send (URL sendTo, String action, Hashtable headers,
267                     Envelope env, SOAPMappingRegistry smr, SOAPContext ctx)
268     throws SOAPException {
269     try {
270       String payload = null;
271       if (env != null) {
272         StringWriter payloadSW = new StringWriter ();
273         env.marshall (payloadSW, smr, ctx);
274         payload = payloadSW.toString ();
275       }
276
277       if (headers == null) {
278         headers = new Hashtable ();
279       }
280       if (maintainSession) {
281         // if there is saved cookie headers, put them in to the request
282
if (cookieHeader2 != null) { // RFC 2965 header
283
headers.put ("Cookie2", cookieHeader2);
284         }
285         if (cookieHeader != null) { // RFC 2109 header
286
headers.put ("Cookie", cookieHeader);
287         }
288       }
289
290       headers.put (Constants.HEADER_SOAP_ACTION,
291                    (action != null) ? ('\"' + action + '\"') : "");
292       if (userName != null) {
293         // add the Authorization header for Basic authentication
294
headers.put (Constants.HEADER_AUTHORIZATION,
295                      "Basic " + encodeAuth(userName, password));
296
297       }
298       if (proxyUserName != null) {
299         // add the Proxy-Authorization header for proxy authentication
300
headers.put (Constants.HEADER_PROXY_AUTHORIZATION,
301                     "Basic " + encodeAuth(proxyUserName, proxyPassword));
302       }
303
304       TransportMessage response;
305       try
306       {
307         TransportMessage msg = new TransportMessage(payload, ctx, headers);
308         msg.save();
309         response = HTTPUtils.post (sendTo, msg,
310                                    timeout, httpProxyHost, httpProxyPort,
311                                    outputBufferSize, tcpNoDelay);
312       } catch (MessagingException me) {
313         throw new IOException ("Failed to encode mime multipart: " + me);
314       } catch (UnsupportedEncodingException uee) {
315         throw new IOException ("Failed to encode mime multipart: " + uee);
316       }
317
318       Reader envReader = response.getEnvelopeReader();
319       if (envReader != null)
320         responseReader = new BufferedReader(envReader);
321       else
322         responseReader = null;
323       responseSOAPContext = response.getSOAPContext();
324       responseHeaders = response.getHeaders();
325       if (maintainSession) {
326         // look for Set-Cookie2 and Set-Cookie headers and save them after
327
// stripping everything after the ';' (i.e., ignore all cookie attrs).
328
// Only update my state iff the header is there .. otherwise
329
// leave the current
330
// Note: Header is case-insensitive
331
String hdr;
332
333         hdr = getHeaderValue (responseHeaders, "Set-Cookie2");
334
335         if (hdr != null) {
336           cookieHeader2 = hdr;
337           int index = cookieHeader2.indexOf (';');
338           if (index != -1) {
339             cookieHeader2 = cookieHeader2.substring (0, index);
340           }
341         }
342
343         hdr = getHeaderValue (responseHeaders, "Set-Cookie");
344
345         if (hdr != null) {
346           cookieHeader = hdr;
347           int index = cookieHeader.indexOf (';');
348           if (index != -1) {
349             cookieHeader = cookieHeader.substring (0, index);
350           }
351         }
352       }
353     } catch (IllegalArgumentException e) {
354       throw new SOAPException (Constants.FAULT_CODE_CLIENT, e.getMessage(), e);
355     } catch (MessagingException e) {
356       throw new SOAPException (Constants.FAULT_CODE_CLIENT, e.getMessage(), e);
357     } catch (IOException e) {
358       throw new SOAPException (Constants.FAULT_CODE_CLIENT, e.getMessage(), e);
359     }
360   }
361
362   /**
363    * Return a buffered reader to receive back the response to whatever
364    * was sent to whatever.
365    *
366    * @return a reader to read the results from or null if that's not
367    * possible.
368    */

369   public BufferedReader receive () {
370     return responseReader;
371   }
372
373   /**
374    * Return access to headers generated by the protocol.
375    *
376    * @return a hashtable containing all the headers
377    */

378   public Hashtable getHeaders () {
379     return responseHeaders;
380   }
381
382   /**
383    * Return the SOAPContext associated with the response.
384    *
385    * @return response SOAPContext
386    */

387   public SOAPContext getResponseSOAPContext () {
388     return responseSOAPContext;
389   }
390
391   /**
392    * Obtain a header value from the table using a case insensitive search.
393    *
394    * @param headers a colletion of headers from the http response
395    * @param headerName the name of the header to find
396    * @return the header value or null if not found
397    */

398   private static String getHeaderValue (Hashtable headers, String headerName)
399   {
400     for (Enumeration enum = headers.keys (); enum.hasMoreElements ();) {
401       String key = (String) enum.nextElement();
402
403       if (key.equalsIgnoreCase (headerName)) {
404         return (String) headers.get(key);
405       }
406     }
407
408     return null;
409   }
410 }
411
Popular Tags