Coverage Report - org.apache.xmlrpc.client.XmlRpcLiteHttpTransport
 
Classes in this File Line Coverage Branch Coverage Complexity
XmlRpcLiteHttpTransport
75% 
79% 
3,429
 
 1  24
 /*
 2  
  * Copyright 1999,2005 The Apache Software Foundation.
 3  
  * 
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  * 
 8  
  *      http://www.apache.org/licenses/LICENSE-2.0
 9  
  * 
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.apache.xmlrpc.client;
 17  
 
 18  
 import java.io.BufferedInputStream;
 19  
 import java.io.BufferedOutputStream;
 20  
 import java.io.IOException;
 21  
 import java.io.InputStream;
 22  
 import java.io.OutputStream;
 23  
 import java.io.UnsupportedEncodingException;
 24  
 import java.net.ConnectException;
 25  
 import java.net.Socket;
 26  
 import java.net.URL;
 27  
 import java.util.ArrayList;
 28  
 import java.util.HashMap;
 29  
 import java.util.Iterator;
 30  
 import java.util.List;
 31  
 import java.util.Map;
 32  
 import java.util.StringTokenizer;
 33  
 
 34  
 import org.apache.xmlrpc.XmlRpcException;
 35  
 import org.apache.xmlrpc.common.XmlRpcStreamRequestConfig;
 36  
 import org.apache.xmlrpc.util.HttpUtil;
 37  
 import org.apache.xmlrpc.util.LimitedInputStream;
 38  
 
 39  
 
 40  
 /** A "light" HTTP transport implementation.
 41  
  */
 42  
 public class XmlRpcLiteHttpTransport extends XmlRpcHttpTransport {
 43  
         private class Connection {
 44  70
                 private final String hostname;
 45  0
             private final String host;
 46  70
                 private int port;
 47  70
                 private final String uri;
 48  424
             private Socket socket;
 49  422
                 private OutputStream output;
 50  691
             private InputStream input;
 51  642
                 private final Map headers = new HashMap();
 52  96
                 Connection(URL pURL) {
 53  96
                 hostname = pURL.getHost();
 54  96
                 int p = pURL.getPort();
 55  96
                         port = p < 1 ? 80 : p;
 56  96
                         String u = pURL.getFile();
 57  96
                         uri = (u == null  ||  "".equals(u)) ? "/" : u;
 58  96
                         host = port == 80 ? hostname : hostname + ":" + port;
 59  96
                         headers.put("Host", host);
 60  96
                 }
 61  
         }
 62  
 
 63  96
         private final String userAgent = super.getUserAgent() + " (Lite HTTP Transport)";
 64  
 
 65  
         /** Creates a new instance.
 66  
          * @param pClient The client controlling this instance.
 67  
          */
 68  
         public XmlRpcLiteHttpTransport(XmlRpcClient pClient) {
 69  96
                 super(pClient);
 70  96
         }
 71  
 
 72  96
         protected String getUserAgent() { return userAgent; }
 73  
 
 74  
         protected void setRequestHeader(Object pConnection, String pHeader,
 75  
                                                                         String pValue) {
 76  238
                 Connection conn = (Connection) pConnection;
 77  238
                 Object value = conn.headers.get(pHeader);
 78  238
                 if (value == null) {
 79  238
                         conn.headers.put(pHeader, pValue);
 80  
                 } else {
 81  
                         List list;
 82  0
                         if (value instanceof String) {
 83  0
                                 list = new ArrayList();
 84  0
                                 list.add(value);
 85  0
                                 conn.headers.put(pHeader, list);
 86  
                         } else {
 87  0
                                 list = (List) value;
 88  
                         }
 89  0
                         list.add(pValue);
 90  
                 }
 91  238
         }
 92  
 
 93  
         protected boolean isResponseGzipCompressed(
 94  
                         XmlRpcStreamRequestConfig pConfig, Object pConnection) {
 95  
                 // TODO Auto-generated method stub
 96  70
                 return false;
 97  
         }
 98  
 
 99  
         protected Object newConnection(XmlRpcStreamRequestConfig pConfig)
 100  
                         throws XmlRpcClientException {
 101  96
                 return new Connection(((XmlRpcHttpClientConfig) pConfig).getServerURL());
 102  
         }
 103  
 
 104  
         protected void closeConnection(Object pConnection)
 105  
                         throws XmlRpcClientException {
 106  96
                 Connection conn = (Connection) pConnection;
 107  96
                 IOException e = null;
 108  96
                 if (conn.input != null) {
 109  
                         try {
 110  70
                                 conn.input.close();
 111  0
                         } catch (IOException ex) {
 112  0
                                 e = ex;
 113  
                         }
 114  
                 }
 115  96
                 if (conn.output != null) {
 116  
                         try {
 117  70
                                 conn.output.close();
 118  24
                         } catch (IOException ex) {
 119  24
                                 if (e != null) {
 120  0
                                         e = ex;
 121  
                                 }
 122  
                         }
 123  
                 }
 124  96
                 if (conn.socket != null) {
 125  
                         try {
 126  70
                                 conn.socket.close();
 127  0
                         } catch (IOException ex) {
 128  0
                                 if (e != null) {
 129  0
                                         e = ex;
 130  
                                 }
 131  
                         }
 132  
                 }
 133  96
                 if (e != null) {
 134  0
                         throw new XmlRpcClientException("Failed to close connection: " + e.getMessage(), e);
 135  
                 }
 136  96
         }
 137  
 
 138  
         protected OutputStream newOutputStream(XmlRpcStreamRequestConfig pConfig,
 139  
                                                                                    Object pConnection) throws XmlRpcClientException {
 140  24
                 final Connection conn = (Connection) pConnection;
 141  24
                 final int retries = 3;
 142  24
         final int delayMillis = 100;
 143  
         
 144  24
                 for (int tries = 0;  ;  tries++) {
 145  
                         try {
 146  24
                                 conn.socket = new Socket(conn.hostname, conn.port);
 147  24
                                 conn.output = new BufferedOutputStream(conn.socket.getOutputStream()){
 148  
                                         /** Closing the output stream would close the whole socket, which we don't want,
 149  
                                          * because the don't want until the request is processed completely.
 150  
                                          * A close will later occur within
 151  
                                          * {@link XmlRpcLiteHttpTransport#closeConnection(Object)}.
 152  
                                          */
 153  
                                         public void close() throws IOException {
 154  48
                                                 flush();
 155  48
                                                 conn.socket.shutdownOutput();
 156  24
                                         }
 157  
                                 };
 158  24
                                 sendRequestHeaders(conn, conn.output);
 159  24
                                 return conn.output;
 160  0
                         } catch (ConnectException e) {
 161  0
                                 if (tries >= retries) {
 162  0
                                         throw new XmlRpcClientException("Failed to connect to " + conn.host + ": " + e.getMessage(), e);
 163  
                                 } else {
 164  
                     try {
 165  0
                         Thread.sleep(delayMillis);
 166  0
                     } catch (InterruptedException ignore) {
 167  
                     }
 168  
                                 }
 169  0
                         } catch (IOException e) {
 170  0
                                 throw new XmlRpcClientException("Failed to connect to " + conn.host + ": " + e.getMessage(), e);
 171  
                         }
 172  
                 }
 173  
         }
 174  
 
 175  
         private byte[] toHTTPBytes(String pValue) throws UnsupportedEncodingException {
 176  326
                 return pValue.getBytes("US-ASCII");
 177  
         }
 178  
 
 179  
         private void sendHeader(OutputStream pOut, String pKey, String pValue) throws IOException {
 180  256
                 pOut.write(toHTTPBytes(pKey + ": " + pValue + "\r\n"));
 181  256
         }
 182  
 
 183  
         private void sendRequestHeaders(Connection pConnection,
 184  
                                                                         OutputStream pOut) throws IOException {
 185  70
                 pOut.write(("POST " + pConnection.uri + " HTTP/1.0\r\n").getBytes("US-ASCII"));
 186  396
                 for (Iterator iter = pConnection.headers.entrySet().iterator();  iter.hasNext();  ) {
 187  256
                         Map.Entry entry = (Map.Entry) iter.next();
 188  256
                         String key = (String) entry.getKey();
 189  256
                         Object value = entry.getValue();
 190  256
                         if (value instanceof String) {
 191  256
                                 sendHeader(pOut, key, (String) value);
 192  
                         } else {
 193  0
                                 List list = (List) value;
 194  0
                                 for (int i = 0;  i < list.size();  i++) {
 195  0
                                         sendHeader(pOut, key, (String) list.get(i));
 196  
                                 }
 197  
                         }
 198  
                 }
 199  70
                 pOut.write(toHTTPBytes("\r\n"));
 200  70
         }
 201  
 
 202  
         protected InputStream newInputStream(XmlRpcStreamRequestConfig pConfig,
 203  
                                                                                  Object pConnection,
 204  
                                                                                  byte[] pContent) throws XmlRpcException {
 205  
                 try {
 206  46
                         Connection conn = (Connection) pConnection;
 207  46
                         conn.socket = new Socket(conn.hostname, conn.port);
 208  46
                         conn.output = new BufferedOutputStream(conn.socket.getOutputStream());
 209  46
                         sendRequestHeaders(conn, conn.output);
 210  46
                         conn.output.write(pContent);
 211  46
                         conn.output.flush();
 212  0
                 } catch (IOException e) {
 213  0
                         throw new XmlRpcClientException("Failed to send request to sender: " + e.getMessage(), e);
 214  
                 }
 215  46
                 return newInputStream(pConfig, pConnection);
 216  
         }
 217  
 
 218  
         protected InputStream newInputStream(XmlRpcStreamRequestConfig pConfig,
 219  
                                                                                  Object pConnection) throws XmlRpcException {
 220  70
                 Connection conn = (Connection) pConnection;
 221  70
                 final byte[] buffer = new byte[2048];
 222  
                 try {
 223  70
                         conn.input = new BufferedInputStream(conn.socket.getInputStream());
 224  
                         // start reading  server response headers
 225  70
                         String line = HttpUtil.readLine(conn.input, buffer);
 226  70
                         StringTokenizer tokens = new StringTokenizer(line);
 227  70
                         tokens.nextToken(); // Skip HTTP version
 228  70
                         String statusCode = tokens.nextToken();
 229  70
                         String statusMsg = tokens.nextToken("\n\r");
 230  70
                         if (! "200".equals(statusCode)) {
 231  0
                                 throw new IOException("Unexpected Response from Server: "
 232  0
                                                                           + statusMsg);
 233  
                         }
 234  70
                         int contentLength = -1;
 235  245
                         for (;;) {
 236  315
                                 line = HttpUtil.readLine(conn.input, buffer);
 237  315
                                 if (line == null  ||  "".equals(line)) {
 238  70
                                         break;
 239  
                                 }
 240  245
                                 line = line.toLowerCase();
 241  245
                                 if (line.startsWith("content-length:")) {
 242  35
                                         contentLength = Integer.parseInt(line.substring("content-length:".length()).trim());
 243  
                                 }
 244  
                         }
 245  
                         InputStream result;
 246  70
                         if (contentLength == -1) {
 247  35
                                 result = conn.input;
 248  
                         } else {
 249  35
                                 result = new LimitedInputStream(conn.input, contentLength);
 250  
                         }
 251  70
                         return result;
 252  0
                 } catch (IOException e) {
 253  0
                         throw new XmlRpcClientException("Failed to read server response: " + e.getMessage(), e);
 254  
                 }
 255  
         }
 256  
 }