2970 lines
116 KiB
Diff
2970 lines
116 KiB
Diff
From b5b548a4be9f1ced6f5599b62765216f9ab8af00 Mon Sep 17 00:00:00 2001
|
|
From: Ecco Park <eccopark@google.com>
|
|
Date: Tue, 8 May 2018 13:44:14 -0700
|
|
Subject: [PATCH 1/1] ksoap2 update
|
|
|
|
Change-Id: Iace4c0f3cb31c9532c5fa0c44c2dc863bd81b23e
|
|
Signed-off-by: Ecco Park <eccopark@google.com>
|
|
---
|
|
.../main/java/org/ksoap2/SoapEnvelope.java | 17 +-
|
|
.../src/main/java/org/ksoap2/SoapFault12.java | 13 +-
|
|
.../serialization/AttributeContainer.java | 128 +++++-
|
|
.../java/org/ksoap2/serialization/DM.java | 57 ++-
|
|
.../ksoap2/serialization/HasAttributes.java | 16 +
|
|
.../ksoap2/serialization/HasInnerText.java | 17 +
|
|
.../ksoap2/serialization/KvmSerializable.java | 25 +-
|
|
.../org/ksoap2/serialization/Marshal.java | 3 +-
|
|
.../ksoap2/serialization/MarshalBase64.java | 3 +-
|
|
.../org/ksoap2/serialization/MarshalDate.java | 3 +-
|
|
.../serialization/MarshalHashtable.java | 8 +-
|
|
.../org/ksoap2/serialization/SoapObject.java | 340 +++++++++++++-
|
|
.../ksoap2/serialization/SoapPrimitive.java | 20 +-
|
|
.../SoapSerializationEnvelope.java | 419 ++++++++++++------
|
|
.../org/ksoap2/serialization/ValueWriter.java | 13 +
|
|
.../ksoap2/transport/ServiceConnection.java | 13 +-
|
|
.../java/org/ksoap2/transport/Transport.java | 131 ++++--
|
|
.../ksoap2/serialization/MarshalFloat.java | 3 +-
|
|
.../transport/HttpResponseException.java | 60 +++
|
|
.../org/ksoap2/transport/HttpTransportSE.java | 348 +++++++--------
|
|
.../transport/HttpsServiceConnectionSE.java | 58 ++-
|
|
.../ksoap2/transport/HttpsTransportSE.java | 81 ++--
|
|
.../transport/KeepAliveHttpsTransportSE.java | 20 +-
|
|
.../ksoap2/transport/ServiceConnectionSE.java | 44 +-
|
|
24 files changed, 1298 insertions(+), 542 deletions(-)
|
|
create mode 100644 ksoap2-base/src/main/java/org/ksoap2/serialization/HasAttributes.java
|
|
create mode 100644 ksoap2-base/src/main/java/org/ksoap2/serialization/HasInnerText.java
|
|
create mode 100644 ksoap2-base/src/main/java/org/ksoap2/serialization/ValueWriter.java
|
|
create mode 100644 ksoap2-j2se/src/main/java/org/ksoap2/transport/HttpResponseException.java
|
|
|
|
diff --git a/ksoap2-base/src/main/java/org/ksoap2/SoapEnvelope.java b/ksoap2-base/src/main/java/org/ksoap2/SoapEnvelope.java
|
|
index 8a0b894..1c43656 100644
|
|
--- a/ksoap2-base/src/main/java/org/ksoap2/SoapEnvelope.java
|
|
+++ b/ksoap2-base/src/main/java/org/ksoap2/SoapEnvelope.java
|
|
@@ -54,10 +54,8 @@ public class SoapEnvelope {
|
|
/** Namespace constant: http://www.w3.org/1999/XMLSchema */
|
|
public static final String XSI1999 = "http://www.w3.org/1999/XMLSchema-instance";
|
|
|
|
- //public static final String NS20 = "http://www.wi-fi-org/specifications/hotspot2dot0/spp/1.0/";
|
|
public static final String NS20 = "http://www.wi-fi.org/specifications/hotspot2dot0/v1.0/spp";
|
|
|
|
- //public static final String OMADM12 = "http://www.openmobilealliance.org/tech/DTD/dm_ddf-v1_2.dtd";
|
|
|
|
/**
|
|
* Returns true for the string values "1" and "true", ignoring upper/lower
|
|
@@ -105,9 +103,8 @@ public class SoapEnvelope {
|
|
/** Xml Schema data namespace, set by the constructor */
|
|
public String xsd;
|
|
|
|
- ///M: HS20 Add by Jungo
|
|
+ // HS20 change
|
|
public String ns;
|
|
- public String omadm;
|
|
|
|
/**
|
|
* Initializes a SOAP Envelope. The version parameter must be set to one of
|
|
@@ -129,10 +126,8 @@ public class SoapEnvelope {
|
|
enc = SoapEnvelope.ENC2003;
|
|
env = SoapEnvelope.ENV2003;
|
|
}
|
|
-
|
|
+ // HS20 change
|
|
ns = SoapEnvelope.NS20;
|
|
- //omadm = SoapEnvelope.OMADM12;
|
|
-
|
|
}
|
|
|
|
/** Parses the SOAP envelope from the given parser */
|
|
@@ -206,13 +201,9 @@ public class SoapEnvelope {
|
|
* given XML writer.
|
|
*/
|
|
public void write(XmlSerializer writer) throws IOException {
|
|
- ///M: HS20 modify by Jungo
|
|
- //writer.setPrefix("i", xsi);
|
|
- //writer.setPrefix("d", xsd);
|
|
- //writer.setPrefix("c", enc);
|
|
- writer.setPrefix("soap", env);//the prefix for namespace env in xml output
|
|
+ // HS 2.0 changes
|
|
+ writer.setPrefix("soap", env); //the prefix for namespace env in xml output
|
|
writer.setPrefix("spp", ns);
|
|
- //writer.setPrefix("omadm", omadm);
|
|
|
|
writer.startTag(env, "Envelope");
|
|
writer.startTag(env, "Header");
|
|
diff --git a/ksoap2-base/src/main/java/org/ksoap2/SoapFault12.java b/ksoap2-base/src/main/java/org/ksoap2/SoapFault12.java
|
|
index 5667cb4..3f39147 100644
|
|
--- a/ksoap2-base/src/main/java/org/ksoap2/SoapFault12.java
|
|
+++ b/ksoap2-base/src/main/java/org/ksoap2/SoapFault12.java
|
|
@@ -72,27 +72,28 @@ public class SoapFault12 extends SoapFault {
|
|
|
|
while (parser.nextTag() == XmlPullParser.START_TAG) {
|
|
String name = parser.getName();
|
|
+ String namespace = parser.getNamespace();
|
|
parser.nextTag();
|
|
- if (name.equals("Code")) {
|
|
+ if (name.toLowerCase().equals("Code".toLowerCase())) {
|
|
this.Code = new Node();
|
|
this.Code.parse(parser);
|
|
- } else if (name.equals("Reason")) {
|
|
+ } else if (name.toLowerCase().equals("Reason".toLowerCase())) {
|
|
this.Reason = new Node();
|
|
this.Reason.parse(parser);
|
|
- } else if (name.equals("Node")) {
|
|
+ } else if (name.toLowerCase().equals("Node".toLowerCase())) {
|
|
this.Node = new Node();
|
|
this.Node.parse(parser);
|
|
- } else if (name.equals("Role")) {
|
|
+ } else if (name.toLowerCase().equals("Role".toLowerCase())) {
|
|
this.Role = new Node();
|
|
this.Role.parse(parser);
|
|
- } else if (name.equals("Detail")) {
|
|
+ } else if (name.toLowerCase().equals("Detail".toLowerCase())) {
|
|
this.Detail = new Node();
|
|
this.Detail.parse(parser);
|
|
} else {
|
|
throw new RuntimeException("unexpected tag:" + name);
|
|
}
|
|
|
|
- parser.require(XmlPullParser.END_TAG, SoapEnvelope.ENV2003, name);
|
|
+ parser.require(XmlPullParser.END_TAG, namespace, name);
|
|
}
|
|
parser.require(XmlPullParser.END_TAG, SoapEnvelope.ENV2003, "Fault");
|
|
parser.nextTag();
|
|
diff --git a/ksoap2-base/src/main/java/org/ksoap2/serialization/AttributeContainer.java b/ksoap2-base/src/main/java/org/ksoap2/serialization/AttributeContainer.java
|
|
index 6b83847..34d2723 100644
|
|
--- a/ksoap2-base/src/main/java/org/ksoap2/serialization/AttributeContainer.java
|
|
+++ b/ksoap2-base/src/main/java/org/ksoap2/serialization/AttributeContainer.java
|
|
@@ -3,8 +3,8 @@ package org.ksoap2.serialization;
|
|
|
|
import java.util.Vector;
|
|
|
|
-public class AttributeContainer {
|
|
- private Vector attributes = new Vector();
|
|
+public class AttributeContainer implements HasAttributes{
|
|
+ protected Vector attributes = new Vector();
|
|
|
|
/**
|
|
* Places AttributeInfo of desired attribute into a designated AttributeInfo object
|
|
@@ -29,9 +29,9 @@ public class AttributeContainer {
|
|
return ((AttributeInfo) attributes.elementAt(index)).getValue();
|
|
}
|
|
|
|
- /**
|
|
- * Get the attribute's toString value.
|
|
- */
|
|
+ /**
|
|
+ * Get the attribute's toString value.
|
|
+ */
|
|
public String getAttributeAsString(int index) {
|
|
AttributeInfo attributeInfo = (AttributeInfo) attributes.elementAt(index);
|
|
return attributeInfo.getValue().toString();
|
|
@@ -51,6 +51,20 @@ public class AttributeContainer {
|
|
}
|
|
}
|
|
|
|
+ /**
|
|
+ * Get the attribute with the given name
|
|
+ *
|
|
+ * @throws RuntimeException if the attribute does not exist
|
|
+ */
|
|
+ public Object getAttribute(String namespace,String name) {
|
|
+ Integer i = attributeIndex(namespace,name);
|
|
+ if (i != null) {
|
|
+ return getAttribute(i.intValue());
|
|
+ } else {
|
|
+ throw new RuntimeException("illegal property: " + name);
|
|
+ }
|
|
+ }
|
|
+
|
|
/**
|
|
* Get the toString value of the attribute with the given name.
|
|
*
|
|
@@ -65,6 +79,19 @@ public class AttributeContainer {
|
|
}
|
|
}
|
|
|
|
+ /**
|
|
+ * Get the toString value of the attribute with the given name.
|
|
+ *
|
|
+ * @throws RuntimeException if the attribute does not exist
|
|
+ */
|
|
+ public String getAttributeAsString(String namespace,String name) {
|
|
+ Integer i = attributeIndex(namespace,name);
|
|
+ if (i != null) {
|
|
+ return getAttribute(i.intValue()).toString();
|
|
+ } else {
|
|
+ throw new RuntimeException("illegal property: " + name);
|
|
+ }
|
|
+ }
|
|
/**
|
|
* Knows whether the given attribute exists
|
|
*/
|
|
@@ -76,6 +103,16 @@ public class AttributeContainer {
|
|
}
|
|
}
|
|
|
|
+ /**
|
|
+ * Knows whether the given attribute exists
|
|
+ */
|
|
+ public boolean hasAttribute(final String namespace,final String name) {
|
|
+ if (attributeIndex(namespace,name) != null) {
|
|
+ return true;
|
|
+ } else {
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
/**
|
|
* Get an attribute without chance of throwing an exception
|
|
*
|
|
@@ -91,6 +128,21 @@ public class AttributeContainer {
|
|
}
|
|
}
|
|
|
|
+ /**
|
|
+ * Get an attribute without chance of throwing an exception
|
|
+ *
|
|
+ * @param name the name of the attribute to retrieve
|
|
+ * @return the value of the attribute if it exists; {@code null} if it does not exist
|
|
+ */
|
|
+ public Object getAttributeSafely(String namespace,String name) {
|
|
+ Integer i = attributeIndex(namespace,name);
|
|
+ if (i != null) {
|
|
+ return getAttribute(i.intValue());
|
|
+ } else {
|
|
+ return null;
|
|
+ }
|
|
+ }
|
|
+
|
|
/**
|
|
* Get an attributes' toString value without chance of throwing an
|
|
* exception.
|
|
@@ -108,6 +160,23 @@ public class AttributeContainer {
|
|
}
|
|
}
|
|
|
|
+ /**
|
|
+ * Get an attributes' toString value without chance of throwing an
|
|
+ * exception.
|
|
+
|
|
+ * @param name
|
|
+ * @return the value of the attribute,s toString method if it exists; ""
|
|
+ * if it does not exist
|
|
+ */
|
|
+ public Object getAttributeSafelyAsString(String namespace,String name) {
|
|
+ Integer i = attributeIndex(namespace,name);
|
|
+ if (i != null) {
|
|
+ return getAttribute(i.intValue()).toString();
|
|
+ } else {
|
|
+ return "";
|
|
+ }
|
|
+ }
|
|
+
|
|
private Integer attributeIndex(String name) {
|
|
for (int i = 0; i < attributes.size(); i++) {
|
|
if (name.equals(((AttributeInfo) attributes.elementAt(i)).getName())) {
|
|
@@ -117,6 +186,16 @@ public class AttributeContainer {
|
|
return null;
|
|
}
|
|
|
|
+ private Integer attributeIndex(String namespace,String name) {
|
|
+ for (int i = 0; i < attributes.size(); i++) {
|
|
+ AttributeInfo attrInfo=(AttributeInfo) attributes.elementAt(i);
|
|
+ if (name.equals(attrInfo.getName()) && namespace.equals(attrInfo.getNamespace())) {
|
|
+ return new Integer(i);
|
|
+ }
|
|
+ }
|
|
+ return null;
|
|
+ }
|
|
+
|
|
/**
|
|
* Returns the number of attributes
|
|
*
|
|
@@ -160,13 +239,25 @@ public class AttributeContainer {
|
|
* @return {@code this} object.
|
|
*/
|
|
public void addAttribute(String name, Object value) {
|
|
+ addAttribute(null,name,value);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Adds a attribute (parameter) to the object.
|
|
+ *
|
|
+ * @param namespace The namespace of the attribute
|
|
+ * @param name The name of the attribute
|
|
+ * @param value the value of the attribute
|
|
+ * @return {@code this} object.
|
|
+ */
|
|
+ public void addAttribute(String namespace,String name, Object value) {
|
|
AttributeInfo attributeInfo = new AttributeInfo();
|
|
attributeInfo.name = name;
|
|
+ attributeInfo.namespace = namespace;
|
|
attributeInfo.type = value == null ? PropertyInfo.OBJECT_CLASS : value.getClass();
|
|
attributeInfo.value = value;
|
|
addAttribute(attributeInfo);
|
|
}
|
|
-
|
|
/**
|
|
* Add an attribute if the value is not null.
|
|
* @param name
|
|
@@ -178,6 +269,18 @@ public class AttributeContainer {
|
|
}
|
|
}
|
|
|
|
+ /**
|
|
+ * Add an attribute if the value is not null.
|
|
+ * @param namespace The namespace of the attribute
|
|
+ * @param name
|
|
+ * @param value
|
|
+ */
|
|
+ public void addAttributeIfValue(String namespace,String name, Object value) {
|
|
+ if (value != null) {
|
|
+ addAttribute(namespace,name, value);
|
|
+ }
|
|
+ }
|
|
+
|
|
/**
|
|
* Add a new attribute by providing an {@link AttributeInfo} object. {@code AttributeInfo}
|
|
* contains all data about the attribute, including name and value.}
|
|
@@ -198,4 +301,17 @@ public class AttributeContainer {
|
|
attributes.addElement(attributeInfo);
|
|
}
|
|
}
|
|
+
|
|
+
|
|
+ public void setAttribute(AttributeInfo info) {
|
|
+
|
|
+
|
|
+ }
|
|
+
|
|
+
|
|
+ public void getAttribute(int index, AttributeInfo info) {
|
|
+
|
|
+
|
|
+ }
|
|
+
|
|
}
|
|
diff --git a/ksoap2-base/src/main/java/org/ksoap2/serialization/DM.java b/ksoap2-base/src/main/java/org/ksoap2/serialization/DM.java
|
|
index 78d4449..255126e 100644
|
|
--- a/ksoap2-base/src/main/java/org/ksoap2/serialization/DM.java
|
|
+++ b/ksoap2-base/src/main/java/org/ksoap2/serialization/DM.java
|
|
@@ -20,9 +20,12 @@
|
|
|
|
package org.ksoap2.serialization;
|
|
|
|
-import java.io.*;
|
|
-import org.xmlpull.v1.*;
|
|
-import org.ksoap2.*;
|
|
+import java.io.IOException;
|
|
+
|
|
+import org.ksoap2.SoapEnvelope;
|
|
+import org.xmlpull.v1.XmlPullParser;
|
|
+import org.xmlpull.v1.XmlPullParserException;
|
|
+import org.xmlpull.v1.XmlSerializer;
|
|
|
|
/**
|
|
* This class is not public, so save a few bytes by using a short class name (DM
|
|
@@ -30,8 +33,7 @@ import org.ksoap2.*;
|
|
*/
|
|
class DM implements Marshal {
|
|
|
|
- public Object readInstance(XmlPullParser parser, String namespace, String name,
|
|
- PropertyInfo expected)
|
|
+ public Object readInstance(XmlPullParser parser, String namespace, String name, PropertyInfo excepted)
|
|
throws IOException, XmlPullParserException {
|
|
String text = parser.nextText();
|
|
switch (name.charAt(0)) {
|
|
@@ -49,9 +51,10 @@ class DM implements Marshal {
|
|
}
|
|
|
|
/**
|
|
- * Write the instance out. In case it is an AttributeContainer write those our first though.
|
|
- * @param writer
|
|
- * the xml serializer.
|
|
+ * Write the instance out. In case it is an AttributeContainer write those our first though.
|
|
+ * If it HasAttributes then write the attributes and values.
|
|
+ *
|
|
+ * @param writer the xml serializer.
|
|
* @param instance
|
|
* @throws IOException
|
|
*/
|
|
@@ -62,11 +65,43 @@ class DM implements Marshal {
|
|
for (int counter = 0; counter < cnt; counter++) {
|
|
AttributeInfo attributeInfo = new AttributeInfo();
|
|
attributeContainer.getAttributeInfo(counter, attributeInfo);
|
|
- writer.attribute(attributeInfo.getNamespace(), attributeInfo.getName(),
|
|
- attributeInfo.getValue().toString());
|
|
+ try {
|
|
+ attributeContainer.getAttribute(counter, attributeInfo);
|
|
+ } catch (Exception e) {
|
|
+ e.printStackTrace();
|
|
+ }
|
|
+ if (attributeInfo.getValue() != null) {
|
|
+ writer.attribute(attributeInfo.getNamespace(), attributeInfo.getName(),
|
|
+ (attributeInfo.getValue() != null) ? attributeInfo.getValue().toString() : "");
|
|
+ }
|
|
+ }
|
|
+ } else if (instance instanceof HasAttributes) {
|
|
+ HasAttributes soapObject = (HasAttributes) instance;
|
|
+ int cnt = soapObject.getAttributeCount();
|
|
+ for (int counter = 0; counter < cnt; counter++) {
|
|
+ AttributeInfo attributeInfo = new AttributeInfo();
|
|
+ soapObject.getAttributeInfo(counter, attributeInfo);
|
|
+ try {
|
|
+ soapObject.getAttribute(counter, attributeInfo);
|
|
+ } catch (Exception e) {
|
|
+ e.printStackTrace();
|
|
+ }
|
|
+ if (attributeInfo.getValue() != null) {
|
|
+ writer.attribute(attributeInfo.getNamespace(), attributeInfo.getName(),
|
|
+ attributeInfo.getValue() != null ? attributeInfo.getValue().toString() : "");
|
|
+ }
|
|
}
|
|
}
|
|
- writer.text(instance.toString());
|
|
+
|
|
+ if(instance instanceof ValueWriter)
|
|
+ {
|
|
+ ((ValueWriter)instance).write(writer);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ writer.text(instance.toString());
|
|
+ }
|
|
+
|
|
}
|
|
|
|
public void register(SoapSerializationEnvelope cm) {
|
|
diff --git a/ksoap2-base/src/main/java/org/ksoap2/serialization/HasAttributes.java b/ksoap2-base/src/main/java/org/ksoap2/serialization/HasAttributes.java
|
|
new file mode 100644
|
|
index 0000000..b513138
|
|
--- /dev/null
|
|
+++ b/ksoap2-base/src/main/java/org/ksoap2/serialization/HasAttributes.java
|
|
@@ -0,0 +1,16 @@
|
|
+package org.ksoap2.serialization;
|
|
+
|
|
+/**
|
|
+ * Common inteface for classes which want to serialize attributes to outgoing soap message
|
|
+ *
|
|
+ * @author robocik
|
|
+ */
|
|
+public interface HasAttributes {
|
|
+ int getAttributeCount();
|
|
+
|
|
+ void getAttributeInfo(int index, AttributeInfo info);
|
|
+
|
|
+ void getAttribute(int index, AttributeInfo info);
|
|
+
|
|
+ void setAttribute(AttributeInfo info);
|
|
+}
|
|
diff --git a/ksoap2-base/src/main/java/org/ksoap2/serialization/HasInnerText.java b/ksoap2-base/src/main/java/org/ksoap2/serialization/HasInnerText.java
|
|
new file mode 100644
|
|
index 0000000..b35c35b
|
|
--- /dev/null
|
|
+++ b/ksoap2-base/src/main/java/org/ksoap2/serialization/HasInnerText.java
|
|
@@ -0,0 +1,17 @@
|
|
+package org.ksoap2.serialization;
|
|
+/**
|
|
+ * Interface for classes requiring inner text of xml tags
|
|
+ *
|
|
+ * @author satansly
|
|
+ */
|
|
+public interface HasInnerText {
|
|
+ /**
|
|
+ * Gets the inner text of xml tags
|
|
+ */
|
|
+ Object getInnerText();
|
|
+
|
|
+ /**
|
|
+ * @param s String to be set as inner text for an outgoing soap object
|
|
+ */
|
|
+ void setInnerText(Object s);
|
|
+}
|
|
diff --git a/ksoap2-base/src/main/java/org/ksoap2/serialization/KvmSerializable.java b/ksoap2-base/src/main/java/org/ksoap2/serialization/KvmSerializable.java
|
|
index bded0c0..09d7b32 100644
|
|
--- a/ksoap2-base/src/main/java/org/ksoap2/serialization/KvmSerializable.java
|
|
+++ b/ksoap2-base/src/main/java/org/ksoap2/serialization/KvmSerializable.java
|
|
@@ -39,31 +39,26 @@ public interface KvmSerializable {
|
|
*/
|
|
Object getProperty(int index);
|
|
|
|
- /**
|
|
- * @return the number of serializable properties
|
|
+ /**
|
|
+ * @return the number of serializable properties
|
|
*/
|
|
int getPropertyCount();
|
|
|
|
/**
|
|
* Sets the property with the given index to the given value.
|
|
- *
|
|
- * @param index
|
|
- * the index to be set
|
|
- * @param value
|
|
- * the value of the property
|
|
+ *
|
|
+ * @param index the index to be set
|
|
+ * @param value the value of the property
|
|
*/
|
|
void setProperty(int index, Object value);
|
|
|
|
/**
|
|
* Fills the given property info record.
|
|
- *
|
|
- * @param index
|
|
- * the index to be queried
|
|
- * @param properties
|
|
- * information about the (de)serializer. Not frequently used.
|
|
- * @param info
|
|
- * The return parameter, to be filled with information about the
|
|
- * property with the given index.
|
|
+ *
|
|
+ * @param index the index to be queried
|
|
+ * @param properties information about the (de)serializer. Not frequently used.
|
|
+ * @param info The return parameter, to be filled with information about the
|
|
+ * property with the given index.
|
|
*/
|
|
void getPropertyInfo(int index, Hashtable properties, PropertyInfo info);
|
|
|
|
diff --git a/ksoap2-base/src/main/java/org/ksoap2/serialization/Marshal.java b/ksoap2-base/src/main/java/org/ksoap2/serialization/Marshal.java
|
|
index cfa9d81..100f107 100644
|
|
--- a/ksoap2-base/src/main/java/org/ksoap2/serialization/Marshal.java
|
|
+++ b/ksoap2-base/src/main/java/org/ksoap2/serialization/Marshal.java
|
|
@@ -41,8 +41,7 @@ public interface Marshal {
|
|
* the namespace.
|
|
* @return the object read from the xml stream.
|
|
*/
|
|
- public Object readInstance(XmlPullParser parser, String namespace, String name,
|
|
- PropertyInfo expected)
|
|
+ public Object readInstance(XmlPullParser parser, String namespace, String name, PropertyInfo expected)
|
|
throws IOException, XmlPullParserException;
|
|
|
|
/**
|
|
diff --git a/ksoap2-base/src/main/java/org/ksoap2/serialization/MarshalBase64.java b/ksoap2-base/src/main/java/org/ksoap2/serialization/MarshalBase64.java
|
|
index 2f8420c..2239027 100644
|
|
--- a/ksoap2-base/src/main/java/org/ksoap2/serialization/MarshalBase64.java
|
|
+++ b/ksoap2-base/src/main/java/org/ksoap2/serialization/MarshalBase64.java
|
|
@@ -31,8 +31,7 @@ import org.xmlpull.v1.*;
|
|
public class MarshalBase64 implements Marshal {
|
|
public static Class BYTE_ARRAY_CLASS = new byte[0].getClass();
|
|
|
|
- public Object readInstance(XmlPullParser parser, String namespace, String name,
|
|
- PropertyInfo expected)
|
|
+ public Object readInstance(XmlPullParser parser, String namespace, String name, PropertyInfo expected)
|
|
throws IOException, XmlPullParserException {
|
|
return Base64.decode(parser.nextText());
|
|
}
|
|
diff --git a/ksoap2-base/src/main/java/org/ksoap2/serialization/MarshalDate.java b/ksoap2-base/src/main/java/org/ksoap2/serialization/MarshalDate.java
|
|
index 3e4fa06..489ba3b 100644
|
|
--- a/ksoap2-base/src/main/java/org/ksoap2/serialization/MarshalDate.java
|
|
+++ b/ksoap2-base/src/main/java/org/ksoap2/serialization/MarshalDate.java
|
|
@@ -31,8 +31,7 @@ import org.ksoap2.kobjects.isodate.*;
|
|
public class MarshalDate implements Marshal {
|
|
public static Class DATE_CLASS = new Date().getClass();
|
|
|
|
- public Object readInstance(XmlPullParser parser, String namespace, String name,
|
|
- PropertyInfo expected)
|
|
+ public Object readInstance(XmlPullParser parser, String namespace, String name, PropertyInfo expected)
|
|
throws IOException, XmlPullParserException {
|
|
return IsoDate.stringToDate(parser.nextText(), IsoDate.DATE_TIME);
|
|
}
|
|
diff --git a/ksoap2-base/src/main/java/org/ksoap2/serialization/MarshalHashtable.java b/ksoap2-base/src/main/java/org/ksoap2/serialization/MarshalHashtable.java
|
|
index d2367e9..0c6b53e 100644
|
|
--- a/ksoap2-base/src/main/java/org/ksoap2/serialization/MarshalHashtable.java
|
|
+++ b/ksoap2-base/src/main/java/org/ksoap2/serialization/MarshalHashtable.java
|
|
@@ -46,8 +46,7 @@ public class MarshalHashtable implements Marshal {
|
|
public static final Class HASHTABLE_CLASS = new Hashtable().getClass();
|
|
SoapSerializationEnvelope envelope;
|
|
|
|
- public Object readInstance(XmlPullParser parser, String namespace, String name,
|
|
- PropertyInfo expected)
|
|
+ public Object readInstance(XmlPullParser parser, String namespace, String name, PropertyInfo expected)
|
|
throws IOException, XmlPullParserException {
|
|
Hashtable instance = new Hashtable();
|
|
String elementName = parser.getName();
|
|
@@ -81,7 +80,7 @@ public class MarshalHashtable implements Marshal {
|
|
Object key = keys.nextElement();
|
|
item.setProperty(0, key);
|
|
item.setProperty(1, h.get(key));
|
|
- envelope.writeObjectBody(writer, item);
|
|
+ envelope.writeObjectBodyWithAttributes(writer, item);
|
|
writer.endTag("", "item");
|
|
}
|
|
}
|
|
@@ -89,7 +88,6 @@ public class MarshalHashtable implements Marshal {
|
|
class ItemSoapObject extends SoapObject {
|
|
Hashtable h;
|
|
int resolvedIndex = -1;
|
|
-
|
|
ItemSoapObject(Hashtable h) {
|
|
super(null, null);
|
|
this.h = h;
|
|
@@ -107,7 +105,7 @@ public class MarshalHashtable implements Marshal {
|
|
Object resolved = resolvedIndex == 0 ? getProperty(0) : getProperty(1);
|
|
if (index == 0) {
|
|
h.put(value, resolved);
|
|
- } else {
|
|
+ } else {
|
|
h.put(resolved, value);
|
|
}
|
|
}
|
|
diff --git a/ksoap2-base/src/main/java/org/ksoap2/serialization/SoapObject.java b/ksoap2-base/src/main/java/org/ksoap2/serialization/SoapObject.java
|
|
index 24a1ffe..f11210a 100644
|
|
--- a/ksoap2-base/src/main/java/org/ksoap2/serialization/SoapObject.java
|
|
+++ b/ksoap2-base/src/main/java/org/ksoap2/serialization/SoapObject.java
|
|
@@ -38,7 +38,7 @@ import java.util.*;
|
|
* KvmSerializable interface.
|
|
*/
|
|
|
|
-public class SoapObject extends AttributeContainer implements KvmSerializable {
|
|
+public class SoapObject extends AttributeContainer implements KvmSerializable, HasInnerText {
|
|
|
|
private static final String EMPTY_STRING = "";
|
|
/**
|
|
@@ -54,6 +54,8 @@ public class SoapObject extends AttributeContainer implements KvmSerializable {
|
|
*/
|
|
protected Vector properties = new Vector();
|
|
|
|
+ protected Object innerText;
|
|
+
|
|
// TODO: accessing properties and attributes would work much better if we
|
|
// kept a list of known properties instead of iterating through the list
|
|
// each time
|
|
@@ -181,6 +183,230 @@ public class SoapObject extends AttributeContainer implements KvmSerializable {
|
|
}
|
|
}
|
|
|
|
+ /**
|
|
+ * Get the property with the given name
|
|
+ *
|
|
+ * return null
|
|
+ * if the property does not exist
|
|
+ */
|
|
+ public Object getProperty(String namespace,String name) {
|
|
+ Integer index = propertyIndex(namespace,name);
|
|
+ if (index != null) {
|
|
+ return getProperty(index.intValue());
|
|
+ }
|
|
+ else {
|
|
+ throw new RuntimeException("illegal property: " + name);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get a property using namespace and name without chance of throwing an exception
|
|
+ *
|
|
+ * @return the property if it exists; if not, {@link NullSoapObject} is
|
|
+ * returned
|
|
+ */
|
|
+ public Object getPropertyByNamespaceSafely(final String namespace, final String name) {
|
|
+ Integer i = propertyIndex(namespace,name);
|
|
+ if (i != null) {
|
|
+ return getProperty(i.intValue());
|
|
+ } else {
|
|
+ return new NullSoapObject();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get the toString value of a property without chance of throwing an
|
|
+ * exception
|
|
+ *
|
|
+ * @return the string value of the property if it exists; if not, #EMPTY_STRING is
|
|
+ * returned
|
|
+ */
|
|
+ public String getPropertyByNamespaceSafelyAsString(final String namespace,final String name) {
|
|
+ Integer i = propertyIndex(namespace,name);
|
|
+ if (i != null) {
|
|
+ Object foo = getProperty(i.intValue());
|
|
+ if (foo == null) {
|
|
+ return EMPTY_STRING;
|
|
+ } else {
|
|
+ return foo.toString();
|
|
+ }
|
|
+ } else {
|
|
+ return EMPTY_STRING;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get a property without chance of throwing an exception. An object can be
|
|
+ * provided to this method; if the property is not found, this object will
|
|
+ * be returned.
|
|
+ *
|
|
+ * @param defaultThing
|
|
+ * the object to return if the property is not found
|
|
+ * @return the property if it exists; defaultThing if the property does not
|
|
+ * exist
|
|
+ */
|
|
+ public Object getPropertySafely(final String namespace,final String name, final Object defaultThing) {
|
|
+ Integer i = propertyIndex(namespace,name);
|
|
+ if (i != null) {
|
|
+ return getProperty(i.intValue());
|
|
+ } else {
|
|
+ return defaultThing;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get the toString value of a property without chance of throwing an
|
|
+ * exception. An object can be provided to this method; if the property is
|
|
+ * not found, this object's string representation will be returned.
|
|
+ *
|
|
+ * @param defaultThing
|
|
+ * toString of the object to return if the property is not found
|
|
+ * @return the property toString if it exists; defaultThing toString if the
|
|
+ * property does not exist, if the defaultThing is null #EMPTY_STRING
|
|
+ * is returned
|
|
+ */
|
|
+ public String getPropertySafelyAsString(final String namespace,final String name,
|
|
+ final Object defaultThing) {
|
|
+ Integer i = propertyIndex(namespace,name);
|
|
+ if (i != null) {
|
|
+ Object property = getProperty(i.intValue());
|
|
+ if (property != null) {
|
|
+ return property.toString();
|
|
+ } else {
|
|
+ return EMPTY_STRING;
|
|
+ }
|
|
+ } else {
|
|
+ if (defaultThing != null) {
|
|
+ return defaultThing.toString();
|
|
+ } else {
|
|
+ return EMPTY_STRING;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get the primitive property with the given name.
|
|
+ *
|
|
+ * @param name
|
|
+ * @return PropertyInfo containing an empty string if property either complex or empty
|
|
+ */
|
|
+ public Object getPrimitiveProperty(final String namespace,final String name){
|
|
+ Integer index = propertyIndex(namespace,name);
|
|
+ if (index != null){
|
|
+ PropertyInfo propertyInfo = (PropertyInfo) properties.elementAt(index.intValue());
|
|
+ if (propertyInfo.getType()!=SoapObject.class && propertyInfo.getValue()!=null){
|
|
+ return propertyInfo.getValue();
|
|
+ } else {
|
|
+ propertyInfo = new PropertyInfo();
|
|
+ propertyInfo.setType(String.class);
|
|
+ propertyInfo.setValue(EMPTY_STRING);
|
|
+ propertyInfo.setName(name);
|
|
+ propertyInfo.setNamespace(namespace);
|
|
+ return (Object) propertyInfo.getValue();
|
|
+ }
|
|
+ } else {
|
|
+ throw new RuntimeException("illegal property: " + name);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get the toString value of the primitive property with the given name.
|
|
+ * Returns empty string if property either complex or empty
|
|
+ *
|
|
+ * @param name
|
|
+ * @return the string value of the property
|
|
+ */
|
|
+ public String getPrimitivePropertyAsString(final String namespace,final String name){
|
|
+ Integer index = propertyIndex(namespace,name);
|
|
+ if (index != null){
|
|
+ PropertyInfo propertyInfo = (PropertyInfo) properties.elementAt(index.intValue());
|
|
+ if (propertyInfo.getType()!=SoapObject.class && propertyInfo.getValue()!=null){
|
|
+ return propertyInfo.getValue().toString();
|
|
+ } else {
|
|
+ return EMPTY_STRING;
|
|
+ }
|
|
+ } else {
|
|
+ throw new RuntimeException("illegal property: " + name);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get the toString value of a primitive property without chance of throwing an
|
|
+ * exception
|
|
+ *
|
|
+ * @param name
|
|
+ * @return the string value of the property if it exists and is primitive; if not, #EMPTY_STRING is
|
|
+ * returned
|
|
+ */
|
|
+ public Object getPrimitivePropertySafely(final String namespace,final String name) {
|
|
+ Integer index = propertyIndex(namespace,name);
|
|
+ if (index != null){
|
|
+ PropertyInfo propertyInfo = (PropertyInfo) properties.elementAt(index.intValue());
|
|
+ if (propertyInfo.getType()!=SoapObject.class && propertyInfo.getValue()!=null){
|
|
+ return propertyInfo.getValue().toString();
|
|
+ } else {
|
|
+ propertyInfo = new PropertyInfo();
|
|
+ propertyInfo.setType(String.class);
|
|
+ propertyInfo.setValue(EMPTY_STRING);
|
|
+ propertyInfo.setName(name);
|
|
+ propertyInfo.setNamespace(namespace);
|
|
+ return (Object) propertyInfo.getValue();
|
|
+ }
|
|
+ } else {
|
|
+ return new NullSoapObject();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get the toString value of a primitive property without chance of throwing an
|
|
+ * exception
|
|
+ *
|
|
+ * @param name
|
|
+ * @return the string value of the property if it exists and is primitive; if not, #EMPTY_STRING is
|
|
+ * returned
|
|
+ */
|
|
+ public String getPrimitivePropertySafelyAsString(final String namespace,final String name) {
|
|
+ Integer index = propertyIndex(namespace,name);
|
|
+ if (index != null){
|
|
+ PropertyInfo propertyInfo = (PropertyInfo) properties.elementAt(index.intValue());
|
|
+ if (propertyInfo.getType()!=SoapObject.class && propertyInfo.getValue()!=null){
|
|
+ return propertyInfo.getValue().toString();
|
|
+ } else {
|
|
+ return EMPTY_STRING;
|
|
+ }
|
|
+ } else {
|
|
+ return EMPTY_STRING;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Knows whether the given property exists
|
|
+ */
|
|
+ public boolean hasProperty(final String namespace,final String name) {
|
|
+ if (propertyIndex(namespace,name) != null) {
|
|
+ return true;
|
|
+ } else {
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get the toString value of the property.
|
|
+ *
|
|
+ * @param namespace
|
|
+ * @param name
|
|
+ * @return
|
|
+ */
|
|
+
|
|
+ public String getPropertyAsString(String namespace,String name) {
|
|
+ Integer index = propertyIndex(namespace,name);
|
|
+ if (index != null) {
|
|
+ return getProperty(index.intValue()).toString();
|
|
+ } else {
|
|
+ throw new RuntimeException("illegal property: " + name);
|
|
+ }
|
|
+ }
|
|
+
|
|
/**
|
|
* Get the toString value of the property.
|
|
*
|
|
@@ -301,9 +527,9 @@ public class SoapObject extends AttributeContainer implements KvmSerializable {
|
|
*/
|
|
public Object getPrimitiveProperty(final String name) {
|
|
Integer index = propertyIndex(name);
|
|
- if (index != null) {
|
|
+ if (index != null){
|
|
PropertyInfo propertyInfo = (PropertyInfo) properties.elementAt(index.intValue());
|
|
- if (propertyInfo.getType() != SoapObject.class) {
|
|
+ if (propertyInfo.getType()!=SoapObject.class && propertyInfo.getValue()!=null){
|
|
return propertyInfo.getValue();
|
|
} else {
|
|
propertyInfo = new PropertyInfo();
|
|
@@ -326,9 +552,9 @@ public class SoapObject extends AttributeContainer implements KvmSerializable {
|
|
*/
|
|
public String getPrimitivePropertyAsString(final String name) {
|
|
Integer index = propertyIndex(name);
|
|
- if (index != null) {
|
|
+ if (index != null){
|
|
PropertyInfo propertyInfo = (PropertyInfo) properties.elementAt(index.intValue());
|
|
- if (propertyInfo.getType() != SoapObject.class) {
|
|
+ if (propertyInfo.getType()!=SoapObject.class && propertyInfo.getValue()!=null){
|
|
return propertyInfo.getValue().toString();
|
|
} else {
|
|
return EMPTY_STRING;
|
|
@@ -348,9 +574,9 @@ public class SoapObject extends AttributeContainer implements KvmSerializable {
|
|
*/
|
|
public Object getPrimitivePropertySafely(final String name) {
|
|
Integer index = propertyIndex(name);
|
|
- if (index != null) {
|
|
+ if (index != null){
|
|
PropertyInfo propertyInfo = (PropertyInfo) properties.elementAt(index.intValue());
|
|
- if (propertyInfo.getType() != SoapObject.class) {
|
|
+ if (propertyInfo.getType()!=SoapObject.class && propertyInfo.getValue()!=null){
|
|
return propertyInfo.getValue().toString();
|
|
} else {
|
|
propertyInfo = new PropertyInfo();
|
|
@@ -374,9 +600,9 @@ public class SoapObject extends AttributeContainer implements KvmSerializable {
|
|
*/
|
|
public String getPrimitivePropertySafelyAsString(final String name) {
|
|
Integer index = propertyIndex(name);
|
|
- if (index != null) {
|
|
+ if (index != null){
|
|
PropertyInfo propertyInfo = (PropertyInfo) properties.elementAt(index.intValue());
|
|
- if (propertyInfo.getType() != SoapObject.class) {
|
|
+ if (propertyInfo.getType()!=SoapObject.class && propertyInfo.getValue()!=null){
|
|
return propertyInfo.getValue().toString();
|
|
} else {
|
|
return EMPTY_STRING;
|
|
@@ -397,6 +623,18 @@ public class SoapObject extends AttributeContainer implements KvmSerializable {
|
|
return null;
|
|
}
|
|
|
|
+
|
|
+ private Integer propertyIndex(String namespace,String name) {
|
|
+ if (name != null && namespace!=null) {
|
|
+ for (int i = 0; i < properties.size(); i++) {
|
|
+ PropertyInfo info= (PropertyInfo) properties.elementAt(i);
|
|
+ if (name.equals(info.getName()) && namespace.equals(info.getNamespace())) {
|
|
+ return new Integer(i);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return null;
|
|
+ }
|
|
/**
|
|
* Returns the number of properties
|
|
*
|
|
@@ -453,6 +691,17 @@ public class SoapObject extends AttributeContainer implements KvmSerializable {
|
|
}
|
|
}
|
|
|
|
+ public PropertyInfo getPropertyInfo(int index) {
|
|
+ Object element = properties.elementAt(index);
|
|
+ if (element instanceof PropertyInfo) {
|
|
+ PropertyInfo p = (PropertyInfo) element;
|
|
+ return p;
|
|
+ } else {
|
|
+ // SoapObject
|
|
+ return null;
|
|
+ }
|
|
+ }
|
|
+
|
|
/**
|
|
* Creates a new SoapObject based on this, allows usage of SoapObjects as
|
|
* templates. One application is to set the expected return type of a soap
|
|
@@ -466,17 +715,17 @@ public class SoapObject extends AttributeContainer implements KvmSerializable {
|
|
Object prop = properties.elementAt(propIndex);
|
|
if (prop instanceof PropertyInfo) {
|
|
PropertyInfo propertyInfo = (PropertyInfo) properties.elementAt(propIndex);
|
|
- PropertyInfo propertyInfoClonned = (PropertyInfo) propertyInfo.clone();
|
|
- o.addProperty(propertyInfoClonned);
|
|
- } else if (prop instanceof SoapObject) {
|
|
- o.addSoapObject(((SoapObject) prop).newInstance());
|
|
+ PropertyInfo propertyInfoClonned = (PropertyInfo)propertyInfo.clone();
|
|
+ o.addProperty( propertyInfoClonned );
|
|
+ } else if(prop instanceof SoapObject) {
|
|
+ o.addSoapObject(((SoapObject)prop).newInstance());
|
|
}
|
|
}
|
|
for (int attribIndex = 0; attribIndex < getAttributeCount(); attribIndex++) {
|
|
AttributeInfo newAI = new AttributeInfo();
|
|
getAttributeInfo(attribIndex, newAI);
|
|
AttributeInfo attributeInfo = newAI; // (AttributeInfo)
|
|
- // attributes.elementAt(attribIndex);
|
|
+ // attributes.elementAt(attribIndex);
|
|
o.addAttribute(attributeInfo);
|
|
}
|
|
return o;
|
|
@@ -513,11 +762,49 @@ public class SoapObject extends AttributeContainer implements KvmSerializable {
|
|
propertyInfo.type = value == null ? PropertyInfo.OBJECT_CLASS : value
|
|
.getClass();
|
|
propertyInfo.value = value;
|
|
+ return addProperty(propertyInfo);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Adds a property (parameter) to the object. This is essentially a sub
|
|
+ * element.
|
|
+ *
|
|
+ * @param namespace
|
|
+ * The namespace of the property
|
|
+ * @param name
|
|
+ * The name of the property
|
|
+ * @param value
|
|
+ * the value of the property
|
|
+ */
|
|
+ public SoapObject addProperty(String namespace,String name, Object value) {
|
|
+ PropertyInfo propertyInfo = new PropertyInfo();
|
|
+ propertyInfo.name = name;
|
|
propertyInfo.namespace = namespace;
|
|
- ///M: HS20 modify by Jungo
|
|
+ propertyInfo.type = value == null ? PropertyInfo.OBJECT_CLASS : value
|
|
+ .getClass();
|
|
+ propertyInfo.value = value;
|
|
return addProperty(propertyInfo);
|
|
}
|
|
|
|
+ /**
|
|
+ * Add a property only if the value is not null.
|
|
+ *
|
|
+ * @param namespace
|
|
+ * The namespace of the property
|
|
+ * @param name
|
|
+ * The name of the property
|
|
+ * @param value
|
|
+ * the value of the property
|
|
+ * @return
|
|
+ */
|
|
+ public SoapObject addPropertyIfValue(String namespace,String name, Object value) {
|
|
+ if (value != null) {
|
|
+ return addProperty(namespace,name, value);
|
|
+ } else {
|
|
+ return this;
|
|
+ }
|
|
+ }
|
|
+
|
|
/**
|
|
* Add a property only if the value is not null.
|
|
*
|
|
@@ -597,12 +884,12 @@ public class SoapObject extends AttributeContainer implements KvmSerializable {
|
|
StringBuffer buf = new StringBuffer(EMPTY_STRING + name + "{");
|
|
for (int i = 0; i < getPropertyCount(); i++) {
|
|
Object prop = properties.elementAt(i);
|
|
- if (prop instanceof PropertyInfo) {
|
|
+ if(prop instanceof PropertyInfo) {
|
|
buf.append(EMPTY_STRING)
|
|
- .append(((PropertyInfo) prop).getName())
|
|
- .append("=")
|
|
- .append(getProperty(i))
|
|
- .append("; ");
|
|
+ .append(((PropertyInfo) prop).getName())
|
|
+ .append("=")
|
|
+ .append(getProperty(i))
|
|
+ .append("; ");
|
|
} else {
|
|
buf.append(((SoapObject) prop).toString());
|
|
}
|
|
@@ -610,4 +897,17 @@ public class SoapObject extends AttributeContainer implements KvmSerializable {
|
|
buf.append("}");
|
|
return buf.toString();
|
|
}
|
|
+ public Object getInnerText() {
|
|
+ return innerText;
|
|
+ }
|
|
+
|
|
+ public void setInnerText(Object innerText)
|
|
+ {
|
|
+ this.innerText=innerText;
|
|
+ }
|
|
+
|
|
+ public void removePropertyInfo(Object info)
|
|
+ {
|
|
+ properties.remove(info);
|
|
+ }
|
|
}
|
|
diff --git a/ksoap2-base/src/main/java/org/ksoap2/serialization/SoapPrimitive.java b/ksoap2-base/src/main/java/org/ksoap2/serialization/SoapPrimitive.java
|
|
index d09f7a7..32fe333 100644
|
|
--- a/ksoap2-base/src/main/java/org/ksoap2/serialization/SoapPrimitive.java
|
|
+++ b/ksoap2-base/src/main/java/org/ksoap2/serialization/SoapPrimitive.java
|
|
@@ -34,11 +34,14 @@ package org.ksoap2.serialization;
|
|
*/
|
|
|
|
public class SoapPrimitive extends AttributeContainer {
|
|
- String namespace;
|
|
- String name;
|
|
- String value;
|
|
+ protected String namespace;
|
|
+ protected String name;
|
|
+ protected Object value;
|
|
|
|
- public SoapPrimitive(String namespace, String name, String value) {
|
|
+ public static final Object NullSkip = new Object();
|
|
+ public static final Object NullNilElement = new Object();
|
|
+
|
|
+ public SoapPrimitive(String namespace, String name, Object value) {
|
|
this.namespace = namespace;
|
|
this.name = name;
|
|
this.value = value;
|
|
@@ -50,7 +53,7 @@ public class SoapPrimitive extends AttributeContainer {
|
|
}
|
|
SoapPrimitive p = (SoapPrimitive) o;
|
|
boolean varsEqual = name.equals(p.name)
|
|
- && (namespace == null ? p.namespace == null : namespace.equals(p.namespace))
|
|
+ && (namespace == null ? p.namespace == null:namespace.equals(p.namespace))
|
|
&& (value == null ? (p.value == null) : value.equals(p.value));
|
|
return varsEqual && attributesAreEqual(p);
|
|
}
|
|
@@ -60,7 +63,7 @@ public class SoapPrimitive extends AttributeContainer {
|
|
}
|
|
|
|
public String toString() {
|
|
- return value;
|
|
+ return value != null ? value.toString() : null;
|
|
}
|
|
|
|
public String getNamespace() {
|
|
@@ -70,4 +73,9 @@ public class SoapPrimitive extends AttributeContainer {
|
|
public String getName() {
|
|
return name;
|
|
}
|
|
+
|
|
+ public Object getValue() {
|
|
+ return value;
|
|
+ }
|
|
+
|
|
}
|
|
diff --git a/ksoap2-base/src/main/java/org/ksoap2/serialization/SoapSerializationEnvelope.java b/ksoap2-base/src/main/java/org/ksoap2/serialization/SoapSerializationEnvelope.java
|
|
index dae09d2..ceeb3f4 100644
|
|
--- a/ksoap2-base/src/main/java/org/ksoap2/serialization/SoapSerializationEnvelope.java
|
|
+++ b/ksoap2-base/src/main/java/org/ksoap2/serialization/SoapSerializationEnvelope.java
|
|
@@ -27,9 +27,9 @@ import org.xmlpull.v1.XmlPullParserException;
|
|
import org.xmlpull.v1.XmlSerializer;
|
|
|
|
import java.io.IOException;
|
|
+import java.util.ArrayList;
|
|
import java.util.Hashtable;
|
|
import java.util.Vector;
|
|
-import java.io.ByteArrayOutputStream;
|
|
|
|
import org.kxml2.io.*;
|
|
|
|
@@ -43,29 +43,29 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
protected static final int QNAME_TYPE = 1;
|
|
protected static final int QNAME_NAMESPACE = 0;
|
|
protected static final int QNAME_MARSHAL = 3;
|
|
+ protected static final String NULL_LABEL = "null";
|
|
+ protected static final String NIL_LABEL = "nil";
|
|
+ static final Marshal DEFAULT_MARSHAL = new DM();
|
|
private static final String ANY_TYPE_LABEL = "anyType";
|
|
private static final String ARRAY_MAPPING_NAME = "Array";
|
|
- private static final String NULL_LABEL = "null";
|
|
- private static final String NIL_LABEL = "nil";
|
|
private static final String HREF_LABEL = "href";
|
|
private static final String ID_LABEL = "id";
|
|
private static final String ROOT_LABEL = "root";
|
|
private static final String TYPE_LABEL = "type";
|
|
private static final String ITEM_LABEL = "item";
|
|
private static final String ARRAY_TYPE_LABEL = "arrayType";
|
|
- static final Marshal DEFAULT_MARSHAL = new DM();
|
|
public Hashtable properties = new Hashtable();
|
|
-
|
|
- Hashtable idMap = new Hashtable();
|
|
- Vector multiRef; // = new Vector();
|
|
-
|
|
/**
|
|
* Set this variable to true if you don't want that type definitions for complex types/objects
|
|
* are automatically generated (with type "anyType") in the XML-Request, if you don't call the
|
|
* Method addMapping. This is needed by some Servers which have problems with these type-definitions.
|
|
*/
|
|
public boolean implicitTypes;
|
|
-
|
|
+ /**
|
|
+ * If set to true then all properties with null value will be skipped from the soap message.
|
|
+ * If false then null properties will be sent as <element nil="true" />
|
|
+ */
|
|
+ public boolean skipNullProperties;
|
|
/**
|
|
* Set this variable to true for compatibility with what seems to be the default encoding for
|
|
* .Net-Services. This feature is an extremely ugly hack. A much better option is to change the
|
|
@@ -96,9 +96,10 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
* Set to true to add and ID and ROOT label to the envelope. Change to false for compatibility with WSDL.
|
|
*/
|
|
protected boolean addAdornments = true;
|
|
+ Hashtable idMap = new Hashtable();
|
|
+ Vector multiRef; // = new Vector();
|
|
|
|
- public SoapSerializationEnvelope(int version)
|
|
- {
|
|
+ public SoapSerializationEnvelope(int version) {
|
|
super(version);
|
|
addMapping(enc, ARRAY_MAPPING_NAME, PropertyInfo.VECTOR_CLASS);
|
|
DEFAULT_MARSHAL.register(this);
|
|
@@ -107,23 +108,21 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
/**
|
|
* @return the addAdornments
|
|
*/
|
|
- public boolean isAddAdornments()
|
|
- {
|
|
+ public boolean isAddAdornments() {
|
|
return addAdornments;
|
|
}
|
|
|
|
/**
|
|
- * @param addAdornments
|
|
- * the addAdornments to set
|
|
+ * @param addAdornments the addAdornments to set
|
|
*/
|
|
- public void setAddAdornments(boolean addAdornments)
|
|
- {
|
|
+ public void setAddAdornments(boolean addAdornments) {
|
|
this.addAdornments = addAdornments;
|
|
}
|
|
|
|
/**
|
|
* Set the bodyOut to be empty so that no un-needed xml is create. The null value for bodyOut will
|
|
* cause #writeBody to skip writing anything redundant.
|
|
+ *
|
|
* @param emptyBody
|
|
* @see "http://code.google.com/p/ksoap2-android/issues/detail?id=77"
|
|
*/
|
|
@@ -133,8 +132,7 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
}
|
|
}
|
|
|
|
- public void parseBody(XmlPullParser parser) throws IOException, XmlPullParserException
|
|
- {
|
|
+ public void parseBody(XmlPullParser parser) throws IOException, XmlPullParserException {
|
|
bodyIn = null;
|
|
parser.nextTag();
|
|
if (parser.getEventType() == XmlPullParser.START_TAG && parser.getNamespace().equals(env)
|
|
@@ -161,10 +159,11 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
}
|
|
}
|
|
|
|
- /** Read a SoapObject. This extracts any attributes and then reads the object as a KvmSerializable. */
|
|
+ /**
|
|
+ * Read a SoapObject. This extracts any attributes and then reads the object as a KvmSerializable.
|
|
+ */
|
|
protected void readSerializable(XmlPullParser parser, SoapObject obj) throws IOException,
|
|
- XmlPullParserException
|
|
- {
|
|
+ XmlPullParserException {
|
|
for (int counter = 0; counter < parser.getAttributeCount(); counter++) {
|
|
String attributeName = parser.getAttributeName(counter);
|
|
String value = parser.getAttributeValue(counter);
|
|
@@ -173,11 +172,21 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
readSerializable(parser, (KvmSerializable) obj);
|
|
}
|
|
|
|
- /** Read a KvmSerializable. */
|
|
+ /**
|
|
+ * Read a KvmSerializable.
|
|
+ */
|
|
protected void readSerializable(XmlPullParser parser, KvmSerializable obj) throws IOException,
|
|
- XmlPullParserException
|
|
- {
|
|
- while (parser.nextTag() != XmlPullParser.END_TAG) {
|
|
+ XmlPullParserException {
|
|
+ int tag = 0;
|
|
+ try {
|
|
+ tag = parser.nextTag();
|
|
+ } catch (XmlPullParserException e) {
|
|
+ if(obj instanceof HasInnerText){
|
|
+ ((HasInnerText)obj).setInnerText((parser.getText() != null) ? parser.getText() : "");
|
|
+ }
|
|
+ tag = parser.nextTag();
|
|
+ }
|
|
+ while (tag != XmlPullParser.END_TAG) {
|
|
String name = parser.getName();
|
|
if (!implicitTypes || !(obj instanceof SoapObject)) {
|
|
PropertyInfo info = new PropertyInfo();
|
|
@@ -188,8 +197,7 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
info.clear();
|
|
obj.getPropertyInfo(i, properties, info);
|
|
|
|
- if ((name.equals(info.name) && info.namespace == null)
|
|
- ||
|
|
+ if ((name.equals(info.name) && info.namespace == null) ||
|
|
(name.equals(info.name) && parser.getNamespace().equals(info.namespace))) {
|
|
propertyFound = true;
|
|
obj.setProperty(i, read(parser, obj, i, null, null, info));
|
|
@@ -199,21 +207,42 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
if (!propertyFound) {
|
|
if (avoidExceptionForUnknownProperty) {
|
|
// Dummy loop to read until corresponding END tag
|
|
- while (parser.next() != XmlPullParser.END_TAG
|
|
- || !name.equals(parser.getName())) {
|
|
+ while (parser.next() != XmlPullParser.END_TAG || !name.equals(parser.getName())) {
|
|
}
|
|
;
|
|
} else {
|
|
throw new RuntimeException("Unknown Property: " + name);
|
|
}
|
|
+ } else {
|
|
+ if (obj instanceof HasAttributes) {
|
|
+ HasAttributes soapObject = (HasAttributes) obj;
|
|
+ int cnt = parser.getAttributeCount();
|
|
+ for (int counter = 0; counter < cnt; counter++) {
|
|
+ AttributeInfo attributeInfo = new AttributeInfo();
|
|
+ attributeInfo.setName(parser.getAttributeName(counter));
|
|
+ attributeInfo.setValue(parser.getAttributeValue(counter));
|
|
+ attributeInfo.setNamespace(parser.getAttributeNamespace(counter));
|
|
+ attributeInfo.setType(parser.getAttributeType(counter));
|
|
+ soapObject.setAttribute(attributeInfo);
|
|
+
|
|
+ }
|
|
+ }
|
|
}
|
|
} else {
|
|
// I can only make this work for SoapObjects - hence the check above
|
|
// I don't understand namespaces well enough to know whether it is correct in the next line...
|
|
- ((SoapObject) obj).addProperty(parser.getName(),
|
|
- read(parser, obj, obj.getPropertyCount(),
|
|
- ((SoapObject) obj).getNamespace(), name, PropertyInfo.OBJECT_TYPE));
|
|
+ ((SoapObject) obj).addProperty(parser.getName(), read(parser, obj, obj.getPropertyCount(),
|
|
+ ((SoapObject) obj).getNamespace(), name, PropertyInfo.OBJECT_TYPE));
|
|
+ }
|
|
+ try {
|
|
+ tag = parser.nextTag();
|
|
+ } catch (XmlPullParserException e) {
|
|
+ if(obj instanceof HasInnerText){
|
|
+ ((HasInnerText)obj).setInnerText((parser.getText() != null) ? parser.getText() : "");
|
|
+ }
|
|
+ tag = parser.nextTag();
|
|
}
|
|
+
|
|
}
|
|
parser.require(XmlPullParser.END_TAG, null, null);
|
|
}
|
|
@@ -278,9 +307,8 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
}
|
|
|
|
while (parser.getEventType() != XmlPullParser.END_TAG) {
|
|
- so.addProperty(parser.getName(),
|
|
- read(parser, so, so.getPropertyCount(), null, null,
|
|
- PropertyInfo.OBJECT_TYPE));
|
|
+ so.addProperty(parser.getNamespace(),parser.getName(), read(parser, so, so.getPropertyCount(),
|
|
+ null, null, PropertyInfo.OBJECT_TYPE));
|
|
parser.nextTag();
|
|
}
|
|
result = so;
|
|
@@ -293,12 +321,15 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
if (value == null) {
|
|
return dflt;
|
|
}
|
|
- return value.length() - start < 3 ? dflt : Integer.parseInt(value.substring(start + 1,
|
|
- value.length() - 1));
|
|
+ try {
|
|
+ return value.length() - start < 3 ? dflt : Integer.parseInt(value.substring(start + 1,
|
|
+ value.length() - 1));
|
|
+ } catch (Exception ex) {
|
|
+ return dflt;
|
|
+ }
|
|
}
|
|
|
|
- protected void readVector(XmlPullParser parser, Vector v, PropertyInfo elementType)
|
|
- throws IOException,
|
|
+ protected void readVector(XmlPullParser parser, Vector v, PropertyInfo elementType) throws IOException,
|
|
XmlPullParserException {
|
|
String namespace = null;
|
|
String name = null;
|
|
@@ -337,14 +368,23 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
parser.require(XmlPullParser.END_TAG, null, null);
|
|
}
|
|
|
|
+ /**
|
|
+ * This method returns id from the href attribute value.
|
|
+ * By default we assume that href value looks like this: #id so we basically have to remove the first character.
|
|
+ * But in theory there could be a different value format, like cid:value, etc...
|
|
+ */
|
|
+ protected String getIdFromHref(String hrefValue) {
|
|
+ return hrefValue.substring(1);
|
|
+ }
|
|
+
|
|
/**
|
|
* Builds an object from the XML stream. This method is public for usage in conjuction with Marshal
|
|
* subclasses. Precondition: On the start tag of the object or property, so href can be read.
|
|
*/
|
|
|
|
- public Object read(XmlPullParser parser, Object owner, int index, String namespace,
|
|
- String name,
|
|
- PropertyInfo expected) throws IOException, XmlPullParserException {
|
|
+ public Object read(XmlPullParser parser, Object owner, int index, String namespace, String name,
|
|
+ PropertyInfo expected)
|
|
+ throws IOException, XmlPullParserException {
|
|
String elementName = parser.getName();
|
|
String href = parser.getAttributeValue(null, HREF_LABEL);
|
|
Object obj;
|
|
@@ -352,7 +392,7 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
if (owner == null) {
|
|
throw new RuntimeException("href at root level?!?");
|
|
}
|
|
- href = href.substring(1);
|
|
+ href = getIdFromHref(href);
|
|
obj = idMap.get(href);
|
|
if (obj == null || obj instanceof FwdRef) {
|
|
FwdRef f = new FwdRef();
|
|
@@ -402,21 +442,8 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
}
|
|
// finally, care about the id....
|
|
if (id != null) {
|
|
- Object hlp = idMap.get(id);
|
|
- if (hlp instanceof FwdRef) {
|
|
- FwdRef f = (FwdRef) hlp;
|
|
- do {
|
|
- if (f.obj instanceof KvmSerializable) {
|
|
- ((KvmSerializable) f.obj).setProperty(f.index, obj);
|
|
- } else {
|
|
- ((Vector) f.obj).setElementAt(obj, f.index);
|
|
- }
|
|
- f = f.next;
|
|
- } while (f != null);
|
|
- } else if (hlp != null) {
|
|
- throw new RuntimeException("double ID");
|
|
- }
|
|
- idMap.put(id, obj);
|
|
+ resolveReference(id, obj);
|
|
+
|
|
}
|
|
}
|
|
|
|
@@ -424,12 +451,30 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
return obj;
|
|
}
|
|
|
|
+ protected void resolveReference(String id, Object obj) {
|
|
+ Object hlp = idMap.get(id);
|
|
+ if (hlp instanceof FwdRef) {
|
|
+ FwdRef f = (FwdRef) hlp;
|
|
+ do {
|
|
+ if (f.obj instanceof KvmSerializable) {
|
|
+ ((KvmSerializable) f.obj).setProperty(f.index, obj);
|
|
+ } else {
|
|
+ ((Vector) f.obj).setElementAt(obj, f.index);
|
|
+ }
|
|
+ f = f.next;
|
|
+ }
|
|
+ while (f != null);
|
|
+ } else if (hlp != null) {
|
|
+ throw new RuntimeException("double ID");
|
|
+ }
|
|
+ idMap.put(id, obj);
|
|
+ }
|
|
+
|
|
/**
|
|
* Returns a new object read from the given parser. If no mapping is found, null is returned. This method
|
|
* is used by the SoapParser in order to convert the XML code to Java objects.
|
|
*/
|
|
- public Object readInstance(XmlPullParser parser, String namespace, String name,
|
|
- PropertyInfo expected)
|
|
+ public Object readInstance(XmlPullParser parser, String namespace, String name, PropertyInfo expected)
|
|
throws IOException, XmlPullParserException {
|
|
Object obj = qNameToClass.get(new SoapPrimitive(namespace, name, null));
|
|
if (obj == null) {
|
|
@@ -448,10 +493,30 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
throw new RuntimeException(e.toString());
|
|
}
|
|
}
|
|
+ if (obj instanceof HasAttributes) {
|
|
+ HasAttributes soapObject = (HasAttributes) obj;
|
|
+ int cnt = parser.getAttributeCount();
|
|
+ for (int counter = 0; counter < cnt; counter++) {
|
|
+
|
|
+ AttributeInfo attributeInfo = new AttributeInfo();
|
|
+ attributeInfo.setName(parser.getAttributeName(counter));
|
|
+ attributeInfo.setValue(parser.getAttributeValue(counter));
|
|
+ attributeInfo.setNamespace(parser.getAttributeNamespace(counter));
|
|
+ attributeInfo.setType(parser.getAttributeType(counter));
|
|
+
|
|
+ soapObject.setAttribute(attributeInfo);
|
|
+
|
|
+ }
|
|
+ }
|
|
+
|
|
// ok, obj is now the instance, fill it....
|
|
if (obj instanceof SoapObject) {
|
|
readSerializable(parser, (SoapObject) obj);
|
|
} else if (obj instanceof KvmSerializable) {
|
|
+
|
|
+ if(obj instanceof HasInnerText){
|
|
+ ((HasInnerText)obj).setInnerText((parser.getText() != null) ? parser.getText() : "");
|
|
+ }
|
|
readSerializable(parser, (KvmSerializable) obj);
|
|
} else if (obj instanceof Vector) {
|
|
readVector(parser, (Vector) obj, expected.elementType);
|
|
@@ -476,15 +541,11 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
}
|
|
if (type instanceof SoapObject) {
|
|
SoapObject so = (SoapObject) type;
|
|
- return new Object[] {
|
|
- so.getNamespace(), so.getName(), null, null
|
|
- };
|
|
+ return new Object[]{so.getNamespace(), so.getName(), null, null};
|
|
}
|
|
if (type instanceof SoapPrimitive) {
|
|
SoapPrimitive sp = (SoapPrimitive) type;
|
|
- return new Object[] {
|
|
- sp.getNamespace(), sp.getName(), null, DEFAULT_MARSHAL
|
|
- };
|
|
+ return new Object[]{sp.getNamespace(), sp.getName(), null, DEFAULT_MARSHAL};
|
|
}
|
|
if ((type instanceof Class) && type != PropertyInfo.OBJECT_CLASS) {
|
|
Object[] tmp = (Object[]) classToQName.get(((Class) type).getName());
|
|
@@ -492,9 +553,7 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
return tmp;
|
|
}
|
|
}
|
|
- return new Object[] {
|
|
- xsd, ANY_TYPE_LABEL, null, null
|
|
- };
|
|
+ return new Object[]{xsd, ANY_TYPE_LABEL, null, null};
|
|
}
|
|
|
|
/**
|
|
@@ -503,11 +562,8 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
*/
|
|
public void addMapping(String namespace, String name, Class clazz, Marshal marshal) {
|
|
qNameToClass
|
|
- .put(new SoapPrimitive(namespace, name, null), marshal == null ? (Object) clazz
|
|
- : marshal);
|
|
- classToQName.put(clazz.getName(), new Object[] {
|
|
- namespace, name, null, marshal
|
|
- });
|
|
+ .put(new SoapPrimitive(namespace, name, null), marshal == null ? (Object) clazz : marshal);
|
|
+ classToQName.put(clazz.getName(), new Object[]{namespace, name, null, marshal});
|
|
}
|
|
|
|
/**
|
|
@@ -528,11 +584,14 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
/**
|
|
* Response from the soap call. Pulls the object from the wrapper object and returns it.
|
|
*
|
|
- * @since 2.0.3
|
|
* @return response from the soap call.
|
|
* @throws SoapFault
|
|
+ * @since 2.0.3
|
|
*/
|
|
public Object getResponse() throws SoapFault {
|
|
+ if (bodyIn == null) {
|
|
+ return null;
|
|
+ }
|
|
if (bodyIn instanceof SoapFault) {
|
|
throw (SoapFault) bodyIn;
|
|
}
|
|
@@ -554,8 +613,7 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
/**
|
|
* Serializes the request object to the given XmlSerliazer object
|
|
*
|
|
- * @param writer
|
|
- * XmlSerializer object to write the body into.
|
|
+ * @param writer XmlSerializer object to write the body into.
|
|
*/
|
|
public void writeBody(XmlSerializer writer) throws IOException {
|
|
// allow an empty body without any tags in it
|
|
@@ -564,36 +622,48 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
multiRef = new Vector();
|
|
multiRef.addElement(bodyOut);
|
|
Object[] qName = getInfo(null, bodyOut);
|
|
- writer.startTag((dotNet) ? "" : (String) qName[QNAME_NAMESPACE],
|
|
- (String) qName[QNAME_TYPE]); //<spp:sppPostDevData
|
|
- if (dotNet) {
|
|
- writer.attribute(null, "xmlns", (String) qName[QNAME_NAMESPACE]);
|
|
- }
|
|
+
|
|
+ writer.startTag((dotNet) ? "" : (String) qName[QNAME_NAMESPACE], (String) qName[QNAME_TYPE]);
|
|
+
|
|
+ if (dotNet) {
|
|
+ writer.attribute(null, "xmlns", (String) qName[QNAME_NAMESPACE]);
|
|
+ }
|
|
+
|
|
if (addAdornments) {
|
|
writer.attribute(null, ID_LABEL, qName[2] == null ? ("o" + 0) : (String) qName[2]);
|
|
writer.attribute(enc, ROOT_LABEL, "1");
|
|
}
|
|
- writeElement(writer, bodyOut, null, qName[QNAME_MARSHAL]); //....
|
|
- writer.endTag((dotNet) ? "" : (String) qName[QNAME_NAMESPACE],
|
|
- (String) qName[QNAME_TYPE]);//</spp:sppPostDevData>
|
|
+ writeElement(writer, bodyOut, null, qName[QNAME_MARSHAL]);
|
|
+ writer.endTag((dotNet) ? "" : (String) qName[QNAME_NAMESPACE], (String) qName[QNAME_TYPE]);
|
|
}
|
|
}
|
|
|
|
- /**
|
|
- * Writes the body of an SoapObject. This method write the attributes and then calls
|
|
- * "writeObjectBody (writer, (KvmSerializable)obj);"
|
|
- */
|
|
- public void writeObjectBody(XmlSerializer writer, SoapObject obj) throws IOException {
|
|
- SoapObject soapObject = (SoapObject) obj;
|
|
+ private void writeAttributes(XmlSerializer writer, HasAttributes obj) throws IOException {
|
|
+ HasAttributes soapObject = (HasAttributes) obj;
|
|
int cnt = soapObject.getAttributeCount();
|
|
for (int counter = 0; counter < cnt; counter++) {
|
|
AttributeInfo attributeInfo = new AttributeInfo();
|
|
soapObject.getAttributeInfo(counter, attributeInfo);
|
|
- writer.attribute(attributeInfo.getNamespace(), attributeInfo.getName(), attributeInfo
|
|
- .getValue()
|
|
- .toString());
|
|
+ soapObject.getAttribute(counter, attributeInfo);
|
|
+ if (attributeInfo.getValue() != null) {
|
|
+ writer.attribute(attributeInfo.getNamespace(), attributeInfo.getName(),
|
|
+ attributeInfo.getValue().toString());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public void writeArrayListBodyWithAttributes(XmlSerializer writer, KvmSerializable obj) throws IOException {
|
|
+ if (obj instanceof HasAttributes) {
|
|
+ writeAttributes(writer, (HasAttributes) obj);
|
|
}
|
|
- writeObjectBody(writer, (KvmSerializable) obj);
|
|
+ writeArrayListBody(writer, (ArrayList) obj);
|
|
+ }
|
|
+
|
|
+ public void writeObjectBodyWithAttributes(XmlSerializer writer, KvmSerializable obj) throws IOException {
|
|
+ if (obj instanceof HasAttributes) {
|
|
+ writeAttributes(writer, (HasAttributes) obj);
|
|
+ }
|
|
+ writeObjectBody(writer, obj);
|
|
}
|
|
|
|
/**
|
|
@@ -614,9 +684,12 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
if (!(prop instanceof SoapObject)) {
|
|
// prop is a PropertyInfo
|
|
if ((propertyInfo.flags & PropertyInfo.TRANSIENT) == 0) {
|
|
- writer.startTag(propertyInfo.namespace, propertyInfo.name);
|
|
- writeProperty(writer, obj.getProperty(i), propertyInfo);
|
|
- writer.endTag(propertyInfo.namespace, propertyInfo.name);
|
|
+ Object objValue = obj.getProperty(i);
|
|
+ if ((prop != null || !skipNullProperties) && (objValue != SoapPrimitive.NullSkip)) {
|
|
+ writer.startTag(propertyInfo.namespace, propertyInfo.name);
|
|
+ writeProperty(writer, objValue, propertyInfo);
|
|
+ writer.endTag(propertyInfo.namespace, propertyInfo.name);
|
|
+ }
|
|
}
|
|
} else {
|
|
// prop is a SoapObject
|
|
@@ -633,46 +706,47 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
name = (String) qName[QNAME_TYPE];
|
|
}
|
|
|
|
- // treat MO data as CDATA
|
|
- if (name.equals("DevInfo") || name.equals("DevDetail")
|
|
- || name.equals("PerProviderSubscription") || // format v4
|
|
- name.equals("MgmtTree") // format v6
|
|
- ) {
|
|
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
- XmlSerializer xw = new KXmlSerializer();
|
|
- xw.setOutput(bos, "UTF-8");
|
|
- xw.startTag((dotNet) ? "" : namespace, name);
|
|
- if (!implicitTypes) {
|
|
- String prefix = writer.getPrefix(namespace, true);
|
|
- writer.attribute(xsi, TYPE_LABEL, prefix + ":" + type);
|
|
- }
|
|
- writeObjectBody(xw, nestedSoap);
|
|
- xw.endTag((dotNet) ? "" : namespace, name);
|
|
- xw.flush();
|
|
- //bos.write('\r');
|
|
- //bos.write('\n');
|
|
- bos.flush();
|
|
- writer.cdsect(bos.toString());
|
|
+ // prefer the namespace from the property info
|
|
+ if (propertyInfo.namespace != null && propertyInfo.namespace.length() > 0) {
|
|
+ namespace = propertyInfo.namespace;
|
|
+ } else {
|
|
+ namespace = (String) qName[QNAME_NAMESPACE];
|
|
+ }
|
|
+
|
|
+ writer.startTag(namespace, name);
|
|
+ if (!implicitTypes) {
|
|
+ String prefix = writer.getPrefix(namespace, true);
|
|
+ writer.attribute(xsi, TYPE_LABEL, prefix + ":" + type);
|
|
+ }
|
|
+ writeObjectBodyWithAttributes(writer, nestedSoap);
|
|
+ writer.endTag(namespace, name);
|
|
+ }
|
|
+ }
|
|
+ writeInnerText(writer, obj);
|
|
+
|
|
+ }
|
|
+
|
|
+ private void writeInnerText(XmlSerializer writer, KvmSerializable obj) throws IOException {
|
|
+ if(obj instanceof HasInnerText){
|
|
+
|
|
+ Object value=((HasInnerText)obj).getInnerText();
|
|
+ if (value != null) {
|
|
+ if(value instanceof ValueWriter)
|
|
+ {
|
|
+ ((ValueWriter)value).write(writer);
|
|
}
|
|
else
|
|
{
|
|
- writer.startTag((dotNet) ? "" : namespace, name);
|
|
- if (!implicitTypes) {
|
|
- String prefix = writer.getPrefix(namespace, true);
|
|
- writer.attribute(xsi, TYPE_LABEL, prefix + ":" + type);
|
|
- }
|
|
- writeObjectBody(writer, nestedSoap);
|
|
- writer.endTag((dotNet) ? "" : namespace, name);
|
|
+ writer.cdsect(value.toString());
|
|
}
|
|
+
|
|
}
|
|
}
|
|
}
|
|
|
|
- protected void writeProperty(XmlSerializer writer, Object obj, PropertyInfo type)
|
|
- throws IOException {
|
|
- if (obj == null) {
|
|
- ///M: Modify for HS20
|
|
- //writer.attribute(xsi, version >= VER12 ? NIL_LABEL : NULL_LABEL, "true");
|
|
+ protected void writeProperty(XmlSerializer writer, Object obj, PropertyInfo type) throws IOException {
|
|
+ if (obj == null || obj == SoapPrimitive.NullNilElement) {
|
|
+ writer.attribute(xsi, version >= VER12 ? NIL_LABEL : NULL_LABEL, "true");
|
|
return;
|
|
}
|
|
Object[] qName = getInfo(null, obj);
|
|
@@ -692,15 +766,19 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
}
|
|
}
|
|
|
|
- private void writeElement(XmlSerializer writer, Object element, PropertyInfo type,
|
|
- Object marshal)
|
|
+ protected void writeElement(XmlSerializer writer, Object element, PropertyInfo type, Object marshal)
|
|
throws IOException {
|
|
if (marshal != null) {
|
|
((Marshal) marshal).writeInstance(writer, element);
|
|
- } else if (element instanceof SoapObject) {
|
|
- writeObjectBody(writer, (SoapObject) element);
|
|
- } else if (element instanceof KvmSerializable) {
|
|
- writeObjectBody(writer, (KvmSerializable) element);
|
|
+ } else if (element instanceof KvmSerializable || element == SoapPrimitive.NullNilElement
|
|
+ || element == SoapPrimitive.NullSkip) {
|
|
+ if (element instanceof ArrayList) {
|
|
+ writeArrayListBodyWithAttributes(writer, (KvmSerializable) element);
|
|
+ } else {
|
|
+ writeObjectBodyWithAttributes(writer, (KvmSerializable) element);
|
|
+ }
|
|
+ } else if (element instanceof HasAttributes) {
|
|
+ writeAttributes(writer, (HasAttributes) element);
|
|
} else if (element instanceof Vector) {
|
|
writeVectorBody(writer, (Vector) element, type.elementType);
|
|
} else {
|
|
@@ -708,6 +786,65 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
}
|
|
}
|
|
|
|
+ protected void writeArrayListBody(XmlSerializer writer, ArrayList list)
|
|
+ throws IOException {
|
|
+ KvmSerializable obj = (KvmSerializable) list;
|
|
+ int cnt = list.size();
|
|
+ PropertyInfo propertyInfo = new PropertyInfo();
|
|
+ String namespace;
|
|
+ String name;
|
|
+ String type;
|
|
+ for (int i = 0; i < cnt; i++) {
|
|
+ // get the property
|
|
+ Object prop = obj.getProperty(i);
|
|
+ // and importantly also get the property info which holds the name potentially!
|
|
+ obj.getPropertyInfo(i, properties, propertyInfo);
|
|
+
|
|
+ if (!(prop instanceof SoapObject)) {
|
|
+ // prop is a PropertyInfo
|
|
+ if ((propertyInfo.flags & PropertyInfo.TRANSIENT) == 0) {
|
|
+ Object objValue = obj.getProperty(i);
|
|
+ if ((prop != null || !skipNullProperties) && (objValue != SoapPrimitive.NullSkip)) {
|
|
+ writer.startTag(propertyInfo.namespace, propertyInfo.name);
|
|
+ writeProperty(writer, objValue, propertyInfo);
|
|
+ writer.endTag(propertyInfo.namespace, propertyInfo.name);
|
|
+ }
|
|
+ }
|
|
+ } else {
|
|
+
|
|
+ // prop is a SoapObject
|
|
+ SoapObject nestedSoap = (SoapObject) prop;
|
|
+ // lets get the info from the soap object itself
|
|
+ Object[] qName = getInfo(null, nestedSoap);
|
|
+ namespace = (String) qName[QNAME_NAMESPACE];
|
|
+ type = (String) qName[QNAME_TYPE];
|
|
+
|
|
+ // prefer the name from the property info
|
|
+ if (propertyInfo.name != null && propertyInfo.name.length() > 0) {
|
|
+ name = propertyInfo.name;
|
|
+ } else {
|
|
+ name = (String) qName[QNAME_TYPE];
|
|
+ }
|
|
+
|
|
+ // prefer the namespace from the property info
|
|
+ if (propertyInfo.namespace != null && propertyInfo.namespace.length() > 0) {
|
|
+ namespace = propertyInfo.namespace;
|
|
+ } else {
|
|
+ namespace = (String) qName[QNAME_NAMESPACE];
|
|
+ }
|
|
+
|
|
+ writer.startTag(namespace, name);
|
|
+ if (!implicitTypes) {
|
|
+ String prefix = writer.getPrefix(namespace, true);
|
|
+ writer.attribute(xsi, TYPE_LABEL, prefix + ":" + type);
|
|
+ }
|
|
+ writeObjectBodyWithAttributes(writer, nestedSoap);
|
|
+ writer.endTag(namespace, name);
|
|
+ }
|
|
+ }
|
|
+ writeInnerText(writer, obj);
|
|
+ }
|
|
+
|
|
protected void writeVectorBody(XmlSerializer writer, Vector vector, PropertyInfo elementType)
|
|
throws IOException {
|
|
String itemsTagName = ITEM_LABEL;
|
|
@@ -727,9 +864,13 @@ public class SoapSerializationEnvelope extends SoapEnvelope
|
|
|
|
// This removes the arrayType attribute from the xml for arrays(required for most .Net services to work)
|
|
if (!implicitTypes) {
|
|
- writer.attribute(enc, ARRAY_TYPE_LABEL, writer.getPrefix((String) arrType[0], false)
|
|
- + ":"
|
|
+ writer.attribute(enc, ARRAY_TYPE_LABEL, writer.getPrefix((String) arrType[0], false) + ":"
|
|
+ arrType[1] + "[" + cnt + "]");
|
|
+ } else {
|
|
+ // Get the namespace from mappings if available when arrayType is removed for .Net
|
|
+ if (itemsNamespace == null) {
|
|
+ itemsNamespace = (String) arrType[0];
|
|
+ }
|
|
}
|
|
|
|
boolean skipped = false;
|
|
diff --git a/ksoap2-base/src/main/java/org/ksoap2/serialization/ValueWriter.java b/ksoap2-base/src/main/java/org/ksoap2/serialization/ValueWriter.java
|
|
new file mode 100644
|
|
index 0000000..fdbaa21
|
|
--- /dev/null
|
|
+++ b/ksoap2-base/src/main/java/org/ksoap2/serialization/ValueWriter.java
|
|
@@ -0,0 +1,13 @@
|
|
+package org.ksoap2.serialization;
|
|
+
|
|
+import org.xmlpull.v1.XmlSerializer;
|
|
+
|
|
+import java.io.IOException;
|
|
+
|
|
+/**
|
|
+ * Created by robocik on 2015-09-25.
|
|
+ */
|
|
+public interface ValueWriter
|
|
+{
|
|
+ void write(XmlSerializer writer) throws IOException;
|
|
+}
|
|
diff --git a/ksoap2-base/src/main/java/org/ksoap2/transport/ServiceConnection.java b/ksoap2-base/src/main/java/org/ksoap2/transport/ServiceConnection.java
|
|
index 8e14ee7..9dd3837 100644
|
|
--- a/ksoap2-base/src/main/java/org/ksoap2/transport/ServiceConnection.java
|
|
+++ b/ksoap2-base/src/main/java/org/ksoap2/transport/ServiceConnection.java
|
|
@@ -21,8 +21,10 @@
|
|
|
|
package org.ksoap2.transport;
|
|
|
|
+import java.io.IOException;
|
|
+import java.io.InputStream;
|
|
+import java.io.OutputStream;
|
|
import java.util.List;
|
|
-import java.io.*;
|
|
|
|
/**
|
|
* Interface to allow the abstraction of the raw transport information
|
|
@@ -58,6 +60,13 @@ public interface ServiceConnection {
|
|
*/
|
|
public List getResponseProperties() throws IOException;
|
|
|
|
+ /**
|
|
+ * Returns the numerical HTTP status to the caller
|
|
+ * @return an integer status value
|
|
+ * @throws IOException
|
|
+ */
|
|
+ public int getResponseCode() throws IOException;
|
|
+
|
|
/**
|
|
* Set properties on the outgoing connection.
|
|
*
|
|
@@ -88,6 +97,8 @@ public interface ServiceConnection {
|
|
**/
|
|
public void setFixedLengthStreamingMode(int contentLength);
|
|
|
|
+ public void setChunkedStreamingMode();
|
|
+
|
|
/**
|
|
* Open and return the outputStream to the endpoint.
|
|
*
|
|
diff --git a/ksoap2-base/src/main/java/org/ksoap2/transport/Transport.java b/ksoap2-base/src/main/java/org/ksoap2/transport/Transport.java
|
|
index b2f6587..2f3d523 100644
|
|
--- a/ksoap2-base/src/main/java/org/ksoap2/transport/Transport.java
|
|
+++ b/ksoap2-base/src/main/java/org/ksoap2/transport/Transport.java
|
|
@@ -23,9 +23,13 @@
|
|
|
|
package org.ksoap2.transport;
|
|
|
|
+import java.util.HashMap;
|
|
+import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.io.*;
|
|
+import java.net.MalformedURLException;
|
|
import java.net.Proxy;
|
|
+import java.net.URL;
|
|
|
|
import org.ksoap2.*;
|
|
import org.kxml2.io.*;
|
|
@@ -40,9 +44,9 @@ import org.xmlpull.v1.*;
|
|
abstract public class Transport {
|
|
|
|
/**
|
|
- * Added to enable web service interactions on the emulator
|
|
- * to be debugged with Fiddler2 (Windows) but provides utility
|
|
- * for other proxy requirements.
|
|
+ * Added to enable web service interactions on the emulator to be debugged
|
|
+ * with Fiddler2 (Windows) but provides utility for other proxy
|
|
+ * requirements.
|
|
*/
|
|
protected Proxy proxy;
|
|
protected String url;
|
|
@@ -61,6 +65,12 @@ abstract public class Transport {
|
|
|
|
private int bufferLength = ServiceConnection.DEFAULT_BUFFER_SIZE;
|
|
|
|
+ private HashMap prefixes = new HashMap();
|
|
+
|
|
+ public HashMap getPrefixes() {
|
|
+ return prefixes;
|
|
+ }
|
|
+
|
|
public Transport() {
|
|
}
|
|
|
|
@@ -82,9 +92,12 @@ abstract public class Transport {
|
|
/**
|
|
* Construct the transport object
|
|
*
|
|
- * @param proxy Specifies the proxy server to use for
|
|
- * accessing the web service or <code>null</code> if a direct connection is available
|
|
- * @param url Specifies the web service url
|
|
+ * @param proxy
|
|
+ * Specifies the proxy server to use for accessing the web
|
|
+ * service or <code>null</code> if a direct connection is
|
|
+ * available
|
|
+ * @param url
|
|
+ * Specifies the web service url
|
|
*
|
|
*/
|
|
public Transport(Proxy proxy, String url) {
|
|
@@ -114,23 +127,30 @@ abstract public class Transport {
|
|
xp.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
|
|
xp.setInput(is, null);
|
|
envelope.parse(xp);
|
|
+ /*
|
|
+ * Fix memory leak when running on android in strict mode. Issue 133
|
|
+ */
|
|
+ is.close();
|
|
}
|
|
|
|
/**
|
|
* Serializes the request.
|
|
*/
|
|
- protected byte[] createRequestData(SoapEnvelope envelope, String encoding) throws IOException {
|
|
- System.out.println("createRequestData");
|
|
+ protected byte[] createRequestData(SoapEnvelope envelope, String encoding)
|
|
+ throws IOException {
|
|
ByteArrayOutputStream bos = new ByteArrayOutputStream(bufferLength);
|
|
byte result[] = null;
|
|
bos.write(xmlVersionTag.getBytes());
|
|
- System.out.println("bos.write");
|
|
XmlSerializer xw = new KXmlSerializer();
|
|
- System.out.println("new KXmlSerializer");
|
|
+
|
|
+ final Iterator keysIter = prefixes.keySet().iterator();
|
|
+
|
|
xw.setOutput(bos, encoding);
|
|
- System.out.println("xw.setOutput");
|
|
+ while (keysIter.hasNext()) {
|
|
+ String key = (String) keysIter.next();
|
|
+ xw.setPrefix(key, (String) prefixes.get(key));
|
|
+ }
|
|
envelope.write(xw);
|
|
- System.out.println("envelope.write");
|
|
xw.flush();
|
|
bos.write('\r');
|
|
bos.write('\n');
|
|
@@ -138,14 +158,14 @@ abstract public class Transport {
|
|
result = bos.toByteArray();
|
|
xw = null;
|
|
bos = null;
|
|
- System.out.println("createRequestData end");
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Serializes the request.
|
|
*/
|
|
- protected byte[] createRequestData(SoapEnvelope envelope) throws IOException {
|
|
+ protected byte[] createRequestData(SoapEnvelope envelope)
|
|
+ throws IOException {
|
|
return createRequestData(envelope, null);
|
|
}
|
|
|
|
@@ -159,6 +179,12 @@ abstract public class Transport {
|
|
this.url = url;
|
|
}
|
|
|
|
+ public String getUrl()
|
|
+ {
|
|
+ return url;
|
|
+ }
|
|
+
|
|
+
|
|
/**
|
|
* Sets the version tag for the outgoing soap call. Example <?xml
|
|
* version=\"1.0\" encoding=\"UTF-8\"?>
|
|
@@ -177,57 +203,94 @@ abstract public class Transport {
|
|
}
|
|
|
|
/**
|
|
- * Perform a soap call with a given namespace and the given envelope providing
|
|
- * any extra headers that the user requires such as cookies. Headers that are
|
|
- * returned by the web service will be returned to the caller in the form of a
|
|
- * <code>List</code> of <code>HeaderProperty</code> instances.
|
|
+ * Perform a soap call with a given namespace and the given envelope
|
|
+ * providing any extra headers that the user requires such as cookies.
|
|
+ * Headers that are returned by the web service will be returned to the
|
|
+ * caller in the form of a <code>List</code> of <code>HeaderProperty</code>
|
|
+ * instances.
|
|
+ *
|
|
+ * @param soapAction
|
|
+ * the namespace with which to perform the call in.
|
|
+ * @param envelope
|
|
+ * the envelope the contains the information for the call.
|
|
+ * @param headers
|
|
+ * <code>List</code> of <code>HeaderProperty</code> headers to
|
|
+ * send with the SOAP request.
|
|
+ *
|
|
+ * @return Headers returned by the web service as a <code>List</code> of
|
|
+ * <code>HeaderProperty</code> instances.
|
|
+ */
|
|
+ abstract public List call(String soapAction, SoapEnvelope envelope,
|
|
+ List headers) throws IOException, XmlPullParserException;
|
|
+
|
|
+ /**
|
|
+ * Perform a soap call with a given namespace and the given envelope
|
|
+ * providing any extra headers that the user requires such as cookies.
|
|
+ * Headers that are returned by the web service will be returned to the
|
|
+ * caller in the form of a <code>List</code> of <code>HeaderProperty</code>
|
|
+ * instances.
|
|
*
|
|
- * @param targetNamespace
|
|
+ * @param soapAction
|
|
* the namespace with which to perform the call in.
|
|
* @param envelope
|
|
* the envelope the contains the information for the call.
|
|
* @param headers
|
|
- * <code>List</code> of <code>HeaderProperty</code> headers to send with the SOAP request.
|
|
+ * <code>List</code> of <code>HeaderProperty</code> headers to
|
|
+ * send with the SOAP request.
|
|
+ * @param outputFile
|
|
+ * a file to stream the response into rather than parsing it,
|
|
+ * streaming happens when file is not null
|
|
*
|
|
* @return Headers returned by the web service as a <code>List</code> of
|
|
- * <code>HeaderProperty</code> instances.
|
|
+ * <code>HeaderProperty</code> instances.
|
|
*/
|
|
- abstract public List call(String targetNamespace, SoapEnvelope envelope, List headers)
|
|
- throws IOException, XmlPullParserException;
|
|
+ abstract public List call(String soapAction, SoapEnvelope envelope,
|
|
+ List headers, File outputFile) throws IOException,
|
|
+ XmlPullParserException;
|
|
|
|
/**
|
|
* Perform a soap call with a given namespace and the given envelope.
|
|
*
|
|
- * @param targetNamespace
|
|
+ * @param soapAction
|
|
* the namespace with which to perform the call in.
|
|
* @param envelope
|
|
* the envelope the contains the information for the call.
|
|
*/
|
|
- public void call(String targetNamespace, SoapEnvelope envelope) throws IOException,
|
|
- XmlPullParserException {
|
|
- call(targetNamespace, envelope, null);
|
|
+ public void call(String soapAction, SoapEnvelope envelope)
|
|
+ throws IOException, XmlPullParserException {
|
|
+ call(soapAction, envelope, null);
|
|
}
|
|
|
|
/**
|
|
* Return the name of the host that is specified as the web service target
|
|
- *
|
|
+ *
|
|
* @return Host name
|
|
*/
|
|
- abstract public String getHost();
|
|
+ public String getHost() throws MalformedURLException {
|
|
+
|
|
+ return new URL(url).getHost();
|
|
+ }
|
|
|
|
/**
|
|
- * Return the port number of the host that is specified as the web service target
|
|
- *
|
|
+ * Return the port number of the host that is specified as the web service
|
|
+ * target
|
|
+ *
|
|
* @return Port number
|
|
*/
|
|
- abstract public int getPort();
|
|
+ public int getPort() throws MalformedURLException {
|
|
+
|
|
+ return new URL(url).getPort();
|
|
+ }
|
|
|
|
/**
|
|
* Return the path to the web service target
|
|
- *
|
|
+ *
|
|
* @return The URL's path
|
|
*/
|
|
- abstract public String getPath();
|
|
+ public String getPath() throws MalformedURLException {
|
|
+
|
|
+ return new URL(url).getPath();
|
|
+ }
|
|
|
|
abstract public ServiceConnection getServiceConnection() throws IOException;
|
|
}
|
|
diff --git a/ksoap2-j2se/src/main/java/org/ksoap2/serialization/MarshalFloat.java b/ksoap2-j2se/src/main/java/org/ksoap2/serialization/MarshalFloat.java
|
|
index 71c8caa..61a5e2c 100644
|
|
--- a/ksoap2-j2se/src/main/java/org/ksoap2/serialization/MarshalFloat.java
|
|
+++ b/ksoap2-j2se/src/main/java/org/ksoap2/serialization/MarshalFloat.java
|
|
@@ -27,8 +27,7 @@ import org.xmlpull.v1.*;
|
|
|
|
public class MarshalFloat implements Marshal {
|
|
|
|
- public Object readInstance(XmlPullParser parser, String namespace, String name,
|
|
- PropertyInfo propertyInfo)
|
|
+ public Object readInstance(XmlPullParser parser, String namespace, String name, PropertyInfo propertyInfo)
|
|
throws IOException, XmlPullParserException {
|
|
String stringValue = parser.nextText();
|
|
Object result;
|
|
diff --git a/ksoap2-j2se/src/main/java/org/ksoap2/transport/HttpResponseException.java b/ksoap2-j2se/src/main/java/org/ksoap2/transport/HttpResponseException.java
|
|
new file mode 100644
|
|
index 0000000..f7fb866
|
|
--- /dev/null
|
|
+++ b/ksoap2-j2se/src/main/java/org/ksoap2/transport/HttpResponseException.java
|
|
@@ -0,0 +1,60 @@
|
|
+package org.ksoap2.transport;
|
|
+
|
|
+import java.io.IOException;
|
|
+import java.util.List;
|
|
+
|
|
+/**
|
|
+ * HttpResponseException is an IOException that is to be thrown when a Http response code is different from 200.
|
|
+ * It allows for easier retrieval of the Http response code from the connection.
|
|
+ *
|
|
+ * @author Rui Pereira <syshex@gmail.com>
|
|
+ */
|
|
+public class HttpResponseException extends IOException {
|
|
+
|
|
+ private int statusCode;
|
|
+ private List responseHeaders;
|
|
+
|
|
+ public HttpResponseException(int statusCode) {
|
|
+ super();
|
|
+ this.statusCode = statusCode;
|
|
+ }
|
|
+
|
|
+ public HttpResponseException(String detailMessage, int statusCode) {
|
|
+ super(detailMessage);
|
|
+ this.statusCode = statusCode;
|
|
+ }
|
|
+
|
|
+ public HttpResponseException(String detailMessage, int statusCode,List responseHeaders) {
|
|
+ super(detailMessage);
|
|
+ this.statusCode = statusCode;
|
|
+ this.responseHeaders=responseHeaders;
|
|
+ }
|
|
+
|
|
+ public HttpResponseException(String message, Throwable cause, int statusCode) {
|
|
+ super(message, cause);
|
|
+ this.statusCode = statusCode;
|
|
+ }
|
|
+
|
|
+ public HttpResponseException(Throwable cause, int statusCode) {
|
|
+ super(cause);
|
|
+ this.statusCode = statusCode;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns the unexpected Http response code
|
|
+ *
|
|
+ * @return response code
|
|
+ */
|
|
+ public int getStatusCode() {
|
|
+ return statusCode;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns all http headers from this response
|
|
+ *
|
|
+ * @return response code
|
|
+ */
|
|
+ public List getResponseHeaders() {
|
|
+ return responseHeaders;
|
|
+ }
|
|
+}
|
|
diff --git a/ksoap2-j2se/src/main/java/org/ksoap2/transport/HttpTransportSE.java b/ksoap2-j2se/src/main/java/org/ksoap2/transport/HttpTransportSE.java
|
|
index d92ac09..920ca60 100644
|
|
--- a/ksoap2-j2se/src/main/java/org/ksoap2/transport/HttpTransportSE.java
|
|
+++ b/ksoap2-j2se/src/main/java/org/ksoap2/transport/HttpTransportSE.java
|
|
@@ -25,24 +25,21 @@
|
|
|
|
package org.ksoap2.transport;
|
|
|
|
-import java.util.List;
|
|
-import java.util.zip.GZIPInputStream;
|
|
+import org.ksoap2.HeaderProperty;
|
|
+import org.ksoap2.SoapEnvelope;
|
|
+import org.ksoap2.serialization.*;
|
|
+import org.xmlpull.v1.XmlPullParserException;
|
|
+
|
|
import java.io.*;
|
|
-import java.net.MalformedURLException;
|
|
import java.net.Proxy;
|
|
-import java.net.URL;
|
|
-
|
|
-import org.ksoap2.*;
|
|
-import org.ksoap2.serialization.SoapSerializationEnvelope;
|
|
-import org.xmlpull.v1.*;
|
|
+import java.util.*;
|
|
+import java.util.zip.GZIPInputStream;
|
|
|
|
/**
|
|
* A J2SE based HttpTransport layer.
|
|
*/
|
|
public class HttpTransportSE extends Transport {
|
|
|
|
- private ServiceConnection serviceConnection;
|
|
-
|
|
/**
|
|
* Creates instance of HttpTransportSE with set url
|
|
*
|
|
@@ -107,249 +104,254 @@ public class HttpTransportSE extends Transport {
|
|
* the desired soapAction
|
|
* @param envelope
|
|
* the envelope containing the information for the soap call.
|
|
+ * @throws HttpResponseException
|
|
* @throws IOException
|
|
* @throws XmlPullParserException
|
|
*/
|
|
- public void call(String soapAction, SoapEnvelope envelope) throws IOException,
|
|
- XmlPullParserException {
|
|
-
|
|
+ public void call(String soapAction, SoapEnvelope envelope)
|
|
+ throws HttpResponseException, IOException, XmlPullParserException {
|
|
+
|
|
call(soapAction, envelope, null);
|
|
}
|
|
|
|
+ public List call(String soapAction, SoapEnvelope envelope, List headers)
|
|
+ throws HttpResponseException, IOException, XmlPullParserException {
|
|
+ return call(soapAction, envelope, headers, null);
|
|
+ }
|
|
+
|
|
/**
|
|
- *
|
|
- * set the desired soapAction header field
|
|
- *
|
|
+ * Perform a soap call with a given namespace and the given envelope providing
|
|
+ * any extra headers that the user requires such as cookies. Headers that are
|
|
+ * returned by the web service will be returned to the caller in the form of a
|
|
+ * <code>List</code> of <code>HeaderProperty</code> instances.
|
|
+ *
|
|
* @param soapAction
|
|
- * the desired soapAction
|
|
+ * the namespace with which to perform the call in.
|
|
* @param envelope
|
|
- * the envelope containing the information for the soap call.
|
|
+ * the envelope the contains the information for the call.
|
|
* @param headers
|
|
- * a list of HeaderProperties to be http header properties when establishing the connection
|
|
+ * <code>List</code> of <code>HeaderProperty</code> headers to send with the SOAP request.
|
|
+ * @param outputFile
|
|
+ * a file to stream the response into rather than parsing it, streaming happens when file is not null
|
|
*
|
|
- * @return <code>CookieJar</code> with any cookies sent by the server
|
|
- * @throws IOException
|
|
- * @throws XmlPullParserException
|
|
+ * @return Headers returned by the web service as a <code>List</code> of
|
|
+ * <code>HeaderProperty</code> instances.
|
|
+ *
|
|
+ * @throws HttpResponseException
|
|
+ * an IOException when Http response code is different from 200
|
|
*/
|
|
- public List call(String soapAction, SoapEnvelope envelope, List headers)
|
|
- throws IOException, XmlPullParserException {
|
|
+ public List call(String soapAction, SoapEnvelope envelope, List headers, File outputFile)
|
|
+ throws HttpResponseException, IOException, XmlPullParserException {
|
|
|
|
if (soapAction == null) {
|
|
soapAction = "\"\"";
|
|
}
|
|
|
|
- System.out.println("call action:" + soapAction);
|
|
byte[] requestData = createRequestData(envelope, "UTF-8");
|
|
|
|
- if (requestData != null) {
|
|
- requestDump = debug ? new String(requestData) : null;
|
|
- }
|
|
- else {
|
|
- requestDump = null;
|
|
- }
|
|
+ requestDump = debug ? new String(requestData) : null;
|
|
responseDump = null;
|
|
-
|
|
- System.out.println("requestDump:" + requestDump);
|
|
+ System.out.println("requestDump: " + requestDump);
|
|
ServiceConnection connection = getServiceConnection();
|
|
- System.out.println("connection:" + connection);
|
|
|
|
connection.setRequestProperty("User-Agent", USER_AGENT);
|
|
// SOAPAction is not a valid header for VER12 so do not add
|
|
// it
|
|
// @see "http://code.google.com/p/ksoap2-android/issues/detail?id=67
|
|
- System.out.println("envelope:" + envelope);
|
|
- if (envelope != null) {
|
|
- if (envelope.version != SoapSerializationEnvelope.VER12) {
|
|
- connection.setRequestProperty("SOAPAction", soapAction);
|
|
- }
|
|
+ if (envelope.version != SoapSerializationEnvelope.VER12) {
|
|
+ connection.setRequestProperty("SOAPAction", soapAction);
|
|
+ }
|
|
|
|
- if (envelope.version == SoapSerializationEnvelope.VER12) {
|
|
- connection.setRequestProperty("Content-Type", CONTENT_TYPE_SOAP_XML_CHARSET_UTF_8);
|
|
- } else {
|
|
- connection.setRequestProperty("Content-Type", CONTENT_TYPE_XML_CHARSET_UTF_8);
|
|
- }
|
|
+ if (envelope.version == SoapSerializationEnvelope.VER12) {
|
|
+ connection.setRequestProperty("Content-Type", CONTENT_TYPE_SOAP_XML_CHARSET_UTF_8);
|
|
+ } else {
|
|
+ connection.setRequestProperty("Content-Type", CONTENT_TYPE_XML_CHARSET_UTF_8);
|
|
+ }
|
|
|
|
- connection.setRequestProperty("Connection", "close");
|
|
- connection.setRequestProperty("Accept-Encoding", "gzip");
|
|
- connection.setRequestProperty("Content-Length", "" + requestData.length);
|
|
+ // this seems to cause issues so we are removing it
|
|
+ //connection.setRequestProperty("Connection", "close");
|
|
+ connection.setRequestProperty("Accept-Encoding", "gzip");
|
|
|
|
- //M: Retry for HTTP Authentication
|
|
- //connection.setFixedLengthStreamingMode(requestData.length);
|
|
|
|
- // Pass the headers provided by the user along with the call
|
|
- if (headers != null) {
|
|
- for (int i = 0; i < headers.size(); i++) {
|
|
- HeaderProperty hp = (HeaderProperty) headers.get(i);
|
|
- connection.setRequestProperty(hp.getKey(), hp.getValue());
|
|
- }
|
|
+ // Pass the headers provided by the user along with the call
|
|
+ if (headers != null) {
|
|
+ for (int i = 0; i < headers.size(); i++) {
|
|
+ HeaderProperty hp = (HeaderProperty) headers.get(i);
|
|
+ connection.setRequestProperty(hp.getKey(), hp.getValue());
|
|
}
|
|
-
|
|
- connection.setRequestMethod("POST");
|
|
-
|
|
- }
|
|
- else {
|
|
- connection.setRequestProperty("Connection", "close");
|
|
- connection.setRequestProperty("Accept-Encoding", "gzip");
|
|
- connection.setRequestMethod("GET");
|
|
}
|
|
|
|
- if (requestData != null) {
|
|
- OutputStream os = connection.openOutputStream();
|
|
-
|
|
- os.write(requestData, 0, requestData.length);
|
|
- os.flush();
|
|
- os.close();
|
|
- requestData = null;
|
|
- }
|
|
- InputStream is;
|
|
+ connection.setRequestMethod("POST");
|
|
+ sendData(requestData, connection,envelope);
|
|
+ requestData = null;
|
|
+ InputStream is = null;
|
|
List retHeaders = null;
|
|
+ byte[] buf = null; // To allow releasing the resource after used
|
|
+ int contentLength = 8192; // To determine the size of the response and adjust buffer size
|
|
boolean gZippedContent = false;
|
|
- boolean bcaCert = false;
|
|
+ boolean xmlContent = false;
|
|
+ int status = connection.getResponseCode();
|
|
|
|
try {
|
|
retHeaders = connection.getResponseProperties();
|
|
- System.out.println("[HttpTransportSE] retHeaders = " + retHeaders);
|
|
+
|
|
for (int i = 0; i < retHeaders.size(); i++) {
|
|
- HeaderProperty hp = (HeaderProperty) retHeaders.get(i);
|
|
+ HeaderProperty hp = (HeaderProperty)retHeaders.get(i);
|
|
// HTTP response code has null key
|
|
if (null == hp.getKey()) {
|
|
continue;
|
|
}
|
|
+
|
|
+ // If we know the size of the response, we should use the size to initiate vars
|
|
+ if (hp.getKey().equalsIgnoreCase("content-length") ) {
|
|
+ if ( hp.getValue() != null ) {
|
|
+ try {
|
|
+ contentLength = Integer.parseInt( hp.getValue() );
|
|
+ } catch ( NumberFormatException nfe ) {
|
|
+ contentLength = 8192;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+
|
|
+ // Check the content-type header to see if we're getting back XML, in case of a
|
|
+ // SOAP fault on 500 codes
|
|
+ if (hp.getKey().equalsIgnoreCase("Content-Type")
|
|
+ && hp.getValue().contains("xml")) {
|
|
+ xmlContent = true;
|
|
+ }
|
|
+
|
|
+
|
|
// ignoring case since users found that all smaller case is used on some server
|
|
// and even if it is wrong according to spec, we rather have it work..
|
|
if (hp.getKey().equalsIgnoreCase("Content-Encoding")
|
|
- && hp.getValue().equalsIgnoreCase("gzip")) {
|
|
+ && hp.getValue().equalsIgnoreCase("gzip")) {
|
|
gZippedContent = true;
|
|
}
|
|
}
|
|
- if (gZippedContent) {
|
|
- is = getUnZippedInputStream(connection.openInputStream());
|
|
- } else {
|
|
- is = connection.openInputStream();
|
|
- }
|
|
- } catch (IOException e) {
|
|
- if (gZippedContent) {
|
|
- is = getUnZippedInputStream(connection.getErrorStream());
|
|
- } else {
|
|
- is = connection.getErrorStream();
|
|
- }
|
|
|
|
- if (is == null) {
|
|
- connection.disconnect();
|
|
- throw (e);
|
|
+ //first check the response code....
|
|
+ if (status != 200 && status != 202) {
|
|
+ //202 is a correct status returned by WCF OneWay operation
|
|
+ throw new HttpResponseException("HTTP request failed, HTTP status: " + status, status,retHeaders);
|
|
}
|
|
- }
|
|
-
|
|
- if (debug) {
|
|
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
- byte[] buf = new byte[8192];
|
|
|
|
- while (true) {
|
|
- int rd = is.read(buf, 0, 8192);
|
|
- if (rd == -1) {
|
|
- break;
|
|
+ if (contentLength > 0) {
|
|
+ if (gZippedContent) {
|
|
+ is = getUnZippedInputStream(
|
|
+ new BufferedInputStream(connection.openInputStream(),contentLength));
|
|
+ } else {
|
|
+ is = new BufferedInputStream(connection.openInputStream(),contentLength);
|
|
+ }
|
|
+ }
|
|
+ } catch (IOException e) {
|
|
+ if (contentLength > 0) {
|
|
+ if(gZippedContent) {
|
|
+ is = getUnZippedInputStream(
|
|
+ new BufferedInputStream(connection.getErrorStream(),contentLength));
|
|
+ } else {
|
|
+ is = new BufferedInputStream(connection.getErrorStream(),contentLength);
|
|
}
|
|
- bos.write(buf, 0, rd);
|
|
}
|
|
|
|
- bos.flush();
|
|
- buf = bos.toByteArray();
|
|
+ if ( e instanceof HttpResponseException) {
|
|
+ if (!xmlContent) {
|
|
+ if (debug && is != null) {
|
|
+ //go ahead and read the error stream into the debug buffers/file if needed.
|
|
+ readDebug(is, contentLength, outputFile);
|
|
+ }
|
|
|
|
- responseDump = new String(buf);
|
|
+ //we never want to drop through to attempting to parse the HTTP error stream as a SOAP response.
|
|
+ connection.disconnect();
|
|
+ throw e;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
|
|
- System.out.println("responseDump:" + responseDump);
|
|
- is.close();
|
|
- is = new ByteArrayInputStream(buf);
|
|
+ if (debug) {
|
|
+ is = readDebug(is, contentLength, outputFile);
|
|
}
|
|
|
|
- if (envelope != null) {
|
|
- parseResponse(envelope, is);
|
|
+ if(is!=null)
|
|
+ {
|
|
+ parseResponse(envelope, is,retHeaders);
|
|
}
|
|
|
|
+ // release all resources
|
|
+ // input stream is will be released inside parseResponse
|
|
+ is = null;
|
|
+ buf = null;
|
|
+ //This fixes Issue 173 read my explanation here: https://code.google.com/p/ksoap2-android/issues/detail?id=173
|
|
+ connection.disconnect();
|
|
+ connection = null;
|
|
return retHeaders;
|
|
}
|
|
|
|
- private InputStream getUnZippedInputStream(InputStream inputStream) throws IOException {
|
|
- /* workaround for Android 2.3
|
|
- (see http://stackoverflow.com/questions/5131016/)
|
|
- */
|
|
- try {
|
|
- return (GZIPInputStream) inputStream;
|
|
- } catch (ClassCastException e) {
|
|
- return new GZIPInputStream(inputStream);
|
|
- }
|
|
- }
|
|
+ protected void sendData(byte[] requestData, ServiceConnection connection, SoapEnvelope envelope)
|
|
+ throws IOException
|
|
+ {
|
|
+ connection.setRequestProperty("Content-Length", "" + requestData.length);
|
|
+ connection.setFixedLengthStreamingMode(requestData.length);
|
|
|
|
- public ServiceConnection getServiceConnection() throws IOException {
|
|
- if (serviceConnection == null) {
|
|
- System.out.println("new ServiceConnectionSE:" + proxy + " " + url + " " + timeout);
|
|
- serviceConnection = new ServiceConnectionSE(proxy, url, timeout);
|
|
- }
|
|
- return serviceConnection;
|
|
+ OutputStream os = connection.openOutputStream();
|
|
+ os.write(requestData, 0, requestData.length);
|
|
+ os.flush();
|
|
+ os.close();
|
|
}
|
|
|
|
- public String getHost() {
|
|
-
|
|
- String retVal = null;
|
|
-
|
|
- try {
|
|
- retVal = new URL(url).getHost();
|
|
- } catch (MalformedURLException e) {
|
|
- e.printStackTrace();
|
|
- }
|
|
-
|
|
- return retVal;
|
|
+ protected void parseResponse(SoapEnvelope envelope, InputStream is,List returnedHeaders)
|
|
+ throws XmlPullParserException, IOException
|
|
+ {
|
|
+ parseResponse(envelope, is);
|
|
}
|
|
|
|
- public int getPort() {
|
|
-
|
|
- int retVal = -1;
|
|
|
|
- try {
|
|
- retVal = new URL(url).getPort();
|
|
- } catch (MalformedURLException e) {
|
|
- e.printStackTrace();
|
|
+ private InputStream readDebug(InputStream is, int contentLength, File outputFile) throws IOException {
|
|
+ OutputStream bos;
|
|
+ if (outputFile != null) {
|
|
+ bos = new FileOutputStream(outputFile);
|
|
+ } else {
|
|
+ // If known use the size if not use default value
|
|
+ bos = new ByteArrayOutputStream( (contentLength > 0 ) ? contentLength : 256*1024);
|
|
}
|
|
|
|
- return retVal;
|
|
- }
|
|
-
|
|
- public String getPath() {
|
|
-
|
|
- String retVal = null;
|
|
+ byte[] buf = new byte[256];
|
|
|
|
- try {
|
|
- retVal = new URL(url).getPath();
|
|
- } catch (MalformedURLException e) {
|
|
- e.printStackTrace();
|
|
+ while (true) {
|
|
+ int rd = is.read(buf, 0, 256);
|
|
+ if (rd == -1) {
|
|
+ break;
|
|
+ }
|
|
+ bos.write(buf, 0, rd);
|
|
}
|
|
|
|
- return retVal;
|
|
- }
|
|
-
|
|
- public String getQuery() {
|
|
-
|
|
- String retVal = null;
|
|
-
|
|
- try {
|
|
- retVal = new URL(url).getQuery();
|
|
- } catch (MalformedURLException e) {
|
|
- e.printStackTrace();
|
|
+ bos.flush();
|
|
+ if (bos instanceof ByteArrayOutputStream) {
|
|
+ buf = ((ByteArrayOutputStream) bos).toByteArray();
|
|
+ }
|
|
+ bos = null;
|
|
+ responseDump = new String(buf);
|
|
+ is.close();
|
|
+ System.out.println("responseDump: " + requestDump);
|
|
+ if (outputFile != null) {
|
|
+ return new FileInputStream(outputFile);
|
|
+ } else {
|
|
+ return new ByteArrayInputStream(buf);
|
|
}
|
|
-
|
|
- return retVal;
|
|
}
|
|
|
|
- /**
|
|
- * @hide
|
|
- */
|
|
- public byte[] getRequestData(SoapEnvelope envelope, String encoding) {
|
|
+ private InputStream getUnZippedInputStream(InputStream inputStream) throws IOException {
|
|
+ /* workaround for Android 2.3
|
|
+ (see http://stackoverflow.com/questions/5131016/)
|
|
+ */
|
|
try {
|
|
- return createRequestData(envelope, encoding);
|
|
- } catch (Exception e) {
|
|
- e.printStackTrace();
|
|
+ return (GZIPInputStream) inputStream;
|
|
+ } catch (ClassCastException e) {
|
|
+ return new GZIPInputStream(inputStream);
|
|
}
|
|
+ }
|
|
|
|
- return null;
|
|
+ public ServiceConnection getServiceConnection() throws IOException {
|
|
+ return new ServiceConnectionSE(proxy, url, timeout);
|
|
}
|
|
}
|
|
diff --git a/ksoap2-j2se/src/main/java/org/ksoap2/transport/HttpsServiceConnectionSE.java b/ksoap2-j2se/src/main/java/org/ksoap2/transport/HttpsServiceConnectionSE.java
|
|
index 9ad9ba9..376c7d8 100644
|
|
--- a/ksoap2-j2se/src/main/java/org/ksoap2/transport/HttpsServiceConnectionSE.java
|
|
+++ b/ksoap2-j2se/src/main/java/org/ksoap2/transport/HttpsServiceConnectionSE.java
|
|
@@ -1,21 +1,16 @@
|
|
|
|
package org.ksoap2.transport;
|
|
|
|
+import org.ksoap2.HeaderProperty;
|
|
+
|
|
+import javax.net.ssl.HttpsURLConnection;
|
|
+import javax.net.ssl.SSLSocketFactory;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.OutputStream;
|
|
+import java.net.Proxy;
|
|
import java.net.URL;
|
|
-import java.util.Iterator;
|
|
-import java.util.LinkedList;
|
|
-import java.util.Map;
|
|
-import java.util.List;
|
|
-import java.util.Set;
|
|
-
|
|
-import javax.net.ssl.HostnameVerifier;
|
|
-import javax.net.ssl.SSLSocketFactory;
|
|
-import javax.net.ssl.HttpsURLConnection;
|
|
-//import com.android.okhttp.internal.http.HttpsURLConnectionImpl;
|
|
-import org.ksoap2.HeaderProperty;
|
|
+import java.util.*;
|
|
|
|
/**
|
|
* HttpsServiceConnectionSE is a service connection that uses a https url connection and requires explicit setting of
|
|
@@ -49,10 +44,29 @@ public class HttpsServiceConnectionSE implements ServiceConnection {
|
|
* @param timeout the timeout for the connection in milliseconds
|
|
* @throws IOException
|
|
*/
|
|
- public HttpsServiceConnectionSE(String host, int port, String file,
|
|
- int timeout) throws IOException {
|
|
- connection = (HttpsURLConnection) new URL(HttpsTransportSE.PROTOCOL, host, port, file)
|
|
- .openConnection();
|
|
+ public HttpsServiceConnectionSE(String host, int port, String file, int timeout) throws IOException {
|
|
+ this(null, host, port, file, timeout);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Create the transport with the supplied parameters.
|
|
+ * @param proxy proxy server to use
|
|
+ * @param host the name of the host e.g. webservices.somewhere.com
|
|
+ * @param port the http port to connect on
|
|
+ * @param file the path to the file on the webserver that represents the
|
|
+ * webservice e.g. /api/services/myservice.jsp
|
|
+ * @param timeout the timeout for the connection in milliseconds
|
|
+ * @throws IOException
|
|
+ */
|
|
+ public HttpsServiceConnectionSE(Proxy proxy, String host, int port, String file, int timeout) throws IOException {
|
|
+
|
|
+ if (proxy == null) {
|
|
+ connection = (HttpsURLConnection) new URL(HttpsTransportSE.PROTOCOL, host, port, file).openConnection();
|
|
+ } else {
|
|
+ connection =
|
|
+ (HttpsURLConnection) new URL(HttpsTransportSE.PROTOCOL, host, port, file).openConnection(proxy);
|
|
+ }
|
|
+
|
|
updateConnectionParameters(timeout);
|
|
}
|
|
|
|
@@ -89,6 +103,10 @@ public class HttpsServiceConnectionSE implements ServiceConnection {
|
|
return retList;
|
|
}
|
|
|
|
+ public int getResponseCode() throws IOException {
|
|
+ return connection.getResponseCode();
|
|
+ }
|
|
+
|
|
public void setRequestProperty(String key, String value) {
|
|
connection.setRequestProperty(key, value);
|
|
}
|
|
@@ -101,6 +119,11 @@ public class HttpsServiceConnectionSE implements ServiceConnection {
|
|
connection.setFixedLengthStreamingMode(contentLength);
|
|
}
|
|
|
|
+ public void setChunkedStreamingMode() {
|
|
+ connection.setChunkedStreamingMode(0);
|
|
+ }
|
|
+
|
|
+
|
|
public OutputStream openOutputStream() throws IOException {
|
|
return connection.getOutputStream();
|
|
}
|
|
@@ -128,9 +151,4 @@ public class HttpsServiceConnectionSE implements ServiceConnection {
|
|
public void setSSLSocketFactory(SSLSocketFactory sf) {
|
|
connection.setSSLSocketFactory(sf);
|
|
}
|
|
-
|
|
- public void setHostnameVerifier(HostnameVerifier v) {
|
|
- connection.setHostnameVerifier(v);
|
|
- }
|
|
-
|
|
}
|
|
diff --git a/ksoap2-j2se/src/main/java/org/ksoap2/transport/HttpsTransportSE.java b/ksoap2-j2se/src/main/java/org/ksoap2/transport/HttpsTransportSE.java
|
|
index d220ac9..a7d7023 100644
|
|
--- a/ksoap2-j2se/src/main/java/org/ksoap2/transport/HttpsTransportSE.java
|
|
+++ b/ksoap2-j2se/src/main/java/org/ksoap2/transport/HttpsTransportSE.java
|
|
@@ -1,8 +1,8 @@
|
|
-
|
|
package org.ksoap2.transport;
|
|
|
|
import java.io.IOException;
|
|
import java.net.MalformedURLException;
|
|
+import java.net.Proxy;
|
|
import java.net.URL;
|
|
|
|
/**
|
|
@@ -14,17 +14,31 @@ import java.net.URL;
|
|
public class HttpsTransportSE extends HttpTransportSE {
|
|
|
|
static final String PROTOCOL = "https";
|
|
+ private static final String PROTOCOL_FULL = PROTOCOL + "://";
|
|
+
|
|
+ //connection instance, used for setting the SSLSocketFactory
|
|
+ private HttpsServiceConnectionSE connection;
|
|
|
|
- private ServiceConnection serviceConnection = null;
|
|
- private final String host;
|
|
- private final int port;
|
|
- private final String file;
|
|
- private final int timeout;
|
|
+ protected final String host;
|
|
+ protected final int port;
|
|
+ protected final String file;
|
|
|
|
- public HttpsTransportSE(String host, int port, String file, int timeout) {
|
|
- super(HttpsTransportSE.PROTOCOL + "://" + host + ":" + port + file);
|
|
- System.out.println("Establistion connection to: " + HttpsTransportSE.PROTOCOL + "://"
|
|
- + host + ":" + port + file);
|
|
+ public HttpsTransportSE (String host, int port, String file, int timeout) {
|
|
+ super(HttpsTransportSE.PROTOCOL_FULL + host + ":" + port + file, timeout);
|
|
+ this.host = host;
|
|
+ this.port = port;
|
|
+ this.file = file;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Creates instance of HttpTransportSE with set url and defines a
|
|
+ * proxy server to use to access it
|
|
+ *
|
|
+ * @param proxy
|
|
+ * Proxy information or <code>null</code> for direct access
|
|
+ */
|
|
+ public HttpsTransportSE(Proxy proxy, String host, int port, String file, int timeout) {
|
|
+ super(proxy, HttpsTransportSE.PROTOCOL_FULL + host + ":" + port + file);
|
|
this.host = host;
|
|
this.port = port;
|
|
this.file = file;
|
|
@@ -37,48 +51,11 @@ public class HttpsTransportSE extends HttpTransportSE {
|
|
*/
|
|
public ServiceConnection getServiceConnection() throws IOException
|
|
{
|
|
- if (serviceConnection == null) {
|
|
- serviceConnection = new HttpsServiceConnectionSE(host, port, file, timeout);
|
|
- }
|
|
- return serviceConnection;
|
|
- }
|
|
-
|
|
- public String getHost() {
|
|
-
|
|
- String retVal = null;
|
|
-
|
|
- try {
|
|
- retVal = new URL(url).getHost();
|
|
- } catch (MalformedURLException e) {
|
|
- e.printStackTrace();
|
|
+ if(connection != null) {
|
|
+ return connection;
|
|
+ } else {
|
|
+ connection = new HttpsServiceConnectionSE(proxy, host, port, file, timeout);
|
|
+ return connection;
|
|
}
|
|
-
|
|
- return retVal;
|
|
- }
|
|
-
|
|
- public int getPort() {
|
|
-
|
|
- int retVal = -1;
|
|
-
|
|
- try {
|
|
- retVal = new URL(url).getPort();
|
|
- } catch (MalformedURLException e) {
|
|
- e.printStackTrace();
|
|
- }
|
|
-
|
|
- return retVal;
|
|
- }
|
|
-
|
|
- public String getPath() {
|
|
-
|
|
- String retVal = null;
|
|
-
|
|
- try {
|
|
- retVal = new URL(url).getPath();
|
|
- } catch (MalformedURLException e) {
|
|
- e.printStackTrace();
|
|
- }
|
|
-
|
|
- return retVal;
|
|
}
|
|
}
|
|
diff --git a/ksoap2-j2se/src/main/java/org/ksoap2/transport/KeepAliveHttpsTransportSE.java b/ksoap2-j2se/src/main/java/org/ksoap2/transport/KeepAliveHttpsTransportSE.java
|
|
index 287fed1..65ba582 100644
|
|
--- a/ksoap2-j2se/src/main/java/org/ksoap2/transport/KeepAliveHttpsTransportSE.java
|
|
+++ b/ksoap2-j2se/src/main/java/org/ksoap2/transport/KeepAliveHttpsTransportSE.java
|
|
@@ -24,18 +24,8 @@ import java.io.IOException;
|
|
*/
|
|
public class KeepAliveHttpsTransportSE extends HttpsTransportSE
|
|
{
|
|
- private final String host;
|
|
- private final int port;
|
|
- private final String file;
|
|
- private final int timeout;
|
|
- private ServiceConnection serviceConnection;
|
|
-
|
|
- public KeepAliveHttpsTransportSE(String host, int port, String file, int timeout) {
|
|
+ public KeepAliveHttpsTransportSE (String host, int port, String file, int timeout) {
|
|
super(host, port, file, timeout);
|
|
- this.host = host;
|
|
- this.port = port;
|
|
- this.file = file;
|
|
- this.timeout = timeout;
|
|
}
|
|
|
|
/**
|
|
@@ -47,11 +37,9 @@ public class KeepAliveHttpsTransportSE extends HttpsTransportSE
|
|
//@Override
|
|
public ServiceConnection getServiceConnection() throws IOException
|
|
{
|
|
- if (serviceConnection == null) {
|
|
- serviceConnection = new HttpsServiceConnectionSEIgnoringConnectionClose(host, port,
|
|
- file, timeout);
|
|
- serviceConnection.setRequestProperty("Connection", "keep-alive");
|
|
- }
|
|
+ ServiceConnection serviceConnection =
|
|
+ new HttpsServiceConnectionSEIgnoringConnectionClose(host, port, file, timeout);
|
|
+ serviceConnection.setRequestProperty("Connection", "keep-alive");
|
|
return serviceConnection;
|
|
}
|
|
|
|
diff --git a/ksoap2-j2se/src/main/java/org/ksoap2/transport/ServiceConnectionSE.java b/ksoap2-j2se/src/main/java/org/ksoap2/transport/ServiceConnectionSE.java
|
|
index 029ee9a..bfdfe11 100644
|
|
--- a/ksoap2-j2se/src/main/java/org/ksoap2/transport/ServiceConnectionSE.java
|
|
+++ b/ksoap2-j2se/src/main/java/org/ksoap2/transport/ServiceConnectionSE.java
|
|
@@ -21,16 +21,16 @@
|
|
|
|
package org.ksoap2.transport;
|
|
|
|
-import java.io.*;
|
|
-import java.net.*;
|
|
-import java.util.Iterator;
|
|
-import java.util.LinkedList;
|
|
-import java.util.List;
|
|
-import java.util.Map;
|
|
-import java.util.Set;
|
|
-
|
|
import org.ksoap2.HeaderProperty;
|
|
|
|
+import java.io.IOException;
|
|
+import java.io.InputStream;
|
|
+import java.io.OutputStream;
|
|
+import java.net.HttpURLConnection;
|
|
+import java.net.Proxy;
|
|
+import java.net.URL;
|
|
+import java.util.*;
|
|
+
|
|
/**
|
|
* Connection for J2SE environments.
|
|
*/
|
|
@@ -80,23 +80,29 @@ public class ServiceConnectionSE implements ServiceConnection {
|
|
connection.disconnect();
|
|
}
|
|
|
|
- public List getResponseProperties() {
|
|
- Map properties = connection.getHeaderFields();
|
|
- Set keys = properties.keySet();
|
|
+ public List getResponseProperties() throws IOException {
|
|
List retList = new LinkedList();
|
|
|
|
- for (Iterator i = keys.iterator(); i.hasNext();) {
|
|
- String key = (String) i.next();
|
|
- List values = (List) properties.get(key);
|
|
-
|
|
- for (int j = 0; j < values.size(); j++) {
|
|
- retList.add(new HeaderProperty(key, (String) values.get(j)));
|
|
+ Map properties = connection.getHeaderFields();
|
|
+ if(properties != null) {
|
|
+ Set keys = properties.keySet();
|
|
+ for (Iterator i = keys.iterator(); i.hasNext();) {
|
|
+ String key = (String) i.next();
|
|
+ List values = (List) properties.get(key);
|
|
+
|
|
+ for (int j = 0; j < values.size(); j++) {
|
|
+ retList.add(new HeaderProperty(key, (String) values.get(j)));
|
|
+ }
|
|
}
|
|
}
|
|
|
|
return retList;
|
|
}
|
|
|
|
+ public int getResponseCode() throws IOException {
|
|
+ return connection.getResponseCode();
|
|
+ }
|
|
+
|
|
public void setRequestProperty(String string, String soapAction) {
|
|
connection.setRequestProperty(string, soapAction);
|
|
}
|
|
@@ -116,6 +122,10 @@ public class ServiceConnectionSE implements ServiceConnection {
|
|
connection.setFixedLengthStreamingMode(contentLength);
|
|
}
|
|
|
|
+ public void setChunkedStreamingMode() {
|
|
+ connection.setChunkedStreamingMode(0);
|
|
+ }
|
|
+
|
|
public OutputStream openOutputStream() throws IOException {
|
|
return connection.getOutputStream();
|
|
}
|
|
--
|
|
2.17.0.441.gb46fe60e1d-goog
|
|
|