?? httptransport.java
字號:
/* kSOAP * * The contents of this file are subject to the Enhydra Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License * on the Enhydra web site ( http://www.enhydra.org/ ). * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific terms governing rights and limitations * under the License. * * The Initial Developer of kSOAP is Stefan Haustein. Copyright (C) * 2000, 2001 Stefan Haustein, D-46045 Oberhausen (Rhld.), * Germany. All Rights Reserved. * * Contributor(s): John D. Beatty, Dave Dash, F. Hunter, Renaud Tognelli, * Thomas Strang, Alexander Krebs, Sean McDaniel * */package org.ksoap.transport;import java.io.*;import javax.microedition.io.*;import org.kxml.*;import org.kxml.io.*;import org.kxml.parser.*;import org.ksoap.*;/** Methods to facilitate SOAP calls over HTTP using the J2ME generic connection framework. <p> Instances of HttpTransport can be in one of two states: connected and not connected. When an invocation on call is made the instance is in a connected state until call returns or throws an IOException. in any case once control is returned to the caller the instance is again in the not connected state. HttpTransport is not thread safe and applications should ensure that only one thread is inside the call method at any given time. It is designed in such a way that applications can reuse a single instance for all soap calls to one, or multiple, target endpoints.<p> The underlying HttpConnection is opened with the timeout flag set. In the MIDP API this flag is only a hint to the underlying protocol handler to throw an InterrruptIOException, however, there are no guarantees that it will be handled. So rather than support a timeout mechanism internally the design is such that applications can manage timeouts in an environment dependent way.<p> For example some environments may allow for a timeout parameter that can be externally specified in perhaps a system property (which? I don't know. it's in the api). Others like the emulator (ok, who cares) and the Motorola i85s can use a simple and effective timeout mechanism that closes the connection and associated streams in an asynchronous fashion. Calling the close( ) method inside of a separate thread can provide for this timeout handling by releasing threads that maybe stuck inside of call( ) performing network io.<p> Here is some sample code to demonstrate how such a timeout mechanism may look:<br> <pre> private HttpTransport soap; ... TimerTask task = new TimerTask( ) { public void run( ) { soap.close( ); } }; try { new Timer( ).schedule( task, TIMEOUT ); soap.call( soapobject ); // invoke method task.cancel( ); // cancel the timeout } catch ( InterruptedIOException e ) { // handle timeout here... } catch ( IOException e ) { // some other io problem... } </pre><br> The call( ) method will throw and InterruptedIOException if the instance is no longer in the connected state before control is returned to the caller. The call to soap.close( ) inside the TimerTask transitions the HttpConnection into a not connected state.<p> <b>Note</b>: The InterruptedIOException will be caught by a thread waiting on network io, however, it may not be immediate. It is assumed that the protocol handler will gracefully handle the lifecycle of the outputstream and therefore it is not closed inside the close method. IOW the waiting thread will be interrupted after the outputstream has been flushed. If the waiting thread is hung up waiting for input a call to close from a separate thread the exception is observed right away and will return before the thread calling close. <b>At least this is what has been observation on the i85s handset.</b> On this device, if a call to outputstream.close( ) is made while the outputstream is being flushed it seems to cause a deadlock, ie outputstream will never return. */public class HttpTransport { String url; String soapAction = "\"\""; SoapEnvelope requestEnvelope = new SoapEnvelope (); SoapEnvelope responseEnvelope = new SoapEnvelope (); HttpConnection connection; OutputStream os; InputStream is; InputStreamReader reader; /** state info */ private boolean connected = false; /** Set to true if debugging */ public boolean debug; /** String dump of request for debugging. */ public String requestDump; /** String dump of response for debugging */ public String responseDump; /** default constructor */ public HttpTransport () { } /** * Creates instance of HttpTransport with set url and SoapAction * * @param url the destination to POST SOAP data * @param soapAction the desired SOAP action (for HTTP headers) */ public HttpTransport (String url, String soapAction) { this.url = url; this.soapAction = soapAction; } /** * Set the target url. * * @param url the target url. */ public void setUrl (String url) { this.url = url; } /** * set the desired soapAction header field * * @param soapAction the desired soapAction */ public void setSoapAction (String soapAction) { this.soapAction = soapAction; } /** * set the desired ClassMap for the SOAP Envelopes * * @param classMap the desired ClassMap */ public void setClassMap (ClassMap classMap) { requestEnvelope.setClassMap (classMap); responseEnvelope.setClassMap (classMap); } /** Sends the requestEnvelope and fills the responseEnvelope @exception InterruptedIOException if transport was closed async. @exception IOException if an error occurs */ public void call () throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream (); XmlWriter xw = new XmlWriter (new OutputStreamWriter (bos)); requestEnvelope.write (xw); xw.flush (); bos.write ('\r'); bos.write ('\n'); byte [] requestData = bos.toByteArray (); bos = null; xw = null; requestDump = debug ? new String (requestData) : null; responseDump = null; try { connected = true; connection = (HttpConnection) Connector.open (url, Connector.READ_WRITE, true); connection.setRequestProperty ("SOAPAction", soapAction); connection.setRequestProperty ("Content-Type", "text/xml"); connection.setRequestProperty ("Content-Length", ""+requestData.length); connection.setRequestProperty ("User-Agent", "kSOAP/1.0"); connection.setRequestMethod (HttpConnection.POST); os = connection.openOutputStream (); os.write (requestData, 0, requestData.length);// os.flush (); // removed in order to avoid chunked encoding os.close (); requestData = null; is = connection.openInputStream (); if (debug) { bos = new ByteArrayOutputStream (); byte [] buf = new byte [256]; while (true) { int rd = is.read (buf, 0, 256); if (rd == -1) break; bos.write (buf, 0, rd); } buf = bos.toByteArray (); responseDump = new String (buf); is.close (); is = new ByteArrayInputStream (buf); } reader = new InputStreamReader (is); XmlParser xp = new XmlParser (reader); responseEnvelope.parse (xp); } finally { if (!connected) throw new InterruptedIOException (); reset (); } } /** * Executes a SOAP Method and returns a response * * @param method the remote soap method to be executed * @return the result of the soap method * @exception IOException if an error occurs */ public Object call (SoapObject method) throws IOException { requestEnvelope.setBody (method); call (); if (responseEnvelope.getBody () instanceof SoapFault) throw((SoapFault)responseEnvelope.getBody ()); return responseEnvelope.getResult (); } public void call (XmlIO request, XmlIO result) throws IOException { requestEnvelope.setBody (request); responseEnvelope.setBody (result); if (responseEnvelope.getBody () instanceof SoapFault) throw((SoapFault)responseEnvelope.getBody ()); } /** * Closes the connection and associated streams. This method * does not need to be explictly called since the uderlying * connections and streams are only opened and valid inside of * the call method. Close can be called ansynchronously, * from another thread to potentially release another thread * that is hung up doing network io inside of call. Caution * should be taken, however when using this as a psedu timeout * mechanism. it is a valid and suggested approach for the * motorola handsets. oh, and it works in the emulator... */ public void reset () { connected = false; if (reader != null) { try { reader.close (); } catch (Throwable e) { } reader = null; } if (is != null) { try { is.close (); } catch (Throwable e) { } is = null; } if (connection != null) { try { connection.close (); } catch (Throwable e) { } connection = null; } }}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -