Adds in some XmlRpc functions

This commit is contained in:
Aria 2023-06-13 22:34:45 -07:00
parent 3d34b5f508
commit 609ffd6a86
4 changed files with 431 additions and 0 deletions

View file

@ -0,0 +1,44 @@
package dev.zontreck.ariaslib.xmlrpc;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
public class XmlRpcDeserializer {
private XmlRpcStreamReader xmlStreamReader;
public XmlRpcDeserializer ( InputStream inputStream ) throws Exception {
xmlStreamReader = new XmlRpcStreamReader ( inputStream );
}
public String skipXmlHeader(String xml) {
int startIndex = xml.indexOf("<?xml");
if (startIndex >= 0) {
int endIndex = xml.indexOf("?>", startIndex);
if (endIndex >= 0) {
return xml.substring(endIndex + 2);
}
}
return xml;
}
public XmlRpcDeserializer ( String xml ) throws Exception {
byte[] xmlBytes = xml.getBytes ( );
ByteArrayInputStream inputStream = new ByteArrayInputStream ( xmlBytes );
xmlStreamReader = new XmlRpcStreamReader ( inputStream );
}
public String readMethodName ( ) throws Exception {
return xmlStreamReader.readMethodCallMethodName ( );
}
public Object[] readMethodParams ( ) throws Exception {
return xmlStreamReader.readMethodCallParams ( );
}
public Object readMethodResponse ( ) throws Exception {
return xmlStreamReader.readMethodResponseResult ( );
}
public void close ( ) throws Exception {
xmlStreamReader.close ( );
}
}

View file

@ -0,0 +1,26 @@
package dev.zontreck.ariaslib.xmlrpc;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
public class XmlRpcSerializer {
private XmlRpcStreamWriter writer;
public XmlRpcSerializer ( OutputStream outputStream ) {
this.writer = new XmlRpcStreamWriter ( outputStream );
}
public void serializeMethodCall ( String methodName , List<Object> params ) throws IOException {
writer.writeMethodCall ( methodName , params );
}
public void serializeMethodResponse ( Object value ) throws IOException {
writer.writeMethodResponse ( value );
}
public void close ( ) throws IOException {
writer.close ( );
}
}

View file

@ -0,0 +1,205 @@
package dev.zontreck.ariaslib.xmlrpc;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
public class XmlRpcStreamReader {
private XMLStreamReader xmlStreamReader;
public XmlRpcStreamReader ( InputStream inputStream ) throws XMLStreamException {
XMLInputFactory inputFactory = XMLInputFactory.newInstance ( );
xmlStreamReader = inputFactory.createXMLStreamReader ( inputStream );
}
public boolean nextTag ( ) throws XMLStreamException {
while ( xmlStreamReader.hasNext ( ) ) {
int eventType = xmlStreamReader.next ( );
if ( eventType == XMLStreamConstants.START_ELEMENT || eventType == XMLStreamConstants.END_ELEMENT ) {
return true;
}
}
return false;
}
public String getLocalName ( ) {
return xmlStreamReader.getLocalName ( );
}
public String getElementText ( ) throws XMLStreamException {
return xmlStreamReader.getElementText ( );
}
public void require ( int type , String namespaceURI , String localName ) throws XMLStreamException {
xmlStreamReader.require ( type , namespaceURI , localName );
}
public String readMethodCallMethodName ( ) throws XMLStreamException {
nextTag ( );
require ( XMLStreamConstants.START_ELEMENT , null , "methodCall" );
nextTag ( );
require ( XMLStreamConstants.START_ELEMENT , null , "methodName" );
return getElementText ( );
}
public Object[] readMethodCallParams ( ) throws XMLStreamException {
nextTag ( );
require ( XMLStreamConstants.START_ELEMENT , null , "params" );
return deserializeParams ( );
}
private Object[] deserializeParams ( ) throws XMLStreamException {
Object[] params = new Object[ 0 ];
boolean isValueElement = false;
while ( nextTag ( ) ) {
if ( xmlStreamReader.getLocalName ( ).equals ( "value" ) ) {
isValueElement = true;
}
else if ( xmlStreamReader.getLocalName ( ).equals ( "param" ) ) {
if ( isValueElement ) {
Object value = deserializeValue ( );
Object[] newParams = new Object[ params.length + 1 ];
System.arraycopy ( params , 0 , newParams , 0 , params.length );
newParams[ params.length ] = value;
params = newParams;
isValueElement = false;
}
}
}
return params;
}
public Object readMethodResponseResult ( ) throws XMLStreamException {
nextTag ( );
require ( XMLStreamConstants.START_ELEMENT , null , "methodResponse" );
nextTag ( );
require ( XMLStreamConstants.START_ELEMENT , null , "params" );
nextTag ( );
require ( XMLStreamConstants.START_ELEMENT , null , "param" );
return deserializeValue ( );
}
private Object deserializeValue ( ) throws XMLStreamException {
nextTag ( );
int eventType = xmlStreamReader.getEventType ( );
if ( eventType == XMLStreamConstants.CHARACTERS || eventType == XMLStreamConstants.CDATA ) {
return xmlStreamReader.getText ( );
}
else if ( eventType == XMLStreamConstants.START_ELEMENT ) {
String localName = xmlStreamReader.getLocalName ( );
switch ( localName ) {
case "string":
return deserializeString ( );
case "int":
return deserializeInt ( );
case "double":
return deserializeDouble ( );
case "boolean":
return deserializeBoolean ( );
case "array":
return deserializeArray ( );
case "struct":
return deserializeStruct ( );
case "nil":
return null;
default:
throw new IllegalArgumentException ( "Unsupported element: " + localName );
}
}
else {
throw new IllegalArgumentException ( "Unexpected event type: " + eventType );
}
}
private String deserializeString ( ) throws XMLStreamException {
return getElementText ( );
}
private int deserializeInt ( ) throws XMLStreamException {
return Integer.parseInt ( getElementText ( ) );
}
private double deserializeDouble ( ) throws XMLStreamException {
return Double.parseDouble ( getElementText ( ) );
}
private boolean deserializeBoolean ( ) throws XMLStreamException {
return Boolean.parseBoolean ( getElementText ( ) );
}
private Object[] deserializeArray ( ) throws XMLStreamException {
Object[] array = new Object[ 0 ];
boolean isValueElement = false;
while ( nextTag ( ) ) {
if ( xmlStreamReader.getLocalName ( ).equals ( "value" ) ) {
isValueElement = true;
}
else if ( xmlStreamReader.getLocalName ( ).equals ( "data" ) ) {
if ( isValueElement ) {
array = deserializeArrayData ( );
}
}
}
return array;
}
private Object[] deserializeArrayData ( ) throws XMLStreamException {
Object[] array = new Object[ 0 ];
boolean isArrayElement = false;
while ( nextTag ( ) ) {
if ( xmlStreamReader.getLocalName ( ).equals ( "array" ) ) {
isArrayElement = true;
}
else if ( xmlStreamReader.getLocalName ( ).equals ( "value" ) ) {
if ( isArrayElement ) {
Object value = deserializeValue ( );
Object[] newArray = new Object[ array.length + 1 ];
System.arraycopy ( array , 0 , newArray , 0 , array.length );
newArray[ array.length ] = value;
array = newArray;
}
}
}
return array;
}
private Map<String, Object> deserializeStruct ( ) throws XMLStreamException {
Map<String, Object> struct = new HashMap<> ( );
String name = null;
while ( nextTag ( ) ) {
if ( xmlStreamReader.getLocalName ( ).equals ( "member" ) ) {
name = null;
}
else if ( xmlStreamReader.getLocalName ( ).equals ( "name" ) ) {
name = getElementText ( );
}
else if ( xmlStreamReader.getLocalName ( ).equals ( "value" ) ) {
if ( name != null ) {
Object value = deserializeValue ( );
struct.put ( name , value );
}
}
}
return struct;
}
public static String skipXmlHeader(String xml) {
int startIndex = xml.indexOf("<?xml");
if (startIndex >= 0) {
int endIndex = xml.indexOf("?>", startIndex);
if (endIndex >= 0) {
return xml.substring(endIndex + 2);
}
}
return xml;
}
public void close ( ) throws XMLStreamException {
xmlStreamReader.close ( );
}
}

View file

@ -0,0 +1,156 @@
package dev.zontreck.ariaslib.xmlrpc;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.List;
import java.util.Map;
public class XmlRpcStreamWriter {
private static final String XML_VERSION = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
private static final String METHOD_CALL_START_TAG = "<methodCall>";
private static final String METHOD_CALL_END_TAG = "</methodCall>";
private static final String METHOD_NAME_START_TAG = "<methodName>";
private static final String METHOD_NAME_END_TAG = "</methodName>";
private static final String METHOD_RESPONSE_START_TAG = "<methodResponse>";
private static final String METHOD_RESPONSE_END_TAG = "</methodResponse>";
private static final String PARAMS_START_TAG = "<params>";
private static final String PARAMS_END_TAG = "</params>";
private static final String PARAM_START_TAG = "<param>";
private static final String PARAM_END_TAG = "</param>";
private static final String VALUE_START_TAG = "<value>";
private static final String VALUE_END_TAG = "</value>";
private static final String ARRAY_START_TAG = "<array>";
private static final String ARRAY_END_TAG = "</array>";
private static final String DATA_START_TAG = "<data>";
private static final String DATA_END_TAG = "</data>";
private static final String STRUCT_START_TAG = "<struct>";
private static final String STRUCT_END_TAG = "</struct>";
private static final String MEMBER_START_TAG = "<member>";
private static final String MEMBER_END_TAG = "</member>";
private static final String NAME_START_TAG = "<name>";
private static final String NAME_END_TAG = "</name>";
private Writer writer;
public XmlRpcStreamWriter ( OutputStream outputStream ) {
this.writer = new OutputStreamWriter ( outputStream );
}
public void writeMethodCall ( String methodName , List<Object> params ) throws IOException {
writer.write ( XML_VERSION );
writer.write ( METHOD_CALL_START_TAG );
writer.write ( METHOD_NAME_START_TAG );
writer.write ( methodName );
writer.write ( METHOD_NAME_END_TAG );
writer.write ( PARAMS_START_TAG );
if ( params != null ) {
for ( Object param : params ) {
writer.write ( PARAM_START_TAG );
writeValue ( param );
writer.write ( PARAM_END_TAG );
}
}
writer.write ( PARAMS_END_TAG );
writer.write ( METHOD_CALL_END_TAG );
writer.flush ( );
}
public void writeMethodResponse ( Object value ) throws IOException {
writer.write ( XML_VERSION );
writer.write ( METHOD_RESPONSE_START_TAG );
writer.write ( PARAMS_START_TAG );
writer.write ( PARAM_START_TAG );
writeValue ( value );
writer.write ( PARAM_END_TAG );
writer.write ( PARAMS_END_TAG );
writer.write ( METHOD_RESPONSE_END_TAG );
writer.flush ( );
}
private void writeValue ( Object value ) throws IOException {
if ( value == null ) {
writer.write ( VALUE_START_TAG );
writer.write ( "<nil/>" );
writer.write ( VALUE_END_TAG );
}
else if ( value instanceof String ) {
writer.write ( VALUE_START_TAG );
writer.write ( "<string>" );
writer.write ( escapeXml ( ( String ) value ) );
writer.write ( "</string>" );
writer.write ( VALUE_END_TAG );
}
else if ( value instanceof Integer ) {
writer.write ( VALUE_START_TAG );
writer.write ( "<int>" );
writer.write ( value.toString ( ) );
writer.write ( "</int>" );
writer.write ( VALUE_END_TAG );
}
else if ( value instanceof Double ) {
writer.write ( VALUE_START_TAG );
writer.write ( "<double>" );
writer.write ( value.toString ( ) );
writer.write ( "</double>" );
writer.write ( VALUE_END_TAG );
}
else if ( value instanceof Boolean ) {
writer.write ( VALUE_START_TAG );
writer.write ( "<boolean>" );
writer.write ( value.toString ( ) );
writer.write ( "</boolean>" );
writer.write ( VALUE_END_TAG );
}
else if ( value instanceof List ) {
writer.write ( VALUE_START_TAG );
writer.write ( ARRAY_START_TAG );
writer.write ( DATA_START_TAG );
List<?> list = ( List<?> ) value;
for ( Object item : list ) {
writer.write ( VALUE_START_TAG );
writeValue ( item );
writer.write ( VALUE_END_TAG );
}
writer.write ( DATA_END_TAG );
writer.write ( ARRAY_END_TAG );
writer.write ( VALUE_END_TAG );
}
else if ( value instanceof Map ) {
writer.write ( VALUE_START_TAG );
writer.write ( STRUCT_START_TAG );
Map<?, ?> map = ( Map<?, ?> ) value;
for ( Map.Entry<?, ?> entry : map.entrySet ( ) ) {
writer.write ( MEMBER_START_TAG );
writer.write ( NAME_START_TAG );
writer.write ( escapeXml ( entry.getKey ( ).toString ( ) ) );
writer.write ( NAME_END_TAG );
writer.write ( VALUE_START_TAG );
writeValue ( entry.getValue ( ) );
writer.write ( VALUE_END_TAG );
writer.write ( MEMBER_END_TAG );
}
writer.write ( STRUCT_END_TAG );
writer.write ( VALUE_END_TAG );
}
else {
throw new IllegalArgumentException ( "Unsupported data type: " + value.getClass ( ).getName ( ) );
}
}
private String escapeXml ( String value ) {
return value
.replace ( "&" , "&amp;" )
.replace ( "<" , "&lt;" )
.replace ( ">" , "&gt;" )
.replace ( "\"" , "&quot;" )
.replace ( "'" , "&apos;" );
}
public void close ( ) throws IOException {
writer.close ( );
}
}