/*
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.
*
*
*/