/* 
 * E-XML Library:  For XML, XML-RPC, HTTP, and related.
 * Copyright (C) 2002-2008  Elias Ross
 * 
 * genman@noderunner.net
 * http://noderunner.net/~genman
 * 
 * 1025 NE 73RD ST
 * SEATTLE WA 98115
 * USA
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * $Id$
 */

package net.noderunner.xmlrpc;

import java.io.Reader;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

/**
 * This class defines a concrete XmlRpcServer.
 */
public class XmlRpcServerImpl
	implements XmlRpcServer
{

	/**
	 * Registered handlers.
	 */
	private Map handlers;

	private XmlRpcReader reader;
	private XmlRpcWriter writer;
   
	/** 
	 * Construct a new Xml-Rpc server.  
	 */
	public XmlRpcServerImpl() {
		handlers = new HashMap();
		reader = new XmlRpcReaderImpl();
		writer = new XmlRpcWriterImpl();
	}
		
	public void addHandler(String handlerName, XmlRpcHandler handler) 
	{
		handlers.put(handlerName, handler);
	}

	public void removeHandler(String handlerName) 
	{
		handlers.remove(handlerName);
	}

	/**
	 * Shows debug information.
	 */
	public String toString() {
		return "XmlRpcServerImpl [handlers=" + handlers + "]";
	}

	public void accept(Reader in, Writer out) 
		throws XmlRpcException
	{
		reader.setReader(in);
		String methodName = reader.readMethodName();

		// find a handler by name
		XmlRpcHandler handler = null;
		int dot = methodName.indexOf(".");
		if (dot > -1) {
			String handlerName = methodName.substring(0, dot);
			handler = (XmlRpcHandler)handlers.get(handlerName);
			methodName = methodName.substring(dot+1);
		}
		if (handler == null) {
			handler = (XmlRpcHandler)handlers.get(DEFAULT_HANDLER);
		}
		if (handler == null) {
		   throw new NoHandlerException("Rpc handler object not found for \""+methodName+"\": no default handler registered.");
		}

		writer.setWriter(out);
		ParamIterator inParam = null;
		ParamIterator outParam = null;
		try {
			inParam = reader.readMethodRequest();
			outParam = handler.execute(methodName, inParam);
			// This ensures that inParam is completely read and valid.
			// Otherwise, we would assume the rest of the Xml has valid
			// closing tags.
			inParam.close();
			writer.writeResponse(outParam);
		} catch (XmlRpcException xre) {
			xre.printStackTrace();
			writer.writeError(xre);
		} finally {
			// This insures that the outParam resources will be
			// released.
			if (outParam != null)
				outParam.close();
		}
	}

}
