From eed242264b9c3da9ec947e143da4f055c8085410 Mon Sep 17 00:00:00 2001 From: Felipe Barriga Richards Date: Tue, 7 Feb 2017 12:37:12 -0300 Subject: [PATCH 1/5] gradle: Update gradle 2.1.0 => 2.2.3 --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 5657e594..1017cb40 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.1.0' + classpath 'com.android.tools.build:gradle:2.2.3' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2890231d..c8da4d7d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Jan 20 12:20:00 CET 2016 +#Tue Feb 07 12:36:33 CLT 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip From 3fa6bf9bdc860459907224f1cd0dc4701a8ffcf7 Mon Sep 17 00:00:00 2001 From: Felipe Barriga Richards Date: Mon, 6 Feb 2017 15:49:45 -0300 Subject: [PATCH 2/5] axmlrpc: Use XmlPullParser to deserialize xml objects. Serialization remains the same. Code copied from WordPress-Android. https://github.com/wordpress-mobile/WordPress-Android --- .../de/timroes/axmlrpc/ResponseParser.java | 92 ++++----- .../axmlrpc/serializer/ArraySerializer.java | 33 --- .../axmlrpc/serializer/Base64Serializer.java | 4 - .../axmlrpc/serializer/BooleanSerializer.java | 5 - .../serializer/DateTimeSerializer.java | 12 +- .../axmlrpc/serializer/DoubleSerializer.java | 4 - .../axmlrpc/serializer/IntSerializer.java | 4 - .../axmlrpc/serializer/LongSerializer.java | 4 - .../axmlrpc/serializer/NullSerializer.java | 4 - .../axmlrpc/serializer/Serializer.java | 9 - .../axmlrpc/serializer/SerializerHandler.java | 191 ++++++++++++------ .../axmlrpc/serializer/StringSerializer.java | 11 +- .../axmlrpc/serializer/StructSerializer.java | 59 ------ 13 files changed, 165 insertions(+), 267 deletions(-) diff --git a/app/src/main/java/de/timroes/axmlrpc/ResponseParser.java b/app/src/main/java/de/timroes/axmlrpc/ResponseParser.java index b0968963..b6d110f1 100644 --- a/app/src/main/java/de/timroes/axmlrpc/ResponseParser.java +++ b/app/src/main/java/de/timroes/axmlrpc/ResponseParser.java @@ -3,10 +3,10 @@ package de.timroes.axmlrpc; import de.timroes.axmlrpc.serializer.SerializerHandler; import java.io.InputStream; import java.util.Map; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlPullParserFactory; /** * The ResponseParser parses the response of an XMLRPC server to an object. @@ -28,69 +28,45 @@ class ResponseParser { * @throws XMLRPCServerException Will be thrown, if the server returns an error. */ public Object parse(InputStream response) throws XMLRPCException { - try { - - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document dom = builder.parse(response); - Element e = dom.getDocumentElement(); - - // Check for root tag - if(!e.getNodeName().equals(XMLRPCClient.METHOD_RESPONSE)) { - throw new XMLRPCException("MethodResponse root tag is missing."); - } - - e = XMLUtil.getOnlyChildElement(e.getChildNodes()); - - if(e.getNodeName().equals(XMLRPCClient.PARAMS)) { - - e = XMLUtil.getOnlyChildElement(e.getChildNodes()); - - if(!e.getNodeName().equals(XMLRPCClient.PARAM)) { - throw new XMLRPCException("The params tag must contain a param tag."); + XmlPullParser pullParser = XmlPullParserFactory.newInstance().newPullParser(); + pullParser.setInput(response, "UTF-8"); + + pullParser.nextTag(); + pullParser.require(XmlPullParser.START_TAG, null, XMLRPCClient.METHOD_RESPONSE); + + pullParser.nextTag(); // either TAG_PARAMS () or TAG_FAULT () + String tag = pullParser.getName(); + if (tag.equals(XMLRPCClient.PARAMS)) { + // normal response + pullParser.nextTag(); // TAG_PARAM () + pullParser.require(XmlPullParser.START_TAG, null, XMLRPCClient.PARAM); + pullParser.nextTag(); // TAG_VALUE () + // no parser.require() here since its called in XMLRPCSerializer.deserialize() below + // deserialize result + Object obj = SerializerHandler.getDefault().deserialize(pullParser); + return obj; + } else if (tag.equals(XMLRPCClient.FAULT)) { + // fault response + pullParser.nextTag(); // TAG_VALUE () + Map map = (Map) SerializerHandler.getDefault().deserialize(pullParser); + + //Check that required tags are in the response + if (!map.containsKey(FAULT_STRING) || !map.containsKey(FAULT_CODE)) { + throw new XMLRPCException("Bad XMLRPC Fault response received - and/or missing!"); } - - return getReturnValueFromElement(e); - - } else if(e.getNodeName().equals(XMLRPCClient.FAULT)) { - - @SuppressWarnings("unchecked") - Map o = (Map)getReturnValueFromElement(e); - - throw new XMLRPCServerException((String)o.get(FAULT_STRING), (Integer)o.get(FAULT_CODE)); - + throw new XMLRPCServerException((String) map.get(FAULT_STRING), (Integer) map.get(FAULT_CODE)); + } else { + throw new XMLRPCException("Bad tag <" + tag + "> in XMLRPC response - neither nor "); } - throw new XMLRPCException("The methodResponse tag must contain a fault or params tag."); - + } catch (XmlPullParserException ex) { + throw new XMLRPCException("Error parsing response.", ex); } catch (Exception ex) { - if(ex instanceof XMLRPCServerException) throw (XMLRPCServerException)ex; else throw new XMLRPCException("Error getting result from server.", ex); - } - } - - /** - * This method takes an element (must be a param or fault element) and - * returns the deserialized object of this param tag. - * - * @param element An param element. - * @return The deserialized object within the given param element. - * @throws XMLRPCException Will be thrown when the structure of the document - * doesn't match the XML-RPC specification. - */ - private Object getReturnValueFromElement(Element element) throws XMLRPCException { - - element = XMLUtil.getOnlyChildElement(element.getChildNodes()); - - return SerializerHandler.getDefault().deserialize(element); - - } - } \ No newline at end of file diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/ArraySerializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/ArraySerializer.java index 5850f806..3e48151c 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/ArraySerializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/ArraySerializer.java @@ -18,39 +18,6 @@ public class ArraySerializer implements Serializer { private static final String ARRAY_DATA = "data"; private static final String ARRAY_VALUE = "value"; - public Object deserialize(Element content) throws XMLRPCException { - - List list = new ArrayList(); - - Element data = XMLUtil.getOnlyChildElement(content.getChildNodes()); - - if(!ARRAY_DATA.equals(data.getNodeName())) { - throw new XMLRPCException("The array must contain one data tag."); - } - - // Deserialize every array element - Node value; - for(int i = 0; i < data.getChildNodes().getLength(); i++) { - - value = data.getChildNodes().item(i); - - // Strip only whitespace text elements and comments - if(value == null || (value.getNodeType() == Node.TEXT_NODE - && value.getNodeValue().trim().length() <= 0) - || value.getNodeType() == Node.COMMENT_NODE) - continue; - - if(value.getNodeType() != Node.ELEMENT_NODE) { - throw new XMLRPCException("Wrong element inside of array."); - } - - list.add(SerializerHandler.getDefault().deserialize((Element)value)); - - } - - return list.toArray(); - } - public XmlElement serialize(Object object) { Iterable iter = (Iterable)object; diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/Base64Serializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/Base64Serializer.java index d8e468e9..bffa40bb 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/Base64Serializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/Base64Serializer.java @@ -12,10 +12,6 @@ import org.w3c.dom.Element; */ public class Base64Serializer implements Serializer { - public Object deserialize(Element content) throws XMLRPCException { - return Base64.decode(XMLUtil.getOnlyTextContent(content.getChildNodes())); - } - public XmlElement serialize(Object object) { return XMLUtil.makeXmlTag(SerializerHandler.TYPE_BASE64, Base64.encode((Byte[])object)); diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/BooleanSerializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/BooleanSerializer.java index 4267b092..74bf0fbe 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/BooleanSerializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/BooleanSerializer.java @@ -11,11 +11,6 @@ import org.w3c.dom.Element; */ public class BooleanSerializer implements Serializer { - public Object deserialize(Element content) throws XMLRPCException { - return (XMLUtil.getOnlyTextContent(content.getChildNodes()).equals("1")) - ? Boolean.TRUE : Boolean.FALSE; - } - public XmlElement serialize(Object object) { return XMLUtil.makeXmlTag(SerializerHandler.TYPE_BOOLEAN, ((Boolean)object == true) ? "1" : "0"); diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/DateTimeSerializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/DateTimeSerializer.java index a95219a5..b55e4875 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/DateTimeSerializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/DateTimeSerializer.java @@ -13,16 +13,8 @@ import org.w3c.dom.Element; */ public class DateTimeSerializer implements Serializer { - private static final String DATETIME_FORMAT = "yyyyMMdd'T'HH:mm:ss"; - private static final SimpleDateFormat DATE_FORMATER = new SimpleDateFormat(DATETIME_FORMAT); - - public Object deserialize(Element content) throws XMLRPCException { - try { - return DATE_FORMATER.parse(XMLUtil.getOnlyTextContent(content.getChildNodes())); - } catch (ParseException ex) { - throw new XMLRPCException("Unable to parse given date.", ex); - } - } + public static final String DATETIME_FORMAT = "yyyyMMdd'T'HH:mm:ss"; + public static final SimpleDateFormat DATE_FORMATER = new SimpleDateFormat(DATETIME_FORMAT); public XmlElement serialize(Object object) { return XMLUtil.makeXmlTag(SerializerHandler.TYPE_DATETIME, diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/DoubleSerializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/DoubleSerializer.java index 361ca2d1..3f0b7941 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/DoubleSerializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/DoubleSerializer.java @@ -13,10 +13,6 @@ import org.w3c.dom.Element; */ public class DoubleSerializer implements Serializer { - public Object deserialize(Element content) throws XMLRPCException { - return Double.valueOf(XMLUtil.getOnlyTextContent(content.getChildNodes())); - } - public XmlElement serialize(Object object) { // Turn double value of object into a BigDecimal to get the // right decimal point format. diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/IntSerializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/IntSerializer.java index 5d7b23db..f8f48d7e 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/IntSerializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/IntSerializer.java @@ -11,10 +11,6 @@ import org.w3c.dom.Element; */ public class IntSerializer implements Serializer { - public Object deserialize(Element content) throws XMLRPCException { - return Integer.parseInt(XMLUtil.getOnlyTextContent(content.getChildNodes())); - } - public XmlElement serialize(Object object) { return XMLUtil.makeXmlTag(SerializerHandler.TYPE_INT, object.toString()); diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/LongSerializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/LongSerializer.java index 15ba9f65..1952fb2e 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/LongSerializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/LongSerializer.java @@ -11,10 +11,6 @@ import org.w3c.dom.Element; */ class LongSerializer implements Serializer { - public Object deserialize(Element content) throws XMLRPCException { - return Long.parseLong(XMLUtil.getOnlyTextContent(content.getChildNodes())); - } - public XmlElement serialize(Object object) { return XMLUtil.makeXmlTag(SerializerHandler.TYPE_LONG, ((Long)object).toString()); diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/NullSerializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/NullSerializer.java index e1619b61..ae3424eb 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/NullSerializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/NullSerializer.java @@ -10,10 +10,6 @@ import org.w3c.dom.Element; */ public class NullSerializer implements Serializer { - public Object deserialize(Element content) throws XMLRPCException { - return null; - } - public XmlElement serialize(Object object) { return new XmlElement(SerializerHandler.TYPE_NULL); } diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/Serializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/Serializer.java index c139ebce..5a64c423 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/Serializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/Serializer.java @@ -12,15 +12,6 @@ import org.w3c.dom.Element; */ public interface Serializer { - /** - * This method takes an xml type element and deserialize it to an object. - * - * @param content Must be an xml element of a specific type. - * @return The deserialized content. - * @throws XMLRPCException Will be thrown whenervt the deserialization fails. - */ - public Object deserialize(Element content) throws XMLRPCException; - /** * This method takes an object and returns a representation as a string * containing the right xml type tag. The returning string must be useable diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/SerializerHandler.java b/app/src/main/java/de/timroes/axmlrpc/serializer/SerializerHandler.java index 02f25d40..ab81c476 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/SerializerHandler.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/SerializerHandler.java @@ -5,11 +5,27 @@ import de.timroes.axmlrpc.XMLRPCException; import de.timroes.axmlrpc.XMLRPCRuntimeException; import de.timroes.axmlrpc.XMLUtil; import de.timroes.axmlrpc.xmlcreator.XmlElement; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; import java.math.BigDecimal; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Calendar; import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; import java.util.Map; -import org.w3c.dom.Element; +import java.util.SimpleTimeZone; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import android.util.Base64; +import android.util.Log; /** * The serializer handler serializes and deserialized objects. @@ -21,6 +37,18 @@ import org.w3c.dom.Element; * @author Tim Roes */ public class SerializerHandler { + private static final String LOG_NAME = "SerializerHandler"; + + public static final String TAG_NAME = "name"; + public static final String TAG_MEMBER = "member"; + public static final String TAG_VALUE = "value"; + public static final String TAG_DATA = "data"; + + + public static final String TYPE_DATE_TIME_ISO8601 = "dateTime.iso8601"; + + static SimpleDateFormat dateFormat = DateTimeSerializer.DATE_FORMATER; + static Calendar cal = Calendar.getInstance(new SimpleTimeZone(0, "GMT")); public static final String TYPE_STRING = "string"; public static final String TYPE_BOOLEAN = "boolean"; @@ -81,83 +109,120 @@ public class SerializerHandler { */ private SerializerHandler(int flags) { this.flags = flags; - string = new StringSerializer( - (flags & XMLRPCClient.FLAGS_NO_STRING_ENCODE) == 0, - (flags & XMLRPCClient.FLAGS_NO_STRING_DECODE) == 0 - ); + string = new StringSerializer((flags & XMLRPCClient.FLAGS_NO_STRING_ENCODE) == 0); } /** - * Deserializes an incoming xml element to an java object. - * The xml element must be the value element around the type element. + * Deserialize an incoming xml to a java object. * The type of the returning object depends on the type tag. * - * @param element An type element from within a value tag. + * @param parser Initialized parser. * @return The deserialized object. - * @throws XMLRPCException Will be thrown whenever an error occurs. + * @throws XmlPullParserException + * @throws IOException + * @throws NumberFormatException */ - public Object deserialize(Element element) throws XMLRPCException { + public static Object deserialize(XmlPullParser parser) throws XmlPullParserException, IOException, NumberFormatException { + parser.require(XmlPullParser.START_TAG, null, TAG_VALUE); - if(!XMLRPCClient.VALUE.equals(element.getNodeName())) { - throw new XMLRPCException("Value tag is missing around value."); - } - - if(!XMLUtil.hasChildElement(element.getChildNodes())) { - // Value element doesn't contain a child element - if((flags & XMLRPCClient.FLAGS_DEFAULT_TYPE_STRING) != 0) { - return string.deserialize(element); - } else { - throw new XMLRPCException("Missing type element inside of value element."); - } - } - - // Grep type element from inside value element - element = XMLUtil.getOnlyChildElement(element.getChildNodes()); - - Serializer s = null; + parser.nextTag(); + String typeNodeName = parser.getName(); - String type; - - // If FLAGS_IGNORE_NAMESPACE has been set, only use local name. - if((flags & XMLRPCClient.FLAGS_IGNORE_NAMESPACES) != 0) { - type = element.getLocalName() == null ? element.getNodeName() : element.getLocalName(); - } else { - type = element.getNodeName(); - } + Object obj; + if (typeNodeName.equals(TYPE_INT) || typeNodeName.equals(TYPE_INT2)) { + String value = parser.nextText(); + try { + obj = Integer.parseInt(value); + } catch (NumberFormatException nfe) { + Log.w(LOG_NAME, "Server replied with an invalid 4 bytes int value, trying to parse it as 8 bytes long."); + obj = Long.parseLong(value); + } + } else + if (typeNodeName.equals(TYPE_LONG)) { + String value = parser.nextText(); + obj = Long.parseLong(value); + } else + if (typeNodeName.equals(TYPE_DOUBLE)) { + String value = parser.nextText(); + obj = Double.parseDouble(value); + } else + if (typeNodeName.equals(TYPE_BOOLEAN)) { + String value = parser.nextText(); + obj = value.equals("1") ? Boolean.TRUE : Boolean.FALSE; + } else + if (typeNodeName.equals(TYPE_STRING)) { + obj = parser.nextText(); + } else + if (typeNodeName.equals(TYPE_DATE_TIME_ISO8601)) { + dateFormat.setCalendar(cal); + String value = parser.nextText(); + try { + obj = dateFormat.parseObject(value); + } catch (ParseException e) { + Log.e(LOG_NAME, "Error parsing date, using non-parsed string."); + obj = value; + } + } else + if (typeNodeName.equals(TYPE_BASE64)) { + String value = parser.nextText(); + BufferedReader reader = new BufferedReader(new StringReader(value)); + String line; + StringBuffer sb = new StringBuffer(); + while ((line = reader.readLine()) != null) { + sb.append(line); + } + obj = Base64.decode(sb.toString(), Base64.DEFAULT); + } else + if (typeNodeName.equals(TYPE_ARRAY)) { + parser.nextTag(); // TAG_DATA () + parser.require(XmlPullParser.START_TAG, null, TAG_DATA); - if((flags & XMLRPCClient.FLAGS_NIL) != 0 && TYPE_NULL.equals(type)) { - s = nil; - } else if(TYPE_STRING.equals(type)) { - s = string; - } else if(TYPE_BOOLEAN.equals(type)) { - s = bool; - } else if(TYPE_DOUBLE.equals(type)) { - s = floating; - } else if (TYPE_INT.equals(type) || TYPE_INT2.equals(type)) { - s = integer; - } else if(TYPE_DATETIME.equals(type)) { - s = datetime; - } else if (TYPE_LONG.equals(type)) { - if((flags & XMLRPCClient.FLAGS_8BYTE_INT) != 0) { - s = long8; - } else { - throw new XMLRPCException("8 byte integer is not in the specification. " - + "You must use FLAGS_8BYTE_INT to enable the i8 tag."); + parser.nextTag(); + List list = new ArrayList(); + while (parser.getName().equals(TAG_VALUE)) { + list.add(deserialize(parser)); + parser.nextTag(); } - } else if(TYPE_STRUCT.equals(type)) { - s = struct; - } else if(TYPE_ARRAY.equals(type)) { - s = array; - } else if(TYPE_BASE64.equals(type)) { - s = base64; + parser.require(XmlPullParser.END_TAG, null, TAG_DATA); + parser.nextTag(); // TAG_ARRAY () + parser.require(XmlPullParser.END_TAG, null, TYPE_ARRAY); + obj = list.toArray(); + } else + if (typeNodeName.equals(TYPE_STRUCT)) { + parser.nextTag(); + Map map = new HashMap(); + while (parser.getName().equals(TAG_MEMBER)) { + String memberName = null; + Object memberValue = null; + while (true) { + parser.nextTag(); + String name = parser.getName(); + if (name.equals(TAG_NAME)) { + memberName = parser.nextText(); + } else + if (name.equals(TAG_VALUE)) { + memberValue = deserialize(parser); + } else { + break; + } + } + if (memberName != null && memberValue != null) { + map.put(memberName, memberValue); + } + parser.require(XmlPullParser.END_TAG, null, TAG_MEMBER); + parser.nextTag(); + } + parser.require(XmlPullParser.END_TAG, null, TYPE_STRUCT); + obj = map; } else { - throw new XMLRPCException("No deserializer found for type '" + type + "'."); + throw new IOException("Cannot deserialize " + parser.getName()); } - - return s.deserialize(element); - + parser.nextTag(); // TAG_VALUE () + parser.require(XmlPullParser.END_TAG, null, TAG_VALUE); + return obj; } + /** * Serialize an object to its representation as an xml element. * The xml element will be the type element for the use within a value tag. diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/StringSerializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/StringSerializer.java index 1ef1ee9e..8712a486 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/StringSerializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/StringSerializer.java @@ -11,21 +11,12 @@ import org.w3c.dom.Element; */ public class StringSerializer implements Serializer { - private boolean decodeStrings; private boolean encodeStrings; - public StringSerializer(boolean encodeStrings, boolean decodeStrings) { - this.decodeStrings = decodeStrings; + public StringSerializer(boolean encodeStrings) { this.encodeStrings = encodeStrings; } - public Object deserialize(Element content) throws XMLRPCException { - String text = XMLUtil.getOnlyTextContent(content.getChildNodes()); - if(decodeStrings) { - text = text.replaceAll("<", "<").replaceAll("&", "&"); - } - return text; - } public XmlElement serialize(Object object) { String content = object.toString(); diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/StructSerializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/StructSerializer.java index 87fa9615..82333829 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/StructSerializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/StructSerializer.java @@ -19,65 +19,6 @@ public class StructSerializer implements Serializer { private static final String STRUCT_NAME = "name"; private static final String STRUCT_VALUE = "value"; - public Object deserialize(Element content) throws XMLRPCException { - - Map map = new HashMap(); - - Node n, m; - String s; - Object o; - for(int i = 0; i < content.getChildNodes().getLength(); i++) { - - n = content.getChildNodes().item(i); - - // Strip only whitespace text elements and comments - if((n.getNodeType() == Node.TEXT_NODE - && n.getNodeValue().trim().length() <= 0) - || n.getNodeType() == Node.COMMENT_NODE) - continue; - - if(n.getNodeType() != Node.ELEMENT_NODE - || !STRUCT_MEMBER.equals(n.getNodeName())) { - throw new XMLRPCException("Only struct members allowed within a struct."); - } - - // Grep name and value from member - s = null; o = null; - for(int j = 0; j < n.getChildNodes().getLength(); j++) { - m = n.getChildNodes().item(j); - - // Strip only whitespace text elements and comments - if((m.getNodeType() == Node.TEXT_NODE - && m.getNodeValue().trim().length() <= 0) - || m.getNodeType() == Node.COMMENT_NODE) - continue; - - if(STRUCT_NAME.equals(m.getNodeName())) { - if(s != null) { - throw new XMLRPCException("Name of a struct member cannot be set twice."); - } else { - s = XMLUtil.getOnlyTextContent(m.getChildNodes()); - } - } else if(m.getNodeType() == Node.ELEMENT_NODE && STRUCT_VALUE.equals(m.getNodeName())) { - if(o != null) { - throw new XMLRPCException("Value of a struct member cannot be set twice."); - } else { - o = SerializerHandler.getDefault().deserialize((Element)m); - } - } else { - throw new XMLRPCException("A struct member must only contain one name and one value."); - } - - } - - map.put(s, o); - - } - - return map; - - } - public XmlElement serialize(Object object) { XmlElement struct = new XmlElement(SerializerHandler.TYPE_STRUCT); From 919ce210602436628a60f4099d3db70847e90301 Mon Sep 17 00:00:00 2001 From: Felipe Barriga Richards Date: Mon, 6 Feb 2017 19:53:17 -0300 Subject: [PATCH 3/5] axmlrpc: fix: consume http entities after parsing them. --- .../de/timroes/axmlrpc/ResponseParser.java | 33 ++++++++++++++++++- .../java/de/timroes/axmlrpc/XMLRPCClient.java | 2 +- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/de/timroes/axmlrpc/ResponseParser.java b/app/src/main/java/de/timroes/axmlrpc/ResponseParser.java index b6d110f1..c58b13d3 100644 --- a/app/src/main/java/de/timroes/axmlrpc/ResponseParser.java +++ b/app/src/main/java/de/timroes/axmlrpc/ResponseParser.java @@ -1,9 +1,12 @@ package de.timroes.axmlrpc; import de.timroes.axmlrpc.serializer.SerializerHandler; + +import java.io.IOException; import java.io.InputStream; import java.util.Map; +import org.apache.http.HttpEntity; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; @@ -18,6 +21,30 @@ class ResponseParser { private static final String FAULT_CODE = "faultCode"; private static final String FAULT_STRING = "faultString"; + + /** + * Deallocate Http Entity and close streams + */ + private static void consumeHttpEntity(InputStream response, HttpEntity entity) { + // Ideally we should use EntityUtils.consume(), introduced in apache http utils 4.1 - not available in + // Android yet + if (entity != null) { + try { + entity.consumeContent(); + } catch (IOException e) { + // ignore exception (could happen if Content-Length is wrong) + } + } + + if (response != null) { + try { + response.close(); + } catch (Exception e) { + // ignore exception + } + } + } + /** * The given InputStream must contain the xml response from an xmlrpc server. * This method extract the content of it as an object. @@ -27,7 +54,7 @@ class ResponseParser { * @throws XMLRPCException Will be thrown whenever something fails. * @throws XMLRPCServerException Will be thrown, if the server returns an error. */ - public Object parse(InputStream response) throws XMLRPCException { + public Object parse(InputStream response, HttpEntity entity) throws XMLRPCException { try { XmlPullParser pullParser = XmlPullParserFactory.newInstance().newPullParser(); pullParser.setInput(response, "UTF-8"); @@ -45,11 +72,13 @@ class ResponseParser { // no parser.require() here since its called in XMLRPCSerializer.deserialize() below // deserialize result Object obj = SerializerHandler.getDefault().deserialize(pullParser); + consumeHttpEntity(response, entity); return obj; } else if (tag.equals(XMLRPCClient.FAULT)) { // fault response pullParser.nextTag(); // TAG_VALUE () Map map = (Map) SerializerHandler.getDefault().deserialize(pullParser); + consumeHttpEntity(response, entity); //Check that required tags are in the response if (!map.containsKey(FAULT_STRING) || !map.containsKey(FAULT_CODE)) { @@ -61,8 +90,10 @@ class ResponseParser { } } catch (XmlPullParserException ex) { + consumeHttpEntity(response, entity); throw new XMLRPCException("Error parsing response.", ex); } catch (Exception ex) { + consumeHttpEntity(response, entity); if(ex instanceof XMLRPCServerException) throw (XMLRPCServerException)ex; else diff --git a/app/src/main/java/de/timroes/axmlrpc/XMLRPCClient.java b/app/src/main/java/de/timroes/axmlrpc/XMLRPCClient.java index 9a6b8f44..0a88100b 100644 --- a/app/src/main/java/de/timroes/axmlrpc/XMLRPCClient.java +++ b/app/src/main/java/de/timroes/axmlrpc/XMLRPCClient.java @@ -444,7 +444,7 @@ public class XMLRPCClient { } } - return responseParser.parse(istream); + return responseParser.parse(istream, entity); } catch(SocketTimeoutException ex) { throw new XMLRPCTimeoutException("The XMLRPC call timed out."); From 098be2d41980ee7de79ff335d23489415c6b243e Mon Sep 17 00:00:00 2001 From: Felipe Barriga Richards Date: Mon, 6 Feb 2017 16:04:46 -0300 Subject: [PATCH 4/5] axmlrpc: Remove unused/dead code/imports. --- .../main/java/de/timroes/axmlrpc/XMLUtil.java | 99 ------------------- .../axmlrpc/serializer/ArraySerializer.java | 5 - .../axmlrpc/serializer/Base64Serializer.java | 2 - .../axmlrpc/serializer/BooleanSerializer.java | 2 - .../serializer/DateTimeSerializer.java | 3 - .../axmlrpc/serializer/DoubleSerializer.java | 2 - .../axmlrpc/serializer/IntSerializer.java | 2 - .../axmlrpc/serializer/LongSerializer.java | 2 - .../axmlrpc/serializer/NullSerializer.java | 2 - .../axmlrpc/serializer/Serializer.java | 2 - .../axmlrpc/serializer/SerializerHandler.java | 2 - .../axmlrpc/serializer/StringSerializer.java | 2 - .../axmlrpc/serializer/StructSerializer.java | 4 - 13 files changed, 129 deletions(-) diff --git a/app/src/main/java/de/timroes/axmlrpc/XMLUtil.java b/app/src/main/java/de/timroes/axmlrpc/XMLUtil.java index fb3b2cc6..7e444591 100644 --- a/app/src/main/java/de/timroes/axmlrpc/XMLUtil.java +++ b/app/src/main/java/de/timroes/axmlrpc/XMLUtil.java @@ -1,9 +1,6 @@ package de.timroes.axmlrpc; import de.timroes.axmlrpc.xmlcreator.XmlElement; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; /** * This class provides some utility methods for the use with the Java DOM parser. @@ -12,102 +9,6 @@ import org.w3c.dom.NodeList; */ public class XMLUtil { - /** - * Returns the only child element in a given NodeList. - * Will throw an error if there is more then one child element or any other - * child that is not an element or an empty text string (whitespace are normal). - * - * @param list A NodeList of children nodes. - * @return The only child element in the given node list. - * @throws XMLRPCException Will be thrown if there is more then one child element - * except empty text nodes. - */ - public static Element getOnlyChildElement(NodeList list) throws XMLRPCException { - - Element e = null; - Node n; - for(int i = 0; i < list.getLength(); i++) { - n = list.item(i); - // Strip only whitespace text elements and comments - if((n.getNodeType() == Node.TEXT_NODE - && n.getNodeValue().trim().length() <= 0) - || n.getNodeType() == Node.COMMENT_NODE) - continue; - - // Check if there is anything else than an element node. - if(n.getNodeType() != Node.ELEMENT_NODE) { - throw new XMLRPCException("Only element nodes allowed."); - } - - // If there was already an element, throw exception. - if(e != null) { - throw new XMLRPCException("Element has more than one children."); - } - - e = (Element)n; - - } - - return e; - - } - - /** - * Returns the text node from a given NodeList. If the list contains - * more then just text nodes, an exception will be thrown. - * - * @param list The given list of nodes. - * @return The text of the given node list. - * @throws XMLRPCException Will be thrown if there is more than just one - * text node within the list. - */ - public static String getOnlyTextContent(NodeList list) throws XMLRPCException { - - StringBuilder builder = new StringBuilder(); - Node n; - - for(int i = 0; i < list.getLength(); i++) { - n = list.item(i); - - // Skip comments inside text tag. - if(n.getNodeType() == Node.COMMENT_NODE) { - continue; - } - - if(n.getNodeType() != Node.TEXT_NODE) { - throw new XMLRPCException("Element must contain only text elements."); - } - - builder.append(n.getNodeValue()); - - } - - return builder.toString(); - - } - - /** - * Checks if the given {@link NodeList} contains a child element. - * - * @param list The {@link NodeList} to check. - * @return Whether the {@link NodeList} contains children. - */ - public static boolean hasChildElement(NodeList list) { - - Node n; - - for(int i = 0; i < list.getLength(); i++) { - n = list.item(i); - - if(n.getNodeType() == Node.ELEMENT_NODE) { - return true; - } - } - - return false; - - } - /** * Creates an xml tag with a given type and content. * diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/ArraySerializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/ArraySerializer.java index 3e48151c..d1b054fe 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/ArraySerializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/ArraySerializer.java @@ -2,12 +2,7 @@ package de.timroes.axmlrpc.serializer; import de.timroes.axmlrpc.XMLRPCException; import de.timroes.axmlrpc.XMLRPCRuntimeException; -import de.timroes.axmlrpc.XMLUtil; import de.timroes.axmlrpc.xmlcreator.XmlElement; -import java.util.ArrayList; -import java.util.List; -import org.w3c.dom.Element; -import org.w3c.dom.Node; /** * diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/Base64Serializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/Base64Serializer.java index bffa40bb..699e7f75 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/Base64Serializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/Base64Serializer.java @@ -1,10 +1,8 @@ package de.timroes.axmlrpc.serializer; -import de.timroes.axmlrpc.XMLRPCException; import de.timroes.axmlrpc.XMLUtil; import de.timroes.axmlrpc.xmlcreator.XmlElement; import de.timroes.base64.Base64; -import org.w3c.dom.Element; /** * diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/BooleanSerializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/BooleanSerializer.java index 74bf0fbe..f64a7f4e 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/BooleanSerializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/BooleanSerializer.java @@ -1,9 +1,7 @@ package de.timroes.axmlrpc.serializer; -import de.timroes.axmlrpc.XMLRPCException; import de.timroes.axmlrpc.XMLUtil; import de.timroes.axmlrpc.xmlcreator.XmlElement; -import org.w3c.dom.Element; /** * diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/DateTimeSerializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/DateTimeSerializer.java index b55e4875..8c19f0f3 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/DateTimeSerializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/DateTimeSerializer.java @@ -1,11 +1,8 @@ package de.timroes.axmlrpc.serializer; -import de.timroes.axmlrpc.XMLRPCException; import de.timroes.axmlrpc.XMLUtil; import de.timroes.axmlrpc.xmlcreator.XmlElement; -import java.text.ParseException; import java.text.SimpleDateFormat; -import org.w3c.dom.Element; /** * diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/DoubleSerializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/DoubleSerializer.java index 3f0b7941..528afcd8 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/DoubleSerializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/DoubleSerializer.java @@ -1,10 +1,8 @@ package de.timroes.axmlrpc.serializer; -import de.timroes.axmlrpc.XMLRPCException; import de.timroes.axmlrpc.XMLUtil; import de.timroes.axmlrpc.xmlcreator.XmlElement; import java.math.BigDecimal; -import org.w3c.dom.Element; /** * This serializer is responsible for floating point numbers. diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/IntSerializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/IntSerializer.java index f8f48d7e..65d11aab 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/IntSerializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/IntSerializer.java @@ -1,9 +1,7 @@ package de.timroes.axmlrpc.serializer; -import de.timroes.axmlrpc.XMLRPCException; import de.timroes.axmlrpc.XMLUtil; import de.timroes.axmlrpc.xmlcreator.XmlElement; -import org.w3c.dom.Element; /** * diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/LongSerializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/LongSerializer.java index 1952fb2e..59158d9c 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/LongSerializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/LongSerializer.java @@ -1,9 +1,7 @@ package de.timroes.axmlrpc.serializer; -import de.timroes.axmlrpc.XMLRPCException; import de.timroes.axmlrpc.XMLUtil; import de.timroes.axmlrpc.xmlcreator.XmlElement; -import org.w3c.dom.Element; /** * diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/NullSerializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/NullSerializer.java index ae3424eb..df5f0f7f 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/NullSerializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/NullSerializer.java @@ -1,8 +1,6 @@ package de.timroes.axmlrpc.serializer; -import de.timroes.axmlrpc.XMLRPCException; import de.timroes.axmlrpc.xmlcreator.XmlElement; -import org.w3c.dom.Element; /** * diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/Serializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/Serializer.java index 5a64c423..96914a2a 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/Serializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/Serializer.java @@ -1,8 +1,6 @@ package de.timroes.axmlrpc.serializer; -import de.timroes.axmlrpc.XMLRPCException; import de.timroes.axmlrpc.xmlcreator.XmlElement; -import org.w3c.dom.Element; /** * A Serializer is responsible to serialize a specific type of data to diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/SerializerHandler.java b/app/src/main/java/de/timroes/axmlrpc/serializer/SerializerHandler.java index ab81c476..8666183e 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/SerializerHandler.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/SerializerHandler.java @@ -3,7 +3,6 @@ package de.timroes.axmlrpc.serializer; import de.timroes.axmlrpc.XMLRPCClient; import de.timroes.axmlrpc.XMLRPCException; import de.timroes.axmlrpc.XMLRPCRuntimeException; -import de.timroes.axmlrpc.XMLUtil; import de.timroes.axmlrpc.xmlcreator.XmlElement; import java.io.BufferedReader; @@ -17,7 +16,6 @@ import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.SimpleTimeZone; diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/StringSerializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/StringSerializer.java index 8712a486..823edad6 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/StringSerializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/StringSerializer.java @@ -1,9 +1,7 @@ package de.timroes.axmlrpc.serializer; -import de.timroes.axmlrpc.XMLRPCException; import de.timroes.axmlrpc.XMLUtil; import de.timroes.axmlrpc.xmlcreator.XmlElement; -import org.w3c.dom.Element; /** * diff --git a/app/src/main/java/de/timroes/axmlrpc/serializer/StructSerializer.java b/app/src/main/java/de/timroes/axmlrpc/serializer/StructSerializer.java index 82333829..722f54a3 100644 --- a/app/src/main/java/de/timroes/axmlrpc/serializer/StructSerializer.java +++ b/app/src/main/java/de/timroes/axmlrpc/serializer/StructSerializer.java @@ -2,12 +2,8 @@ package de.timroes.axmlrpc.serializer; import de.timroes.axmlrpc.XMLRPCException; import de.timroes.axmlrpc.XMLRPCRuntimeException; -import de.timroes.axmlrpc.XMLUtil; import de.timroes.axmlrpc.xmlcreator.XmlElement; -import java.util.HashMap; import java.util.Map; -import org.w3c.dom.Element; -import org.w3c.dom.Node; /** * From 4a9a8b602719d3d6b8a099ceca2f5cbe8d9cce26 Mon Sep 17 00:00:00 2001 From: Felipe Barriga Richards Date: Thu, 9 Feb 2017 15:42:59 -0300 Subject: [PATCH 5/5] XMLRPCClient: Add FIXME comment. --- app/src/main/java/de/timroes/axmlrpc/XMLRPCClient.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/de/timroes/axmlrpc/XMLRPCClient.java b/app/src/main/java/de/timroes/axmlrpc/XMLRPCClient.java index 0a88100b..f6003f87 100644 --- a/app/src/main/java/de/timroes/axmlrpc/XMLRPCClient.java +++ b/app/src/main/java/de/timroes/axmlrpc/XMLRPCClient.java @@ -9,6 +9,7 @@ import java.util.concurrent.ConcurrentHashMap; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.params.ClientPNames; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.protocol.HTTP; @@ -356,7 +357,7 @@ public class XMLRPCClient { * Read the README file delivered with the source code of this library for more * information. * - * @param method A method name to call. + * @param methodName A method name to call. * @param params An array of parameters for the method. * @return The result of the server. * @throws XMLRPCException Will be thrown if an error occurred during the call. @@ -369,8 +370,9 @@ public class XMLRPCClient { Call c = createCall(methodName, params); // Prepare POST request + // FIXME: where creating a new HttpPost so calling #cancel isn't going to do anything HttpPost post = new HttpPost(url); - post.getParams().setParameter("http.protocol.handle-redirects", false); + post.getParams().setParameter(ClientPNames.HANDLE_REDIRECTS, false); post.setHeader(CONTENT_TYPE, TYPE_XML); StringEntity entity = new StringEntity(c.getXML(), HTTP.UTF_8); entity.setContentType(TYPE_XML);