/* * The contents of this file are subject to the Mozilla Public License Version 1.1 * (the "License"); you may not use this file except in compliance with the License. * You may obtain a copy of the License at . * * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT * WARRANTY OF ANY KIND, either express or implied. See the License for the specific * language governing rights and limitations under the License. * * The Original Code is the Venice Web Communities System. * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ package com.silverwrist.venice.ui.rpc; import java.beans.*; import java.io.*; import java.lang.ref.*; import java.lang.reflect.*; import java.util.*; import javax.mail.*; import javax.mail.internet.*; import org.apache.log4j.*; import com.silverwrist.util.*; public class XmlRpcSerializer { /*-------------------------------------------------------------------------------- * Static data members *-------------------------------------------------------------------------------- */ private static Category logger = Category.getInstance(XmlRpcSerializer.class); private static XmlRpcSerializer self = null; private static SimpleTimeZone utc = new SimpleTimeZone(0,"UTC"); /*-------------------------------------------------------------------------------- * Constructor *-------------------------------------------------------------------------------- */ private XmlRpcSerializer() { // do nothing } // end constructor /*-------------------------------------------------------------------------------- * External operations *-------------------------------------------------------------------------------- */ public final String serialize(boolean b) { return "" + (b ? "1" : "0") + ""; } // end serialize public final String serialize(byte b) { return this.serialize((int)b); } // end serialize public final String serialize(char c) { return "" + c + ""; } // end serialize public final String serialize(double d) { return "" + d + ""; } // end serialize public final String serialize(float f) { return this.serialize((double)f); } // end serialize public final String serialize(int i) { return "" + i + ""; } // end serialize public final String serialize(long l) { return this.serialize((double)l); } // end serialize public final String serialize(short s) { return this.serialize((int)s); } // end serialize public final String serialize(Object obj) throws XmlRpcFault { if (obj.getClass().isArray()) { // treat arrays specially Class ct = obj.getClass().getComponentType(); if (ct==Byte.TYPE) return this.serialize((byte[])obj); else if (ct==Boolean.TYPE) return this.serialize((boolean[])obj); else if (ct==Character.TYPE) return this.serialize((char[])obj); else if (ct==Short.TYPE) return this.serialize((short[])obj); else if (ct==Integer.TYPE) return this.serialize((int[])obj); else if (ct==Long.TYPE) return this.serialize((long[])obj); else if (ct==Float.TYPE) return this.serialize((float[])obj); else if (ct==Double.TYPE) return this.serialize((double[])obj); else return this.serialize((Object[])obj); } // end if if (obj==null) return serializeString(null); // self-serializing objects if (obj instanceof XmlRpcSelfSerializer) return ((XmlRpcSelfSerializer)obj).serializeXmlRpc(); // types from java.io.* if (obj instanceof InputStream) return serializeInputStream((InputStream)obj); // types from java.sql.* if (obj instanceof java.sql.Blob) { // serialize the blob as a binary stream try { // just get its input stream return serializeInputStream(((java.sql.Blob)obj).getBinaryStream()); } // end try catch (java.sql.SQLException e) { // fault on error here throw new XmlRpcFault(XmlRpcFault.INTERNAL_ERROR,"unable to save binary data"); } // end catch } // end if // types from java.util.* if (obj instanceof Calendar) return serializeCalendar((Calendar)obj); if (obj instanceof Collection) return serializeCollection((Collection)obj); if (obj instanceof java.util.Date) return serializeDate((java.util.Date)obj); if (obj instanceof Enumeration) return serializeEnumeration((Enumeration)obj); if (obj instanceof Iterator) return serializeIterator((Iterator)obj); if (obj instanceof Map) return serializeMap((Map)obj); // types from java.lang.ref.* if (obj instanceof Reference) // for a reference, encode its referent return this.serialize(((Reference)obj).get()); // types from java.lang.* if (obj instanceof Boolean) return this.serialize(((Boolean)obj).booleanValue()); if (obj instanceof Character) return this.serialize(((Character)obj).charValue()); if ((obj instanceof Byte) || (obj instanceof Short) || (obj instanceof Integer)) return this.serialize(((Number)obj).intValue()); if ((obj instanceof Long) || (obj instanceof Float) || (obj instanceof Double)) return this.serialize(((Number)obj).doubleValue()); // String and StringBuffer are handled properly by the fallback mechanism below // last-ditch fallback method - use toString, get the string, and encode it return serializeString(obj.toString()); } // end serialize public final String serialize(boolean[] ba) { StringBuffer b = new StringBuffer("\r\n\r\n"); for (int i=0; i").append(this.serialize(ba[i])).append("\r\n"); b.append("\r\n"); return b.toString(); } // end serialize public final String serialize(byte[] ba) throws XmlRpcFault { return this.serializeInputStream(new ByteArrayInputStream(ba)); } // end serialize public final String serialize(char[] ca) { StringBuffer b = new StringBuffer("\r\n\r\n"); for (int i=0; i").append(this.serialize(ca[i])).append("\r\n"); b.append("\r\n"); return b.toString(); } // end serialize public final String serialize(double[] da) { StringBuffer b = new StringBuffer("\r\n\r\n"); for (int i=0; i").append(this.serialize(da[i])).append("\r\n"); b.append("\r\n"); return b.toString(); } // end serialize public final String serialize(float[] fa) { StringBuffer b = new StringBuffer("\r\n\r\n"); for (int i=0; i").append(this.serialize((double)(fa[i]))).append("\r\n"); b.append("\r\n"); return b.toString(); } // end serialize public final String serialize(int[] ia) { StringBuffer b = new StringBuffer("\r\n\r\n"); for (int i=0; i").append(this.serialize(ia[i])).append("\r\n"); b.append("\r\n"); return b.toString(); } // end serialize public final String serialize(long[] la) { StringBuffer b = new StringBuffer("\r\n\r\n"); for (int i=0; i").append(this.serialize((double)(la[i]))).append("\r\n"); b.append("\r\n"); return b.toString(); } // end serialize public final String serialize(short[] sa) { StringBuffer b = new StringBuffer("\r\n\r\n"); for (int i=0; i").append(this.serialize((int)(sa[i]))).append("\r\n"); b.append("\r\n"); return b.toString(); } // end serialize public final String serialize(Object[] arr) throws XmlRpcFault { StringBuffer b = new StringBuffer("\r\n\r\n"); for (int i=0; i").append(this.serialize(arr[i])).append("\r\n"); b.append("\r\n"); return b.toString(); } // end serialize public final String serializeBean(Object obj, BeanInfo binf) throws XmlRpcFault { PropertyDescriptor[] props = binf.getPropertyDescriptors(); StringBuffer b = new StringBuffer("\r\n"); final Object[] no_params = new Object[0]; for (int i=0; i\r\n").append(StringUtil.encodeHTML(props[i].getName())); b.append("\r\n").append(this.serialize(mread.invoke(obj,no_params))); b.append("\r\n\r\n"); } // end try catch (IllegalAccessException iae) { // unable to access that method throw new XmlRpcFault(XmlRpcFault.INTERNAL_ERROR,iae); } // end catch catch (InvocationTargetException ite) { // the method we invoked threw an exception throw new XmlRpcFault(XmlRpcFault.INTERNAL_ERROR,ite.getTargetException()); } // end catch } // end if } // end for b.append("\r\n"); return b.toString(); } // end serializeBean public final String serializeBean(Object obj) throws XmlRpcFault { try { // get the BeanInfo via introspection return serializeBean(obj,Introspector.getBeanInfo(obj.getClass())); } // end try catch (IntrospectionException e) { // introspection failed throw new XmlRpcFault(XmlRpcFault.INTERNAL_ERROR,e); } // end catch } // end serializeBean public final String serializeCalendar(Calendar cal) { // Create the two string buffers converting the date. StringBuffer rc = new StringBuffer(""); StringBuffer conv = new StringBuffer(); String c; // Encode the year first. conv.append("0000").append(cal.get(Calendar.YEAR)); c = conv.toString(); rc.append(c.substring(c.length()-4)); // Now the month... conv.setLength(0); conv.append("00").append(cal.get(Calendar.MONTH) - Calendar.JANUARY + 1); c = conv.toString(); rc.append(c.substring(c.length()-2)); // And the day... conv.setLength(0); conv.append("00").append(cal.get(Calendar.DAY_OF_MONTH)); c = conv.toString(); rc.append(c.substring(c.length()-2)).append('T'); // And the hour... conv.setLength(0); conv.append("00").append(cal.get(Calendar.HOUR_OF_DAY)); c = conv.toString(); rc.append(c.substring(c.length()-2)).append(':'); // And the minute... conv.setLength(0); conv.append("00").append(cal.get(Calendar.MINUTE)); c = conv.toString(); rc.append(c.substring(c.length()-2)).append(':'); // And the second... conv.setLength(0); conv.append("00").append(cal.get(Calendar.SECOND)); c = conv.toString(); rc.append(c.substring(c.length()-2)).append(""); // This is the resulting date/time value. return rc.toString(); } // end serializeCalendar public final String serializeCollection(Collection coll) throws XmlRpcFault { return serializeIterator(coll.iterator()); } // end serializeCollection public final String serializeDate(java.util.Date date) throws XmlRpcFault { GregorianCalendar cal = new GregorianCalendar(utc); cal.setTime(date); return serializeCalendar(cal); } // end serializeDate public final String serializeEnumeration(Enumeration enum) throws XmlRpcFault { StringBuffer b = new StringBuffer("\r\n\r\n"); while (enum.hasMoreElements()) b.append("").append(this.serialize(enum.nextElement())).append(""); b.append("\r\n"); return b.toString(); } // end serializeIterator public final String serializeInputStream(InputStream stm) throws XmlRpcFault { String rc = null; try { // convert the data bytes to encoded bytes first ByteArrayOutputStream internal_stm = new ByteArrayOutputStream(); OutputStream encode_stm = MimeUtility.encode(internal_stm,"base64"); IOUtil.copy(stm,encode_stm); encode_stm.flush(); // turn our encoded output into an InputStream ByteArrayInputStream internal2_stm = new ByteArrayInputStream(internal_stm.toByteArray()); IOUtil.shutdown(encode_stm); IOUtil.shutdown(internal_stm); // build a StringWriter containing the converted contents StringWriter wr = new StringWriter(); wr.write(""); InputStreamReader rd = new InputStreamReader(internal2_stm,"US-ASCII"); IOUtil.copy(rd,wr); IOUtil.shutdown(rd); IOUtil.shutdown(internal2_stm); wr.write(""); // send out the complete string rc = wr.toString(); IOUtil.shutdown(wr); } // end try catch (IOException ioe) { // this is an internal error throw new XmlRpcFault(XmlRpcFault.INTERNAL_ERROR,"unable to save binary data"); } // end catch catch (MessagingException me) { // and so is this throw new XmlRpcFault(XmlRpcFault.INTERNAL_ERROR,"unable to encode binary data"); } // end catch return rc; } // end serializeInputStream public final String serializeIterator(Iterator it) throws XmlRpcFault { StringBuffer b = new StringBuffer("\r\n\r\n"); while (it.hasNext()) b.append("").append(this.serialize(it.next())).append("\r\n"); b.append("\r\n"); return b.toString(); } // end serializeIterator public final String serializeMap(Map m) throws XmlRpcFault { StringBuffer b = new StringBuffer("\r\n"); Iterator it = m.entrySet().iterator(); while (it.hasNext()) { // serialize each entry in turn Map.Entry ntry = (Map.Entry)(it.next()); b.append("\r\n").append(StringUtil.encodeHTML(ntry.getKey().toString())); b.append("\r\n").append(this.serialize(ntry.getValue())); b.append("\r\n\r\n"); } // end while b.append("\r\n"); return b.toString(); } // end serializeMap public final String serializeString(String s) { if (s==null) return ""; return "" + StringUtil.encodeHTML(s) + ""; } // end serializeString /*-------------------------------------------------------------------------------- * External static operations *-------------------------------------------------------------------------------- */ public static final synchronized XmlRpcSerializer get() { if (self==null) self = new XmlRpcSerializer(); return self; } // end get } // end class XmlRpcSerializer