KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mule > providers > soap > axis > extensions > MuleHttpSender


1 /*
2  * $Id: MuleHttpSender.java 3798 2006-11-04 04:07:14Z aperepel $
3  * --------------------------------------------------------------------------------------
4  * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
5  *
6  * The software in this package is published under the terms of the MuleSource MPL
7  * license, a copy of which has been included with this distribution in the
8  * LICENSE.txt file.
9  */

10
11 package org.mule.providers.soap.axis.extensions;
12
13 import org.apache.axis.AxisFault;
14 import org.apache.axis.Constants;
15 import org.apache.axis.Message;
16 import org.apache.axis.MessageContext;
17 import org.apache.axis.client.Call;
18 import org.apache.axis.components.logger.LogFactory;
19 import org.apache.axis.components.net.BooleanHolder;
20 import org.apache.axis.components.net.DefaultSocketFactory;
21 import org.apache.axis.components.net.SocketFactory;
22 import org.apache.axis.components.net.SocketFactoryFactory;
23 import org.apache.axis.encoding.Base64;
24 import org.apache.axis.handlers.BasicHandler;
25 import org.apache.axis.soap.SOAP12Constants;
26 import org.apache.axis.soap.SOAPConstants;
27 import org.apache.axis.transport.http.ChunkedInputStream;
28 import org.apache.axis.transport.http.ChunkedOutputStream;
29 import org.apache.axis.transport.http.HTTPConstants;
30 import org.apache.axis.transport.http.HTTPSender;
31 import org.apache.axis.transport.http.SocketHolder;
32 import org.apache.axis.transport.http.SocketInputStream;
33 import org.apache.axis.utils.Messages;
34 import org.apache.axis.utils.TeeOutputStream;
35 import org.apache.commons.io.output.ByteArrayOutputStream;
36 import org.apache.commons.lang.StringUtils;
37 import org.apache.commons.lang.SystemUtils;
38 import org.apache.commons.logging.Log;
39
40 import javax.xml.soap.MimeHeader JavaDoc;
41 import javax.xml.soap.MimeHeaders JavaDoc;
42 import javax.xml.soap.SOAPException JavaDoc;
43
44 import java.io.BufferedInputStream JavaDoc;
45 import java.io.BufferedOutputStream JavaDoc;
46 import java.io.IOException JavaDoc;
47 import java.io.InputStream JavaDoc;
48 import java.io.OutputStream JavaDoc;
49 import java.net.Socket JavaDoc;
50 import java.net.URL JavaDoc;
51 import java.util.Enumeration JavaDoc;
52 import java.util.Hashtable JavaDoc;
53 import java.util.Iterator JavaDoc;
54
55 /**
56  * <code>MuleHttpSender</code> is a rewrite of the Axis HttpSender. Unfortunately,
57  * the Axis implementation is not extensible so this class is a copy of it with
58  * modifications. The enhancements made are to allow for asynchronous Http method
59  * calls which Mule initiates when the endpoint is asynchronous.
60  *
61  * @author <a HREF="mailto:ross.mason@symphonysoft.com">Ross Mason</a>
62  * @version $Revision: 3798 $
63  * @deprecated Use the UniversalSender instead
64  */

65 public class MuleHttpSender extends BasicHandler
66 {
67     /**
68      * Serial version
69      */

70     private static final long serialVersionUID = -1730816323289419500L;
71
72     protected static Log log = LogFactory.getLog(HTTPSender.class.getName());
73
74     private static final String JavaDoc ACCEPT_HEADERS = HTTPConstants.HEADER_ACCEPT
75                                                  // limit to the types that are
76
// meaningful to us.
77
+ ": " + HTTPConstants.HEADER_ACCEPT_APPL_SOAP + ", "
78                                                  + HTTPConstants.HEADER_ACCEPT_APPLICATION_DIME + ", "
79                                                  + HTTPConstants.HEADER_ACCEPT_MULTIPART_RELATED + ", "
80                                                  + HTTPConstants.HEADER_ACCEPT_TEXT_ALL + "\r\n"
81                                                  + HTTPConstants.HEADER_USER_AGENT // Tell
82
// who
83
// we
84
// are.
85
+ ": " + Messages.getMessage("axisUserAgent") + "\r\n";
86
87     private static final String JavaDoc CACHE_HEADERS = HTTPConstants.HEADER_CACHE_CONTROL
88                                                 // stop caching proxies from caching
89
// SOAP request.
90
+ ": " + HTTPConstants.HEADER_CACHE_CONTROL_NOCACHE + "\r\n"
91                                                 + HTTPConstants.HEADER_PRAGMA + ": "
92                                                 + HTTPConstants.HEADER_CACHE_CONTROL_NOCACHE + "\r\n";
93
94     private static final String JavaDoc CHUNKED_HEADER = HTTPConstants.HEADER_TRANSFER_ENCODING + ": "
95                                                  + HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED + "\r\n";
96
97     private static final String JavaDoc HEADER_CONTENT_TYPE_LC = HTTPConstants.HEADER_CONTENT_TYPE.toLowerCase();
98
99     private static final String JavaDoc HEADER_LOCATION_LC = HTTPConstants.HEADER_LOCATION.toLowerCase();
100
101     private static final String JavaDoc HEADER_CONTENT_LOCATION_LC = HTTPConstants.HEADER_CONTENT_LOCATION.toLowerCase();
102
103     private static final String JavaDoc HEADER_CONTENT_LENGTH_LC = HTTPConstants.HEADER_CONTENT_LENGTH.toLowerCase();
104
105     private static final String JavaDoc HEADER_TRANSFER_ENCODING_LC = HTTPConstants.HEADER_TRANSFER_ENCODING.toLowerCase();
106
107     /**
108      * the url; used for error reporting
109      */

110     URL JavaDoc targetURL;
111
112     /**
113      * invoke creates a socket connection, sends the request SOAP message and then
114      * reads the response SOAP message back from the SOAP server
115      *
116      * @param msgContext the messsage context
117      * @throws AxisFault
118      */

119     public void invoke(MessageContext msgContext) throws AxisFault
120     {
121
122         if (log.isDebugEnabled())
123         {
124             log.debug(Messages.getMessage("enter00", "HTTPSender::invoke"));
125         }
126         try
127         {
128             Call call = (Call)msgContext.getProperty("call_object");
129             String JavaDoc transURL = msgContext.getStrProp(MessageContext.TRANS_URL);
130             String JavaDoc uri = transURL;
131             if (call != null && call.useSOAPAction())
132             {
133                 uri = call.getSOAPActionURI();
134             }
135             msgContext.setProperty("SOAPAction", uri);
136
137             BooleanHolder useFullURL = new BooleanHolder(false);
138             StringBuffer JavaDoc otherHeaders = new StringBuffer JavaDoc(64);
139             targetURL = new URL JavaDoc(transURL);
140             String JavaDoc host = targetURL.getHost();
141             int port = targetURL.getPort();
142
143             SocketHolder socketHolder = new SocketHolder(null);
144
145             // Send the SOAP request to the server
146
InputStream inp = writeToSocket(socketHolder, msgContext, targetURL, otherHeaders, host, port,
147                 msgContext.getTimeout(), useFullURL);
148
149             if (msgContext.isClient() && call != null)
150             {
151                 if (Boolean.TRUE.equals(call.getProperty("axis.one.way")))
152                 {
153                     return;
154                 }
155             }
156
157             // Read the response back from the server
158
Hashtable JavaDoc headers = new Hashtable JavaDoc();
159             inp = readHeadersFromSocket(socketHolder, msgContext, inp, headers);
160             readFromSocket(socketHolder, msgContext, inp, headers);
161         }
162         catch (Exception JavaDoc e)
163         {
164             log.debug(e);
165             throw AxisFault.makeFault(e);
166         }
167         if (log.isDebugEnabled())
168         {
169             log.debug(Messages.getMessage("exit00", "HTTPDispatchHandler::invoke"));
170         }
171     }
172
173     /**
174      * Creates a socket connection to the SOAP server
175      *
176      * @param protocol "http" for standard, "https" for ssl.
177      * @param host host name
178      * @param port port to connect to
179      * @param otherHeaders buffer for storing additional headers that need to be sent
180      * @param useFullURL flag to indicate if the complete URL has to be sent
181      * @throws java.io.IOException
182      */

183     protected void getSocket(SocketHolder sockHolder,
184                              MessageContext msgContext,
185                              String JavaDoc protocol,
186                              String JavaDoc host,
187                              int port,
188                              int timeout,
189                              StringBuffer JavaDoc otherHeaders,
190                              BooleanHolder useFullURL) throws Exception JavaDoc
191     {
192         Hashtable JavaDoc options = getOptions();
193         if (timeout > 0)
194         {
195             if (options == null)
196             {
197                 options = new Hashtable JavaDoc();
198             }
199             options.put(DefaultSocketFactory.CONNECT_TIMEOUT, Integer.toString(timeout));
200         }
201         SocketFactory factory = SocketFactoryFactory.getFactory(protocol, options);
202         if (factory == null)
203         {
204             throw new IOException JavaDoc(Messages.getMessage("noSocketFactory", protocol));
205         }
206         // log.fatal("Axis client: connect on socket: " + host + ":" + port);
207
Socket JavaDoc sock = null;
208         try
209         {
210             sock = factory.create(host, port, otherHeaders, useFullURL);
211         }
212         catch (Exception JavaDoc e)
213         {
214             Thread.sleep(1000);
215             try
216             {
217                 sock = factory.create(host, port, otherHeaders, useFullURL);
218             }
219             catch (Exception JavaDoc e1)
220             {
221                 log.fatal("Axis client Failed: connect on socket: " + host + ":" + port, e);
222                 throw e;
223             }
224         }
225         if (timeout > 0)
226         {
227             sock.setSoTimeout(timeout);
228         }
229         sockHolder.setSocket(sock);
230     }
231
232     /**
233      * Send the soap request message to the server
234      *
235      * @param msgContext message context
236      * @param tmpURL url to connect to
237      * @param otherHeaders other headers if any
238      * @param host host name
239      * @param port port
240      * @param useFullURL flag to indicate if the whole url needs to be sent
241      * @throws IOException
242      */

243     private InputStream writeToSocket(SocketHolder sockHolder,
244                                       MessageContext msgContext,
245                                       URL JavaDoc tmpURL,
246                                       StringBuffer JavaDoc otherHeaders,
247                                       String JavaDoc host,
248                                       int port,
249                                       int timeout,
250                                       BooleanHolder useFullURL) throws Exception JavaDoc
251     {
252
253         String JavaDoc userID = msgContext.getUsername();
254         String JavaDoc passwd = msgContext.getPassword();
255
256         // Get SOAPAction, default to ""
257
String JavaDoc action = msgContext.useSOAPAction() ? msgContext.getSOAPActionURI() : "";
258
259         if (action == null)
260         {
261             action = "";
262         }
263
264         // if UserID is not part of the context, but is in the URL, use
265
// the one in the URL.
266
if ((userID == null) && (tmpURL.getUserInfo() != null))
267         {
268             String JavaDoc info = tmpURL.getUserInfo();
269             int sep = info.indexOf(':');
270
271             if ((sep >= 0) && (sep + 1 < info.length()))
272             {
273                 userID = info.substring(0, sep);
274                 passwd = info.substring(sep + 1);
275             }
276             else
277             {
278                 userID = info;
279             }
280         }
281         if (userID != null)
282         {
283             StringBuffer JavaDoc tmpBuf = new StringBuffer JavaDoc(64);
284             tmpBuf.append(userID).append(":").append((passwd == null) ? "" : passwd);
285             otherHeaders.append(HTTPConstants.HEADER_AUTHORIZATION).append(": Basic ").append(
286                 Base64.encode(tmpBuf.toString().getBytes())).append("\r\n");
287         }
288
289         // don't forget the cookies!
290
// mmm... cookies
291
if (msgContext.getMaintainSession())
292         {
293             String JavaDoc cookie = msgContext.getStrProp(HTTPConstants.HEADER_COOKIE);
294             String JavaDoc cookie2 = msgContext.getStrProp(HTTPConstants.HEADER_COOKIE2);
295
296             if (cookie != null)
297             {
298                 otherHeaders.append(HTTPConstants.HEADER_COOKIE).append(": ").append(cookie).append("\r\n");
299             }
300             if (cookie2 != null)
301             {
302                 otherHeaders.append(HTTPConstants.HEADER_COOKIE2).append(": ").append(cookie2).append("\r\n");
303             }
304         }
305
306         StringBuffer JavaDoc header2 = new StringBuffer JavaDoc(64);
307
308         String JavaDoc webMethod = null;
309         boolean posting = true;
310
311         Message reqMessage = msgContext.getRequestMessage();
312
313         boolean http10 = true; // True if this is to use HTTP 1.0 / false HTTP
314
// 1.1
315
boolean httpChunkStream = false; // Use HTTP chunking or not.
316
boolean httpContinueExpected = false; // Under HTTP 1.1 if false you
317
// *MAY* need to wait for a 100
318
// rc,
319
// if true the server MUST reply with 100 continue.
320
String JavaDoc httpConnection = null;
321
322         String JavaDoc httpver = msgContext.getStrProp(MessageContext.HTTP_TRANSPORT_VERSION);
323         if (null == httpver)
324         {
325             httpver = HTTPConstants.HEADER_PROTOCOL_V10;
326         }
327         httpver = httpver.trim();
328         if (httpver.equals(HTTPConstants.HEADER_PROTOCOL_V11))
329         {
330             http10 = false;
331         }
332
333         // process user defined headers for information.
334
Hashtable JavaDoc userHeaderTable = (Hashtable JavaDoc)msgContext.getProperty(HTTPConstants.REQUEST_HEADERS);
335
336         if (userHeaderTable != null)
337         {
338             if (null == otherHeaders)
339             {
340                 otherHeaders = new StringBuffer JavaDoc(1024);
341             }
342
343             for (java.util.Iterator JavaDoc e = userHeaderTable.entrySet().iterator(); e.hasNext();)
344             {
345
346                 java.util.Map.Entry me = (java.util.Map.Entry)e.next();
347                 Object JavaDoc keyObj = me.getKey();
348                 if (null == keyObj)
349                 {
350                     continue;
351                 }
352                 String JavaDoc key = keyObj.toString().trim();
353
354                 if (key.equalsIgnoreCase(HTTPConstants.HEADER_TRANSFER_ENCODING))
355                 {
356                     if (!http10)
357                     {
358                         String JavaDoc val = me.getValue().toString();
359                         if (null != val
360                             && val.trim().equalsIgnoreCase(HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED))
361                         {
362                             httpChunkStream = true;
363                         }
364                     }
365                 }
366                 else if (key.equalsIgnoreCase(HTTPConstants.HEADER_CONNECTION))
367                 {
368                     if (!http10)
369                     {
370                         String JavaDoc val = me.getValue().toString();
371                         if (val.trim().equalsIgnoreCase(HTTPConstants.HEADER_CONNECTION_CLOSE))
372                         {
373                             httpConnection = HTTPConstants.HEADER_CONNECTION_CLOSE;
374                         }
375                     }
376                     // HTTP 1.0 will always close.
377
// HTTP 1.1 will use persistent. //no need to specify
378
}
379                 else
380                 {
381                     if (!http10 && key.equalsIgnoreCase(HTTPConstants.HEADER_EXPECT))
382                     {
383                         String JavaDoc val = me.getValue().toString();
384                         if (null != val
385                             && val.trim().equalsIgnoreCase(HTTPConstants.HEADER_EXPECT_100_Continue))
386                         {
387                             httpContinueExpected = true;
388                         }
389                     }
390
391                     otherHeaders.append(key).append(": ").append(me.getValue()).append("\r\n");
392                 }
393             }
394         }
395
396         if (!http10)
397         {
398             // Force close for now.
399
// TODO HTTP/1.1
400
httpConnection = HTTPConstants.HEADER_CONNECTION_CLOSE;
401         }
402
403         header2.append(" ");
404         header2.append(http10 ? HTTPConstants.HEADER_PROTOCOL_10 : HTTPConstants.HEADER_PROTOCOL_11).append(
405             "\r\n");
406         MimeHeaders JavaDoc mimeHeaders = reqMessage.getMimeHeaders();
407
408         if (posting)
409         {
410             String JavaDoc contentType;
411             if (mimeHeaders.getHeader(HTTPConstants.HEADER_CONTENT_TYPE) != null)
412             {
413                 contentType = mimeHeaders.getHeader(HTTPConstants.HEADER_CONTENT_TYPE)[0];
414             }
415             else
416             {
417                 contentType = reqMessage.getContentType(msgContext.getSOAPConstants());
418             }
419             header2.append(HTTPConstants.HEADER_CONTENT_TYPE).append(": ").append(contentType).append("\r\n");
420         }
421
422         header2.append(ACCEPT_HEADERS).append(HTTPConstants.HEADER_HOST)
423         // used for virtual connections
424
.append(": ")
425             .append(host)
426             .append((port == -1) ? ("") : (":" + port))
427             .append("\r\n")
428             .append(CACHE_HEADERS)
429             .append(HTTPConstants.HEADER_SOAP_ACTION)
430             // The SOAP action.
431
.append(": \"")
432             .append(action)
433             .append("\"\r\n");
434
435         if (posting)
436         {
437             if (!httpChunkStream)
438             {
439                 // Content length MUST be sent on HTTP 1.0 requests.
440
header2.append(HTTPConstants.HEADER_CONTENT_LENGTH).append(": ").append(
441                     reqMessage.getContentLength()).append("\r\n");
442             }
443             else
444             {
445                 // Do http chunking.
446
header2.append(CHUNKED_HEADER);
447             }
448         }
449
450         // Transfer MIME headers of SOAPMessage to HTTP headers.
451
if (mimeHeaders != null)
452         {
453             for (Iterator JavaDoc i = mimeHeaders.getAllHeaders(); i.hasNext();)
454             {
455                 MimeHeader JavaDoc mimeHeader = (MimeHeader JavaDoc)i.next();
456                 String JavaDoc headerName = mimeHeader.getName();
457                 if (headerName.equals(HTTPConstants.HEADER_CONTENT_TYPE)
458                     || headerName.equals(HTTPConstants.HEADER_SOAP_ACTION))
459                 {
460                     continue;
461                 }
462                 header2.append(mimeHeader.getName())
463                     .append(": ")
464                     .append(mimeHeader.getValue())
465                     .append("\r\n");
466             }
467         }
468
469         if (null != httpConnection)
470         {
471             header2.append(HTTPConstants.HEADER_CONNECTION);
472             header2.append(": ");
473             header2.append(httpConnection);
474             header2.append("\r\n");
475         }
476
477         getSocket(sockHolder, msgContext, targetURL.getProtocol(), host, port, timeout, otherHeaders,
478             useFullURL);
479
480         if (null != otherHeaders)
481         {
482             // Add other headers to the end.
483
// for pre java1.4 support, we have to turn the string buffer
484
// argument into
485
// a string before appending.
486
header2.append(otherHeaders.toString());
487         }
488
489         header2.append("\r\n"); // The empty line to start the BODY.
490

491         StringBuffer JavaDoc header = new StringBuffer JavaDoc(128);
492
493         // If we're SOAP 1.2, allow the web method to be set from the
494
// MessageContext.
495
if (msgContext.getSOAPConstants() == SOAPConstants.SOAP12_CONSTANTS)
496         {
497             webMethod = msgContext.getStrProp(SOAP12Constants.PROP_WEBMETHOD);
498         }
499         if (webMethod == null)
500         {
501             webMethod = HTTPConstants.HEADER_POST;
502         }
503         else
504         {
505             posting = webMethod.equals(HTTPConstants.HEADER_POST);
506         }
507
508         header.append(webMethod).append(" ");
509         if (useFullURL.value)
510         {
511             header.append(tmpURL.toExternalForm());
512         }
513         else
514         {
515             header.append(StringUtils.isEmpty(tmpURL.getFile()) ? "/" : tmpURL.getFile());
516         }
517         header.append(header2.toString());
518
519         OutputStream out = sockHolder.getSocket().getOutputStream();
520
521         if (!posting)
522         {
523             out.write(header.toString().getBytes(HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING));
524             out.flush();
525             return null;
526         }
527
528         InputStream inp = null;
529
530         if (httpChunkStream || httpContinueExpected)
531         {
532             out.write(header.toString().getBytes(HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING));
533         }
534
535         if (httpContinueExpected)
536         { // We need to get a reply from the server as
537
// to whether
538
// it wants us send anything more.
539
out.flush();
540             Hashtable JavaDoc cheaders = new Hashtable JavaDoc();
541             inp = readHeadersFromSocket(sockHolder, msgContext, null, cheaders);
542             int returnCode = -1;
543             Integer JavaDoc Irc = (Integer JavaDoc)msgContext.getProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
544             if (null != Irc)
545             {
546                 returnCode = Irc.intValue();
547             }
548             if (100 == returnCode)
549             { // got 100 we may continue.
550
// Need todo a little msgContext house keeping....
551
msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
552                 msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_MESSAGE);
553             }
554             else
555             { // If no 100 Continue then we must not send anything!
556
String JavaDoc statusMessage = (String JavaDoc)msgContext.getProperty(HTTPConstants.MC_HTTP_STATUS_MESSAGE);
557
558                 AxisFault fault = new AxisFault("HTTP", "(" + returnCode + ")" + statusMessage, null, null);
559
560                 fault.setFaultDetailString(Messages.getMessage("return01", "" + returnCode, ""));
561                 throw fault;
562             }
563         }
564         ByteArrayOutputStream baos = null;
565         if (log.isDebugEnabled())
566         {
567             log.debug(Messages.getMessage("xmlSent00"));
568             log.debug("---------------------------------------------------");
569             baos = new ByteArrayOutputStream();
570         }
571         if (httpChunkStream)
572         {
573             ChunkedOutputStream chunkedOutputStream = new ChunkedOutputStream(out);
574             out = new BufferedOutputStream JavaDoc(chunkedOutputStream, Constants.HTTP_TXR_BUFFER_SIZE);
575             try
576             {
577                 if (baos != null)
578                 {
579                     out = new TeeOutputStream(out, baos);
580                 }
581                 reqMessage.writeTo(out);
582             }
583             catch (SOAPException JavaDoc e)
584             {
585                 log.error(Messages.getMessage("exception00"), e);
586             }
587             out.flush();
588             chunkedOutputStream.eos();
589         }
590         else
591         {
592             out = new BufferedOutputStream JavaDoc(out, Constants.HTTP_TXR_BUFFER_SIZE);
593             try
594             {
595                 if (!httpContinueExpected)
596                 {
597                     out.write(header.toString().getBytes(HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING));
598                 }
599                 if (baos != null)
600                 {
601                     out = new TeeOutputStream(out, baos);
602                 }
603                 reqMessage.writeTo(out);
604             }
605             catch (SOAPException JavaDoc e)
606             {
607                 throw e;
608             }
609             finally
610             {
611                 // Flush ONLY once.
612
out.flush();
613             }
614
615         }
616
617         if (log.isDebugEnabled() && baos != null)
618         {
619             log.debug(header + new String JavaDoc(baos.toByteArray()));
620         }
621
622         return inp;
623     }
624
625     private InputStream readHeadersFromSocket(SocketHolder sockHolder,
626                                               MessageContext msgContext,
627                                               InputStream inp,
628                                               Hashtable JavaDoc headers) throws IOException JavaDoc
629     {
630         byte b = 0;
631         int len = 0;
632         int colonIndex = -1;
633         String JavaDoc name, value;
634         int returnCode = 0;
635         if (null == inp)
636         {
637             inp = new BufferedInputStream JavaDoc(sockHolder.getSocket().getInputStream());
638         }
639
640         if (headers == null)
641         {
642             headers = new Hashtable JavaDoc();
643         }
644
645         // Should help performance. Temporary fix only till its all stream
646
// oriented.
647
// Need to add logic for getting the version # and the return code
648
// but that's for tomorrow!
649

650         /* Logic to read HTTP response headers */
651         boolean readTooMuch = false;
652
653         for (ByteArrayOutputStream buf = new ByteArrayOutputStream(4097);;)
654         {
655             if (!readTooMuch)
656             {
657                 b = (byte)inp.read();
658             }
659             if (b == -1)
660             {
661                 break;
662             }
663             readTooMuch = false;
664             if ((b != '\r') && (b != '\n'))
665             {
666                 if ((b == ':') && (colonIndex == -1))
667                 {
668                     colonIndex = len;
669                 }
670                 len++;
671                 buf.write(b);
672             }
673             else if (b == '\r')
674             {
675                 continue;
676             }
677             else
678             { // b== '\n'
679
if (len == 0)
680                 {
681                     break;
682                 }
683                 b = (byte)inp.read();
684                 readTooMuch = true;
685
686                 // A space or tab at the begining of a line means the header
687
// continues.
688
if ((b == ' ') || (b == '\t'))
689                 {
690                     continue;
691                 }
692                 buf.close();
693                 byte[] hdata = buf.toByteArray();
694                 buf.reset();
695                 if (colonIndex != -1)
696                 {
697                     name = new String JavaDoc(hdata, 0, colonIndex, HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING);
698                     value = new String JavaDoc(hdata, colonIndex + 1, len - 1 - colonIndex,
699                         HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING);
700                     colonIndex = -1;
701                 }
702                 else
703                 {
704
705                     name = new String JavaDoc(hdata, 0, len, HTTPConstants.HEADER_DEFAULT_CHAR_ENCODING);
706                     value = "";
707                 }
708                 if (log.isDebugEnabled())
709                 {
710                     log.debug(name + value);
711                 }
712                 if (msgContext.getProperty(HTTPConstants.MC_HTTP_STATUS_CODE) == null)
713                 {
714
715                     // Reader status code
716
int start = name.indexOf(' ') + 1;
717                     String JavaDoc tmp = name.substring(start).trim();
718                     int end = tmp.indexOf(' ');
719
720                     if (end != -1)
721                     {
722                         tmp = tmp.substring(0, end);
723                     }
724                     returnCode = Integer.parseInt(tmp);
725                     msgContext.setProperty(HTTPConstants.MC_HTTP_STATUS_CODE, new Integer JavaDoc(returnCode));
726                     msgContext.setProperty(HTTPConstants.MC_HTTP_STATUS_MESSAGE, name.substring(start + end
727                                                                                                 + 1));
728                 }
729                 else
730                 {
731                     headers.put(name.toLowerCase(), value);
732                 }
733                 len = 0;
734             }
735         }
736
737         return inp;
738     }
739
740     /**
741      * Reads the SOAP response back from the server
742      *
743      * @param msgContext message context
744      * @throws IOException
745      */

746     private InputStream readFromSocket(SocketHolder socketHolder,
747                                        MessageContext msgContext,
748                                        InputStream inp,
749                                        Hashtable JavaDoc headers) throws IOException JavaDoc
750     {
751         Message outMsg = null;
752         byte b;
753
754         Integer JavaDoc rc = (Integer JavaDoc)msgContext.getProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
755         int returnCode = 0;
756         if (rc != null)
757         {
758             returnCode = rc.intValue();
759         }
760         else
761         {
762             // No return code?? Should have one by now.
763
}
764
765         /* All HTTP headers have been read. */
766         String JavaDoc contentType = (String JavaDoc)headers.get(HEADER_CONTENT_TYPE_LC);
767
768         contentType = (null == contentType) ? null : contentType.trim();
769
770         String JavaDoc location = (String JavaDoc)headers.get(HEADER_LOCATION_LC);
771
772         location = (null == location) ? null : location.trim();
773
774         if ((returnCode > 199) && (returnCode < 300))
775         {
776             if (returnCode == 202)
777             {
778                 return inp;
779             }
780             // SOAP return is OK - so fall through
781
}
782         else if (msgContext.getSOAPConstants() == SOAPConstants.SOAP12_CONSTANTS)
783         {
784             // For now, if we're SOAP 1.2, fall through, since the range of
785
// valid result codes is much greater
786
}
787         else if ((contentType != null) && !contentType.startsWith("text/html")
788                  && ((returnCode > 499) && (returnCode < 600)))
789         {
790             // SOAP Fault should be in here - so fall through
791
}
792         else if ((location != null) && ((returnCode == 302) || (returnCode == 307)))
793         {
794             // Temporary Redirect (HTTP: 302/307)
795
// close old connection
796
inp.close();
797             socketHolder.getSocket().close();
798             // remove former result and set new target url
799
msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
800             msgContext.setProperty(MessageContext.TRANS_URL, location);
801             // next try
802
invoke(msgContext);
803             return inp;
804         }
805         else if (returnCode == 100)
806         {
807             msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
808             msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_MESSAGE);
809             readHeadersFromSocket(socketHolder, msgContext, inp, headers);
810             return readFromSocket(socketHolder, msgContext, inp, headers);
811         }
812         else
813         {
814             // Unknown return code - so wrap up the content into a
815
// SOAP Fault.
816
ByteArrayOutputStream buf = new ByteArrayOutputStream(4097);
817
818             while (-1 != (b = (byte)inp.read()))
819             {
820                 buf.write(b);
821             }
822             String JavaDoc statusMessage = msgContext.getStrProp(HTTPConstants.MC_HTTP_STATUS_MESSAGE);
823             AxisFault fault = new AxisFault("HTTP", "(" + returnCode + ")" + statusMessage, null, null);
824
825             fault.setFaultDetailString(Messages.getMessage("return01", "" + returnCode, buf.toString()));
826             fault.addFaultDetail(Constants.QNAME_FAULTDETAIL_HTTPERRORCODE, Integer.toString(returnCode));
827             throw fault;
828         }
829
830         String JavaDoc contentLocation = (String JavaDoc)headers.get(HEADER_CONTENT_LOCATION_LC);
831
832         contentLocation = (null == contentLocation) ? null : contentLocation.trim();
833
834         String JavaDoc contentLength = (String JavaDoc)headers.get(HEADER_CONTENT_LENGTH_LC);
835
836         contentLength = (null == contentLength) ? null : contentLength.trim();
837
838         String JavaDoc transferEncoding = (String JavaDoc)headers.get(HEADER_TRANSFER_ENCODING_LC);
839
840         if (null != transferEncoding)
841         {
842             transferEncoding = transferEncoding.trim().toLowerCase();
843             if (transferEncoding.equals(HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED))
844             {
845                 inp = new ChunkedInputStream(inp);
846             }
847         }
848
849         outMsg = new Message(new SocketInputStream(inp, socketHolder.getSocket()), false, contentType,
850             contentLocation);
851         // Transfer HTTP headers of HTTP message to MIME headers of SOAP message
852
MimeHeaders JavaDoc mimeHeaders = outMsg.getMimeHeaders();
853         for (Enumeration JavaDoc e = headers.keys(); e.hasMoreElements();)
854         {
855             String JavaDoc key = (String JavaDoc)e.nextElement();
856             mimeHeaders.addHeader(key, ((String JavaDoc)headers.get(key)).trim());
857         }
858         outMsg.setMessageType(Message.RESPONSE);
859         msgContext.setResponseMessage(outMsg);
860         if (log.isDebugEnabled())
861         {
862             if (null == contentLength)
863             {
864                 log.debug(SystemUtils.LINE_SEPARATOR + Messages.getMessage("no00", "Content-Length"));
865             }
866             log.debug(SystemUtils.LINE_SEPARATOR + Messages.getMessage("xmlRecd00"));
867             log.debug("-----------------------------------------------");
868             log.debug(outMsg.getSOAPEnvelope().toString());
869         }
870
871         // if we are maintaining session state,
872
// handle cookies (if any)
873
if (msgContext.getMaintainSession())
874         {
875             handleCookie(HTTPConstants.HEADER_COOKIE, HTTPConstants.HEADER_SET_COOKIE, headers, msgContext);
876             handleCookie(HTTPConstants.HEADER_COOKIE2, HTTPConstants.HEADER_SET_COOKIE2, headers, msgContext);
877         }
878         return inp;
879     }
880
881     /**
882      * little helper function for cookies
883      *
884      * @param cookieName
885      * @param setCookieName
886      * @param headers
887      * @param msgContext
888      */

889     public void handleCookie(String JavaDoc cookieName,
890                              String JavaDoc setCookieName,
891                              Hashtable JavaDoc headers,
892                              MessageContext msgContext)
893     {
894
895         if (headers.containsKey(setCookieName.toLowerCase()))
896         {
897             String JavaDoc cookie = (String JavaDoc)headers.get(setCookieName.toLowerCase());
898             cookie = cookie.trim();
899
900             // chop after first ; a la Apache SOAP (see HTTPUtils.java there)
901
int index = cookie.indexOf(';');
902
903             if (index != -1)
904             {
905                 cookie = cookie.substring(0, index);
906             }
907             msgContext.setProperty(cookieName, cookie);
908         }
909     }
910 }
911
Popular Tags