[MOBY-guts] biomoby commit
Paul Gordon
gordonp at pub.open-bio.org
Wed Jul 7 16:02:48 UTC 2004
gordonp
Wed Jul 7 12:02:47 EDT 2004
Update of /home/repository/moby/moby-live/Java/src/main/org/biomoby/client
In directory pub.open-bio.org:/tmp/cvs-serv32166/client
Modified Files:
MobyRequest.java
Log Message:
Fixed issues with SOAP payload parsing related to namespaces and encoding schemes, works with Axis 1.1beta without warnings too
moby-live/Java/src/main/org/biomoby/client MobyRequest.java,1.3,1.4
===================================================================
RCS file: /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/MobyRequest.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/MobyRequest.java 2004/05/20 16:08:05 1.3
+++ /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/MobyRequest.java 2004/07/07 16:02:47 1.4
@@ -16,9 +16,7 @@
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.namespace.QName;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-import org.w3c.dom.Element;
+import org.w3c.dom.*;
// Utilities
import java.util.Hashtable;
@@ -34,6 +32,7 @@
import org.w3c.dom.NodeList;
import org.apache.axis.message.MessageElement;
import java.io.PrintStream;
+import java.io.StringBufferInputStream;
/**
* This class handles the WSDL transaction to request a response
@@ -56,6 +55,7 @@
protected MobyDataSecondaryInstance[] secondaryData = null;
protected Vector outputData = null;
protected Central mobyCentral = null;
+ protected PrefixResolver mobyPrefixResolver = null;
protected Hashtable wsdlCache = null;
protected String lastWsdlCacheKey = null;
@@ -69,6 +69,7 @@
protected XPathContext xpath_context;
protected String responseString = null;
+ private XPath stringEncodedXPath;
private XPath base64EncodedXPath;
private XPath queryResponseXPath;
private XPath simpleChildXPath;
@@ -97,11 +98,20 @@
}
xpath_context = new XPathContext();
- PrefixResolver mobyPrefixResolver = new MobyPrefixResolver();
+ mobyPrefixResolver = new MobyPrefixResolver();
// Now compile the XPath statements that will be used fetch data from the server response
try{
- base64EncodedXPath = new XPath("//*[@xsi:type=\"SOAP-ENC:base64\"]", null, mobyPrefixResolver, XPath.SELECT);
+ base64EncodedXPath = new XPath("//*[starts-with(substring-after(@"+
+ MobyPrefixResolver.XSI1999_PREFIX+
+ ":type, ':'), \"base64\") or starts-with(substring-after(@"+
+ MobyPrefixResolver.XSI2001_PREFIX+
+ ":type, ':'), \"base64\")]", null, mobyPrefixResolver, XPath.SELECT);
+ stringEncodedXPath = new XPath("//*[substring-after(@"+
+ MobyPrefixResolver.XSI1999_PREFIX+
+ ":type, ':')=\"string\" or substring-after(@"+
+ MobyPrefixResolver.XSI2001_PREFIX+
+ ":type, ':')=\"string\"]", null, mobyPrefixResolver, XPath.SELECT);
queryResponseXPath = new XPath("//moby:mobyData | //mobyData", null, mobyPrefixResolver, XPath.SELECT);
simpleChildXPath = new XPath("moby:Simple | Simple", null, mobyPrefixResolver, XPath.SELECT);
collectionChildXPath = new XPath("moby:Collection | Collection", null, mobyPrefixResolver, XPath.SELECT);
@@ -306,23 +316,25 @@
// Should initialize endpoint, etc. This call is AXIS SPECIFIC, otherwise you'll
// have to do the call's info setting manually.
//((org.apache.axis.client.Call) soapCall).setSOAPService(soapService);
- soapCall.setPortTypeName(new QName("http://biomoby.org/",
- mobyService.getName() + "PortType"));
- soapCall.setOperationName(new QName("http://biomoby.org/",
- mobyService.getName()));
+ soapCall.removeAllParameters();
soapCall.setTargetEndpointAddress(mobyService.getURL());
+ soapCall.setPortName(new QName("http://biomoby.org/",
+ mobyService.getName() + "PortType"));
+ //soapCall.setOperationName(new QName("http://biomoby.org/",
+ // mobyService.getName()));
soapCall.setSOAPActionURI("http://biomoby.org/#" + mobyService.getName());
- soapCall.setReturnType(XMLType.SOAP_STRING);
- soapCall.removeAllParameters();
MobyData[] requiredInputData = mobyService.getPrimaryInputs();
if(requiredInputData == null)
return; // A method requiring no input?
else{
// There is one argument, the MOBY request object string
- soapCall.addParameter("MOBYRequest",
- XMLType.SOAP_STRING,
- stringType,
- ParameterMode.IN);
+ /*soapCall.setReturnType(new QName("http://biomoby.org/", mobyService.getName()));
+ soapCall.addParameter("MOBYRequest",
+ XMLType.SOAP_STRING,
+ stringType,
+ ParameterMode.IN);*/
+ if(debug)
+ debugPS.println("Set returnType after addParameter was " + soapCall.getReturnType());
}
return;
}
@@ -337,9 +349,12 @@
//Setup
mobyXMLInputData[0] = mobyInputXML;
+ if(debug)
+ debugPS.println("returnType just before invoke call is " + soapCall.getReturnType());
Object returnedObject = null;
try{
- returnedObject = soapCall.invoke(mobyXMLInputData);
+ returnedObject = soapCall.invoke(new QName("http://biomoby.org/",
+ mobyService.getName()), mobyXMLInputData);
}
catch(Exception e){
throw new SOAPException("While invoking SOAP Call: " + e);
@@ -354,6 +369,7 @@
return decodeSOAPMessage(resultDom);
//return resultDom;
} catch(Exception e){
+ e.printStackTrace();
throw new SOAPException("Could not get SOAP response as DOM Element: "+ e);
}
@@ -368,53 +384,143 @@
* @return The root element of the MOBY response DOM
*/
protected Element decodeSOAPMessage(Element n) throws SOAPException, MobyException{
-
if(n == null){
throw new SOAPException("SOAP Message given to decode is null");
}
- // Find base64 encoded elements in the SOAP message using XPath
NodeList node_list = null;
+ Node responseNode = null;
+ XPath responseElementXPath = null;
try{
- node_list = runXPath(base64EncodedXPath, n);
+ responseElementXPath = new XPath("//"+ MobyPrefixResolver.MOBY_TRANSPORT_PREFIX+
+ ":"+mobyService.getName()+"Response",
+ null, mobyPrefixResolver, XPath.SELECT);
}catch(TransformerException te){
throw new SOAPException("Cannot select SOAP nodes due to exception "+
+ "while compiling XPath statement (code bug?):" +te);
+ }
+ try{
+ node_list = runXPath(responseElementXPath, n);
+ }
+ catch(TransformerException te){
+ throw new SOAPException("Cannot select SOAP nodes due to exception "+
"while executing XPath statement:" +te);
}
if(node_list == null || node_list.getLength() == 0){
- // Note: before giving up we should really have a plain string check as per the MOBY API 0.6
- throw new SOAPException("Could not find a Base64 encoded SOAP payload");
+ throw new SOAPException("Could not find a response element in SOAP payload");
}
- // Do decoding for each part found
- for(int i = 0; i < node_list.getLength(); i++){
-
+
+ if(node_list.getLength() > 1){
+ throw new SOAPException("Found more than one response element in SOAP payload, " +
+ "unable to resolve ambiguity of the payload (service provider error?)");
+ }
+ responseNode = node_list.item(0);
+
+ // Find base64 encoded elements in the SOAP message using XPath and
+ // replace them with the real decoded contents
+ node_list = null;
+ try{
+ node_list = runXPath(base64EncodedXPath, responseNode);
+ }
+ catch(TransformerException te){
+ throw new SOAPException("Cannot select base64 encoded SOAP nodes due to exception "+
+ "while executing XPath statement:" +te);
+ }
+ if(debug && node_list != null){
+ debugPS.println("There were " + node_list.getLength() +
+ " base64 encoded elements in the data");
+ }
+
+ // Do decoding for each base64 part found
+ for(int i = 0; node_list != null && i < node_list.getLength(); i++){
org.w3c.dom.Node change = node_list.item(i);
- change.normalize();
+ /* Make sure the text data is all put into one contiguous piece for decoding*/
+ change.normalize();
+
byte[] decodedBytes = org.apache.axis.encoding.Base64.decode(change.getFirstChild().getNodeValue());
String newText = new String(decodedBytes);
if(debug){
debugPS.println("New decoded text is" + newText);
}
- // release resources related to the Xpath execution, since we won't be using this doc anymore
- releaseXPath(n);
-
- responseString = new String(decodedBytes);
- // Parse the MOBY XML document payload
- Document domDoc = null;
- try{
- domDoc = docBuilder.parse(new ByteArrayInputStream(decodedBytes));
- } catch(org.xml.sax.SAXException saxe){
- throw new MobyException("The SOAP payload defining the MOBY Result " +
- "could not be parsed: " + saxe);
- } catch(java.io.IOException ioe){
- throw new MobyException("The SOAP payload defining the MOBY Result " +
- " could not be read (from a String!)" + ioe);
+ // Swap out this node for the decoded data
+ change.getParentNode().replaceChild(n.getOwnerDocument().createTextNode(new String(decodedBytes)),
+ change);
+ }
+
+ // Now see if there are any strings that need decoding
+ node_list = null;
+ try{
+ node_list = runXPath(stringEncodedXPath, responseNode);
+ }
+ catch(TransformerException te){
+ throw new SOAPException("Cannot select base64 encoded SOAP nodes due to exception "+
+ "while executing XPath statement:" +te);
+ }
+
+ // Do decoding for each base64 part found
+ for(int i = 0; node_list != null && i < node_list.getLength(); i++){
+ org.w3c.dom.Node change = node_list.item(i);
+ /* Make sure the text data is all put into one contiguous piece for decoding*/
+ change.normalize();
+ String plainString = "";
+ int j = 0;
+ for(NodeList children = change.getChildNodes();
+ children != null && j < children.getLength();
+ j++){
+ Node child = children.item(j);
+ if(child instanceof CDATASection || child instanceof Text){
+ plainString += child.getNodeValue();
+ }
+ }
+
+ // Swap out this node for the decoded data
+ change.getParentNode().replaceChild(n.getOwnerDocument().createTextNode(plainString), change);
+ }
+ if(debug && node_list != null){
+ debugPS.println("There were " + node_list.getLength() +
+ " XML Schema string encoded elements in the data");
+ }
+
+ // Parse the MOBY XML document payload
+ responseNode.normalize();
+ NodeList children = responseNode.getChildNodes();
+ if(children == null){
+ throw new MobyException("The MOBY payload has no contents at all");
+ }
+ if(children.getLength() != 1){
+ debugPS.println("Warning: MOBY Payload appears to have more than " +
+ "just text in it, skipping the non-text sections");
+ }
+
+ responseString = "";
+ for(int j = 0; j < children.getLength(); j++){
+ Node child = children.item(j);
+ if(child instanceof CDATASection || child instanceof Text){
+ responseString += child.getNodeValue();
}
- return domDoc.getDocumentElement();
}
- return null; //Shouldn't get here
+
+ if(responseString.length() == 0){
+ throw new MobyException("The MOBY payload has no text contents at all");
+ }
+
+ Document domDoc = null;
+ try{
+ domDoc = docBuilder.parse(new StringBufferInputStream(responseString));
+ } catch(org.xml.sax.SAXException saxe){
+ throw new MobyException("The SOAP payload defining the MOBY Result " +
+ "could not be parsed: " + saxe);
+ } catch(java.io.IOException ioe){
+ throw new MobyException("The SOAP payload defining the MOBY Result " +
+ " could not be read (from a String!)" + ioe);
+ }
+
+ // release resources related to the Xpath execution, since we won't be using this doc anymore
+ releaseXPath(n);
+
+ return domDoc.getDocumentElement();
}
@@ -492,7 +598,7 @@
if(debug){
debugPS.println("Aha! Got " + response_list.getLength() + " mobyContent response elements");
}
- // Do data deserialization for each response's mobyData
+ // Do data decoding for each response's mobyData
for(int i = 0; i < response_list.getLength(); i++){
Node response = response_list.item(i);
More information about the MOBY-guts
mailing list