Coverage Report - org.apache.xmlrpc.client.XmlRpcStreamTransport
 
Classes in this File Line Coverage Branch Coverage Complexity
XmlRpcStreamTransport
72% 
100% 
3,588
 
 1  
 /*
 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.ByteArrayInputStream;
 19  
 import java.io.ByteArrayOutputStream;
 20  
 import java.io.IOException;
 21  
 import java.io.InputStream;
 22  
 import java.io.OutputStream;
 23  
 import java.util.zip.GZIPInputStream;
 24  
 import java.util.zip.GZIPOutputStream;
 25  
 
 26  
 import javax.xml.parsers.ParserConfigurationException;
 27  
 import javax.xml.parsers.SAXParserFactory;
 28  
 
 29  
 import org.apache.xmlrpc.XmlRpcException;
 30  
 import org.apache.xmlrpc.XmlRpcRequest;
 31  
 import org.apache.xmlrpc.common.XmlRpcStreamRequestConfig;
 32  
 import org.apache.xmlrpc.parser.XmlRpcResponseParser;
 33  
 import org.apache.xmlrpc.serializer.XmlRpcWriter;
 34  
 import org.xml.sax.ContentHandler;
 35  
 import org.xml.sax.InputSource;
 36  
 import org.xml.sax.SAXException;
 37  
 import org.xml.sax.XMLReader;
 38  
 
 39  
 
 40  
 /** Implementation of a transport class, which is based on an output
 41  
  * stream for sending the request and an input stream for receiving
 42  
  * the response,
 43  
  */
 44  1
 public abstract class XmlRpcStreamTransport extends XmlRpcTransportImpl {
 45  
         private static final SAXParserFactory spf;
 46  
         static {
 47  1
                 spf = SAXParserFactory.newInstance();
 48  1
                 spf.setNamespaceAware(true);
 49  1
                 spf.setValidating(false);
 50  
         }
 51  
 
 52  
         /** Creates a new instance on behalf of the given client.
 53  
          */
 54  
         protected XmlRpcStreamTransport(XmlRpcClient pClient) {
 55  434
                 super(pClient);
 56  434
         }
 57  
 
 58  
         /** Creates the connection object. The connection object is a
 59  
          * factory for output and input stream.
 60  
          */
 61  
         protected abstract Object newConnection(XmlRpcStreamRequestConfig pConfig) throws XmlRpcClientException;
 62  
 
 63  
         /** Closes the connection object.
 64  
          */
 65  
         protected abstract void closeConnection(Object pConnection) throws XmlRpcClientException;
 66  
 
 67  
         /** Initializes the newly created connection. For example, the HTTP transport
 68  
          * will use this to set headers.
 69  
          * @param pConfig The clients configuration.
 70  
          * @param pConnection The connection being initialized.
 71  
          * @throws XmlRpcClientException A local error on the client occurred.
 72  
          */
 73  
         protected void initConnection(XmlRpcStreamRequestConfig pConfig, Object pConnection) throws XmlRpcClientException {
 74  384
         }
 75  
 
 76  
         /** Creates a new output stream, to which the request may be written.
 77  
          * @param pConfig Client configuration.
 78  
          * @param pConnection Connection being used to send request data.
 79  
          * @return Opened output stream.
 80  
          * @throws XmlRpcClientException An error occurred on the client.
 81  
          */
 82  
         protected abstract OutputStream newOutputStream(XmlRpcStreamRequestConfig pConfig, Object pConnection)
 83  
                         throws XmlRpcClientException;
 84  
 
 85  
         /** Closes the opened output stream, indicating that no more data is being
 86  
          * sent.
 87  
          * @param pStream The stream being closed.
 88  
          * @throws XmlRpcClientException An error occurred on the client.
 89  
          */
 90  
         protected void closeOutputStream(OutputStream pStream) throws XmlRpcClientException {
 91  
                 try {
 92  384
                         pStream.close();
 93  0
                 } catch (IOException e) {
 94  0
                         throw new XmlRpcClientException("Failed to close output stream.", e);
 95  
                 }
 96  384
         }
 97  
 
 98  
         protected OutputStream getOutputStream(XmlRpcStreamRequestConfig pConfig, Object pConnection)
 99  
                         throws XmlRpcClientException {
 100  120
                 OutputStream result = newOutputStream(pConfig, pConnection);
 101  120
                 if (pConfig.isGzipCompressing()) {
 102  
                         try {
 103  0
                                 result = new GZIPOutputStream(result);
 104  0
                         } catch (IOException e) {
 105  0
                                 throw new XmlRpcClientException("Failed to attach gzip encoding to output stream", e);
 106  
                         }
 107  
                 }
 108  120
                 return result;
 109  
         }
 110  
 
 111  
         /** Creates a new input stream for reading the response.
 112  
          * @param pConfig The clients configuration.
 113  
          * @param pConnection The connection object.
 114  
          * @return Opened input stream for reading data.
 115  
          * @throws XmlRpcException Creating the input stream failed.
 116  
          */
 117  
         protected abstract InputStream newInputStream(XmlRpcStreamRequestConfig pConfig, Object pConnection)
 118  
                         throws XmlRpcException;
 119  
 
 120  
         /** Creates a new input stream for reading the response.
 121  
          * @param pConfig The clients configuration.
 122  
          * @param pConnection The connection object.
 123  
          * @param pContent A byte array with the response.
 124  
          * @return Opened input stream for reading data.
 125  
          * @throws XmlRpcException Creating the input stream failed.
 126  
          */
 127  
         protected abstract InputStream newInputStream(XmlRpcStreamRequestConfig pConfig,
 128  
                                                                                                   Object pConnection,
 129  
                                                                                                   byte[] pContent)
 130  
                         throws XmlRpcException;
 131  
 
 132  
         /** Closes the opened input stream, indicating that no more data is being
 133  
          * read.
 134  
          * @param pStream The stream being closed.
 135  
          * @throws XmlRpcClientException An error occurred on the client.
 136  
          */
 137  
         protected void closeInputStream(InputStream pStream) throws XmlRpcClientException {
 138  
                 try {
 139  280
                         pStream.close();
 140  0
                 } catch (IOException e) {
 141  0
                         throw new XmlRpcClientException("Failed to close output stream.", e);
 142  
                 }
 143  280
         }
 144  
 
 145  
         /** Returns, whether the response is gzip compressed.
 146  
          * @param pConfig The clients configuration.
 147  
          * @param pConnection The connection object.
 148  
          * @return Whether the response stream is gzip compressed.
 149  
          */
 150  
         protected abstract boolean isResponseGzipCompressed(XmlRpcStreamRequestConfig pConfig, Object pConnection);
 151  
 
 152  
         protected InputStream getInputStream(XmlRpcStreamRequestConfig pConfig, Object pConnection,
 153  
                                                                                  byte[] pContent)
 154  
                         throws XmlRpcException {
 155  
                 InputStream istream;
 156  280
                 if (pContent == null) {
 157  107
                         istream = newInputStream(pConfig, pConnection);
 158  
                 } else {
 159  173
                         istream = newInputStream(pConfig, pConnection, pContent);
 160  
                 }
 161  280
                 if (isResponseGzipCompressed(pConfig, pConnection)) {
 162  
                         try {
 163  0
                                 istream = new GZIPInputStream(istream);
 164  0
                         } catch (IOException e) {
 165  0
                                 throw new XmlRpcClientException("Failed to attach gzip decompression to the response stream", e);
 166  
                         }
 167  
                 }
 168  280
                 return istream;
 169  
         }
 170  
 
 171  
         /** If this method returns true, then the method
 172  
          * {@link #newInputStream(XmlRpcStreamRequestConfig, Object, byte[])}
 173  
          * will be invoked to create the response. Otherwise, the methods
 174  
          * {@link #getOutputStream(XmlRpcStreamRequestConfig, Object)}, and
 175  
          * {@link #newInputStream(XmlRpcStreamRequestConfig, Object)} will
 176  
          * be used.
 177  
          * @return Whether conversion into a byte array is required to create
 178  
          * the response.
 179  
          */
 180  
         protected boolean isUsingByteArrayOutput(XmlRpcStreamRequestConfig pConfig) {
 181  48
                 return false;
 182  
         }
 183  
 
 184  
         public Object sendRequest(XmlRpcRequest pRequest) throws XmlRpcException {
 185  384
                 XmlRpcStreamRequestConfig config = (XmlRpcStreamRequestConfig) pRequest.getConfig();
 186  384
                 Object connection = newConnection(config);
 187  
                 try {
 188  384
                         initConnection(config, connection);
 189  
                         OutputStream ostream;
 190  
                         ByteArrayOutputStream baos;
 191  384
                         if (isUsingByteArrayOutput(config)) {
 192  264
                                 baos = new ByteArrayOutputStream();
 193  264
                                 if (config.isGzipCompressing()) {
 194  
                                         try {
 195  0
                                                 ostream = new GZIPOutputStream(baos);
 196  0
                                         } catch (IOException e) {
 197  0
                                                 throw new XmlRpcClientException("Failed to create GZIPOutputStream: " + e.getMessage(), e);
 198  
                                         }
 199  
                                 } else {
 200  264
                                         ostream = baos;
 201  
                                 }
 202  
                         } else {
 203  120
                                 baos = null;
 204  120
                                 ostream = getOutputStream(config, connection);
 205  
                         }
 206  
                         try {
 207  384
                                 writeRequest(config, ostream, pRequest);
 208  280
                                 closeOutputStream(ostream);
 209  280
                                 ostream = null;
 210  104
                         } finally {
 211  384
                                 if (ostream != null) { try { closeOutputStream(ostream); } catch (Throwable ignore) {} }
 212  104
                         }
 213  280
                         InputStream istream = getInputStream(config, connection, baos == null ? null : baos.toByteArray());
 214  
                         Object result;
 215  
                         try {
 216  280
                                 result = readResponse(config, istream);
 217  280
                                 closeInputStream(istream);
 218  280
                                 istream = null;
 219  0
                         } finally {
 220  280
                                 if (istream != null) { try { closeInputStream(istream); } catch (Throwable ignore) {} }
 221  0
                         }
 222  280
                         closeConnection(connection);
 223  280
                         connection = null;
 224  560
                         return result;
 225  104
                 } finally {
 226  384
                         if (connection != null) { try { closeConnection(connection); } catch (Throwable ignore) {} }
 227  104
                 }
 228  
         }
 229  
 
 230  
         protected XMLReader newXMLReader() throws XmlRpcClientException {
 231  
                 try {
 232  280
                         return spf.newSAXParser().getXMLReader();
 233  0
                 } catch (ParserConfigurationException e) {
 234  0
                         throw new XmlRpcClientException("Failed to create XMLReader: " + e.getMessage(), e);
 235  0
                 } catch (SAXException e) {
 236  0
                         throw new XmlRpcClientException("Failed to create XMLReader: " + e.getMessage(), e);
 237  
                 }
 238  
         }
 239  
 
 240  
         protected Object readResponse(XmlRpcStreamRequestConfig pConfig, InputStream pStream) throws XmlRpcException {
 241  
                 if (true) {
 242  280
                         ByteArrayOutputStream baos = new ByteArrayOutputStream();
 243  
                         try {
 244  280
                                 byte[] buffer = new byte[1024];
 245  280
                                 for (;;) {
 246  560
                                         int res = pStream.read(buffer);
 247  560
                                         if (res == -1) {
 248  280
                                                 break;
 249  280
                                         } else if (res > 0) {
 250  280
                                                 baos.write(buffer, 0, res);
 251  
                                         }
 252  
                                 }
 253  0
                         } catch (IOException e) {
 254  0
                                 throw new XmlRpcClientException(e.getMessage(), e);
 255  
                         }
 256  280
                         pStream = new ByteArrayInputStream(baos.toByteArray());
 257  
                 }
 258  
 
 259  280
                 InputSource isource = new InputSource(pStream);
 260  280
                 XMLReader xr = newXMLReader();
 261  
                 XmlRpcResponseParser xp;
 262  
                 try {
 263  280
                         xp = new XmlRpcResponseParser(pConfig, getClient().getTypeFactory());
 264  280
                         xr.setContentHandler(xp);
 265  280
                         xr.parse(isource);
 266  0
                 } catch (SAXException e) {
 267  0
                         throw new XmlRpcClientException("Failed to parse servers response: " + e.getMessage(), e);
 268  0
                 } catch (IOException e) {
 269  0
                         throw new XmlRpcClientException("Failed to read servers response: " + e.getMessage(), e);
 270  
                 }
 271  280
                 if (xp.isSuccess()) {
 272  280
                         return xp.getResult();
 273  
                 } else {
 274  0
                         throw new XmlRpcException(xp.getErrorCode(), xp.getErrorMessage());
 275  
                 }
 276  
         }
 277  
 
 278  
         protected void writeRequest(XmlRpcStreamRequestConfig pConfig, OutputStream pStream, XmlRpcRequest pRequest)
 279  
                         throws XmlRpcException {
 280  384
                 ContentHandler h = getClient().getXmlWriterFactory().getXmlWriter(pConfig, pStream);
 281  384
                 XmlRpcWriter xw = new XmlRpcWriter(pConfig, h, getClient().getTypeFactory());
 282  
                 try {
 283  384
                         xw.write(pRequest);
 284  104
                 } catch (SAXException e) {
 285  104
                         Exception ex = e.getException();
 286  104
                         if (ex != null  &&  ex instanceof XmlRpcException) {
 287  104
                                 throw (XmlRpcException) ex;
 288  
                         } else {
 289  0
                                 throw new XmlRpcClientException("Failed to send request: " + e.getMessage(), e);
 290  
                         }
 291  
                 }
 292  280
         }
 293  
 }