/*
 * Created on Jan 4, 2004
 */
package uk.co.wilson.net.xmlrpc;

/*
 Copyright (c) 2004 John Wilson (tug@wilson.co.uk).
 All rights reserved.
 Redistribution and use in source and binary forms,
 with or without modification, are permitted provided
 that the following conditions are met:

 Redistributions of source code must retain the above
 copyright notice, this list of conditions and the
 following disclaimer.

 Redistributions in binary form must reproduce the
 above copyright notice, this list of conditions and
 the following disclaimer in the documentation and/or
 other materials provided with the distribution.

 THIS SOFTWARE IS PROVIDED BY JOHN WILSON ``AS IS'' AND ANY
 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JOHN WILSON
 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 OF THE POSSIBILITY OF SUCH DAMAGE
 */

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import org.xml.sax.AttributeList;
import org.xml.sax.SAXException;

import uk.co.wilson.xml.MinML;



public class XMLRPCMessageProcessor extends MinML {
	private static final byte[] translateTable = (
			//
			"\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
			//                    \t    \n                \r
			+ "\u0042\u0042\u0041\u0041\u0042\u0042\u0041\u0042"
			//
			+ "\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
			//
			+ "\u0042\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
			//        sp    !     "     #     $     %     &     '
			+ "\u0041\u0042\u0042\u0042\u0042\u0042\u0042\u0042"
			//         (    )     *     +     ,     -     .     /
			+ "\u0042\u0042\u0042\u003E\u0042\u0042\u0042\u003F"
			//         0    1     2     3     4     5     6     7
			+ "\u0034\u0035\u0036\u0037\u0038\u0039\u003A\u003B"
			//         8    9     :     ;     <     =     >     ?
			+ "\u003C\u003D\u0042\u0042\u0042\u0040\u0042\u0042"
			//         @    A     B     C     D     E     F     G
			+ "\u0042\u0000\u0001\u0002\u0003\u0004\u0005\u0006"
			//         H    I   J K   L     M   N   O
			+ "\u0007\u0008\t\n\u000B\u000C\r\u000E"
			//         P    Q     R     S     T     U     V    W
			+ "\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016"
			//         X    Y     Z     [     \     ]     ^    _
			+ "\u0017\u0018\u0019\u0042\u0042\u0042\u0042\u0042"
			//         '    a     b     c     d     e     f     g
			+ "\u0042\u001A\u001B\u001C\u001D\u001E\u001F\u0020"
			//        h   i   j     k     l     m     n     o    p
			+ "\u0021\"\u0023\u0024\u0025\u0026\u0027\u0028"
			//        p     q     r     s     t     u     v     w
			+ "\u0029\u002A\u002B\u002C\u002D\u002E\u002F\u0030"
			//        x     y     z
			+ "\u0031\u0032\u0033").getBytes();
	
	private interface Emitter {
		void emit(StringBuffer buffer, Object value) throws SAXException;
	}
	
	private final static Map elements = new HashMap();
	static {
		final char[] tTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".toCharArray();
		
		elements.put(Integer.class,
				new Emitter() {
					public void emit(final StringBuffer buffer, final Object integer) {
						buffer.append("<value><i4>").append(integer).append("</i4></value>");
					}
				});
		elements.put(Character.class, elements.get(Integer.class));
		elements.put(Byte.class, elements.get(Integer.class));
		elements.put(Short.class, elements.get(Integer.class));
		
		elements.put(Double.class,
				new Emitter() {
					public void emit(final StringBuffer buffer, final Object number) {
						buffer.append("<value><double>").append(number).append("</double></value>");
					}
				});
		elements.put(Float.class, elements.get(Double.class));
		
		elements.put(String.class,
				new Emitter() {
					public void emit(final StringBuffer buffer, final Object string) throws SAXException {
						encodeString(buffer.append("<value><string>"), (String)string).append("</string></value>");
					}
				});
		
		elements.put(Boolean.class,
				new Emitter() {
					public void emit(final StringBuffer buffer, final Object bool) {
						buffer.append("<value><boolean>").append((((Boolean)bool).booleanValue()) ? "1" : "0").append("</boolean></value>");
					}
				});
		
		elements.put(byte [].class,
				new Emitter() {
					public void emit(final StringBuffer buffer, final Object bytes) {
						int charCount = 0;
						final byte[] data = (byte[])bytes;
						final int numChars = ((data.length + 2) / 3) * 4;
						final int dLimit = (data.length / 3) * 3;
						
						buffer.ensureCapacity(numChars + 128 + (data.length / 54));
						buffer.append("<value><base64>\n");

						for (int dIndex = 0; dIndex != dLimit; dIndex += 3) {
							int d = ((data[dIndex] & 0XFF) << 16) |  ((data[dIndex + 1] & 0XFF) << 8) | (data[dIndex + 2] & 0XFF);

							buffer.append(tTable[d >> 18]);
							buffer.append(tTable[(d >> 12) & 0X3F]);
							buffer.append(tTable[(d >> 6) & 0X3F]);
							buffer.append(tTable[d & 0X3F]);

							if (++charCount == 18) {
								buffer.append('\n');
								charCount = 0;
							}
						}

						if (dLimit != data.length) {
							int d = (data[dLimit] & 0XFF) << 16;

							if (dLimit + 1 != data.length) {
								d |= (data[dLimit + 1] & 0XFF) << 8;
							}

							buffer.append(tTable[d >> 18]);
							buffer.append(tTable[(d >> 12) & 0X3F]);
							buffer.append((dLimit + 1 < data.length) ? tTable[(d >> 6) & 0X3F] : '=');
							buffer.append('=');
						}
						
						buffer.append("\n</base64></value>");
					}
				});
		
		elements.put(Date.class,
				new Emitter() {
					private final DateFormat dateTime = new SimpleDateFormat ("yyyyMMdd'T'HH:mm:ss");
					
					public synchronized void emit(final StringBuffer buffer, final Object date) {
						buffer.append("<value><dateTime.iso8601>").append(this.dateTime.format((Date)date)).append("</dateTime.iso8601></value>");
					}
				});
	}
	
	public static StringBuffer emit(final StringBuffer buffer, final Object param) throws SAXException {
		final Emitter emitter = (Emitter)elements.get(param.getClass());
		
		if (emitter == null) {
			if (param instanceof List) {
				final Iterator iterator = ((List)param).iterator();
				
				buffer.append("<value><array><data>");
				
				while (iterator.hasNext()) {
					emit(buffer, iterator.next());
				}
				
				buffer.append("</data></array></value>");
				
			} else if (param instanceof Map) {
				final Iterator iterator =((Map)param).entrySet().iterator();
				
				buffer.append("<value><struct>");
				
				while (iterator.hasNext()) {
				final Map.Entry entry = (Map.Entry)iterator.next();
					
					emit(encodeString(buffer.append("<member><name>"), (String)entry.getKey()).append("</name>"), entry.getValue()).append("</member>");
				}
				
				buffer.append("</struct></value>");
			}
		} else {
			emitter.emit(buffer, param);
		}
		
		return buffer;
	}
	
	public static StringBuffer encodeString(final StringBuffer buffer, final String string) throws SAXException {
		for (int i = 0; i != string.length(); i++) {
			final char c = string.charAt(i);
			
			if (c >= 0X20 || c == 0X09 || c == 0X0A || c == 0X0D) {
				if (c == '>') {
					buffer.append("&gt;");
				} else if (c == '<') {
					buffer.append("&lt;");
				} else if (c == '&') {
					buffer.append("&amp;");
				} else if (c > 0xff) {
					if (c > 0XD800 && !(c >= 0XE000 && c < 0XFFFE)) 
						throw new SAXException("Can't include character with value 0x"
											   + Integer.toHexString(c)
											   + " in a well formed XML document");
					

					buffer.append("&#x").append(Integer.toHexString(c)).append(';');
				} else {
					buffer.append(c);
				}
			} else {
				throw new SAXException("Can't include character with value 0x"
						               + Integer.toHexString(c)
						               + " in a well formed XML document");
			}
		}
		
		return buffer;
	}
	
	/*
	 * A really cheap and cheerful XML-RPC reponse parser 
	 * It only really cares if the reponse contains a <param> or <fault>
	 * element. When the server is implemented this will be redone to be lots pickier.
	 */
	
	
	private Object params = null;
	private Object name = null;
	private String methodName = null;
	private Map struct = null;
	private List array = null;
	private Boolean inArray = Boolean.FALSE;
	private Stack aggregateStack = new Stack();
	private boolean gotValue = false;
	private final StringBuffer buffer = new StringBuffer();
	private final DateFormat dateTime = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
	private final Boolean bools[] = {new Boolean(false), new Boolean(true)};
	
	public void parseMessage(final InputStream in) throws SAXException, IOException {
		parse(new InputStreamReader(in, "ISO-8859-1"));
	}
	
	public List getParams() {
		return (List)this.params;
	}
	
	public String getMethodname() {
		return this.methodName;
	}
	
	/* (non-Javadoc)
	 * @see org.xml.sax.DocumentHandler#startElement(java.lang.String, org.xml.sax.AttributeList)
	 */
	public void startElement(final String name, final AttributeList attributes) {
		if ("value".equals(name) || "name".equals(name) || "methodName".equals(name)) {
			this.buffer.setLength(0);
			this.gotValue = false;
			this.aggregateStack.push(this.inArray);
			this.inArray = Boolean.FALSE;
		} else if ("struct".equals(name)) {
			this.aggregateStack.push(this.struct);
			this.aggregateStack.push(this.name);
			this.struct = new HashMap();
		} else if ("array".equals(name) || "params".equals(name)) {
			this.aggregateStack.push(this.inArray);
			this.inArray = Boolean.TRUE;
			this.aggregateStack.push(this.array);
			this.array = new ArrayList();
		}
	}
	
	/* (non-Javadoc)
	 * @see org.xml.sax.DocumentHandler#characters(char[], int, int)
	 */
	public void characters(final char[] ch, final int start, final int length) {
		this.buffer.append(ch, start, length);
	}

	/* (non-Javadoc)
	 * @see org.xml.sax.DocumentHandler#endElement(java.lang.String)
	 */
	public void endElement(final String name) throws SAXException {
		if ("value".equals(name)) {
			if (!this.gotValue) {
				this.params = this.buffer.toString();
				this.gotValue = true;
			}
			
			this.inArray = (Boolean)this.aggregateStack.pop();
			
			if (this.inArray.booleanValue())
				this.array.add(this.params);
		} else if ("string".equals(name)) {
			this.params = this.buffer.toString();
			this.gotValue = true;
		} else if ("i4".equals(name) || "int".equals(name)) {
			this.params = new Integer(this.buffer.toString());
			this.gotValue = true;
		} else if ("boolean".equals(name)) {
			try {
				this.params = this.bools[Integer.parseInt(this.buffer.toString())];
			}
			catch (final RuntimeException e) {
				throw new SAXException("bad Boolean value: " + this.buffer.toString());
			}
			
			this.gotValue = true;
		} else if ("dateTime.iso8601".equals(name)) {
			try {
				synchronized (this) {
					this.params = this.dateTime.parse(this.buffer.toString());
				}
			} catch (ParseException e) {
				throw new SAXException(e);
			}
			this.gotValue = true;
		} else if ("base64".equals(name)) {
			int bytesIndex = 0;
			int byteShift = 4;
			int tmp = 0;
			boolean done = false;
			
			for (int i = 0; i != this.buffer.length(); i++) {
			final char c = this.buffer.charAt(i);
			final int sixBit = (c < 123) ? translateTable[c] : 66;

				if (sixBit < 64) {
					if (done) throw new SAXException("= character not at end of base64 value");
	
					tmp = (tmp << 6) | sixBit;
	
					if (byteShift-- != 4) {
						this.buffer.setCharAt(bytesIndex++, (char)((tmp >> (byteShift * 2)) & 0XFF));
					}
	
				} else if (sixBit == 64) {
	
					byteShift--;
					done = true;
	
				} else if (sixBit == 66) {
					// RFC 2045 says that I'm allowed to take the presence of 
					// these characters as evedence of data corruption
					// So I will
					throw new SAXException("bad character in base64 value");
				}

				if (byteShift == 0) byteShift = 4;
			}
			this.buffer.setLength(bytesIndex);
			try {
				this.params = this.buffer.toString().getBytes("ISO-8859-1");
			} catch (UnsupportedEncodingException e) {
				throw new SAXException("Base 64 decode produced byte values > 255");
			}
			this.gotValue = true;
		} else if ("double".equals(name)) {
			this.params = new Double(this.buffer.toString());
			this.gotValue = true;
		} else if ("name".equals(name)) {
			this.name = this.buffer.toString();
			this.inArray = (Boolean)this.aggregateStack.pop();
		} else if ("member".equals(name)) {
			this.struct.put(this.name, this.params);
		} else if ("struct".equals(name)) {
			this.params = this.struct;
			this.name = (String)this.aggregateStack.pop();
			this.struct = (Map)this.aggregateStack.pop();
		} else if ("array".equals(name) || "params".equals(name)) {
			this.params = this.array;
			this.array = (List)this.aggregateStack.pop();
			this.inArray = (Boolean)this.aggregateStack.pop();
		} else if ("methodName".equals(name)) {
			this.methodName = this.buffer.toString();
			this.inArray = (Boolean)this.aggregateStack.pop();
		} else if ("fault".equals(name)) {
			throw new RuntimeException("XML-RPC call Failure: " +
					                   (String)((Map)this.params).get("faultString") +
					                   ", fault code = " +
					                   ((Integer)((Map)this.params).get("faultCode")).toString());
		}
	}
}