diff options
Diffstat (limited to 'projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml')
6 files changed, 1071 insertions, 1398 deletions
diff --git a/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCDecoder.java b/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCDecoder.java index 8da71fe..54658c0 100644 --- a/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCDecoder.java +++ b/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCDecoder.java @@ -32,83 +32,73 @@ import net.wotonomy.foundation.xml.XMLDecoder; import org.xml.sax.SAXException; /** -* An implementation of XMLDecoder that reads objects from -* XMLRPC format. -* This implementation is not thread-safe, so a new instances -* should be created to accomodate multiple threads. -*/ -public class XMLRPCDecoder implements XMLDecoder -{ - XMLRPCDecoderHelper helper = new XMLRPCDecoderHelper(); - - /** - * Decodes an object in XML-RPC format from the specified input stream. - * @param anInputStream The input stream from which to read. - * The stream will be read fully. - * @param aDescription A description to accompany error messages - * for the stream, typically a file name. - * @param aURL A URL against which relative references within the - * XML will be resolved. - * @return The object that was constructed from the XML content, - * or null if no object could be constructed. - */ - public Object decode( - InputStream anInputStream, String aDescription, URL aURL ) - { - Object result = null; - - try { - SAXParser sparser = SAXParserFactory.newInstance().newSAXParser(); - sparser.parse(anInputStream,helper,aURL.toExternalForm()); - result = helper.getResult(); - } catch (ParserConfigurationException e) { - throw new WotonomyException("Problem in parser configuration", e ); - } catch (IOException e) { - throw new WotonomyException("IOException thrown while parsing", e ); - } catch (SAXException e) { - throw new WotonomyException("SAXException thrown while parsing", e ); - } - helper.reset(); - return result; - } + * An implementation of XMLDecoder that reads objects from XMLRPC format. This + * implementation is not thread-safe, so a new instances should be created to + * accomodate multiple threads. + */ +public class XMLRPCDecoder implements XMLDecoder { + XMLRPCDecoderHelper helper = new XMLRPCDecoderHelper(); + + /** + * Decodes an object in XML-RPC format from the specified input stream. + * + * @param anInputStream The input stream from which to read. The stream will be + * read fully. + * @param aDescription A description to accompany error messages for the + * stream, typically a file name. + * @param aURL A URL against which relative references within the XML + * will be resolved. + * @return The object that was constructed from the XML content, or null if no + * object could be constructed. + */ + public Object decode(InputStream anInputStream, String aDescription, URL aURL) { + Object result = null; + + try { + SAXParser sparser = SAXParserFactory.newInstance().newSAXParser(); + sparser.parse(anInputStream, helper, aURL.toExternalForm()); + result = helper.getResult(); + } catch (ParserConfigurationException e) { + throw new WotonomyException("Problem in parser configuration", e); + } catch (IOException e) { + throw new WotonomyException("IOException thrown while parsing", e); + } catch (SAXException e) { + throw new WotonomyException("SAXException thrown while parsing", e); + } + helper.reset(); + return result; + } + + /** + * Decodes an XML-RPC message from the specified input stream. Stand-alone + * values not wrapped in "methodCall" or "param" tags will be treated as a + * response. + * + * @param anInputStream The input stream from which to read. The stream will be + * read fully. + * @param aReceiver an XMLRPCReceiver that will be invoked with the + * appropriate method: request, response, or fault. + */ + public void decode(InputStream anInputStream, XMLRPCReceiver aReceiver) { + try { + SAXParser sparser = SAXParserFactory.newInstance().newSAXParser(); + sparser.parse(anInputStream, helper); - /** - * Decodes an XML-RPC message from the specified input stream. - * Stand-alone values not wrapped in "methodCall" or "param" - * tags will be treated as a response. - * @param anInputStream The input stream from which to read. - * The stream will be read fully. - * @param aReceiver an XMLRPCReceiver that will be invoked with - * the appropriate method: request, response, or fault. - */ - public void decode( - InputStream anInputStream, XMLRPCReceiver aReceiver ) - { - try - { - SAXParser sparser = SAXParserFactory.newInstance().newSAXParser(); - sparser.parse(anInputStream,helper); - - if ( helper.isRequest() ) - { - aReceiver.request( helper.getMethodName(), helper.getParameters() ); - } - else - if ( helper.isFault() ) - { - aReceiver.fault( helper.getFaultCode(), helper.getFaultString() ); - } - else // all else is considered a response - { - aReceiver.response( helper.getResult() ); - } - } catch (ParserConfigurationException e) { - throw new WotonomyException("Problem in parser configuration", e ); - } catch (IOException e) { - throw new WotonomyException("IOException thrown while parsing", e ); - } catch (SAXException e) { - throw new WotonomyException("SAXException thrown while parsing", e ); - } - helper.reset(); - } + if (helper.isRequest()) { + aReceiver.request(helper.getMethodName(), helper.getParameters()); + } else if (helper.isFault()) { + aReceiver.fault(helper.getFaultCode(), helper.getFaultString()); + } else // all else is considered a response + { + aReceiver.response(helper.getResult()); + } + } catch (ParserConfigurationException e) { + throw new WotonomyException("Problem in parser configuration", e); + } catch (IOException e) { + throw new WotonomyException("IOException thrown while parsing", e); + } catch (SAXException e) { + throw new WotonomyException("SAXException thrown while parsing", e); + } + helper.reset(); + } } diff --git a/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCDecoderHelper.java b/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCDecoderHelper.java index 2368672..0806d88 100644 --- a/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCDecoderHelper.java +++ b/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCDecoderHelper.java @@ -38,77 +38,64 @@ import org.xml.sax.SAXParseException; import org.xml.sax.helpers.DefaultHandler; /** -* Used by XMLDecoder to implement the necessary interfaces -* required by the jclark xp parser. -* This class is not thread safe. -*/ -class XMLRPCDecoderHelper extends DefaultHandler -{ - protected final Object nilMarker = new Object(); - protected Stack valueStack; - protected String methodName; - protected int faultCode; - protected String faultString; - protected List parameters; - protected StringBuffer cdataBuffer; - - - - public XMLRPCDecoderHelper() - { - valueStack = new Stack(); - parameters = new LinkedList(); - cdataBuffer = new StringBuffer(); - reset(); - } - - public void reset() - { - valueStack.clear(); - parameters.clear(); - cdataBuffer.setLength( 0 ); - methodName = null; - faultCode = 0; - faultString = null; - } - - public boolean isRequest() - { - return ( methodName != null ); - } - - public boolean isResponse() - { - return ( methodName == null ); - } - - public boolean isFault() - { - // faults are responses - return ( isResponse() ) && ( faultString != null ); - } - - public int getFaultCode() - { - return faultCode; - } - - public String getFaultString() - { - return faultString; - } - - public String getMethodName() - { - return methodName; - } - - public Object[] getParameters() - { - return parameters.toArray(); - } - - public void endDocument() throws SAXException { + * Used by XMLDecoder to implement the necessary interfaces required by the + * jclark xp parser. This class is not thread safe. + */ +class XMLRPCDecoderHelper extends DefaultHandler { + protected final Object nilMarker = new Object(); + protected Stack valueStack; + protected String methodName; + protected int faultCode; + protected String faultString; + protected List parameters; + protected StringBuffer cdataBuffer; + + public XMLRPCDecoderHelper() { + valueStack = new Stack(); + parameters = new LinkedList(); + cdataBuffer = new StringBuffer(); + reset(); + } + + public void reset() { + valueStack.clear(); + parameters.clear(); + cdataBuffer.setLength(0); + methodName = null; + faultCode = 0; + faultString = null; + } + + public boolean isRequest() { + return (methodName != null); + } + + public boolean isResponse() { + return (methodName == null); + } + + public boolean isFault() { + // faults are responses + return (isResponse()) && (faultString != null); + } + + public int getFaultCode() { + return faultCode; + } + + public String getFaultString() { + return faultString; + } + + public String getMethodName() { + return methodName; + } + + public Object[] getParameters() { + return parameters.toArray(); + } + + public void endDocument() throws SAXException { // TODO Auto-generated method stub super.endDocument(); } @@ -118,47 +105,40 @@ class XMLRPCDecoderHelper extends DefaultHandler super.startDocument(); reset(); } - - public Object getResult() - { - if ( valueStack.empty() ) return null; - Object result = valueStack.peek(); - if ( result == nilMarker ) result = null; - return result; - } - - + + public Object getResult() { + if (valueStack.empty()) + return null; + Object result = valueStack.peek(); + if (result == nilMarker) + result = null; + return result; + } + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); - if ( XMLRPCEncoder.VALUE.equals( localName ) ) - { - ValueMarker marker = new ValueMarker(); - String classname = attributes.getValue( uri, XMLRPCEncoder.CLASS ); - if ( classname != null ) - { - try - { - Class c = Class.forName( classname ); - if ( c != null ) - { - marker.setMarkerClass( c ); - } - } - catch ( Exception exc ) - { - System.out.println( "XMLRPCDecoderHelper.startElement: " + - "Can't find class: " + classname ); - } - } - valueStack.push( marker ); - } + if (XMLRPCEncoder.VALUE.equals(localName)) { + ValueMarker marker = new ValueMarker(); + String classname = attributes.getValue(uri, XMLRPCEncoder.CLASS); + if (classname != null) { + try { + Class c = Class.forName(classname); + if (c != null) { + marker.setMarkerClass(c); + } + } catch (Exception exc) { + System.out.println("XMLRPCDecoderHelper.startElement: " + "Can't find class: " + classname); + } + } + valueStack.push(marker); + } } - - public void characters(char[] ch, int start, int length) throws SAXException { + + public void characters(char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); - char[] someChars = new char[((start+length)<=ch.length) ? length : ch.length-start]; - for (int i = 0; i < someChars.length; i++ ) { - someChars[i] = ch[start+i]; + char[] someChars = new char[((start + length) <= ch.length) ? length : ch.length - start]; + for (int i = 0; i < someChars.length; i++) { + someChars[i] = ch[start + i]; } cdataBuffer.append(someChars); } @@ -166,231 +146,140 @@ class XMLRPCDecoderHelper extends DefaultHandler public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); - // if any cdata is buffered or if string value - if ( ( XMLRPCEncoder.STRING.equals( localName ) ) - || ( cdataBuffer.length() > 0 ) ) - { - // push value on the stack - valueStack.push( cdataBuffer.toString() ); - cdataBuffer.setLength( 0 ); - } - - if ( XMLRPCEncoder.VALUE.equals( localName ) ) - { - Object value = valueStack.pop(); - try - { + // if any cdata is buffered or if string value + if ((XMLRPCEncoder.STRING.equals(localName)) || (cdataBuffer.length() > 0)) { + // push value on the stack + valueStack.push(cdataBuffer.toString()); + cdataBuffer.setLength(0); + } + + if (XMLRPCEncoder.VALUE.equals(localName)) { + Object value = valueStack.pop(); + try { // ValueMarker marker = (ValueMarker) valueStack.pop(); - ValueMarker marker = null; - Object markerValue = valueStack.pop(); - if ( markerValue instanceof ValueMarker ) - { - marker = (ValueMarker) markerValue; - } - else - { - throw new WotonomyException( "Expected value marker, found" - + markerValue.getClass() + " : " + markerValue ); - } - + ValueMarker marker = null; + Object markerValue = valueStack.pop(); + if (markerValue instanceof ValueMarker) { + marker = (ValueMarker) markerValue; + } else { + throw new WotonomyException( + "Expected value marker, found" + markerValue.getClass() + " : " + markerValue); + } + //System.out.println( "getMarkerClass: " + marker.getMarkerClass() + " : " + value ); //System.out.println( valueStack ); - if ( marker.getMarkerClass() != null ) - { - // apply introspection - if ( value instanceof Map ) - { - Map map = (Map)value; - Map.Entry entry; - value = marker.getMarkerClass().newInstance(); - Iterator it = map.entrySet().iterator(); - Object entryValue; - while( it.hasNext() ) - { - entry = (Map.Entry) it.next(); - entryValue = entry.getValue(); - if ( entryValue == nilMarker ) entryValue = null; - Introspector.set( - value, entry.getKey().toString(), entryValue ); - } - } - if ( ! ( value.getClass().equals( marker.getMarkerClass() ) ) ) - { - Object converted = - ValueConverter.convertObjectToClass( - value, marker.getMarkerClass() ); - if ( converted != null ) - { - value = converted; - } - } - } - } - catch ( Exception exc ) - { - // fall back on unconverted value - } - - valueStack.push( value ); + if (marker.getMarkerClass() != null) { + // apply introspection + if (value instanceof Map) { + Map map = (Map) value; + Map.Entry entry; + value = marker.getMarkerClass().newInstance(); + Iterator it = map.entrySet().iterator(); + Object entryValue; + while (it.hasNext()) { + entry = (Map.Entry) it.next(); + entryValue = entry.getValue(); + if (entryValue == nilMarker) + entryValue = null; + Introspector.set(value, entry.getKey().toString(), entryValue); + } + } + if (!(value.getClass().equals(marker.getMarkerClass()))) { + Object converted = ValueConverter.convertObjectToClass(value, marker.getMarkerClass()); + if (converted != null) { + value = converted; + } + } + } + } catch (Exception exc) { + // fall back on unconverted value + } + + valueStack.push(value); // System.out.println( "convertedValue: " + value + "("+ value.getClass() +")" ); - } - else - if ( XMLRPCEncoder.MEMBER.equals( localName ) ) // Map.Entry - { - // leave key and value to be handled by struct - } - else - if ( XMLRPCEncoder.STRUCT.equals( localName ) ) // write Entries to map or object - { - // write values to array (reverse the order) - Object value; - Map map = new HashMap(); - while ( ( ! valueStack.empty() ) - && ( ! ( valueStack.peek() instanceof ValueMarker ) ) ) - { - value = valueStack.pop(); - map.put( valueStack.pop(), value ); - } - // push the list on the stack - valueStack.push( map ); - } - else - if ( XMLRPCEncoder.ARRAY.equals( localName ) ) - { + } else if (XMLRPCEncoder.MEMBER.equals(localName)) // Map.Entry + { + // leave key and value to be handled by struct + } else if (XMLRPCEncoder.STRUCT.equals(localName)) // write Entries to map or object + { + // write values to array (reverse the order) + Object value; + Map map = new HashMap(); + while ((!valueStack.empty()) && (!(valueStack.peek() instanceof ValueMarker))) { + value = valueStack.pop(); + map.put(valueStack.pop(), value); + } + // push the list on the stack + valueStack.push(map); + } else if (XMLRPCEncoder.ARRAY.equals(localName)) { //System.out.println( "ended ARRAY: " + valueStack.size() ); - // write values to array (reverse the order) - Object value; - LinkedList list = new LinkedList(); - while ( ( ! valueStack.empty() ) - && ( ! ( valueStack.peek() instanceof ValueMarker ) ) ) - { - value = valueStack.pop(); - if ( value == nilMarker ) value = null; - list.addFirst( value ); - } - // push the list on the stack - valueStack.push( list ); - } - else - if ( XMLRPCEncoder.INT.equals( localName ) ) - { - Object value = valueStack.pop(); - try - { - valueStack.push( - new Integer( value.toString() ) ); - } - catch ( NumberFormatException exc ) - { - throw new WotonomyException( - "Invalid double format: " + value.toString() ); - } - } - else - if ( XMLRPCEncoder.I4.equals( localName ) ) - { - Object value = valueStack.pop(); - try - { - valueStack.push( - new Integer( value.toString() ) ); - } - catch ( NumberFormatException exc ) - { - throw new WotonomyException( - "Invalid double format: " + value.toString() ); - } - } - else - if ( XMLRPCEncoder.NIL.equals( localName ) ) - { - valueStack.push( nilMarker ); - } - else - if ( XMLRPCEncoder.DOUBLE.equals( localName ) ) - { - Object value = valueStack.pop(); - try - { - valueStack.push( - new Double( value.toString() ) ); - } - catch ( NumberFormatException exc ) - { - throw new WotonomyException( - "Invalid double format: " + value.toString() ); - } - } - else - if ( XMLRPCEncoder.DATE.equals( localName ) ) - { - Object value = valueStack.pop(); - try - { - valueStack.push( - XMLRPCEncoder.DATEFORMAT8601.parseObject( - value.toString() ) ); - } - catch ( Exception exc ) - { - throw new WotonomyException( - "Invalid date format: " + value ); - } - } - else - if ( XMLRPCEncoder.BOOLEAN.equals( localName ) ) - { - Object value = valueStack.pop(); - if ( XMLRPCEncoder.TRUE.equals( value ) ) - { - valueStack.push( Boolean.TRUE ); - } - else - if ( XMLRPCEncoder.FALSE.equals( value ) ) - { - valueStack.push( Boolean.FALSE ); - } - else - { - throw new WotonomyException( - "Invalid boolean format: " + value ); - } - } - else - if ( XMLRPCEncoder.BASE64.equals( localName ) ) - { - throw new WotonomyException( "Not implemented yet." ); - } - else - if ( XMLRPCEncoder.FAULT.equals( localName ) ) - { - Map faultMap = (Map) valueStack.pop(); - try - { - faultCode = ((Integer) - faultMap.get( XMLRPCEncoder.FAULTCODE )).intValue(); - faultString = (String) faultMap.get( XMLRPCEncoder.FAULTSTRING ); - } - catch ( Exception exc ) - { - throw new WotonomyException( - "Invalid fault format: " + faultMap ); - } - } - else - if ( XMLRPCEncoder.METHODNAME.equals( localName ) ) - { - methodName = (String) valueStack.pop(); - } - else - if ( XMLRPCEncoder.PARAM.equals( localName ) ) - { - //NOTE: this leaves the parameter on the stack - parameters.add( getResult() ); - } - } - - + // write values to array (reverse the order) + Object value; + LinkedList list = new LinkedList(); + while ((!valueStack.empty()) && (!(valueStack.peek() instanceof ValueMarker))) { + value = valueStack.pop(); + if (value == nilMarker) + value = null; + list.addFirst(value); + } + // push the list on the stack + valueStack.push(list); + } else if (XMLRPCEncoder.INT.equals(localName)) { + Object value = valueStack.pop(); + try { + valueStack.push(new Integer(value.toString())); + } catch (NumberFormatException exc) { + throw new WotonomyException("Invalid double format: " + value.toString()); + } + } else if (XMLRPCEncoder.I4.equals(localName)) { + Object value = valueStack.pop(); + try { + valueStack.push(new Integer(value.toString())); + } catch (NumberFormatException exc) { + throw new WotonomyException("Invalid double format: " + value.toString()); + } + } else if (XMLRPCEncoder.NIL.equals(localName)) { + valueStack.push(nilMarker); + } else if (XMLRPCEncoder.DOUBLE.equals(localName)) { + Object value = valueStack.pop(); + try { + valueStack.push(new Double(value.toString())); + } catch (NumberFormatException exc) { + throw new WotonomyException("Invalid double format: " + value.toString()); + } + } else if (XMLRPCEncoder.DATE.equals(localName)) { + Object value = valueStack.pop(); + try { + valueStack.push(XMLRPCEncoder.DATEFORMAT8601.parseObject(value.toString())); + } catch (Exception exc) { + throw new WotonomyException("Invalid date format: " + value); + } + } else if (XMLRPCEncoder.BOOLEAN.equals(localName)) { + Object value = valueStack.pop(); + if (XMLRPCEncoder.TRUE.equals(value)) { + valueStack.push(Boolean.TRUE); + } else if (XMLRPCEncoder.FALSE.equals(value)) { + valueStack.push(Boolean.FALSE); + } else { + throw new WotonomyException("Invalid boolean format: " + value); + } + } else if (XMLRPCEncoder.BASE64.equals(localName)) { + throw new WotonomyException("Not implemented yet."); + } else if (XMLRPCEncoder.FAULT.equals(localName)) { + Map faultMap = (Map) valueStack.pop(); + try { + faultCode = ((Integer) faultMap.get(XMLRPCEncoder.FAULTCODE)).intValue(); + faultString = (String) faultMap.get(XMLRPCEncoder.FAULTSTRING); + } catch (Exception exc) { + throw new WotonomyException("Invalid fault format: " + faultMap); + } + } else if (XMLRPCEncoder.METHODNAME.equals(localName)) { + methodName = (String) valueStack.pop(); + } else if (XMLRPCEncoder.PARAM.equals(localName)) { + // NOTE: this leaves the parameter on the stack + parameters.add(getResult()); + } + } public void endPrefixMapping(String prefix) throws SAXException { // TODO Auto-generated method stub @@ -423,12 +312,14 @@ class XMLRPCDecoderHelper extends DefaultHandler } public InputSource resolveEntity(String publicId, String systemId) throws SAXException { - // NOTE: Sun accepted an incompatible api difference. The (false) should be tossed by hotspot + // NOTE: Sun accepted an incompatible api difference. The (false) should be + // tossed by hotspot try { - if (false) throw new IOException("Fake exception to make it compile in both 1.4 and 1.5"); - return super.resolveEntity(publicId, systemId); + if (false) + throw new IOException("Fake exception to make it compile in both 1.4 and 1.5"); + return super.resolveEntity(publicId, systemId); } catch (IOException e) { - throw new SAXException(e.getClass().getName() + " thrown while resolving entity.",e); + throw new SAXException(e.getClass().getName() + " thrown while resolving entity.", e); } } @@ -442,14 +333,13 @@ class XMLRPCDecoderHelper extends DefaultHandler super.skippedEntity(name); } - - public void startPrefixMapping(String prefix, String uri) throws SAXException { // TODO Auto-generated method stub super.startPrefixMapping(prefix, uri); } - public void unparsedEntityDecl(String name, String publicId, String systemId, String notationName) throws SAXException { + public void unparsedEntityDecl(String name, String publicId, String systemId, String notationName) + throws SAXException { // TODO Auto-generated method stub super.unparsedEntityDecl(name, publicId, systemId, notationName); } @@ -459,76 +349,65 @@ class XMLRPCDecoderHelper extends DefaultHandler super.warning(e); } - - // marker class - - private class ValueMarker - { - private Class theClass; - - public ValueMarker() - { - theClass = null; - } - - public void setMarkerClass( Class aClass ) - { - theClass = aClass; - } - - public Class getMarkerClass() - { - return theClass; - } - - public String toString() - { - return "[ValueMarker: " + theClass + "]"; - } - } - + // marker class + + private class ValueMarker { + private Class theClass; + + public ValueMarker() { + theClass = null; + } + + public void setMarkerClass(Class aClass) { + theClass = aClass; + } + + public Class getMarkerClass() { + return theClass; + } + + public String toString() { + return "[ValueMarker: " + theClass + "]"; + } + } + } /* - * $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. + * $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 2006/02/16 13:22:22 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.7 2003/08/06 23:07:53 chochos - * general code cleanup (mostly, removing unused imports) + * Revision 1.7 2003/08/06 23:07:53 chochos general code cleanup (mostly, + * removing unused imports) * - * Revision 1.6 2001/03/03 15:16:35 mpowers - * Fixed bug in decoding empty strings: string handler did nothing and - * empty cdatas were ignored, so no value was placed on the stack. + * Revision 1.6 2001/03/03 15:16:35 mpowers Fixed bug in decoding empty strings: + * string handler did nothing and empty cdatas were ignored, so no value was + * placed on the stack. * - * Revision 1.5 2001/02/17 16:52:06 mpowers - * Changes in imports to support building with jdk1.1 collections. + * Revision 1.5 2001/02/17 16:52:06 mpowers Changes in imports to support + * building with jdk1.1 collections. * - * Revision 1.4 2001/02/09 15:51:39 mpowers - * Fixed a pernicious bug: I was using the character event entirely - * incorrectly, but the problem only exhibited itself with large data - * and even then only randomly. Now using a string buffer. + * Revision 1.4 2001/02/09 15:51:39 mpowers Fixed a pernicious bug: I was using + * the character event entirely incorrectly, but the problem only exhibited + * itself with large data and even then only randomly. Now using a string + * buffer. * - * Revision 1.3 2001/02/07 19:24:28 mpowers - * Moved XML classes to separate package. + * Revision 1.3 2001/02/07 19:24:28 mpowers Moved XML classes to separate + * package. * - * Revision 1.2 2001/02/06 14:34:23 mpowers - * Forgot to rename the package declarations. + * Revision 1.2 2001/02/06 14:34:23 mpowers Forgot to rename the package + * declarations. * - * Revision 1.1 2001/02/06 14:31:19 mpowers - * Moving XML utilities from util to xml package. + * Revision 1.1 2001/02/06 14:31:19 mpowers Moving XML utilities from util to + * xml package. * - * Revision 1.1.1.1 2000/12/21 15:52:39 mpowers - * Contributing wotonomy. + * Revision 1.1.1.1 2000/12/21 15:52:39 mpowers Contributing wotonomy. * - * Revision 1.2 2000/12/20 16:25:48 michael - * Added log to all files. + * Revision 1.2 2000/12/20 16:25:48 michael Added log to all files. * * */ - diff --git a/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCEncoder.java b/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCEncoder.java index 3a63d45..d84f164 100644 --- a/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCEncoder.java +++ b/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCEncoder.java @@ -43,484 +43,398 @@ import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; /** -* An implementation of XMLEncoder that serializes objects -* into XMLRPC format, which is found at http://xmlrpc.com/spec. -* We extend that standard only in that we add a "class" -* attribute to the "value" tag, so that a java-based decoder -* can more closely reconstruct the original java data structure. -* The class attribute can be safely ignored by clients. -* This implementation is not thread-safe, so a new instances -* should be created to accomodate multiple threads. -*/ -public class XMLRPCEncoder implements XMLEncoder -{ - public static final String METHODCALL = "methodCall"; - public static final String METHODNAME = "methodName"; - public static final String METHODRESPONSE = "methodResponse"; - public static final String PARAMS = "params"; - public static final String PARAM = "param"; - public static final String FAULT = "fault"; - public static final String FAULTCODE = "faultCode"; - public static final String FAULTSTRING = "faultString"; - - public static final String VALUE = "value"; - public static final String CLASS = "class"; - - public static final String STRUCT = "struct"; - public static final String MEMBER = "member"; - public static final String NAME = "name"; - - public static final String ARRAY = "array"; - public static final String DATA = "data"; - - public static final String NIL = "nil"; - public static final String INT = "int"; - public static final String I4 = "i4"; - public static final String BOOLEAN = "boolean"; - public static final String STRING = "string"; - public static final String DOUBLE = "double"; - public static final String DATE = "dateTime.iso8601"; - public static final String BASE64 = "base64"; - - public static final String TRUE = "1"; - public static final String FALSE = "0"; - - public static final Format DATEFORMAT8601 = - new SimpleDateFormat( "yyyyMMdd'T'HHmmss" ); - - /** - * Encodes an object to the specified output stream as XML. - * @param anObject The object to be serialized to XML format. - * @param anOutputStream The output stream to which the object - * will be written. - */ - public void encode( Object anObject, OutputStream anOutputStream ) - { - try - { - - //XMLWriter writer = new UTF8XMLWriter( anOutputStream ); - RPCXMLWriter writer = new RPCXMLWriter(anOutputStream,OutputFormat.createCompactFormat()); - writeValueToXMLWriter( anObject, writer ); - writer.flush(); - } - catch ( Exception exc ) - { - throw new WotonomyException( exc ); - } - } - - /** - * Encodes a method request in XML-RPC format in a "methodCall" tag, - * and writes the XML to the specified output stream. - * This method only writes XML: the caller is responsible for - * generating the appropriate header, if any, which should set - * the content type as "text/xml" and the content length as appropriate. - * The caller is also responsible for writing the xml version tag. - * @param aMethodName The method name to appear in the "methodName" tag. - * @param aParameterArray An array of objects, each of which will be - * encoded as values enclosed in a "param" tag, all of which will be - * enclosed in a "params" tag. - * @param anOutputStream The stream to which the XML will be written. - */ - public void encodeRequest( - String aMethodName, Object[] aParameterArray, - OutputStream anOutputStream ) - { - try - { - RPCXMLWriter writer = new RPCXMLWriter( anOutputStream, OutputFormat.createCompactFormat()); - writer.processingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" ); - writer.startElement( METHODCALL ); - writer.startElement( METHODNAME ); - writer.write( aMethodName ); - writer.endElement( METHODNAME ); - writer.startElement( PARAMS ); - for ( int i = 0; i < aParameterArray.length; i++ ) - { - writer.startElement( PARAM ); - writeValueToXMLWriter( aParameterArray[i], writer ); - writer.endElement( PARAM ); - } - writer.endElement( PARAMS ); - writer.endElement( METHODCALL ); - writer.flush(); - } - catch ( Exception exc ) - { - throw new WotonomyException( exc ); - } - - //TODO: should this return the content-length? - } - - /** - * Encodes a method response in XML-RPC format in a "methodResponse" tag, - * and writes the XML to the specified output stream. - * This method only writes XML: the caller is responsible for - * generating the appropriate header, if any, which should set - * the content type as "text/xml" and the content length as appropriate. - * The caller is also responsible for writing the xml version tag. - * @param aResult A object which will be - * encoded as values enclosed in a "param" tag, all of which will be - * enclosed in a "params" tag. - * @param anOutputStream The stream to which the XML will be written. - */ - public void encodeResponse( - Object aResult, OutputStream anOutputStream ) - { - try - { - RPCXMLWriter writer = new RPCXMLWriter( anOutputStream, OutputFormat.createCompactFormat() ); - writer.processingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" ); - writer.startElement( METHODRESPONSE ); - writer.startElement( PARAMS ); - writer.startElement( PARAM ); - writeValueToXMLWriter( aResult, writer ); - writer.endElement( PARAM ); - writer.endElement( PARAMS ); - writer.endElement( METHODRESPONSE ); - writer.flush(); - } - catch ( Exception exc ) - { - throw new WotonomyException( exc ); - } - - //TODO: should this return the content-length? - } - - /** - * Encodes a fault response in XML-RPC format in a "methodResponse" tag, - * and writes the XML to the specified output stream. - * This method only writes XML: the caller is responsible for first - * generating the appropriate header, if any, which should set - * the content type as "text/xml" and the content length as appropriate. - * The caller is also responsible for writing the xml version tag. - * @param aFaultCode An application-defined error code. - * @param aFaultString A human-readable error description. - * @param anOutputStream The stream to which the XML will be written. - */ - public void encodeFault( - int aFaultCode, String aFaultString, OutputStream anOutputStream ) - { - try - { - RPCXMLWriter writer = new RPCXMLWriter( anOutputStream, OutputFormat.createCompactFormat() ); - writer.processingInstruction( "xml", "version=\"1.0\"" ); - writer.startElement( METHODRESPONSE ); - writer.startElement( FAULT ); - writer.startElement( VALUE ); - writer.startElement( STRUCT ); - - writer.startElement( MEMBER ); - writer.startElement( NAME ); - writer.write( FAULTCODE ); - writer.endElement( NAME ); - writer.startElement( VALUE ); - writer.startElement( INT ); - writer.write( new Integer( aFaultCode ).toString() ); - writer.endElement( INT ); - writer.endElement( VALUE ); - writer.endElement( MEMBER ); - - writer.startElement( MEMBER ); - writer.startElement( NAME ); - writer.write( FAULTSTRING ); - writer.endElement( NAME ); - writer.startElement( VALUE ); - writer.startElement( STRING ); - writer.write( aFaultString ); - writer.endElement( STRING ); - writer.endElement( VALUE ); - writer.endElement( MEMBER ); - - writer.endElement( STRUCT ); - writer.endElement( VALUE ); - writer.endElement( FAULT ); - writer.endElement( METHODRESPONSE ); - writer.flush(); - } - catch ( Exception exc ) - { - throw new WotonomyException( exc ); - } - - //TODO: should this return the content-length? - } - - /** - * Performs the actual writing of the file to XML. - */ - private void writeValueToXMLWriter( - Object anObject, RPCXMLWriter writer ) - { - try - { - - - if ( anObject == null ) - { - writer.startElement( VALUE ); - // write nil for null - Element nill = new NonLazyElement(NIL); - writer.write(nill); - } - else - if ( anObject instanceof Collection ) - { - // write class so we can restore if possible - AttributesImpl a = new AttributesImpl(); - a.addAttribute(null, CLASS, null, null, anObject.getClass().getName() ); - - writer.startElement( VALUE, a ); - - // write items in the order we get them from the iterator - - writer.startElement( ARRAY ); - writer.startElement( DATA ); - Iterator it = ((Collection)anObject).iterator(); - while ( it.hasNext() ) - { - writeValueToXMLWriter( it.next(), writer ); - } - writer.endElement( DATA ); - writer.endElement( ARRAY ); - - } - else - if ( anObject instanceof Map ) - { - AttributesImpl a = new AttributesImpl(); - a.addAttribute(null, CLASS, null, null, anObject.getClass().getName() ); - - writer.startElement( VALUE, a ); - - // write items in the order we get them from the iterator - //FIXME: The method-based properties are being ignored! - - Map.Entry entry; - writer.startElement( STRUCT ); - writer.startElement( MEMBER ); - Iterator it = ((Map)anObject).entrySet().iterator(); - while ( it.hasNext() ) - { - entry = (Map.Entry) it.next(); - writer.startElement( NAME ); - writeValueToXMLWriter( entry.getKey(), writer ); - writer.endElement( NAME ); - writeValueToXMLWriter( entry.getValue(), writer ); - } - writer.endElement( MEMBER ); - writer.endElement( STRUCT ); - } - else // not a collection - { - // check for primitive types - if ( anObject instanceof String ) - { - writer.startElement( VALUE ); - - writer.startElement( STRING ); - writer.write( anObject.toString() ); - writer.endElement( STRING ); - } - else - if ( anObject instanceof StringBuffer ) - { - // write class so we can restore if possible - AttributesImpl a = new AttributesImpl(); - a.addAttribute(null, CLASS, null, null, anObject.getClass().getName() ); - - writer.startElement( VALUE, a ); - - writer.startElement( STRING ); - writer.write( anObject.toString() ); - writer.endElement( STRING ); - } - else - if ( anObject instanceof Number ) - { - // write class so we can restore if possible - AttributesImpl a = new AttributesImpl(); - a.addAttribute(null, CLASS, null, null, anObject.getClass().getName() ); - - writer.startElement( VALUE, a ); - - if ( ( anObject instanceof Double ) - || ( anObject instanceof Float ) ) - { - writer.startElement( DOUBLE ); - writer.write( anObject.toString() ); - writer.endElement( DOUBLE ); - } - else - { - writer.startElement( INT ); - writer.write( anObject.toString() ); - writer.endElement( INT ); - } - } - else - if ( anObject instanceof Date ) - { - // write class so we can restore if possible - AttributesImpl a = new AttributesImpl(); - a.addAttribute(null, CLASS, null, null, anObject.getClass().getName() ); - - writer.startElement( VALUE, a ); - - writer.startElement( DATE ); - writer.write( DATEFORMAT8601.format( anObject ) ); - writer.endElement( DATE ); - } - else - if ( anObject instanceof Boolean ) - { - writer.startElement( BOOLEAN ); - if ( ((Boolean)anObject).booleanValue() ) - { - writer.write( "1" ); - } - else - { - writer.write( "0" ); - } - writer.endElement( BOOLEAN ); - } - else - if ( anObject.getClass().isArray() ) - { - // write class so we can restore if possible - AttributesImpl a = new AttributesImpl(); - a.addAttribute(null, CLASS, null, null, anObject.getClass().getName() ); - - writer.startElement( VALUE, a ); - - writer.startElement( ARRAY ); - writer.startElement( DATA ); - - int length = Array.getLength( anObject ); - for ( int i = 0; i < length; i++ ) - { - writeValueToXMLWriter( Array.get( anObject, i ), writer ); - } - - writer.endElement( DATA ); - writer.endElement( ARRAY ); - } - else // not primitive or collection, treat as struct - { - // write class so we can restore if possible - AttributesImpl a = new AttributesImpl(); - a.addAttribute(null, CLASS, null, null, anObject.getClass().getName() ); - - writer.startElement( VALUE, a ); - - List readProperties = new ArrayList(); - String[] read = Introspector.getReadPropertiesForObject( anObject ); - for ( int i = 0; i < read.length; i++ ) - { - readProperties.add( read[i] ); - } - - List properties = new ArrayList(); - String[] write = Introspector.getWritePropertiesForObject( anObject ); - for ( int i = 0; i < write.length; i++ ) - { - properties.add( write[i] ); - } - - // only use readable properties - properties.retainAll( readProperties ); - + * An implementation of XMLEncoder that serializes objects into XMLRPC format, + * which is found at http://xmlrpc.com/spec. We extend that standard only in + * that we add a "class" attribute to the "value" tag, so that a java-based + * decoder can more closely reconstruct the original java data structure. The + * class attribute can be safely ignored by clients. This implementation is not + * thread-safe, so a new instances should be created to accomodate multiple + * threads. + */ +public class XMLRPCEncoder implements XMLEncoder { + public static final String METHODCALL = "methodCall"; + public static final String METHODNAME = "methodName"; + public static final String METHODRESPONSE = "methodResponse"; + public static final String PARAMS = "params"; + public static final String PARAM = "param"; + public static final String FAULT = "fault"; + public static final String FAULTCODE = "faultCode"; + public static final String FAULTSTRING = "faultString"; + + public static final String VALUE = "value"; + public static final String CLASS = "class"; + + public static final String STRUCT = "struct"; + public static final String MEMBER = "member"; + public static final String NAME = "name"; + + public static final String ARRAY = "array"; + public static final String DATA = "data"; + + public static final String NIL = "nil"; + public static final String INT = "int"; + public static final String I4 = "i4"; + public static final String BOOLEAN = "boolean"; + public static final String STRING = "string"; + public static final String DOUBLE = "double"; + public static final String DATE = "dateTime.iso8601"; + public static final String BASE64 = "base64"; + + public static final String TRUE = "1"; + public static final String FALSE = "0"; + + public static final Format DATEFORMAT8601 = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + + /** + * Encodes an object to the specified output stream as XML. + * + * @param anObject The object to be serialized to XML format. + * @param anOutputStream The output stream to which the object will be written. + */ + public void encode(Object anObject, OutputStream anOutputStream) { + try { + + // XMLWriter writer = new UTF8XMLWriter( anOutputStream ); + RPCXMLWriter writer = new RPCXMLWriter(anOutputStream, OutputFormat.createCompactFormat()); + writeValueToXMLWriter(anObject, writer); + writer.flush(); + } catch (Exception exc) { + throw new WotonomyException(exc); + } + } + + /** + * Encodes a method request in XML-RPC format in a "methodCall" tag, and writes + * the XML to the specified output stream. This method only writes XML: the + * caller is responsible for generating the appropriate header, if any, which + * should set the content type as "text/xml" and the content length as + * appropriate. The caller is also responsible for writing the xml version tag. + * + * @param aMethodName The method name to appear in the "methodName" tag. + * @param aParameterArray An array of objects, each of which will be encoded as + * values enclosed in a "param" tag, all of which will be + * enclosed in a "params" tag. + * @param anOutputStream The stream to which the XML will be written. + */ + public void encodeRequest(String aMethodName, Object[] aParameterArray, OutputStream anOutputStream) { + try { + RPCXMLWriter writer = new RPCXMLWriter(anOutputStream, OutputFormat.createCompactFormat()); + writer.processingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""); + writer.startElement(METHODCALL); + writer.startElement(METHODNAME); + writer.write(aMethodName); + writer.endElement(METHODNAME); + writer.startElement(PARAMS); + for (int i = 0; i < aParameterArray.length; i++) { + writer.startElement(PARAM); + writeValueToXMLWriter(aParameterArray[i], writer); + writer.endElement(PARAM); + } + writer.endElement(PARAMS); + writer.endElement(METHODCALL); + writer.flush(); + } catch (Exception exc) { + throw new WotonomyException(exc); + } + + // TODO: should this return the content-length? + } + + /** + * Encodes a method response in XML-RPC format in a "methodResponse" tag, and + * writes the XML to the specified output stream. This method only writes XML: + * the caller is responsible for generating the appropriate header, if any, + * which should set the content type as "text/xml" and the content length as + * appropriate. The caller is also responsible for writing the xml version tag. + * + * @param aResult A object which will be encoded as values enclosed in a + * "param" tag, all of which will be enclosed in a + * "params" tag. + * @param anOutputStream The stream to which the XML will be written. + */ + public void encodeResponse(Object aResult, OutputStream anOutputStream) { + try { + RPCXMLWriter writer = new RPCXMLWriter(anOutputStream, OutputFormat.createCompactFormat()); + writer.processingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""); + writer.startElement(METHODRESPONSE); + writer.startElement(PARAMS); + writer.startElement(PARAM); + writeValueToXMLWriter(aResult, writer); + writer.endElement(PARAM); + writer.endElement(PARAMS); + writer.endElement(METHODRESPONSE); + writer.flush(); + } catch (Exception exc) { + throw new WotonomyException(exc); + } + + // TODO: should this return the content-length? + } + + /** + * Encodes a fault response in XML-RPC format in a "methodResponse" tag, and + * writes the XML to the specified output stream. This method only writes XML: + * the caller is responsible for first generating the appropriate header, if + * any, which should set the content type as "text/xml" and the content length + * as appropriate. The caller is also responsible for writing the xml version + * tag. + * + * @param aFaultCode An application-defined error code. + * @param aFaultString A human-readable error description. + * @param anOutputStream The stream to which the XML will be written. + */ + public void encodeFault(int aFaultCode, String aFaultString, OutputStream anOutputStream) { + try { + RPCXMLWriter writer = new RPCXMLWriter(anOutputStream, OutputFormat.createCompactFormat()); + writer.processingInstruction("xml", "version=\"1.0\""); + writer.startElement(METHODRESPONSE); + writer.startElement(FAULT); + writer.startElement(VALUE); + writer.startElement(STRUCT); + + writer.startElement(MEMBER); + writer.startElement(NAME); + writer.write(FAULTCODE); + writer.endElement(NAME); + writer.startElement(VALUE); + writer.startElement(INT); + writer.write(new Integer(aFaultCode).toString()); + writer.endElement(INT); + writer.endElement(VALUE); + writer.endElement(MEMBER); + + writer.startElement(MEMBER); + writer.startElement(NAME); + writer.write(FAULTSTRING); + writer.endElement(NAME); + writer.startElement(VALUE); + writer.startElement(STRING); + writer.write(aFaultString); + writer.endElement(STRING); + writer.endElement(VALUE); + writer.endElement(MEMBER); + + writer.endElement(STRUCT); + writer.endElement(VALUE); + writer.endElement(FAULT); + writer.endElement(METHODRESPONSE); + writer.flush(); + } catch (Exception exc) { + throw new WotonomyException(exc); + } + + // TODO: should this return the content-length? + } + + /** + * Performs the actual writing of the file to XML. + */ + private void writeValueToXMLWriter(Object anObject, RPCXMLWriter writer) { + try { + + if (anObject == null) { + writer.startElement(VALUE); + // write nil for null + Element nill = new NonLazyElement(NIL); + writer.write(nill); + } else if (anObject instanceof Collection) { + // write class so we can restore if possible + AttributesImpl a = new AttributesImpl(); + a.addAttribute(null, CLASS, null, null, anObject.getClass().getName()); + + writer.startElement(VALUE, a); + + // write items in the order we get them from the iterator + + writer.startElement(ARRAY); + writer.startElement(DATA); + Iterator it = ((Collection) anObject).iterator(); + while (it.hasNext()) { + writeValueToXMLWriter(it.next(), writer); + } + writer.endElement(DATA); + writer.endElement(ARRAY); + + } else if (anObject instanceof Map) { + AttributesImpl a = new AttributesImpl(); + a.addAttribute(null, CLASS, null, null, anObject.getClass().getName()); + + writer.startElement(VALUE, a); + + // write items in the order we get them from the iterator + // FIXME: The method-based properties are being ignored! + + Map.Entry entry; + writer.startElement(STRUCT); + writer.startElement(MEMBER); + Iterator it = ((Map) anObject).entrySet().iterator(); + while (it.hasNext()) { + entry = (Map.Entry) it.next(); + writer.startElement(NAME); + writeValueToXMLWriter(entry.getKey(), writer); + writer.endElement(NAME); + writeValueToXMLWriter(entry.getValue(), writer); + } + writer.endElement(MEMBER); + writer.endElement(STRUCT); + } else // not a collection + { + // check for primitive types + if (anObject instanceof String) { + writer.startElement(VALUE); + + writer.startElement(STRING); + writer.write(anObject.toString()); + writer.endElement(STRING); + } else if (anObject instanceof StringBuffer) { + // write class so we can restore if possible + AttributesImpl a = new AttributesImpl(); + a.addAttribute(null, CLASS, null, null, anObject.getClass().getName()); + + writer.startElement(VALUE, a); + + writer.startElement(STRING); + writer.write(anObject.toString()); + writer.endElement(STRING); + } else if (anObject instanceof Number) { + // write class so we can restore if possible + AttributesImpl a = new AttributesImpl(); + a.addAttribute(null, CLASS, null, null, anObject.getClass().getName()); + + writer.startElement(VALUE, a); + + if ((anObject instanceof Double) || (anObject instanceof Float)) { + writer.startElement(DOUBLE); + writer.write(anObject.toString()); + writer.endElement(DOUBLE); + } else { + writer.startElement(INT); + writer.write(anObject.toString()); + writer.endElement(INT); + } + } else if (anObject instanceof Date) { + // write class so we can restore if possible + AttributesImpl a = new AttributesImpl(); + a.addAttribute(null, CLASS, null, null, anObject.getClass().getName()); + + writer.startElement(VALUE, a); + + writer.startElement(DATE); + writer.write(DATEFORMAT8601.format(anObject)); + writer.endElement(DATE); + } else if (anObject instanceof Boolean) { + writer.startElement(BOOLEAN); + if (((Boolean) anObject).booleanValue()) { + writer.write("1"); + } else { + writer.write("0"); + } + writer.endElement(BOOLEAN); + } else if (anObject.getClass().isArray()) { + // write class so we can restore if possible + AttributesImpl a = new AttributesImpl(); + a.addAttribute(null, CLASS, null, null, anObject.getClass().getName()); + + writer.startElement(VALUE, a); + + writer.startElement(ARRAY); + writer.startElement(DATA); + + int length = Array.getLength(anObject); + for (int i = 0; i < length; i++) { + writeValueToXMLWriter(Array.get(anObject, i), writer); + } + + writer.endElement(DATA); + writer.endElement(ARRAY); + } else // not primitive or collection, treat as struct + { + // write class so we can restore if possible + AttributesImpl a = new AttributesImpl(); + a.addAttribute(null, CLASS, null, null, anObject.getClass().getName()); + + writer.startElement(VALUE, a); + + List readProperties = new ArrayList(); + String[] read = Introspector.getReadPropertiesForObject(anObject); + for (int i = 0; i < read.length; i++) { + readProperties.add(read[i]); + } + + List properties = new ArrayList(); + String[] write = Introspector.getWritePropertiesForObject(anObject); + for (int i = 0; i < write.length; i++) { + properties.add(write[i]); + } + + // only use readable properties + properties.retainAll(readProperties); + // if ( properties.size() > 0 ) // { - String key; - Object value; - Iterator it = properties.iterator(); - writer.startElement( STRUCT ); - while ( it.hasNext() ) - { - key = (String) it.next(); - value = Introspector.get( anObject, key ); - - writer.startElement( MEMBER ); - writer.startElement( NAME ); - writer.write( key ); - writer.endElement( NAME ); - writeValueToXMLWriter( value, writer ); - writer.endElement( MEMBER ); - } - writer.endElement( STRUCT ); -/* - } - else // no properties - write a converted string - { - writer.startElement( STRING ); - Object converted = - ValueConverter.convertObjectToClass( anObject, String.class ); - if ( converted != null ) - { - writer.write( converted.toString() ); - } - else - { - writer.write( anObject.toString() ); - } - writer.endElement( STRING ); - } -*/ - } - } - - writer.endElement( VALUE ); - } - catch ( Exception exc ) - { - System.err.println( "XMLFileSoup.writeValueToXMLWriter: " + exc ); - exc.printStackTrace(); - } - - } -/* - public static void main( String[] argv ) - { - System.out.println( "<test>" ); - XMLRPCEncoder encoder = new XMLRPCEncoder(); - encoder.encodeRequest( "systemObject.test", new Object[] { - new net.wotonomy.test.TestObject(), - new net.wotonomy.test.TestObject(), - new net.wotonomy.test.TestObject() }, System.out ); - System.out.println(); - System.out.println(); - encoder.encodeResponse( new net.wotonomy.test.TestObject(), System.out ); - System.out.println(); - System.out.println(); - encoder.encodeFault( -1, "This is a fault.", System.out ); - System.out.println(); - System.out.println(); - System.out.println( "</test>" ); - } -*/ - - private class RPCXMLWriter extends XMLWriter { + String key; + Object value; + Iterator it = properties.iterator(); + writer.startElement(STRUCT); + while (it.hasNext()) { + key = (String) it.next(); + value = Introspector.get(anObject, key); + + writer.startElement(MEMBER); + writer.startElement(NAME); + writer.write(key); + writer.endElement(NAME); + writeValueToXMLWriter(value, writer); + writer.endElement(MEMBER); + } + writer.endElement(STRUCT); + /* + * } else // no properties - write a converted string { writer.startElement( + * STRING ); Object converted = ValueConverter.convertObjectToClass( anObject, + * String.class ); if ( converted != null ) { writer.write( converted.toString() + * ); } else { writer.write( anObject.toString() ); } writer.endElement( STRING + * ); } + */ + } + } + + writer.endElement(VALUE); + } catch (Exception exc) { + System.err.println("XMLFileSoup.writeValueToXMLWriter: " + exc); + exc.printStackTrace(); + } + + } + /* + * public static void main( String[] argv ) { System.out.println( "<test>" ); + * XMLRPCEncoder encoder = new XMLRPCEncoder(); encoder.encodeRequest( + * "systemObject.test", new Object[] { new net.wotonomy.test.TestObject(), new + * net.wotonomy.test.TestObject(), new net.wotonomy.test.TestObject() }, + * System.out ); System.out.println(); System.out.println(); + * encoder.encodeResponse( new net.wotonomy.test.TestObject(), System.out ); + * System.out.println(); System.out.println(); encoder.encodeFault( -1, + * "This is a fault.", System.out ); System.out.println(); System.out.println(); + * System.out.println( "</test>" ); } + */ + + private class RPCXMLWriter extends XMLWriter { public RPCXMLWriter(OutputStream arg0, OutputFormat arg1) throws UnsupportedEncodingException { super(arg0, arg1); } - public void endElement(String localname) throws SAXException { + public void endElement(String localname) throws SAXException { super.endElement(null, localname, null); } public void startElement(String localname) throws SAXException { this.startElement(localname, null); } + public void startElement(String localname, Attributes attributes) throws SAXException { this.startElement(null, localname, null, attributes); } - } - + } + } diff --git a/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCReceiver.java b/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCReceiver.java index 48c9e41..5848cd0 100644 --- a/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCReceiver.java +++ b/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCReceiver.java @@ -19,54 +19,51 @@ License along with this library; if not, see http://www.gnu.org package net.wotonomy.web.xml; /** -* A call-back interface that receives an XML-RPC transaction message. -* Used by XMLRPCDecoder to return values from a message. -*/ -public interface XMLRPCReceiver -{ - /** - * Receives an XML-RPC request. - * @param aMethodName The method name of the request. - * @param aParameterArray The objects contained in the request, in order. - */ - void request( String aMethodName, Object[] aParameterArray ); - - /** - * Receives an XML-RPC response. - * @param aResult The object contained in the response. - */ - void response( Object aResult ); - - /** - * Receives an XML-RPC fault response. - * @param aFaultCode The fault code contained in the response. - * @param aFaultString The fault string contained in the response. - */ - void fault( int aFaultCode, String aFaultString ); + * A call-back interface that receives an XML-RPC transaction message. Used by + * XMLRPCDecoder to return values from a message. + */ +public interface XMLRPCReceiver { + /** + * Receives an XML-RPC request. + * + * @param aMethodName The method name of the request. + * @param aParameterArray The objects contained in the request, in order. + */ + void request(String aMethodName, Object[] aParameterArray); + + /** + * Receives an XML-RPC response. + * + * @param aResult The object contained in the response. + */ + void response(Object aResult); + + /** + * Receives an XML-RPC fault response. + * + * @param aFaultCode The fault code contained in the response. + * @param aFaultString The fault string contained in the response. + */ + void fault(int aFaultCode, String aFaultString); } /* - * $Log$ - * Revision 1.1 2006/02/19 01:44:02 cgruber - * Add xmlrpc files - * Remove jclark and replace with dom4j and javax.xml.sax stuff - * Re-work dependencies and imports so it all compiles. + * $Log$ Revision 1.1 2006/02/19 01:44:02 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 2006/02/16 13:22:22 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.2 2001/02/06 14:34:23 mpowers - * Forgot to rename the package declarations. + * Revision 1.2 2001/02/06 14:34:23 mpowers Forgot to rename the package + * declarations. * - * Revision 1.1 2001/02/06 14:31:19 mpowers - * Moving XML utilities from util to xml package. + * Revision 1.1 2001/02/06 14:31:19 mpowers Moving XML utilities from util to + * xml package. * - * Revision 1.1.1.1 2000/12/21 15:52:44 mpowers - * Contributing wotonomy. + * Revision 1.1.1.1 2000/12/21 15:52:44 mpowers Contributing wotonomy. * - * Revision 1.2 2000/12/20 16:25:49 michael - * Added log to all files. + * Revision 1.2 2000/12/20 16:25:49 michael Added log to all files. * * */ - diff --git a/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCSelector.java b/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCSelector.java index 7c1f104..599481f 100644 --- a/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCSelector.java +++ b/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCSelector.java @@ -32,207 +32,155 @@ 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. <br><br> -* -* 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 ); + * 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. + * <br> + * <br> + * + * 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); } - 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 ); + /** + * 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, 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[] parameters) + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { + return new XMLRPCSelector(methodName, parameterTypes).invoke(anObject, parameters); } - 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, 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 p1, Object p2) - throws IllegalAccessException, IllegalArgumentException, - InvocationTargetException, NoSuchMethodException - { - return XMLRPCSelector.invoke( - methodName, parameterTypes, anObject, new Object[] { p1, p2 } ); + 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; + } } - - 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. + * $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 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. + * Revision 1.1 2001/02/07 19:24:28 mpowers Moved XML classes to separate + * package. * * */ - diff --git a/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCServlet.java b/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCServlet.java index a9981a4..94b5680 100644 --- a/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCServlet.java +++ b/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCServlet.java @@ -34,250 +34,195 @@ import net.wotonomy.foundation.NSSelector; import net.wotonomy.foundation.internal.WotonomyException; /** -* A servlet that can make any java object into an XML-RPC server. -* Simply pass in the object to the constructor and XML-RPC requests -* to this servlet will call the appropriate methods and convert -* the results to an XML-RPC response. <br><br> -* -* Depending on your servlet container, it may be necessary to -* create a simple subclass that creates your handler object -* in its constructor and then calls setHandler(). <br><br> -* -* Responses are in the specification's standard response format.<br><br> -* -* Faults are returned if any exception is thrown in the method, -* or if the specified method is not found on the object. -* The fault string is the toString value of the exception, -* and the fault code is the hasCode value of the exception. <br><br> -* -* Remember that this servlet only responds to POSTs, -* per the XML-RPC spec. -*/ -public class XMLRPCServlet extends HttpServlet -{ - protected Object handler; - protected boolean synchronizing; - private Hashtable selectorCache = new Hashtable(); // thread safe - private boolean copyStream = false; - - /** - * Default constructor initializes internal state. - */ - public XMLRPCServlet() - { - handler = null; - synchronizing = false; - } - - /** - * Constructor takes any java object and allows its methods - * to be invoked via XMLRPC requests to this servlet. - * Simply calls setHandler(). - */ - public XMLRPCServlet( Object aHandler ) - { - this(); - setHandler( aHandler ); - } - - /** - * Gets the object whose methods will be invoked to - * handle incoming requests. - */ - public Object getHandler() - { - return handler; - } - - /** - * Sets the object whose methods will be invoked to - * handle incoming requests. - */ - public void setHandler( Object aHandler ) - { - handler = aHandler; - } - - /** - * Gets whether the servlet should synchonize on the - * object before invoking methods on it. - * Defaults to false. - */ - public boolean isSynchronizing() - { - return synchronizing; - } - - /** - * Sets whether the servlet should synchonize on the - * object before invoking methods on it. - * Defaults to false. - */ - public void setSynchronizing( boolean willSynchronize ) - { - synchronizing = willSynchronize; - } - - /** - * Overridden to service the request. - */ - protected void doPost( - HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException - { - if ( getHandler() != null ) - { - InputStream input = req.getInputStream(); - byte[] copyOfRequest = null; + * A servlet that can make any java object into an XML-RPC server. Simply pass + * in the object to the constructor and XML-RPC requests to this servlet will + * call the appropriate methods and convert the results to an XML-RPC response. + * <br> + * <br> + * + * Depending on your servlet container, it may be necessary to create a simple + * subclass that creates your handler object in its constructor and then calls + * setHandler(). <br> + * <br> + * + * Responses are in the specification's standard response format.<br> + * <br> + * + * Faults are returned if any exception is thrown in the method, or if the + * specified method is not found on the object. The fault string is the toString + * value of the exception, and the fault code is the hasCode value of the + * exception. <br> + * <br> + * + * Remember that this servlet only responds to POSTs, per the XML-RPC spec. + */ +public class XMLRPCServlet extends HttpServlet { + protected Object handler; + protected boolean synchronizing; + private Hashtable selectorCache = new Hashtable(); // thread safe + private boolean copyStream = false; + + /** + * Default constructor initializes internal state. + */ + public XMLRPCServlet() { + handler = null; + synchronizing = false; + } + + /** + * Constructor takes any java object and allows its methods to be invoked via + * XMLRPC requests to this servlet. Simply calls setHandler(). + */ + public XMLRPCServlet(Object aHandler) { + this(); + setHandler(aHandler); + } + + /** + * Gets the object whose methods will be invoked to handle incoming requests. + */ + public Object getHandler() { + return handler; + } + + /** + * Sets the object whose methods will be invoked to handle incoming requests. + */ + public void setHandler(Object aHandler) { + handler = aHandler; + } + + /** + * Gets whether the servlet should synchonize on the object before invoking + * methods on it. Defaults to false. + */ + public boolean isSynchronizing() { + return synchronizing; + } + + /** + * Sets whether the servlet should synchonize on the object before invoking + * methods on it. Defaults to false. + */ + public void setSynchronizing(boolean willSynchronize) { + synchronizing = willSynchronize; + } + + /** + * Overridden to service the request. + */ + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + if (getHandler() != null) { + InputStream input = req.getInputStream(); + byte[] copyOfRequest = null; - if ( copyStream ) - { - ByteArrayOutputStream byteArray = - new ByteArrayOutputStream(); - int b; - while ( ( b = input.read() ) != -1 ) - { - byteArray.write( b ); - } - copyOfRequest = byteArray.toByteArray(); - input = new ByteArrayInputStream( copyOfRequest ); - } - - try - { - new XMLRPCDecoder().decode( input, - new Receiver( this, resp ) ); - } - catch ( WotonomyException exc ) - { - if ( copyOfRequest != null ) - { - System.out.println( new String( copyOfRequest ) ); - exc.printStackTrace(); - } - // catches io exceptions thrown in handleRequest. - Throwable t = exc.getWrappedThrowable(); - if ( t instanceof IOException ) - { - throw (IOException)t; - } - throw exc; - } - } - } - - /** - * Called by doPost after parsing an incoming request, - * and is responsible for invoking the specified method - * with the specified parameters on the handler object. - * (This implementation calls getOutputStream() on the response.) - * Override to customize the handling of the request. - */ - protected void handleRequest( String aMethodName, - Object[] aParameterArray, HttpServletResponse aResponse ) - { - OutputStream output = null; - - try - { - output = aResponse.getOutputStream(); - aResponse.setStatus( HttpServletResponse.SC_OK ); // always 200 - aResponse.setContentType( "text/xml" ); - } - catch ( IOException exc ) - { - // caught in doPost - throw new WotonomyException( exc ); - } - - // get the array of types - XMLRPCEncoder encoder = new XMLRPCEncoder(); - Class[] types = new Class[ aParameterArray.length ]; - for ( int i = 0; i < aParameterArray.length; i++ ) - { - types[i] = aParameterArray[i].getClass(); - } - - //TODO: selectors should be cached if possible - - Object handler = getHandler(); - if ( isSynchronizing() ) - { - synchronized ( handler ) - { - execute( encoder, handler, output, - new NSSelector( aMethodName, types ), aParameterArray ); - } - } - else - { - execute( encoder, handler, output, - new NSSelector( aMethodName, types ), aParameterArray ); - } - } - - private void execute( XMLRPCEncoder anEncoder, Object aHandler, - OutputStream output, NSSelector aSelector, Object[] aParameterArray ) - { - try - { - Object result = - aSelector.invoke( aHandler, aParameterArray ); - anEncoder.encodeResponse( result, output ); - } - catch ( Exception exc ) - { - anEncoder.encodeFault( - exc.hashCode(), exc.toString(), output ); - } - } - - private class Receiver implements XMLRPCReceiver - { - XMLRPCServlet controller; - HttpServletResponse response; - - public Receiver( - XMLRPCServlet aController, - HttpServletResponse aResponse ) - { - controller = aController; - response = aResponse; - } - - public void request( - String aMethodName, Object[] aParameterArray ) - { - controller.handleRequest( - aMethodName, aParameterArray, response ); - } - - public void response( - Object aResult ) - { - // does nothing - } - - public void fault( - int aFaultCode, String aFaultString) - { - // does nothing - } - } + if (copyStream) { + ByteArrayOutputStream byteArray = new ByteArrayOutputStream(); + int b; + while ((b = input.read()) != -1) { + byteArray.write(b); + } + copyOfRequest = byteArray.toByteArray(); + input = new ByteArrayInputStream(copyOfRequest); + } + + try { + new XMLRPCDecoder().decode(input, new Receiver(this, resp)); + } catch (WotonomyException exc) { + if (copyOfRequest != null) { + System.out.println(new String(copyOfRequest)); + exc.printStackTrace(); + } + // catches io exceptions thrown in handleRequest. + Throwable t = exc.getWrappedThrowable(); + if (t instanceof IOException) { + throw (IOException) t; + } + throw exc; + } + } + } + + /** + * Called by doPost after parsing an incoming request, and is responsible for + * invoking the specified method with the specified parameters on the handler + * object. (This implementation calls getOutputStream() on the response.) + * Override to customize the handling of the request. + */ + protected void handleRequest(String aMethodName, Object[] aParameterArray, HttpServletResponse aResponse) { + OutputStream output = null; + + try { + output = aResponse.getOutputStream(); + aResponse.setStatus(HttpServletResponse.SC_OK); // always 200 + aResponse.setContentType("text/xml"); + } catch (IOException exc) { + // caught in doPost + throw new WotonomyException(exc); + } + + // get the array of types + XMLRPCEncoder encoder = new XMLRPCEncoder(); + Class[] types = new Class[aParameterArray.length]; + for (int i = 0; i < aParameterArray.length; i++) { + types[i] = aParameterArray[i].getClass(); + } + + // TODO: selectors should be cached if possible + + Object handler = getHandler(); + if (isSynchronizing()) { + synchronized (handler) { + execute(encoder, handler, output, new NSSelector(aMethodName, types), aParameterArray); + } + } else { + execute(encoder, handler, output, new NSSelector(aMethodName, types), aParameterArray); + } + } + + private void execute(XMLRPCEncoder anEncoder, Object aHandler, OutputStream output, NSSelector aSelector, + Object[] aParameterArray) { + try { + Object result = aSelector.invoke(aHandler, aParameterArray); + anEncoder.encodeResponse(result, output); + } catch (Exception exc) { + anEncoder.encodeFault(exc.hashCode(), exc.toString(), output); + } + } + + private class Receiver implements XMLRPCReceiver { + XMLRPCServlet controller; + HttpServletResponse response; + + public Receiver(XMLRPCServlet aController, HttpServletResponse aResponse) { + controller = aController; + response = aResponse; + } + + public void request(String aMethodName, Object[] aParameterArray) { + controller.handleRequest(aMethodName, aParameterArray, response); + } + + public void response(Object aResult) { + // does nothing + } + + public void fault(int aFaultCode, String aFaultString) { + // does nothing + } + } } /* - * $Log$ - * Revision 1.1 2006/02/19 01:44:02 cgruber - * Add xmlrpc files - * Remove jclark and replace with dom4j and javax.xml.sax stuff - * Re-work dependencies and imports so it all compiles. + * $Log$ Revision 1.1 2006/02/19 01:44:02 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 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. + * Revision 1.1 2001/02/07 19:24:28 mpowers Moved XML classes to separate + * package. * */ - |
