package org.xmlrpc.android; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; 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.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.SimpleTimeZone; import android.util.Base64; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import org.wordpress.android.models.MediaFile; class XMLRPCSerializer { static final String TAG_NAME = "name"; static final String TAG_MEMBER = "member"; static final String TAG_VALUE = "value"; static final String TAG_DATA = "data"; static final String TYPE_INT = "int"; static final String TYPE_I4 = "i4"; static final String TYPE_I8 = "i8"; static final String TYPE_DOUBLE = "double"; static final String TYPE_BOOLEAN = "boolean"; static final String TYPE_STRING = "string"; static final String TYPE_DATE_TIME_ISO8601 = "dateTime.iso8601"; static final String TYPE_BASE64 = "base64"; static final String TYPE_ARRAY = "array"; static final String TYPE_STRUCT = "struct"; static SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyyMMdd'T'HH:mm:ss"); static Calendar cal = Calendar.getInstance(new SimpleTimeZone(0, "GMT")); @SuppressWarnings("unchecked") static void serialize(XmlSerializer serializer, Object object) throws IOException { // check for scalar types: if (object instanceof Integer || object instanceof Short || object instanceof Byte) { serializer.startTag(null, TYPE_I4).text(object.toString()) .endTag(null, TYPE_I4); } else if (object instanceof Long) { serializer.startTag(null, TYPE_I8).text(object.toString()) .endTag(null, TYPE_I8); } else if (object instanceof Double || object instanceof Float) { serializer.startTag(null, TYPE_DOUBLE).text(object.toString()) .endTag(null, TYPE_DOUBLE); } else if (object instanceof Boolean) { Boolean bool = (Boolean) object; String boolStr = bool.booleanValue() ? "1" : "0"; serializer.startTag(null, TYPE_BOOLEAN).text(boolStr) .endTag(null, TYPE_BOOLEAN); } else if (object instanceof String) { serializer.startTag(null, TYPE_STRING).text(object.toString()) .endTag(null, TYPE_STRING); } else if (object instanceof Date || object instanceof Calendar) { Date date = (Date) object; SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyyMMdd'T'HH:mm:ss"); dateFormat.setCalendar(cal); String sDate = dateFormat.format(date); serializer.startTag(null, TYPE_DATE_TIME_ISO8601).text(sDate) .endTag(null, TYPE_DATE_TIME_ISO8601); } else if (object instanceof byte[]) { String value; try { value = Base64.encodeToString((byte[]) object, Base64.DEFAULT); serializer.startTag(null, TYPE_BASE64).text(value) .endTag(null, TYPE_BASE64); } catch (OutOfMemoryError e) { throw new IOException("Out of memory"); } } else if (object instanceof MediaFile) { //convert media file binary to base64 serializer.startTag(null, "base64"); MediaFile videoFile = (MediaFile) object; InputStream inStream = new DataInputStream(new FileInputStream( videoFile.getFilePath())); byte[] buffer = new byte[3600];//you must use a 24bit multiple int length = -1; String chunk = null; //int ctr = 0; //Log.i("WordPress", "converting media file to base64"); while ((length = inStream.read(buffer)) > 0) { chunk = Base64 .encodeToString(buffer, 0, length, Base64.DEFAULT); serializer.text(chunk); //ctr+=3600; //Log.i("WordPress", "chunk " + ctr); } //Log.i("WordPress", "conversion done!"); inStream.close(); serializer.endTag(null, "base64"); } else if (object instanceof List<?>) { serializer.startTag(null, TYPE_ARRAY).startTag(null, TAG_DATA); List<Object> list = (List<Object>) object; Iterator<Object> iter = list.iterator(); while (iter.hasNext()) { Object o = iter.next(); serializer.startTag(null, TAG_VALUE); serialize(serializer, o); serializer.endTag(null, TAG_VALUE); } serializer.endTag(null, TAG_DATA).endTag(null, TYPE_ARRAY); } else if (object instanceof Object[]) { serializer.startTag(null, TYPE_ARRAY).startTag(null, TAG_DATA); Object[] objects = (Object[]) object; for (int i = 0; i < objects.length; i++) { Object o = objects[i]; serializer.startTag(null, TAG_VALUE); serialize(serializer, o); serializer.endTag(null, TAG_VALUE); } serializer.endTag(null, TAG_DATA).endTag(null, TYPE_ARRAY); } else if (object instanceof Map) { serializer.startTag(null, TYPE_STRUCT); Map<String, Object> map = (Map<String, Object>) object; Iterator<Entry<String, Object>> iter = map.entrySet().iterator(); while (iter.hasNext()) { Entry<String, Object> entry = iter.next(); String key = entry.getKey(); Object value = entry.getValue(); serializer.startTag(null, TAG_MEMBER); serializer.startTag(null, TAG_NAME).text(key) .endTag(null, TAG_NAME); serializer.startTag(null, TAG_VALUE); serialize(serializer, value); serializer.endTag(null, TAG_VALUE); serializer.endTag(null, TAG_MEMBER); } serializer.endTag(null, TYPE_STRUCT); } else { throw new IOException("Cannot serialize " + object); } } static Object deserialize(XmlPullParser parser) throws XmlPullParserException, IOException { parser.require(XmlPullParser.START_TAG, null, TAG_VALUE); parser.nextTag(); String typeNodeName = parser.getName(); Object obj; if (typeNodeName.equals(TYPE_INT) || typeNodeName.equals(TYPE_I4)) { String value = parser.nextText(); obj = Integer.parseInt(value); } else if (typeNodeName.equals(TYPE_I8)) { 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) { e.printStackTrace(); obj = value; //throw new IOException("Cannot deserialize dateTime " + 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 (<data>) parser.require(XmlPullParser.START_TAG, null, TAG_DATA); parser.nextTag(); List<Object> list = new ArrayList<Object>(); while (parser.getName().equals(TAG_VALUE)) { list.add(deserialize(parser)); parser.nextTag(); } parser.require(XmlPullParser.END_TAG, null, TAG_DATA); parser.nextTag(); // TAG_ARRAY (</array>) parser.require(XmlPullParser.END_TAG, null, TYPE_ARRAY); obj = list.toArray(); } else if (typeNodeName.equals(TYPE_STRUCT)) { parser.nextTag(); Map<String, Object> map = new HashMap<String, Object>(); 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 IOException("Cannot deserialize " + parser.getName()); } parser.nextTag(); // TAG_VALUE (</value>) parser.require(XmlPullParser.END_TAG, null, TAG_VALUE); return obj; } }