KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xmlrpc > LiteXmlRpcTransport


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
17
18 package org.apache.xmlrpc;
19
20 import java.io.BufferedInputStream JavaDoc;
21 import java.io.BufferedOutputStream JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.io.InputStream JavaDoc;
24 import java.net.ConnectException JavaDoc;
25 import java.net.Socket JavaDoc;
26 import java.net.URL JavaDoc;
27 import java.util.StringTokenizer JavaDoc;
28
29 import org.apache.xmlrpc.util.HttpUtil;
30
31 /**
32  * Interface from XML-RPC to a 'lite' HTTP implementation. This class will use
33  * the XmlRpcClientLite.auth member for the HTTP Basic authentication string.
34  *
35  * @author <a HREF="mailto:hannes@apache.org">Hannes Wallnoefer</a>
36  * @author <a HREF="mailto:andrew@kungfoocoder.org">Andrew Evers</a>
37  * @version $Id: LiteXmlRpcTransport.java,v 1.6 2005/04/22 10:25:57 hgomez Exp $
38  * @since 1.2
39  */

40 class LiteXmlRpcTransport implements XmlRpcTransport
41 {
42     String JavaDoc hostname;
43     String JavaDoc host;
44     protected String JavaDoc auth = null;
45     int port;
46     String JavaDoc uri;
47     Socket JavaDoc socket = null;
48     BufferedOutputStream JavaDoc output;
49     BufferedInputStream JavaDoc input;
50     boolean keepalive;
51     byte[] buffer;
52
53     /**
54      * Create a new DefaultXmlRpcTransport with the specified URL.
55      *
56      * @param url the url to POST XML-RPC requests to.
57      */

58     public LiteXmlRpcTransport(URL JavaDoc url)
59     {
60         hostname = url.getHost();
61         port = url.getPort();
62         if (port < 1)
63         {
64             port = 80;
65         }
66         uri = url.getFile();
67         if (uri == null || "".equals(uri))
68         {
69             uri = "/";
70         }
71         host = port == 80 ? hostname : hostname + ":" + port;
72     }
73
74     public InputStream JavaDoc sendXmlRpc(byte [] request)
75     throws IOException JavaDoc
76     {
77         try
78         {
79             if (socket == null)
80             {
81             initConnection();
82             }
83
84             InputStream JavaDoc in = null;
85
86            // send request to the server and get an input stream
87
// from which to read the response
88
try
89             {
90                 in = sendRequest(request);
91             }
92             catch (IOException JavaDoc iox)
93             {
94                 // if we get an exception while sending the request,
95
// and the connection is a keepalive connection, it may
96
// have been timed out by the server. Try again.
97
if (keepalive)
98                 {
99                     closeConnection();
100                     initConnection();
101                     in = sendRequest(request);
102                 }
103                 else
104                 {
105                     throw iox;
106                 }
107             }
108
109             return in;
110         }
111         catch (IOException JavaDoc iox)
112         {
113             // this is a lower level problem, client could not talk to
114
// server for some reason.
115
throw iox;
116         }
117         catch (Exception JavaDoc x)
118         {
119             // same as above, but exception has to be converted to
120
// IOException.
121
if (XmlRpc.debug)
122             {
123                 x.printStackTrace ();
124             }
125
126             String JavaDoc msg = x.getMessage ();
127             if (msg == null || msg.length () == 0)
128             {
129                 msg = x.toString ();
130             }
131             throw new IOException JavaDoc (msg);
132         }
133     }
134
135     /**
136      *
137      * @throws IOException
138      */

139     protected void initConnection() throws IOException JavaDoc
140     {
141         final int retries = 3;
142         final int delayMillis = 100;
143         
144         int tries = 0;
145         
146         socket = null;
147         while (socket == null) {
148             try {
149                 socket = new Socket JavaDoc(hostname, port);
150             }
151             catch (ConnectException JavaDoc e) {
152                 if (tries >= retries) {
153                     throw e;
154                 } else {
155                     // log.debug("ConnectException: " + e.getMessage() + ", waiting " + new Integer(delayMillis).toString() + " milliseconds and retrying");
156
try {
157                         Thread.sleep(delayMillis);
158                     }
159                     catch (InterruptedException JavaDoc ignore) {
160                     }
161                 }
162             }
163         }
164         
165         output = new BufferedOutputStream JavaDoc(socket.getOutputStream());
166         input = new BufferedInputStream JavaDoc(socket.getInputStream());
167     }
168
169     /**
170      *
171      */

172     protected void closeConnection ()
173     {
174         try
175         {
176             socket.close();
177         }
178         catch (Exception JavaDoc ignore)
179         {
180         }
181         finally
182         {
183             socket = null;
184         }
185     }
186
187     /**
188      *
189      * @param request
190      * @return
191      * @throws IOException
192      */

193     public InputStream JavaDoc sendRequest(byte[] request) throws IOException JavaDoc
194     {
195         output.write(("POST " + uri + " HTTP/1.0\r\n").getBytes());
196         output.write(("User-Agent: " + XmlRpc.version + "\r\n").getBytes());
197         output.write(("Host: " + host + "\r\n").getBytes());
198         if (XmlRpc.getKeepAlive())
199         {
200             output.write("Connection: Keep-Alive\r\n".getBytes());
201         }
202         output.write("Content-Type: text/xml\r\n".getBytes());
203         if (auth != null)
204         {
205             output.write(("Authorization: Basic " + auth + "\r\n")
206                     .getBytes());
207         }
208         output.write(("Content-Length: " + request.length)
209                 .getBytes());
210         output.write("\r\n\r\n".getBytes());
211         output.write(request);
212         output.flush();
213
214         // start reading server response headers
215
String JavaDoc line = readLine();
216         if (XmlRpc.debug)
217         {
218             System.out.println(line);
219         }
220         int contentLength = -1;
221         try
222         {
223             StringTokenizer JavaDoc tokens = new StringTokenizer JavaDoc(line);
224             String JavaDoc httpversion = tokens.nextToken();
225             String JavaDoc statusCode = tokens.nextToken();
226             String JavaDoc statusMsg = tokens.nextToken("\n\r");
227             keepalive = XmlRpc.getKeepAlive()
228                     && "HTTP/1.1".equals(httpversion);
229             if (! "200".equals(statusCode))
230             {
231                 throw new IOException JavaDoc("Unexpected Response from Server: "
232                         + statusMsg);
233             }
234         }
235         catch (IOException JavaDoc iox)
236         {
237             throw iox;
238         }
239         catch (Exception JavaDoc x)
240         {
241             // x.printStackTrace ();
242
throw new IOException JavaDoc("Server returned invalid Response.");
243         }
244         do
245         {
246             line = readLine ();
247             if (line != null)
248             {
249                 if (XmlRpc.debug)
250                 {
251                     System.out.println(line);
252                 }
253                 line = line.toLowerCase();
254                 if (line.startsWith("content-length:"))
255                 {
256                     contentLength = Integer.parseInt(
257                             line.substring(15).trim());
258                 }
259                 if (line.startsWith("connection:"))
260                 {
261                     keepalive = XmlRpc.getKeepAlive()
262                             && line.indexOf("keep-alive") > -1;
263                 }
264             }
265         }
266         while (line != null && ! line.equals(""))
267             ;
268         return new ServerInputStream(input, contentLength);
269     }
270
271     /**
272      * Sets Authentication for this client. This will be sent as Basic
273      * Authentication header to the server as described in
274      * <a HREF="http://www.ietf.org/rfc/rfc2617.txt">
275      * http://www.ietf.org/rfc/rfc2617.txt</a>.
276      */

277     public void setBasicAuthentication(String JavaDoc user, String JavaDoc password)
278     {
279         auth = HttpUtil.encodeBasicAuthentication(user, password);
280     }
281
282     public void endClientRequest()
283     {
284         // eepalive is always false if XmlRpc.keepalive is false
285
if (!keepalive)
286         {
287             closeConnection ();
288         }
289     }
290
291     /**
292      *
293      * @return
294      * @throws IOException
295      */

296     private String JavaDoc readLine() throws IOException JavaDoc
297     {
298         if (buffer == null)
299         {
300             buffer = new byte[2048];
301         }
302         int next;
303         int count = 0;
304         while (true)
305         {
306             next = input.read();
307             if (next < 0 || next == '\n')
308             {
309                 break;
310             }
311             if (next != '\r')
312             {
313                 buffer[count++] = (byte) next;
314             }
315             if (count >= buffer.length)
316             {
317                 throw new IOException JavaDoc ("HTTP Header too long");
318             }
319         }
320         return new String JavaDoc(buffer, 0, count);
321     }
322
323     /**
324      *
325      * @throws Throwable
326      */

327     protected void finalize() throws Throwable JavaDoc
328     {
329         closeConnection ();
330     }
331 }
332
Popular Tags