gt:         StringBuffer sb = new StringBuffer();
context: /*******************************************************************************
   * This file is part of OpenNMS(R).
   *
   * Copyright (C) 2005-2014 The OpenNMS Group, Inc.
   * OpenNMS(R) is Copyright (C) 1999-2014 The OpenNMS Group, Inc.
   *
   * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
   *
   * OpenNMS(R) is free software: you can redistribute it and/or modify
   * it under the terms of the GNU Affero General Public License as published
   * by the Free Software Foundation, either version 3 of the License,
   * or (at your option) any later version.
   *
   * OpenNMS(R) 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 Affero General Public License for more details.
   *
   * You should have received a copy of the GNU Affero General Public License
   * along with OpenNMS(R).  If not, see:
   *      http://www.gnu.org/licenses/
   *
   * For more information contact:
   *     OpenNMS(R) Licensing <license@opennms.org>
   *     http://www.opennms.org/
   *     http://www.opennms.com/
   *******************************************************************************/
  
  package org.opennms.spring.xmlrpc;
  
  import java.lang.reflect.InvocationTargetException;
  import java.net.MalformedURLException;
  import java.util.Collection;
  import java.util.Hashtable;
  import java.util.List;
  import java.util.Map;
  import java.util.Vector;
  
  import org.apache.xmlrpc.WebServer;
  import org.apache.xmlrpc.XmlRpcException;
  import org.apache.xmlrpc.XmlRpcHandler;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.springframework.beans.factory.DisposableBean;
  import org.springframework.beans.factory.InitializingBean;
  import org.springframework.beans.support.ArgumentConvertingMethodInvoker;
  import org.springframework.remoting.support.RemoteExporter;
  import org.springframework.util.MethodInvoker;
  
  /**
   * <p>XmlRpcServiceExporter class.</p>
   *
   * @author <a href="mailto:brozow@opennms.org">Mathew Brozowski</a>
   * @version $Id: $
   */
  public class XmlRpcServiceExporter extends RemoteExporter implements InitializingBean, DisposableBean, XmlRpcHandler {
  	
  	private static final Logger LOG = LoggerFactory.getLogger(XmlRpcServiceExporter.class);
      
      private WebServer webServer;
      private Object proxy;
      private String serviceName;
  
      /**
       * <p>Getter for the field <code>webServer</code>.</p>
       *
       * @return a {@link org.apache.xmlrpc.WebServer} object.
       */
      public WebServer getWebServer() {
          return this.webServer;
      }
      
      /**
       * <p>Setter for the field <code>webServer</code>.</p>
       *
       * @param webServer a {@link org.apache.xmlrpc.WebServer} object.
       */
      public void setWebServer(WebServer webServer) {
          this.webServer = webServer;
      }
      
      /**
       * <p>Getter for the field <code>serviceName</code>.</p>
       *
       * @return a {@link java.lang.String} object.
       */
      public String getServiceName() {
          return this.serviceName;
      }
      
      /**
       * <p>Setter for the field <code>serviceName</code>.</p>
       *
       * @param serviceName a {@link java.lang.String} object.
       */
      public void setServiceName(String serviceName) {
          this.serviceName = serviceName;
      }
      
      /**
       * <p>afterPropertiesSet</p>
       *
       * @throws java.lang.Exception if any.
       */
      @Override
      public void afterPropertiesSet() throws Exception {
          if (this.webServer == null)
              throw new IllegalArgumentException("webServer is required");
          checkService();
          checkServiceInterface();
          this.proxy = getProxyForService();
       
          if (serviceName == null || "".equals(serviceName)) {
              this.webServer.addHandler("$default", this);
          } else {
              this.webServer.addHandler(serviceName, this);
          }
          
      }
  
      /**
       * <p>destroy</p>
       *
       * @throws java.lang.Exception if any.
       */
      @Override
      public void destroy() throws Exception {
          if (serviceName == null || "".equals(serviceName)) {
              this.webServer.removeHandler("$default");
          } else {
              this.webServer.removeHandler(serviceName);
          }
      }
      
      public static class MsgPreservingXmlRpcException extends XmlRpcException {
  
          /**
           * 
           */
          private static final long serialVersionUID = -4693127622262382452L;
  
          public MsgPreservingXmlRpcException(int code, String message) {
              super(code, message);
          }
          
          @Override
          public String toString() {
              return getMessage();
          }
          
      }
  
      /** {@inheritDoc} */
      @Override
      public Object execute(String method, @SuppressWarnings("rawtypes") Vector params) throws Exception {
          
          LOG.debug("calling: {}({})", method, toArgList(params));
          
          MethodInvoker invoker = new ArgumentConvertingMethodInvoker();
          invoker.setTargetObject(this.proxy);
          invoker.setTargetMethod(getMethodName(method));
          invoker.setArguments(params.toArray());
          invoker.prepare();
          
          try {
          Object returnValue =  invoker.invoke();
          
          if (returnValue == null && invoker.getPreparedMethod().getReturnType() == Void.TYPE) {
              returnValue = "void";
          }
          
          else if (returnValue instanceof Map<?,?> && !(returnValue instanceof Hashtable<?,?>)) {
              returnValue = new Hashtable<Object, Object>((Map<?, ?>)returnValue);
          }
          
          else if (returnValue instanceof Collection<?> && !(returnValue instanceof Vector<?>)) {
              returnValue = new Vector<Object>((Collection<?>)returnValue);
          }
          
          LOG.debug("returning from: {}({}) result = {}", method, toArgList(params), returnValue);
          return returnValue;
          
          } catch (InvocationTargetException e) {
              Throwable targetException = e.getTargetException();
              if (targetException instanceof IllegalArgumentException) {
                  throw new MsgPreservingXmlRpcException(XmlRpcConstants.FAULT_INVALID_DATA, targetException.getMessage());
              } else if (targetException instanceof MalformedURLException) {
                  throw new MsgPreservingXmlRpcException(XmlRpcConstants.FAULT_INVALID_URL, targetException.getMessage());
              }
              else if (targetException instanceof Exception && targetException.toString() != null) { 
                  throw (Exception)targetException;
              }
              
              String msg = targetException.toString();
              if (msg == null)
                  msg = targetException.getClass().getName();
              
              Exception ex = new Exception(msg, targetException);
              ex.setStackTrace(targetException.getStackTrace());
              throw ex;
          }
  
      }
  
      private String toArgList(@SuppressWarnings("rawtypes") List params) {
  