You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xmlrpc-dev@ws.apache.org by John Bellone <jo...@flipsidesoftware.com> on 2008/02/06 00:31:35 UTC

Hacking apart the Parser

I figured since this list has helped me greatly that I would contribute 
back and include some examples on how I was able to successfully get the 
XML-RPC parser inside of the library working without the actual need for 
the servlets to run. We already had a working network structure and all 
I needed was the actual type parser, and well, it wasn't as easy as I 
thought it would have been to get it working. But I did! So here's the 
basics.

XmlRpcControllerImpl.java

public class XmlRpcControllerImpl extends XmlRpcController {
	private final StreamConfig config = new StreamConfig();
	
	protected XmlRpcWorkerFactory getDefaultXmlRpcWorkerFactory() { return null; }
	public XmlRpcConfig getConfig() { return config; } 
	
	// @summary: Implementation of the configuration for the Apache XMLRPC parser. This is
	// a default configuration that most likely will never need to be changed.
	// @author: John Bellone (john.bellone@flipsidesoftware.com)
	private class StreamConfig implements XmlRpcStreamConfig
	{
		public StreamConfig() { }
		public String getEncoding() { return UTF8_ENCODING; }
		public boolean isEnabledForExtensions() { return false; }
		public java.util.TimeZone getTimeZone() { return java.util.TimeZone.getDefault(); }
	}
}

XmlRpcTransportParser.java

// @summary: The implementation of the XMLRPC parser that interfaces with
// the apache XMLRPC parser. 
// @author: John Bellone (john.bellone@flipsidesoftware.com)
public class XmlRpcTransportParser extends AbstractTransportParser {

	public XmlRpcTransportParser()
	{

	}
	
	// @summary: This method takes the information from the input stream and parses it
	// through the Apache XML-RPC library (and the SAX XML Parser) to produce our custom
	// MethodCall object.
	public MethodCall parse(ByteBuffer buf)
		throws Exception
	{	
		final XmlRpcRequestParser parser 
			= new XmlRpcRequestParser( new StreamConfig(), new TypeFactoryImpl(new XmlRpcControllerImpl()) );
		final XMLReader xr = SAXParsers.newXMLReader();
		xr.setContentHandler(parser);
		
		StringBuffer packet = new StringBuffer();
		String line = "";
		
		BufferedReader reader = AbstractTransportParser.newBufferedReader(buf);
		
		while( (line = reader.readLine()) != null)
			packet.append(line);
		
		try {
			xr.parse( new InputSource( new StringReader(packet.toString()) ) );
		}
		catch(SAXParseException se)
		{
			throw se;
		}
		return new MethodCall(parser.getMethodName(), parser.getParams() );
	}
	
	// @summary: Implementation of the configuration for the Apache XMLRPC parser. This is
	// a default configuration that most likely will never need to be changed.
	// @author: John Bellone (john.bellone@flipsidesoftware.com)
	private class StreamConfig implements XmlRpcStreamConfig
	{
		public String getEncoding() { return UTF8_ENCODING; }
		public boolean isEnabledForExtensions() { return false; }
		public java.util.TimeZone getTimeZone() { return java.util.TimeZone.getDefault(); }
	}
}

XmlRpcTransportSerializer.java

// @summary: This is the XML-RPC implementation of the Transport Serializer.
// We're using the Apache XML-RPC library to do the serialization.
// @author: John Bellone (john.bellone@flipsidesoftware.com)
class XmlRpcTransportSerializer extends AbstractTransportSerializer {
	private XmlWriterFactory writerFactory = new DefaultXMLWriterFactory();
	
	public ByteBuffer serialize(MethodResponse result)
		throws Exception
	{
		ByteBuffer outcomm = ByteBuffer.allocateDirect(AbstractTransportSerializer.MAXSIZE);
		
		OutputStream stream = AbstractTransportSerializer.newOutputStream(outcomm);
		
		XmlRpcWriter writer = new XmlRpcWriter( new StreamConfig(), 
				writerFactory.getXmlWriter(new StreamConfig(), stream),
				new TypeFactoryImpl(new XmlRpcControllerImpl()) );
		
		writer.write(new RequestConfig(), result.getResult() );
		return outcomm;
	}
	
	// @summary: Implementation of the configuration for the Apache XMLRPC parser. This is
	// a default configuration that most likely will never need to be changed.
	// @author: John Bellone (john.bellone@flipsidesoftware.com)
	private class StreamConfig implements XmlRpcStreamConfig
	{
		public String getEncoding() { return UTF8_ENCODING; }
		public boolean isEnabledForExtensions() { return false; }
		public java.util.TimeZone getTimeZone() { return java.util.TimeZone.getDefault(); }
	}
	private class RequestConfig implements XmlRpcRequestConfig
	{
		public boolean isEnabledForExtensions() { return false; }
		public java.util.TimeZone getTimeZone() { return java.util.TimeZone.getDefault(); }
	}
}

Now that is essentially all the code needed to make the parser active without actually needing to run the server code
that was included with the library. I am posting this because I believe there might be a need for it (for at least someone)
and it took me a couple of weeks to get it working without a hitch. As you can see we are not enabling the parser to accept
extensions. We are also using a default of UTF-8 encoding (which you can change).

The code is basically a hack and we're currently redesigning the whole project. So I figured there would be no foul in psoting
this for anyone that is interested in doing something similar (not needing the built-in servers). If you have any questions feel
free to ask away. We used a custom MethodCall and MethodResponse object. I don't see a need to release that code (as they contain 
some of the structure of the rest of the project) and they are pretty straight forward anyway.

Enjoy!

-- 
-John Bellone
john.bellone@flipsidesoftware.com
609.489.3112