📄 httptransport.java
字号:
/* Copyright (c) 2003,2004, Stefan Haustein, Oberhausen, Rhld., Germany
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* Contributor(s): John D. Beatty, Dave Dash, F. Hunter, Renaud Tognelli,
* Thomas Strang, Alexander Krebs, Sean McDaniel
* */
package org.ksoap2.transport;
import java.io.*;
import javax.microedition.io.*;
import org.ksoap2.*;
import org.xmlpull.v1.*;
/**
* 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 extends Transport {
ServiceConnection connection;
OutputStream os;
InputStream is;
/** state info */
private boolean connected = false;
/**
* Creates instance of HttpTransport with set url
*
* @param url
* the destination to POST SOAP data
*/
public HttpTransport(String url) {
super(url);
}
/**
* set the desired soapAction header field
*
* @param soapAction
* the desired soapAction
*/
public void call(String soapAction, SoapEnvelope envelope) throws IOException, XmlPullParserException {
if (soapAction == null)
soapAction = "\"\"";
byte[] requestData = createRequestData(envelope);
requestDump = debug ? new String(requestData) : null;
responseDump = null;
try {
connected = true;
connection = getServiceConnection();
connection.setRequestProperty("SOAPAction", soapAction);
connection.setRequestProperty("Content-Type", "text/xml");
connection.setRequestProperty("Content-Length", "" + requestData.length);
connection.setRequestProperty("User-Agent", "kSOAP/2.0");
connection.setRequestMethod(HttpConnection.POST);
os = connection.openOutputStream();
os.write(requestData, 0, requestData.length);
os.close();
requestData = null;
is = connection.openInputStream();
if (debug) {
ByteArrayOutputStream 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);
}
bos.flush();
buf = bos.toByteArray();
responseDump = new String(buf);
is.close();
is = new ByteArrayInputStream(buf);
}
parseResponse(envelope, is);
} finally {
if (!connected)
throw new InterruptedIOException();
reset();
}
if (envelope.bodyIn instanceof SoapFault)
throw ((SoapFault) envelope.bodyIn);
}
/**
* 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 (is != null) {
try {
is.close();
} catch (Throwable e) {
}
is = null;
}
if (connection != null) {
try {
connection.disconnect();
} catch (Throwable e) {
}
connection = null;
}
}
protected ServiceConnection getServiceConnection() throws IOException {
return new ServiceConnectionMidp(url);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -