/* Wotonomy: OpenStep design patterns for pure Java applications. Copyright (C) 2001 Intersect Software Corporation 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. You should have received a copy of the GNU Lesser General Public License along with this library; if not, see http://www.gnu.org */ package net.wotonomy.web.xml; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.net.URLConnection; import net.wotonomy.foundation.NSSelector; import net.wotonomy.foundation.internal.WotonomyException; /** * An NSSelector customized to invoke methods with XMLRPC when a URL is passed * in as the object to the invoke() method. The method name and parameters will * be marshalled and sent as an XMLRPC request to the host specified by the URL. *
*
* * To use this class simply as an XMLRPC client, just call invoke() with a URL * referencing the XMLRPC server and an optional array of parameters. * * @author michael@mpowers.net * @author $Author: cgruber $ * @version $Revision: 905 $ */ public class XMLRPCSelector extends NSSelector { private boolean copyStream = false; /** * Constructor specifying a method name. */ public XMLRPCSelector(String aMethodName) { super(aMethodName, EMPTY_CLASS_ARRAY); } /** * Constructor specifying a method name and an array of parameter types. When * accessing XMLRPC servers, invoke() does require that the specified objects * match the types in the parameter type array. */ public XMLRPCSelector(String aMethodName, Class[] aParameterTypeArray) { super(aMethodName, aParameterTypeArray); } /** * Invokes this selector's method on the specified object using the specified * parameters. */ public Object invoke(Object anObject, Object[] parameters) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { if (anObject instanceof URL) { Receiver receiver = new Receiver(); byte[] copyOfResponse = null; try { URLConnection cn = ((URL) anObject).openConnection(); // set properties cn.setDoOutput(true); cn.setDoInput(true); cn.setRequestProperty("content-type", "text/xml"); // send parameters OutputStream out = cn.getOutputStream(); new XMLRPCEncoder().encodeRequest(name(), parameters, out); out.flush(); out.close(); // get response: getInputStream initiates the request InputStream input = new BufferedInputStream(cn.getInputStream()); if (copyStream) { ByteArrayOutputStream byteArray = new ByteArrayOutputStream(); int b; while ((b = input.read()) != -1) { byteArray.write(b); } copyOfResponse = byteArray.toByteArray(); input = new ByteArrayInputStream(copyOfResponse); } new XMLRPCDecoder().decode(input, receiver); } catch (FileNotFoundException exc) { throw new WotonomyException("Server did not return a response."); } catch (Exception exc) { if (copyOfResponse != null) { System.out.println(new String(copyOfResponse)); exc.printStackTrace(); } throw new InvocationTargetException(exc); } if (receiver.faultString == null) { return receiver.result; } else { throw new InvocationTargetException( new WotonomyException(receiver.faultCode + ": " + receiver.faultString)); } } // else: not a URL return super.invoke(anObject, parameters); } public static Object invoke(String methodName, Class[] parameterTypes, Object anObject, Object[] parameters) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { return new XMLRPCSelector(methodName, parameterTypes).invoke(anObject, parameters); } public static Object invoke(String methodName, Object anObject) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { return XMLRPCSelector.invoke(methodName, EMPTY_CLASS_ARRAY, anObject, EMPTY_OBJECT_ARRAY); } public static Object invoke(String methodName, Class[] parameterTypes, Object anObject, Object aParameter) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { return XMLRPCSelector.invoke(methodName, parameterTypes, anObject, new Object[] { aParameter }); } public static Object invoke(String methodName, Class[] parameterTypes, Object anObject, Object p1, Object p2) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { return XMLRPCSelector.invoke(methodName, parameterTypes, anObject, new Object[] { p1, p2 }); } private class Receiver implements XMLRPCReceiver { public Object result; public int faultCode; public String faultString; public Receiver() { result = null; faultCode = -1; faultString = null; } public void request(String aMethodName, Object[] aParameterArray) { throw new WotonomyException("Invalid response: Expected response but received request."); } public void response(Object aResult) { result = aResult; faultCode = -1; faultString = null; } public void fault(int aFaultCode, String aFaultString) { result = null; faultCode = aFaultCode; faultString = aFaultString; } } } /* * $Log$ Revision 1.1 2006/02/19 01:44:03 cgruber Add xmlrpc files Remove jclark * and replace with dom4j and javax.xml.sax stuff Re-work dependencies and * imports so it all compiles. * * Revision 1.1 2006/02/16 13:22:22 cgruber Check in all sources in * eclipse-friendly maven-enabled packages. * * Revision 1.1 2001/02/07 19:24:28 mpowers Moved XML classes to separate * package. * * */