├── .gitignore ├── ksoap2-base ├── .gitignore ├── src │ ├── main │ │ └── java │ │ │ └── org │ │ │ └── ksoap2 │ │ │ ├── serialization │ │ │ ├── package.html │ │ │ ├── FwdRef.java │ │ │ ├── AttributeInfo.java │ │ │ ├── MarshalDate.java │ │ │ ├── MarshalBase64.java │ │ │ ├── DM.java │ │ │ ├── KvmSerializable.java │ │ │ ├── Marshal.java │ │ │ ├── SoapPrimitive.java │ │ │ ├── MarshalHashtable.java │ │ │ ├── PropertyInfo.java │ │ │ └── SoapObject.java │ │ │ ├── package.html │ │ │ ├── transport │ │ │ ├── ServiceConnection.java │ │ │ └── Transport.java │ │ │ ├── SoapFault.java │ │ │ └── SoapEnvelope.java │ └── test │ │ └── java │ │ └── org │ │ └── ksoap2 │ │ ├── serialization │ │ ├── PropertyInfoTest.java │ │ ├── DMTest.java │ │ ├── SoapPrimitiveTest.java │ │ ├── MarshalDateTest.java │ │ ├── MarshalHashtableTest.java │ │ ├── MarshalBase64Test.java │ │ └── SoapObjectTest.java │ │ ├── transport │ │ ├── TransportTestCase.java │ │ └── mock │ │ │ ├── ComplexParameter.java │ │ │ ├── MockTransport.java │ │ │ ├── ComplexResponse.java │ │ │ ├── MockXmlSerializer.java │ │ │ └── MockXmlPullParser.java │ │ ├── SoapEnvelopeTest.java │ │ └── SoapFaultTest.java └── pom.xml ├── ksoap2-j2se ├── .gitignore ├── pom.xml └── src │ ├── test │ └── java │ │ └── org │ │ └── ksoap2 │ │ ├── transport │ │ └── HttpTransportSETest.java │ │ └── serialization │ │ └── MarshalFloatTest.java │ └── main │ └── java │ └── org │ └── ksoap2 │ ├── serialization │ └── MarshalFloat.java │ └── transport │ ├── ServiceConnectionSE.java │ └── HttpTransportSE.java ├── ksoap2-midp ├── .gitignore ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── ksoap2 │ └── transport │ ├── ServiceConnectionMidp.java │ └── HttpTransport.java ├── ksoap2-android ├── .gitignore ├── src │ ├── test │ │ └── java │ │ │ └── org │ │ │ └── ksoap2 │ │ │ └── NewApiSample.java │ └── main │ │ └── java │ │ └── org │ │ └── ksoap2 │ │ └── transport │ │ ├── AndroidServiceConnection.java │ │ └── AndroidHttpTransport.java └── pom.xml ├── ksoap2-extras ├── .gitignore ├── pom.xml └── src │ ├── test │ └── java │ │ └── org │ │ └── ksoap2 │ │ └── transport │ │ └── HttpTransportBasicAuthTest.java │ └── main │ └── java │ └── org │ └── ksoap2 │ └── transport │ └── HttpTransportBasicAuth.java ├── ksoap2-samples ├── .gitignore ├── src │ └── main │ │ └── java │ │ └── org │ │ └── ksoap2 │ │ └── samples │ │ ├── amazon │ │ ├── search │ │ │ ├── messages │ │ │ │ ├── BaseObject.java │ │ │ │ ├── Request.java │ │ │ │ ├── ItemSearchResponse.java │ │ │ │ ├── LiteralArrayVector.java │ │ │ │ ├── Book.java │ │ │ │ ├── BookItems.java │ │ │ │ └── BookAttributes.java │ │ │ └── AmazonSearchClient.java │ │ └── AmazonDemo.java │ │ ├── soccer │ │ ├── StadiumNamesResult.java │ │ ├── LiteralArrayVector.java │ │ └── WorldCupSoccer2006Client.java │ │ ├── axis │ │ └── quotes │ │ │ └── AxisStockQuoteExample.java │ │ └── quotes │ │ └── StockQuoteDemo.java └── pom.xml ├── ksoap2-servlet ├── .gitignore ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── ksoap2 │ └── servlet │ └── SoapServlet.java ├── ksoap2-samples-axis ├── .gitignore ├── src │ └── main │ │ ├── resources │ │ └── AxisService.wsdd │ │ └── java │ │ └── net │ │ └── wessendorf │ │ ├── ws │ │ ├── AxisService.java │ │ └── CustomObject.java │ │ └── j2me │ │ └── SoapDemo.java └── pom.xml ├── LICENSE.txt ├── ksoap2-android-assembly └── pom.xml ├── eclipseTemplates.xml └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Project output 2 | bin/ 3 | target*/ 4 | *.log 5 | 6 | # Project config files 7 | .settings/ 8 | .project 9 | .classpath 10 | 11 | -------------------------------------------------------------------------------- /ksoap2-base/.gitignore: -------------------------------------------------------------------------------- 1 | # Project output 2 | bin/ 3 | target*/ 4 | *.log 5 | 6 | # Project config files 7 | .settings/ 8 | .project 9 | .classpath 10 | 11 | -------------------------------------------------------------------------------- /ksoap2-j2se/.gitignore: -------------------------------------------------------------------------------- 1 | # Project output 2 | bin/ 3 | target*/ 4 | *.log 5 | 6 | # Project config files 7 | .settings/ 8 | .project 9 | .classpath 10 | 11 | -------------------------------------------------------------------------------- /ksoap2-midp/.gitignore: -------------------------------------------------------------------------------- 1 | # Project output 2 | bin/ 3 | target*/ 4 | *.log 5 | 6 | # Project config files 7 | .settings/ 8 | .project 9 | .classpath 10 | 11 | -------------------------------------------------------------------------------- /ksoap2-android/.gitignore: -------------------------------------------------------------------------------- 1 | # Project output 2 | bin/ 3 | target*/ 4 | *.log 5 | 6 | # Project config files 7 | .settings/ 8 | .project 9 | .classpath 10 | 11 | -------------------------------------------------------------------------------- /ksoap2-extras/.gitignore: -------------------------------------------------------------------------------- 1 | # Project output 2 | bin/ 3 | target*/ 4 | *.log 5 | 6 | # Project config files 7 | .settings/ 8 | .project 9 | .classpath 10 | 11 | -------------------------------------------------------------------------------- /ksoap2-samples/.gitignore: -------------------------------------------------------------------------------- 1 | # Project output 2 | bin/ 3 | target*/ 4 | *.log 5 | 6 | # Project config files 7 | .settings/ 8 | .project 9 | .classpath 10 | 11 | -------------------------------------------------------------------------------- /ksoap2-servlet/.gitignore: -------------------------------------------------------------------------------- 1 | # Project output 2 | bin/ 3 | target*/ 4 | *.log 5 | 6 | # Project config files 7 | .settings/ 8 | .project 9 | .classpath 10 | 11 | -------------------------------------------------------------------------------- /ksoap2-samples-axis/.gitignore: -------------------------------------------------------------------------------- 1 | # Project output 2 | bin/ 3 | target*/ 4 | *.log 5 | 6 | # Project config files 7 | .settings/ 8 | .project 9 | .classpath 10 | 11 | -------------------------------------------------------------------------------- /ksoap2-android/src/test/java/org/ksoap2/NewApiSample.java: -------------------------------------------------------------------------------- 1 | package org.ksoap2; 2 | 3 | /** 4 | * Just a scratchpad for some API ideas. 5 | */ 6 | public class NewApiSample 7 | { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /ksoap2-base/src/main/java/org/ksoap2/serialization/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 |This package contains support for the Soap Serialization 8 | specification. Please refer to the documentation of 9 | SoapSerializationEnvelope for more detailed information.
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /ksoap2-samples/src/main/java/org/ksoap2/samples/amazon/search/messages/BaseObject.java: -------------------------------------------------------------------------------- 1 | package org.ksoap2.samples.amazon.search.messages; 2 | 3 | import org.ksoap2.serialization.*; 4 | 5 | public abstract class BaseObject implements KvmSerializable { 6 | 7 | protected static final String NAMESPACE = "http://webservices.amazon.com/AWSECommerceService/2006-05-17"; 8 | 9 | public BaseObject() { 10 | super(); 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /ksoap2-samples-axis/src/main/resources/AxisService.wsdd: -------------------------------------------------------------------------------- 1 |This package contains basic classes required for 8 | handling SOAP Envelopes and literal XML content. 9 | Please refer to the documentation of SoapEnvelope 10 | for more detailed information.
11 | 12 |Support for the SOAP Serialization XML 13 | content format is contained in the package 14 | org.ksoap2.serialization. Support for performing 15 | SOAP calls via the network (sending and receiving 16 | SoapEnvelopes) is available in the package org 17 | .ksoap2.transport.
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /ksoap2-android/src/main/java/org/ksoap2/transport/AndroidServiceConnection.java: -------------------------------------------------------------------------------- 1 | package org.ksoap2.transport; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * This is a simple extension of the {@link HttpTransportSE} class. It provides the exact same functionality 7 | * as that class and is provided purely for backwards-compatibility purposes. It will likely be deprecated at 8 | * some point in the near future. 9 | */ 10 | public class AndroidServiceConnection extends ServiceConnectionSE 11 | { 12 | /** 13 | * @see ServiceConnectionSE#ServiceConnectionSE(String) 14 | */ 15 | public AndroidServiceConnection(String url) throws IOException 16 | { 17 | super(url); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ksoap2-base/src/test/java/org/ksoap2/serialization/PropertyInfoTest.java: -------------------------------------------------------------------------------- 1 | package org.ksoap2.serialization; 2 | 3 | import junit.framework.*; 4 | 5 | public class PropertyInfoTest extends TestCase { 6 | 7 | public void testClearingValues() { 8 | PropertyInfo info = new PropertyInfo(); 9 | info.type = new Integer(1); 10 | info.name = "propertyName"; 11 | info.namespace = "namespaceName"; 12 | info.flags = 12; 13 | 14 | info.clear(); 15 | 16 | assertEquals(PropertyInfo.OBJECT_CLASS, info.type); 17 | assertEquals(0, info.flags); 18 | assertEquals(null, info.name); 19 | assertEquals(null, info.namespace); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /ksoap2-samples/src/main/java/org/ksoap2/samples/soccer/StadiumNamesResult.java: -------------------------------------------------------------------------------- 1 | package org.ksoap2.samples.soccer; 2 | 3 | import org.ksoap2.serialization.*; 4 | 5 | public class StadiumNamesResult extends LiteralArrayVector { 6 | 7 | // in the resultant xml message, the array elements can 8 | // be described with different tags depending on a number 9 | // of factors (doc literal, rpc, etc...). This tells 10 | // our parent class to look for "string" 11 | protected String getItemDescriptor() { 12 | return "string"; 13 | } 14 | 15 | // This describes what type of objects are to be contained in the Array 16 | protected Class getElementClass() { 17 | return PropertyInfo.STRING_CLASS; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /ksoap2-samples-axis/pom.xml: -------------------------------------------------------------------------------- 1 |38 | * Instances of HttpTransport can be in one of two states: connected and not 39 | * connected. When an invocation on call is made the instance is in a connected 40 | * state until call returns or throws an IOException. in any case once control 41 | * is returned to the caller the instance is again in the not connected state. 42 | * HttpTransport is not thread safe and applications should ensure that only one 43 | * thread is inside the call method at any given time. It is designed in such a 44 | * way that applications can reuse a single instance for all soap calls to one, 45 | * or multiple, target endpoints. 46 | *
47 | * 48 | * The underlying HttpConnection is opened with the timeout flag set. In the 49 | * MIDP API this flag is only a hint to the underlying protocol handler to throw 50 | * an InterrruptIOException, however, there are no guarantees that it will be 51 | * handled. So rather than support a timeout mechanism internally the design is 52 | * such that applications can manage timeouts in an environment dependent way. 53 | *
54 | * 55 | * For example some environments may allow for a timeout parameter that can be 56 | * externally specified in perhaps a system property (which? I don't know. it's 57 | * in the api). Others like the emulator (ok, who cares) and the Motorola i85s 58 | * can use a simple and effective timeout mechanism that closes the connection 59 | * and associated streams in an asynchronous fashion. Calling the close( ) 60 | * method inside of a separate thread can provide for this timeout handling by 61 | * releasing threads that maybe stuck inside of call( ) performing network io. 62 | *
63 | *
64 | * Here is some sample code to demonstrate how such a timeout mechanism may
65 | * look:
66 | *
67 | *
68 | * private HttpTransport soap;
69 | * ...
70 | * TimerTask task =
71 | * new TimerTask( ) { public void run( ) { soap.close( ); } };
72 | *
73 | * try {
74 | * new Timer( ).schedule( task, TIMEOUT );
75 | * soap.call( soapobject ); // invoke method
76 | * task.cancel( ); // cancel the timeout
77 | *
78 | * } catch ( InterruptedIOException e ) {
79 | * // handle timeout here...
80 | *
81 | * } catch ( IOException e ) {
82 | * // some other io problem...
83 | * }
84 | *
85 | *
86 | *
92 | * Note: The InterruptedIOException will be caught by a thread waiting
93 | * on network io, however, it may not be immediate. It is assumed that the
94 | * protocol handler will gracefully handle the lifecycle of the outputstream and
95 | * therefore it is not closed inside the close method. IOW the waiting thread
96 | * will be interrupted after the outputstream has been flushed. If the waiting
97 | * thread is hung up waiting for input a call to close from a separate thread
98 | * the exception is observed right away and will return before the thread
99 | * calling close. At least this is what has been observation on the i85s
100 | * handset. On this device, if a call to outputstream.close( ) is made
101 | * while the outputstream is being flushed it seems to cause a deadlock, ie
102 | * outputstream will never return.
103 | */
104 |
105 | public class HttpTransport extends Transport {
106 | ServiceConnection connection;
107 | OutputStream os;
108 | InputStream is;
109 | /** state info */
110 | private boolean connected = false;
111 |
112 | /**
113 | * Creates instance of HttpTransport with set url
114 | *
115 | * @param url
116 | * the destination to POST SOAP data
117 | */
118 | public HttpTransport(String url) {
119 | super(url);
120 | }
121 |
122 | /**
123 | * set the desired soapAction header field
124 | *
125 | * @param soapAction
126 | * the desired soapAction
127 | */
128 | public void call(String soapAction, SoapEnvelope envelope) throws IOException, XmlPullParserException {
129 | if (soapAction == null)
130 | soapAction = "\"\"";
131 | byte[] requestData = createRequestData(envelope);
132 | requestDump = debug ? new String(requestData) : null;
133 | responseDump = null;
134 | try {
135 | connected = true;
136 | connection = getServiceConnection();
137 | connection.setRequestProperty("SOAPAction", soapAction);
138 | connection.setRequestProperty("Content-Type", "text/xml");
139 | connection.setRequestProperty("Content-Length", "" + requestData.length);
140 | connection.setRequestProperty("User-Agent", "kSOAP/2.0");
141 | connection.setRequestMethod(HttpConnection.POST);
142 | os = connection.openOutputStream();
143 | os.write(requestData, 0, requestData.length);
144 | os.close();
145 | requestData = null;
146 | is = connection.openInputStream();
147 | if (debug) {
148 | ByteArrayOutputStream bos = new ByteArrayOutputStream();
149 | byte[] buf = new byte[256];
150 | while (true) {
151 | int rd = is.read(buf, 0, 256);
152 | if (rd == -1)
153 | break;
154 | bos.write(buf, 0, rd);
155 | }
156 | bos.flush();
157 | buf = bos.toByteArray();
158 | responseDump = new String(buf);
159 | is.close();
160 | is = new ByteArrayInputStream(buf);
161 | }
162 | parseResponse(envelope, is);
163 | } finally {
164 | if (!connected)
165 | throw new InterruptedIOException();
166 | reset();
167 | }
168 | if (envelope.bodyIn instanceof SoapFault)
169 | throw ((SoapFault) envelope.bodyIn);
170 | }
171 |
172 | /**
173 | * Closes the connection and associated streams. This method does not need
174 | * to be explictly called since the uderlying connections and streams are
175 | * only opened and valid inside of the call method. Close can be called
176 | * ansynchronously, from another thread to potentially release another
177 | * thread that is hung up doing network io inside of call. Caution should be
178 | * taken, however when using this as a psedu timeout mechanism. it is a
179 | * valid and suggested approach for the motorola handsets. oh, and it works
180 | * in the emulator...
181 | */
182 | public void reset() {
183 | connected = false;
184 | if (is != null) {
185 | try {
186 | is.close();
187 | } catch (Throwable e) {
188 | }
189 | is = null;
190 | }
191 | if (connection != null) {
192 | try {
193 | connection.disconnect();
194 | } catch (Throwable e) {
195 | }
196 | connection = null;
197 | }
198 | }
199 |
200 | protected ServiceConnection getServiceConnection() throws IOException {
201 | return new ServiceConnectionMidp(url);
202 | }
203 |
204 | }
205 |
--------------------------------------------------------------------------------
/ksoap2-base/src/main/java/org/ksoap2/SoapEnvelope.java:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2003,2004, Stefan Haustein, Oberhausen, Rhld., Germany
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy
4 | * of this software and associated documentation files (the "Software"), to deal
5 | * in the Software without restriction, including without limitation the rights
6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 | * sell copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in
11 | * all copies or substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 | * IN THE SOFTWARE. */
20 |
21 | package org.ksoap2;
22 |
23 | import java.io.*;
24 | import org.kxml2.kdom.*;
25 | import org.xmlpull.v1.*;
26 |
27 | /**
28 | * A SOAP envelope, holding head and body objects. While this basic envelope
29 | * supports literal encoding as content format via KDom, The
30 | * SoapSerializationEnvelope provides support for the SOAP Serialization format
31 | * specification and simple object serialization.
32 | */
33 |
34 | public class SoapEnvelope {
35 |
36 | /** SOAP Version 1.0 constant */
37 | public static final int VER10 = 100;
38 | /** SOAP Version 1.1 constant */
39 | public static final int VER11 = 110;
40 | /** SOAP Version 1.2 constant */
41 | public static final int VER12 = 120;
42 | public static final String ENV2001 = "http://www.w3.org/2001/12/soap-envelope";
43 | public static final String ENC2001 = "http://www.w3.org/2001/12/soap-encoding";
44 | /** Namespace constant: http://schemas.xmlsoap.org/soap/envelope/ */
45 | public static final String ENV = "http://schemas.xmlsoap.org/soap/envelope/";
46 | /** Namespace constant: http://schemas.xmlsoap.org/soap/encoding/ */
47 | public static final String ENC = "http://schemas.xmlsoap.org/soap/encoding/";
48 | /** Namespace constant: http://www.w3.org/2001/XMLSchema */
49 | public static final String XSD = "http://www.w3.org/2001/XMLSchema";
50 | /** Namespace constant: http://www.w3.org/2001/XMLSchema */
51 | public static final String XSI = "http://www.w3.org/2001/XMLSchema-instance";
52 | /** Namespace constant: http://www.w3.org/1999/XMLSchema */
53 | public static final String XSD1999 = "http://www.w3.org/1999/XMLSchema";
54 | /** Namespace constant: http://www.w3.org/1999/XMLSchema */
55 | public static final String XSI1999 = "http://www.w3.org/1999/XMLSchema-instance";
56 |
57 | /**
58 | * Returns true for the string values "1" and "true", ignoring upper/lower
59 | * case and whitespace, false otherwise.
60 | */
61 | public static boolean stringToBoolean(String booleanAsString) {
62 | if (booleanAsString == null)
63 | return false;
64 | booleanAsString = booleanAsString.trim().toLowerCase();
65 | return (booleanAsString.equals("1") || booleanAsString.equals("true"));
66 | }
67 |
68 | /**
69 | * The body object received with this envelope. Will be an KDom Node for
70 | * literal encoding. For SOAP Serialization, please refer to
71 | * SoapSerializationEnvelope.
72 | */
73 | public Object bodyIn;
74 | /**
75 | * The body object to be sent with this envelope. Must be a KDom Node
76 | * modelling the remote call including all parameters for literal encoding.
77 | * For SOAP Serialization, please refer to SoapSerializationEnvelope
78 | */
79 | public Object bodyOut;
80 | /**
81 | * Incoming header elements
82 | */
83 | public Element[] headerIn;
84 | /**
85 | * Outgoing header elements
86 | */
87 | public Element[] headerOut;
88 | public String encodingStyle;
89 | /**
90 | * The SOAP version, set by the constructor
91 | */
92 | public int version;
93 | /** Envelope namespace, set by the constructor */
94 | public String env;
95 | /** Encoding namespace, set by the constructor */
96 | public String enc;
97 | /** Xml Schema instance namespace, set by the constructor */
98 | public String xsi;
99 | /** Xml Schema data namespace, set by the constructor */
100 | public String xsd;
101 |
102 | /**
103 | * Initializes a SOAP Envelope. The version parameter must be set to one of
104 | * VER10, VER11 or VER12
105 | */
106 | public SoapEnvelope(int version) {
107 | this.version = version;
108 | if (version == SoapEnvelope.VER10) {
109 | xsi = SoapEnvelope.XSI1999;
110 | xsd = SoapEnvelope.XSD1999;
111 | } else {
112 | xsi = SoapEnvelope.XSI;
113 | xsd = SoapEnvelope.XSD;
114 | }
115 | if (version < SoapEnvelope.VER12) {
116 | enc = SoapEnvelope.ENC;
117 | env = SoapEnvelope.ENV;
118 | } else {
119 | enc = SoapEnvelope.ENC2001;
120 | env = SoapEnvelope.ENV2001;
121 | }
122 | }
123 |
124 | /** Parses the SOAP envelope from the given parser */
125 | public void parse(XmlPullParser parser) throws IOException, XmlPullParserException {
126 | parser.nextTag();
127 | parser.require(XmlPullParser.START_TAG, env, "Envelope");
128 | encodingStyle = parser.getAttributeValue(env, "encodingStyle");
129 | parser.nextTag();
130 | if (parser.getEventType() == XmlPullParser.START_TAG && parser.getNamespace().equals(env) && parser.getName().equals("Header")) {
131 | parseHeader(parser);
132 | parser.require(XmlPullParser.END_TAG, env, "Header");
133 | parser.nextTag();
134 | }
135 | parser.require(XmlPullParser.START_TAG, env, "Body");
136 | encodingStyle = parser.getAttributeValue(env, "encodingStyle");
137 | parseBody(parser);
138 | parser.require(XmlPullParser.END_TAG, env, "Body");
139 | parser.nextTag();
140 | parser.require(XmlPullParser.END_TAG, env, "Envelope");
141 | }
142 |
143 | public void parseHeader(XmlPullParser parser) throws IOException, XmlPullParserException {
144 | // consume start header
145 | parser.nextTag();
146 | // look at all header entries
147 | Node headers = new Node();
148 | headers.parse(parser);
149 | int count = 0;
150 | for (int i = 0; i < headers.getChildCount(); i++) {
151 | Element child = headers.getElement(i);
152 | if (child != null)
153 | count++;
154 | }
155 | headerIn = new Element[count];
156 | count = 0;
157 | for (int i = 0; i < headers.getChildCount(); i++) {
158 | Element child = headers.getElement(i);
159 | if (child != null)
160 | headerIn[count++] = child;
161 | }
162 | }
163 |
164 | public void parseBody(XmlPullParser parser) throws IOException, XmlPullParserException {
165 | parser.nextTag();
166 | // insert fault generation code here
167 | if (parser.getEventType() == XmlPullParser.START_TAG && parser.getNamespace().equals(env) && parser.getName().equals("Fault")) {
168 | SoapFault fault = new SoapFault();
169 | fault.parse(parser);
170 | bodyIn = fault;
171 | } else {
172 | Node node = (bodyIn instanceof Node) ? (Node) bodyIn : new Node();
173 | node.parse(parser);
174 | bodyIn = node;
175 | }
176 | }
177 |
178 | /**
179 | * Writes the complete envelope including header and body elements to the
180 | * given XML writer.
181 | */
182 | public void write(XmlSerializer writer) throws IOException {
183 | writer.setPrefix("i", xsi);
184 | writer.setPrefix("d", xsd);
185 | writer.setPrefix("c", enc);
186 | writer.setPrefix("v", env);
187 | writer.startTag(env, "Envelope");
188 | writer.startTag(env, "Header");
189 | writeHeader(writer);
190 | writer.endTag(env, "Header");
191 | writer.startTag(env, "Body");
192 | writeBody(writer);
193 | writer.endTag(env, "Body");
194 | writer.endTag(env, "Envelope");
195 | }
196 |
197 | /**
198 | * Writes the header elements contained in headerOut
199 | */
200 | public void writeHeader(XmlSerializer writer) throws IOException {
201 | if (headerOut != null) {
202 | for (int i = 0; i < headerOut.length; i++) {
203 | headerOut[i].write(writer);
204 | }
205 | }
206 | }
207 |
208 | /**
209 | * Writes the SOAP body stored in the object variable bodyIn, Overwrite this
210 | * method for customized writing of the soap message body.
211 | */
212 | public void writeBody(XmlSerializer writer) throws IOException {
213 | if (encodingStyle != null)
214 | writer.attribute(env, "encodingStyle", encodingStyle);
215 | ((Node) bodyOut).write(writer);
216 | }
217 |
218 | /**
219 | * Assigns the object to the envelope as the outbound message for the soap call.
220 | * @param soapObject the object to send in the soap call.
221 | */
222 | public void setOutputSoapObject(Object soapObject) {
223 | bodyOut = soapObject;
224 | }
225 |
226 | }
227 |
--------------------------------------------------------------------------------
/ksoap2-servlet/src/main/java/org/ksoap2/servlet/SoapServlet.java:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2003,2004, Stefan Haustein, Oberhausen, Rhld., Germany
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy
4 | * of this software and associated documentation files (the "Software"), to deal
5 | * in the Software without restriction, including without limitation the rights
6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 | * sell copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in
11 | * all copies or substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 | * IN THE SOFTWARE. */
20 |
21 | package org.ksoap2.servlet;
22 |
23 | import java.io.ByteArrayInputStream;
24 | import java.io.IOException;
25 | import java.io.StringWriter;
26 | import java.io.Writer;
27 | import java.lang.reflect.InvocationTargetException;
28 | import java.lang.reflect.Method;
29 | import java.lang.reflect.Modifier;
30 | import java.util.Hashtable;
31 |
32 | import javax.servlet.ServletException;
33 | import javax.servlet.http.HttpServlet;
34 | import javax.servlet.http.HttpServletRequest;
35 | import javax.servlet.http.HttpServletResponse;
36 |
37 | import org.ksoap2.SoapFault;
38 | import org.ksoap2.serialization.PropertyInfo;
39 | import org.ksoap2.serialization.SoapObject;
40 | import org.ksoap2.serialization.SoapSerializationEnvelope;
41 | import org.kxml2.io.KXmlParser;
42 | import org.kxml2.io.KXmlSerializer;
43 | import org.xmlpull.v1.XmlPullParser;
44 | import org.xmlpull.v1.XmlSerializer;
45 |
46 | /**
47 | * copy-paste seans interop server orb here as needed....
48 | *
49 | * some design issues: - path and soapaction are not considered. soapaction is
50 | * deprecated; for multiple paths, please use multiple servlets.
51 | */
52 |
53 | public class SoapServlet extends HttpServlet {
54 |
55 | SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapSerializationEnvelope.VER12);
56 | /** static mapping paths -> objects */
57 | Hashtable instanceMap = new Hashtable();
58 |
59 | /**
60 | * the default operation is to map request.getPathInfo to an instance using
61 | * the information given by buildInstance. The returned instance is used as
62 | * target object for the method invocation. Please overwrite this method in
63 | * order to define your own (generic) mapping. If no mapping is found, the
64 | * servlet itself is returned.
65 | */
66 | protected Object getInstance(HttpServletRequest request) {
67 | if (request.getPathInfo() == null)
68 | return this;
69 | Object result = instanceMap.get(request.getPathInfo());
70 | return (result != null) ? result : this;
71 | }
72 |
73 | /** Publish all public methods of the given class */
74 | public void publishClass(Class service, String namespace) {
75 | Method[] methods = service.getMethods();
76 | for (int i = 0; i < methods.length; i++) {
77 | if (Modifier.isPublic(methods[i].getModifiers())) {
78 | Class[] types = methods[i].getParameterTypes();
79 | PropertyInfo[] info = new PropertyInfo[types.length];
80 | for (int j = 0; j < types.length; j++) {
81 | info[j] = new PropertyInfo();
82 | info[j].type = types[j];
83 | }
84 | publishMethod(service, namespace, methods[i].getName(), info);
85 | }
86 | }
87 | }
88 |
89 | /**
90 | * publish an instance by associating the instance with the given local
91 | * path. Please note that (currently) also the methods need to be published
92 | * separateley. Alternatively to this call, it is also possible to overwrite
93 | * the getObject (HttpRequest request) method
94 | */
95 | public void publishInstance(String path, Object instance) {
96 | instanceMap.put(path, instance);
97 | }
98 |
99 | /**
100 | * publish a method. Please note that also a corresponding instance needs to
101 | * be published, either calling publishInstance or by overwriting
102 | * getInstance (), except when the method is a method of the servlet itself.
103 | */
104 |
105 | public void publishMethod(Class service, String namespace, String name, PropertyInfo[] parameters) {
106 | SoapObject template = new SoapObject(namespace, name);
107 | for (int i = 0; i < parameters.length; i++)
108 | template.addProperty(parameters[i], null);
109 | envelope.addTemplate(template);
110 | }
111 |
112 | /**
113 | * convenience method; use this method if the paremeter types can be
114 | * obtained via reflection
115 | */
116 | public void publishMethod(Class service, String namespace, String name, String[] parameterNames) {
117 | // find a fitting method
118 | Method[] methods = service.getMethods();
119 | for (int i = 0; i < methods.length; i++) {
120 | if (methods[i].getName().equals(name) && methods[i].getParameterTypes().length == parameterNames.length) {
121 | Class[] types = methods[i].getParameterTypes();
122 | PropertyInfo[] info = new PropertyInfo[types.length];
123 | for (int j = 0; j < types.length; j++) {
124 | info[j] = new PropertyInfo();
125 | info[j].name = parameterNames[j];
126 | info[j].type = types[j];
127 | }
128 | publishMethod(service, namespace, name, info);
129 | return;
130 | }
131 | }
132 | throw new RuntimeException("Method not found!");
133 | }
134 |
135 | public SoapSerializationEnvelope getEnvelope() {
136 | return envelope;
137 | }
138 |
139 | /**
140 | * Please note: The classMap should not be set after publishing methods,
141 | * because parameter type information may get lost!
142 | */
143 | public void setEnvelope(SoapSerializationEnvelope envelope) {
144 | this.envelope = envelope;
145 | }
146 |
147 | /**
148 | * In order to filter requests, please overwrite doPost and call super for
149 | * soap requests only
150 | */
151 | public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
152 | try {
153 | Object service = getInstance(req);
154 | XmlPullParser parser = new KXmlParser();
155 | if ( false ) {
156 | //parser.setInput(req.getInputStream(), req.getCharacterEncoding());
157 | }
158 | else {
159 | byte[] inputRequest = new byte[req.getInputStream().available()];
160 | req.getInputStream().read(inputRequest);
161 | System.out.println ("Request: " + new String(inputRequest));
162 | ByteArrayInputStream bas = new ByteArrayInputStream(inputRequest);
163 | parser.setInput(bas, null);
164 | }
165 | parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
166 | envelope.parse(parser);
167 | SoapObject soapReq = (SoapObject) envelope.bodyIn;
168 | SoapObject result = invoke(service, soapReq);
169 | System.out.println("result: " + result);
170 | envelope.bodyOut = result;
171 | } catch (SoapFault f) {
172 | f.printStackTrace();
173 | envelope.bodyOut = f;
174 | res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
175 | } catch (Throwable t) {
176 | t.printStackTrace();
177 | SoapFault fault = new SoapFault();
178 | fault.faultcode = "Server";
179 | fault.faultstring = t.getMessage();
180 | envelope.bodyOut = fault;
181 | res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
182 | } finally {
183 | res.setContentType("text/xml; charset=utf-8");
184 | res.setHeader("Connection", "close");
185 | StringWriter sw = new StringWriter();
186 | XmlSerializer writer = new KXmlSerializer();
187 | writer.setOutput(sw);
188 | try {
189 | envelope.write(writer);
190 | } catch (Exception e) {
191 | e.printStackTrace();
192 | }
193 | writer.flush();
194 | System.out.println("result xml: " + sw);
195 | Writer w = res.getWriter();
196 | w.write(sw.toString());
197 | w.close();
198 | }
199 | res.flushBuffer();
200 | }
201 |
202 | protected SoapObject invoke(Object service, SoapObject soapReq) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
203 | String name = soapReq.getName();
204 | Class types[] = new Class[soapReq.getPropertyCount()];
205 | Object[] args = new Object[soapReq.getPropertyCount()];
206 | PropertyInfo arg = new PropertyInfo();
207 | Hashtable properties = new Hashtable();
208 | for (int i = 0; i < types.length; i++) {
209 | soapReq.getPropertyInfo(i, properties, arg);
210 | types[i] = (Class) arg.type;
211 | args[i] = soapReq.getProperty(i);
212 | }
213 | // expensive invocation here.. optimize with method cache,
214 | // want to support method overloading so need to figure in
215 | // the arg types..
216 | Method method = service.getClass().getMethod(name, types);
217 | Object result = method.invoke(service, args);
218 | System.out.println("result:" + result);
219 | SoapObject response = new SoapObject(soapReq.getNamespace(), name + "Response");
220 | if (result != null)
221 | response.addProperty("return", result);
222 | return response;
223 | }
224 |
225 | }
226 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 | SoapObject instance.
48 | *
49 | * @param namespace
50 | * the namespace for the soap object
51 | * @param name
52 | * the name of the soap object
53 | */
54 |
55 | public SoapObject(String namespace, String name)
56 | {
57 | this.namespace = namespace;
58 | this.name = name;
59 | }
60 |
61 | public boolean equals(Object obj)
62 | {
63 | if (!(obj instanceof SoapObject))
64 | return false;
65 |
66 | SoapObject otherSoapObject = (SoapObject) obj;
67 |
68 | int numProperties = properties.size();
69 | if (numProperties != otherSoapObject.properties.size())
70 | return false;
71 | int numAttributes = attributes.size();
72 | if (numAttributes != otherSoapObject.attributes.size())
73 | return false;
74 |
75 | try
76 | {
77 | for (int propIndex = 0; propIndex < numProperties; propIndex++)
78 | {
79 | PropertyInfo thisProp = (PropertyInfo) this.properties.elementAt(propIndex);
80 | Object thisPropValue = thisProp.getValue();
81 | Object otherPropValue = otherSoapObject.getProperty(thisProp.getName());
82 | if (!thisPropValue.equals(otherPropValue))
83 | {
84 | return false;
85 | }
86 | }
87 | for (int attribIndex = 0; attribIndex < numAttributes; attribIndex++)
88 | {
89 | AttributeInfo thisAttrib = (AttributeInfo) this.properties.elementAt(attribIndex);
90 | Object thisAttribValue = thisAttrib.getValue();
91 | Object otherAttribValue = otherSoapObject.getProperty(thisAttrib.getName());
92 | if (!thisAttribValue.equals(otherAttribValue))
93 | {
94 | return false;
95 | }
96 | }
97 | }
98 | catch (Exception e)
99 | {
100 | return false;
101 | }
102 | return true;
103 | }
104 |
105 | public String getName()
106 | {
107 | return name;
108 | }
109 |
110 | public String getNamespace()
111 | {
112 | return namespace;
113 | }
114 |
115 | /**
116 | * Returns a specific property at a certain index.
117 | *
118 | * @param index
119 | * the index of the desired property
120 | * @return the desired property
121 | */
122 | public Object getProperty(int index)
123 | {
124 | return ((PropertyInfo) properties.elementAt(index)).getValue();
125 | }
126 |
127 | public Object getProperty(String name)
128 | {
129 | for (int i = 0; i < properties.size(); i++)
130 | {
131 | if (name.equals(((PropertyInfo) properties.elementAt(i)).getName()))
132 | return getProperty(i);
133 | }
134 | throw new RuntimeException("illegal property: " + name);
135 | }
136 |
137 | /**
138 | * Returns the number of properties
139 | *
140 | * @return the number of properties
141 | */
142 | public int getPropertyCount()
143 | {
144 | return properties.size();
145 | }
146 |
147 | /**
148 | * Places AttributeInfo of desired attribute into a designated AttributeInfo object
149 | *
150 | * @param index
151 | * index of desired attribute
152 | * @param propertyInfo
153 | * designated retainer of desired attribute
154 | */
155 | public void getAttributeInfo(int index, AttributeInfo attributeInfo)
156 | {
157 | AttributeInfo p = (AttributeInfo) attributes.elementAt(index);
158 | attributeInfo.name = p.name;
159 | attributeInfo.namespace = p.namespace;
160 | attributeInfo.flags = p.flags;
161 | attributeInfo.type = p.type;
162 | attributeInfo.elementType = p.elementType;
163 | attributeInfo.value = p.getValue();
164 | }
165 |
166 | /**
167 | * Returns a specific attribute at a certain index.
168 | *
169 | * @param index
170 | * the index of the desired attribute
171 | * @return the value of the desired attribute
172 | *
173 | */
174 | public Object getAttribute(int index)
175 | {
176 | return ((AttributeInfo) attributes.elementAt(index)).getValue();
177 | }
178 |
179 | /** Returns a property with the given name. */
180 | public Object getAttribute(String name)
181 | {
182 | for (int i = 0; i < attributes.size(); i++)
183 | {
184 | if (name.equals(((AttributeInfo) attributes.elementAt(i)).getName()))
185 | return getAttribute(i);
186 | }
187 | throw new RuntimeException("illegal property: " + name);
188 | }
189 |
190 | /**
191 | * Returns the number of attributes
192 | *
193 | * @return the number of attributes
194 | */
195 | public int getAttributeCount()
196 | {
197 | return attributes.size();
198 | }
199 |
200 | /**
201 | * Places PropertyInfo of desired property into a designated PropertyInfo object
202 | *
203 | * @param index
204 | * index of desired property
205 | * @param propertyInfo
206 | * designated retainer of desired property
207 | * @deprecated
208 | */
209 | public void getPropertyInfo(int index, Hashtable properties, PropertyInfo propertyInfo)
210 | {
211 | getPropertyInfo(index, propertyInfo);
212 | }
213 |
214 | /**
215 | * Places PropertyInfo of desired property into a designated PropertyInfo object
216 | *
217 | * @param index
218 | * index of desired property
219 | * @param propertyInfo
220 | * designated retainer of desired property
221 | */
222 | public void getPropertyInfo(int index, PropertyInfo propertyInfo)
223 | {
224 | PropertyInfo p = (PropertyInfo) properties.elementAt(index);
225 | propertyInfo.name = p.name;
226 | propertyInfo.namespace = p.namespace;
227 | propertyInfo.flags = p.flags;
228 | propertyInfo.type = p.type;
229 | propertyInfo.elementType = p.elementType;
230 | }
231 |
232 | /**
233 | * Creates a new SoapObject based on this, allows usage of SoapObjects as templates. One application is to
234 | * set the expected return type of a soap call if the server does not send explicit type information.
235 | *
236 | * @return a copy of this.
237 | */
238 | public SoapObject newInstance()
239 | {
240 | SoapObject o = new SoapObject(namespace, name);
241 | for (int propIndex = 0; propIndex < properties.size(); propIndex++)
242 | {
243 | PropertyInfo propertyInfo = (PropertyInfo) properties.elementAt(propIndex);
244 | o.addProperty(propertyInfo);
245 | }
246 | for (int attribIndex = 0; attribIndex < attributes.size(); attribIndex++)
247 | {
248 | AttributeInfo attributeInfo = (AttributeInfo) attributes.elementAt(attribIndex);
249 | o.addAttribute(attributeInfo);
250 | }
251 | return o;
252 | }
253 |
254 | /**
255 | * Sets a specified property to a certain value.
256 | *
257 | * @param index
258 | * the index of the specified property
259 | * @param value
260 | * the new value of the property
261 | */
262 | public void setProperty(int index, Object value)
263 | {
264 | ((PropertyInfo) properties.elementAt(index)).setValue(value);
265 | }
266 |
267 | /**
268 | * Adds a property (parameter) to the object. This is essentially a sub element.
269 | *
270 | * @param name
271 | * The name of the property
272 | * @param value
273 | * the value of the property
274 | */
275 | public SoapObject addProperty(String name, Object value)
276 | {
277 | PropertyInfo propertyInfo = new PropertyInfo();
278 | propertyInfo.name = name;
279 | propertyInfo.type = value == null ? PropertyInfo.OBJECT_CLASS : value.getClass();
280 | propertyInfo.value = value;
281 | return addProperty(propertyInfo);
282 | }
283 |
284 | /**
285 | * Adds a property (parameter) to the object. This is essentially a sub element.
286 | *
287 | * @param propertyInfo
288 | * designated retainer of desired property
289 | * @param value
290 | * the value of the property
291 | * @deprecated property info now contains the value
292 | */
293 | public SoapObject addProperty(PropertyInfo propertyInfo, Object value)
294 | {
295 | propertyInfo.setValue(value);
296 | addProperty(propertyInfo);
297 | return this;
298 | }
299 |
300 | /**
301 | * Adds a property (parameter) to the object. This is essentially a sub element.
302 | *
303 | * @param propertyInfo
304 | * designated retainer of desired property
305 | */
306 | public SoapObject addProperty(PropertyInfo propertyInfo)
307 | {
308 | properties.addElement(propertyInfo);
309 | return this;
310 | }
311 |
312 | /**
313 | * Adds a attribute (parameter) to the object. This is essentially a sub element.
314 | *
315 | * @param name
316 | * The name of the attribute
317 | * @param value
318 | * the value of the attribute
319 | */
320 | public SoapObject addAttribute(String name, Object value)
321 | {
322 | AttributeInfo attributeInfo = new AttributeInfo();
323 | attributeInfo.name = name;
324 | attributeInfo.type = value == null ? PropertyInfo.OBJECT_CLASS : value.getClass();
325 | attributeInfo.value = value;
326 | return addAttribute(attributeInfo);
327 | }
328 |
329 | /**
330 | * Adds a attribute (parameter) to the object. This is essentially a sub element.
331 | *
332 | * @param propertyInfo
333 | * designated retainer of desired attribute
334 | */
335 | public SoapObject addAttribute(AttributeInfo attributeInfo)
336 | {
337 | attributes.addElement(attributeInfo);
338 | return this;
339 | }
340 |
341 | public String toString()
342 | {
343 | StringBuffer buf = new StringBuffer("" + name + "{");
344 | for (int i = 0; i < getPropertyCount(); i++)
345 | {
346 | buf.append("" + ((PropertyInfo) properties.elementAt(i)).getName() + "=" + getProperty(i) + "; ");
347 | }
348 | buf.append("}");
349 | return buf.toString();
350 | }
351 |
352 | }
353 |
--------------------------------------------------------------------------------