[MOBY-guts] biomoby commit
Paul Gordon
gordonp at dev.open-bio.org
Thu Oct 30 02:33:24 UTC 2008
gordonp
Wed Oct 29 22:33:24 EDT 2008
Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services
In directory dev.open-bio.org:/tmp/cvs-serv10500/src/main/ca/ucalgary/services
Modified Files:
LegacyService.java WSDLService.java
Log Message:
Updates related to SAWSDL wrapping Web Service implementation
moby-live/Java/src/main/ca/ucalgary/services LegacyService.java,1.3,1.4 WSDLService.java,1.1,1.2
===================================================================
RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/LegacyService.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/LegacyService.java 2008/06/30 17:42:29 1.3
+++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/LegacyService.java 2008/10/30 02:33:24 1.4
@@ -41,6 +41,19 @@
return null;
}
+ protected MobyDataInstance getMobyData(org.w3c.dom.Node legacyDOMNode,
+ MobyPrimaryData mobyDataTemplate)
+ throws Exception{
+ try{
+ return mobyClient.getMobyObject(legacyDOMNode, mobyDataTemplate);
+ } catch(MobyServiceException mse){
+ //getMobyObject() throws untransformed-data warnings
+ addException(mse);
+ }
+
+ return null;
+ }
+
protected byte[] getLegacyData(MobyDataInstance mobyData, String legacyFormatName)
throws Exception{
// binary data should be passed through as-is
@@ -54,8 +67,8 @@
/**
* Mechanism to incorporate new tranformation rules
*/
- protected void addLoweringMappingsFromURL(URL u) throws Exception{
- textClient.addMappingsFromURL(u);
+ protected String addLoweringMappingsFromURL(URL u) throws Exception{
+ return textClient.addMappingsFromURL(u);
}
protected void addLiftingMappingsFromURL(URL u) throws Exception{
===================================================================
RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/WSDLService.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/WSDLService.java 2008/06/30 21:19:33 1.1
+++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/WSDLService.java 2008/10/30 02:33:24 1.2
@@ -11,8 +11,12 @@
import org.biomoby.shared.*;
import org.biomoby.shared.data.*;
+import org.w3c.dom.*;
+
import javax.xml.namespace.QName;
+import javax.xml.parsers.*;
import javax.xml.transform.*;
+import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import javax.xml.ws.*;
@@ -38,16 +42,32 @@
protected URL remoteWSDLUrl;
protected WSDLConfig wsdlConfig;
protected Dispatch<Source> dispatch;
- private LSIDResolver lsidResolver; //used to fetch transformation rules, etc. given in the SAWSDL attributes
+ private TransformerFactory transformerFactory;
+ private LSIDResolver lsidResolver; // used to fetch transformation rules, etc. given in the SAWSDL attributes
private Transformer nullTransformer;
+ private Map<String,Transformer> secondaryTransformers; // secondary param to xml schema engines
+ // SAWSDL deals with transformation URIs, but the transformation engine needs a data format name
+ private Map<String,String> uri2XmlFormat;
+ private static DocumentBuilder docBuilder;
private static Logger logger = Logger.getLogger("ca.ucalgary.services.WSDLService");
public void init(){
super.init();
+ // Explicitly set these so Java Web services will work in Java 1.5
+ if(System.getProperty("javax.xml.stream.XMLInputFactory") == null){
+ System.setProperty("javax.xml.stream.XMLInputFactory",
+ "com.ctc.wstx.stax.WstxInputFactory");
+ }
+
+ if(System.getProperty("javax.xml.stream.XMLOutputFactory") == null){
+ System.setProperty("javax.xml.stream.XMLOutputFactory",
+ "com.ctc.wstx.stax.WstxOutputFactory");
+ }
+
lsidResolver = new LSIDResolver();
- TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ transformerFactory = TransformerFactory.newInstance();
try{
nullTransformer = transformerFactory.newTransformer(); // for verbatim copying of SOAP response XML
} catch (TransformerConfigurationException tce){
@@ -55,15 +75,29 @@
"Could not create an XSLT transformer: " + tce,
tce);
}
+ // Keep track of the sawsdl schema mapping uris and link them to the data format names
+ // our engine needs (the mode attribute value in the XSLT template)
+ uri2XmlFormat = new HashMap<String,String>();
+ secondaryTransformers = new HashMap<String,Transformer>();
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ try{
+ docBuilder = dbf.newDocumentBuilder();
+ } catch(Exception e){
+ e.printStackTrace();
+ }
}
public void processRequest(MobyDataJob request, MobyDataJob result) throws Exception{
MobyService service = getService();
// converts a map of strings into a source for the SOAP library
- SourceMap source = new SourceMap(wsdlConfig.getOperationInputQName());
+ //SourceMap source = new SourceMap(wsdlConfig.getOperationInputQName());
+ SourceMap source = new SourceMap(new QName(wsdlConfig.getOperationInputQName().getNamespaceURI(),
+ wsdlConfig.getOperationName()));
- Map<String,String> xmlFormats = wsdlConfig.getPrimaryInputFormats();
+ Map<String,String> ruleURIs = wsdlConfig.getPrimaryInputFormats();
for(MobyPrimaryData mobyInputTemplate: service.getPrimaryInputs()){
String paramName = mobyInputTemplate.getName();
MobyDataInstance mobyData = request.get(paramName);
@@ -77,18 +111,46 @@
// Transform the moby data as required and put it into the SOAP message
// NOTE: We assume, since it's WSDL, that the "legacy" format is XML Schema, which means the
// coercion of the legacy byte data to a String is kosher.
+ String xmlFormat = uri2XmlFormat.get(ruleURIs.get(paramName));
+
+ byte[] paramBytes = getLegacyData(mobyData, xmlFormat);
+ if(paramBytes == null){
+ mobyData.setXmlMode(MobyDataInstance.SERVICE_XML_MODE);
+ throw new MobyException("The Moby parameter '" + paramName +
+ "' could not be transformed into '" +
+ xmlFormat +
+ "' format by an XSLT rule. Source data was:\n"+
+ mobyData.toXML());
+ }
source.put(paramName,
- new String(getLegacyData(mobyData, xmlFormats.get(paramName))));
+ new String(paramBytes));
+ }
+
+ // Now deal with the secondaries
+ for(MobyDataSecondaryInstance mobySec: request.getSecondaryData()){
+ Transformer transformer = secondaryTransformers.get(mobySec.getName());
+ //System.err.println("Transformer class being used is " + transformer.getClass().getName());
+ mobySec.setXmlMode(MobyDataInstance.SERVICE_XML_MODE);
+ StreamSource secSrc = new StreamSource(new ByteArrayInputStream(mobySec.toXML().getBytes()));
+ StringWriter xsltResult = new StringWriter();
+ transformer.transform(secSrc, new StreamResult(xsltResult));
+ source.put(mobySec.getName(), xsltResult.toString());
}
Source resultSource = dispatch.invoke(source);
- Map<String,Map<String,byte[]>> responseData = getResponseData(resultSource);
+ Map<String,Node> responseData = getResponseData(resultSource);
+
+ //for(String key: responseData.keySet()){
+ // System.err.println("Have response key " + key);
+ // System.err.println("Value is "+responseData.get(key));
+ //}
// Parse the results, matching up the correct parameter in the WSDL with the correct Moby type.
// Note that output WSDL and Moby names are the same, allowing auto-matchup.
// Also note that for the moment you can't write a MOB rule that aggregates multiple outputs.
for(MobyPrimaryData mobyOutputTemplate: service.getPrimaryOutputs()){
if(!responseData.containsKey(mobyOutputTemplate.getName())){
+ System.err.println("Couldn't find required service output called " + mobyOutputTemplate.getName());
continue; // Not an output Moby will use
}
MobyDataInstance mdi = getMobyData(responseData.get(mobyOutputTemplate.getName()), mobyOutputTemplate);
@@ -100,7 +162,6 @@
}
result.put(mobyOutputTemplate.getName(), mdi);
}
-
}
public MobyService createServiceFromConfig(javax.servlet.http.HttpServletRequest request)
@@ -142,8 +203,15 @@
"the service " + wsdlConfig.getServiceQName() + ", either the WSDL or the WSDLConfig's " +
"portQName parsed (" + wsdlConfig.getPortQName() + ") is wrong",
e);
+ throw e;
}
-
+
+ // Call to parent, which handles spec-wrapper-to-MobyServlet-config conversion
+ // Need to call the parent so that addLoweringMappingsFromURL(), etc. calls below
+ // work on the instantiated WrapperService data transformation engines (TextClient and MobyClient)
+ // FYI: wsdlConfig contains all of the info about how many parameters there are, their types, etc.
+ MobyService ms = createServiceFromConfig(request, wsdlConfig);
+
// Resolve the LSIDs used to describe the I/O formats into their actual data
// (Moby DEM and MOB conversion rules)
for(String schemaMappingLSID: wsdlConfig.getPrimaryInputFormats().values()){
@@ -155,18 +223,21 @@
e.getClass().getName() + " while resolving lowering schema mapping LSID " +
schemaMappingLSID +" from the SAWSDL document",
e);
+ throw e;
}
try{
- addLoweringMappingsFromURL(u);
+ String dataFormatReturned = addLoweringMappingsFromURL(u);
+ uri2XmlFormat.put(schemaMappingLSID, dataFormatReturned);
} catch(Exception e){
logger.log(Level.SEVERE,
e.getClass().getName() + " while parsing lowering schema mapping (LSID " +
schemaMappingLSID +")",
e);
+ throw e;
}
}
- for(String schemaMappingLSID: wsdlConfig.getPrimaryInputFormats().values()){
+ for(String schemaMappingLSID: wsdlConfig.getPrimaryOutputFormats().values()){
URL u = null;
try{
u = lsidResolver.resolveDataURL(schemaMappingLSID);
@@ -175,6 +246,7 @@
e.getClass().getName() + " while resolving lifting schema mapping LSID " +
schemaMappingLSID +" from the SAWSDL document",
e);
+ throw e;
}
try{
addLiftingMappingsFromURL(u);
@@ -183,11 +255,35 @@
e.getClass().getName() + " while parsing lifting schema mapping (LSID " +
schemaMappingLSID +")",
e);
+ throw e;
}
}
- // Call to parent, which handles spec-wrapper-to-MobyServlet-config conversion
- return createServiceFromConfig(request, wsdlConfig);
+ // Deal with secondary parameters
+ for(Map.Entry<String,String> mapping: wsdlConfig.getSecondaryInputFormats().entrySet()){
+ URL u = null;
+ try{
+ u = lsidResolver.resolveDataURL(mapping.getValue());
+ } catch(Exception e){
+ logger.log(Level.SEVERE,
+ e.getClass().getName() + " while resolving lifting schema mapping LSID " +
+ mapping.getValue() +" from the SAWSDL document for secondary parameter " +
+ mapping.getKey(),
+ e);
+ throw e;
+ }
+ Transformer transformer = null;
+ try{
+ transformer = transformerFactory.newTransformer(new StreamSource(u.openStream()));
+ } catch (TransformerConfigurationException tce){
+ logger.log(Level.SEVERE,
+ "Could not create an XSLT transformer: " + tce,
+ tce);
+ throw tce;
+ }
+ secondaryTransformers.put(mapping.getKey(), transformer);
+ }
+ return ms;
}
public String createInputSpecString(WSDLConfig wsdl){
@@ -201,15 +297,53 @@
}
public String createSecondarySpecString(WSDLConfig form){
- return ""; //everything's primary for now
+ Map<String,String> params = wsdlConfig.getSecondaryInputs();
+ return XHTMLForm.join(",", params.values().toArray(new String[params.size()]));
}
- private Map<String,Map<String,byte[]>> getResponseData(Source source) throws Exception{
- // Structure is (SOAP output param name -> ( -> XML Schema Instance data))
- Map data = new HashMap<String,Map<String,byte[]>>();
- //StringWriter stringWriter = new StringWriter();
- //nullTransformer.transform(source, new StreamResult(stringWriter));
- //return stringWriter.toString();
- return data ;
+ private Map<String,Node> getResponseData(Source source) throws Exception{
+ // Structure is (SOAP output param name -> XML Schema Instance data)
+ Map<String,Node> data = new HashMap<String,Node>();
+ DOMResult domResult = new DOMResult();
+ nullTransformer.transform(source, domResult);
+
+ Node domNode = domResult.getNode();
+ if(domNode == null){
+ throw new Exception("Could not get the result node from the DOM (bad null transformation?)");
+ }
+ Document owner = (domNode instanceof Document ? (Document) domNode : domNode.getOwnerDocument());
+ if(owner == null){
+ throw new Exception("Could not get the owner document from the DOM result (owner was null, node was " +
+ domNode.getClass().getName()+")");
+ }
+ Element responseElement = owner.getDocumentElement();
+
+ NodeList responseParams = responseElement.getChildNodes();
+ for(int i = 0; i < responseParams.getLength(); i++){
+ if(!(responseParams.item(i) instanceof Element)){
+ continue;
+ }
+ Element responseParam = (Element) responseParams.item(i);
+
+ // Use a TreeMap (as opposed to HashMap) so that the order is preserved on iteration
+ TreeMap<String,byte[]> responseValues = new TreeMap<String,byte[]>();
+
+ // If the returned param is an array (xsi:type="SOAP-ENC:Array"), iterate over the values
+ String soapType = responseParam.getAttributeNS(MobyPrefixResolver.XSI_NAMESPACE2001, "type");
+ if(soapType != null && soapType.endsWith(":Array")){
+ data.put(responseParam.getNodeName(),
+ WSDLConfig.renameSoapArrayElements(responseParam, responseParam.getNodeName(), owner));
+ }
+ else{
+ data.put(responseParam.getNodeName(), responseParam);
+ }
+
+ //StringWriter stringWriter = new StringWriter();
+ //nullTransformer.transform(new DOMSource(data.get(responseParam.getNodeName())), new StreamResult(stringWriter));
+ //System.err.println(responseParam.getNodeName()+": "+ stringWriter.toString());
+ }
+
+ return data;
}
+
}
More information about the MOBY-guts
mailing list