From: Thomas D. <tdi...@us...> - 2004-12-03 13:26:16
|
User: tdiesler Date: 04/12/03 05:26:09 Modified: src/main/org/jboss/ws/binding/soap SOAPBindingProvider.java Log: Push xsdSchema generated by jbossws to the JAXB layer. ComplexTypeMarshallerGenTestCase needs work Revision Changes Path 1.8 +167 -174 webservice/src/main/org/jboss/ws/binding/soap/SOAPBindingProvider.java Index: SOAPBindingProvider.java =================================================================== RCS file: /cvsroot/jboss/webservice/src/main/org/jboss/ws/binding/soap/SOAPBindingProvider.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- SOAPBindingProvider.java 3 Dec 2004 01:25:57 -0000 1.7 +++ SOAPBindingProvider.java 3 Dec 2004 13:26:09 -0000 1.8 @@ -12,7 +12,7 @@ import org.jboss.logging.Logger; import org.jboss.ws.binding.BindingException; import org.jboss.ws.binding.BindingProvider; -import org.jboss.ws.jaxb.MarshallableImpl; +import org.jboss.ws.jaxb.MarshallerImpl; import org.jboss.ws.jaxb.SimpleTypeMarshaller; import org.jboss.ws.jaxb.SimpleTypeUnmarshaller; import org.jboss.ws.jaxrpc.DefaultTypeMapping; @@ -23,6 +23,9 @@ import org.jboss.ws.soap.SOAPBodyElementImpl; import org.jboss.ws.soap.SOAPFactoryImpl; import org.jboss.ws.soap.SOAPLazyElement; +import org.jboss.ws.tools.Configuration; +import org.jboss.ws.tools.JavaToWSDL; +import org.jboss.ws.tools.jbossws; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; @@ -39,7 +42,10 @@ import javax.xml.soap.SOAPHeader; import javax.xml.soap.SOAPMessage; import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileWriter; import java.io.StringWriter; +import java.net.URL; import java.util.ArrayList; import java.util.List; @@ -83,7 +89,7 @@ { Object inParam = inParams[i]; ParameterDesc paramDesc = (ParameterDesc)input.get(i); - addSOAPElementForParameter(paramDesc, inParam, soapHeader, soapBodyElement); + addParameterToMessage(paramDesc, inParam, soapHeader, soapBodyElement); } } else @@ -99,72 +105,6 @@ } } - /** Marshall the given input parameter and add it to the SOAPEnvelope - */ - private SOAPElement addSOAPElementForParameter(ParameterDesc paramDesc, Object value, SOAPHeader soapHeader, SOAPBodyElement soapBodyElement) - throws SOAPException, JAXBException - { - SOAPFactory factory = new SOAPFactoryImpl(); - - // Get the JAXB marshaller for complex objects - JAXBContext context = JAXBContext.newInstance("org.jboss.jaxb"); - Marshaller complexMarshaller = context.createMarshaller(); - - // Get the marshaller for simple XMLSchema objects - SimpleTypeMarshaller simpleMarshaller = new SimpleTypeMarshaller(); - - QName pQName = paramDesc.getXmlName(); - QName xmlType = paramDesc.getXmlType(); - - // [TODO] when do we add prefixes - //Name pName = new NameImpl(pQName.getLocalPart(), PREFIX, pQName.getNamespaceURI()); - Name pName = new NameImpl(pQName.getLocalPart()); - - // The SOAPElement to be created - SOAPElement soapElement = null; - - // Handle the JAXRPC default types - if (DefaultTypeMapping.isRegisteredType(xmlType)) - { - // Create the new SOAPElement - soapElement = factory.createElement(pName); - - // Do the marshalling - String strValue = simpleMarshaller.marshal(xmlType, value); - - // Create a TextNode - soapElement.addTextNode(strValue); - } - else - { - // A complex type needs to be marshalled with JAXB - MarshallableImpl marshObj = new MarshallableImpl(xmlType); - marshObj.setXMLName(pName); - marshObj.setValue(value); - - StringWriter strwr = new StringWriter(); - complexMarshaller.marshal(marshObj, strwr); - String strValue = strwr.toString(); - - // The string representation of the complexType is the content - soapElement = new SOAPLazyElement(pName, strValue); - } - - // Add element either as header or as body element - if (paramDesc.isInHeader()) - { - log.debug("Add header element: " + soapElement); - soapElement = soapHeader.addChildElement(soapElement); - } - else - { - log.debug("Add body element: " + soapElement); - soapElement = soapBodyElement.addChildElement(soapElement); - } - - return soapElement; - } - /** On the server side, extract the IN parameters from the payload and populate an Invocation object */ public Invocation unbindRequestMessage(OperationDesc opDesc, SOAPMessage reqMessage) throws BindingException { @@ -174,63 +114,33 @@ // Read the SOAPEnvelope from the reqMessage SOAPEnvelope soapEnvelope = reqMessage.getSOAPPart().getEnvelope(); - SOAPHeader soapHeader = soapEnvelope.getHeader(); SOAPBody soapBody = soapEnvelope.getBody(); - // Get the JAXB unmarshaller for complex objects - JAXBContext context = JAXBContext.newInstance("org.jboss.jaxb"); - Unmarshaller complexUnmarshaller = context.createUnmarshaller(); - - // Get the unmarshaller for simple XMLSchema objects - SimpleTypeUnmarshaller simpleUnmarshaller = new SimpleTypeUnmarshaller(); - Style style = opDesc.getStyle(); if (style == Style.RPC) { SOAPBodyElement soapBodyElement = (SOAPBodyElement)soapBody.getChildElements().next(); Name elName = soapBodyElement.getElementName(); + QName elQName = new QName(elName.getURI(), elName.getLocalName()); QName rpcQName = opDesc.getXmlName(); - Name rpcName = new NameImpl(rpcQName.getLocalPart(), PREFIX, rpcQName.getNamespaceURI()); - - if (elName.equals(rpcName) == false) - throw new BindingException("SOAPBodyElement name mismatch, exp[" + rpcName + "] was[" + elName + "]"); + if (elQName.equals(rpcQName) == false) + throw new BindingException("SOAPBodyElement name mismatch, exp[" + rpcQName + "] was[" + elQName + "]"); // Set the target method in the SEI invocation.setMethod(null); - List input = opDesc.getInputParameters(); - Object[] invocationArgs = new Object[input.size()]; - invocation.setArguments(invocationArgs); - - for (int i = 0; i < input.size(); i++) + List inParamList = new ArrayList(); + List inList = opDesc.getInputParameters(); + for (int i = 0; i < inList.size(); i++) { - ParameterDesc paramDesc = (ParameterDesc)input.get(i); - QName pQName = paramDesc.getXmlName(); - QName xmlType = paramDesc.getXmlType(); - - Name pName = new NameImpl(pQName.getLocalPart(), PREFIX, pQName.getNamespaceURI()); - - // The parameters are expected to be lazy - SOAPLazyElement soapElement = null; - if (paramDesc.isInHeader()) - soapElement = (SOAPLazyElement)soapHeader.getChildElements(pName).next(); - else - soapElement = (SOAPLazyElement)soapBodyElement.getChildElements(pName).next(); - - Object value = null; - if (DefaultTypeMapping.isRegisteredType(xmlType)) - { - String content = soapElement.getValue(); - value = simpleUnmarshaller.unmarshal(xmlType, content); - } - else - { - String content = soapElement.getLazyContent(); - value = complexUnmarshaller.unmarshal(new ByteArrayInputStream(content.getBytes())); - } - invocationArgs[i] = value; + ParameterDesc paramDesc = (ParameterDesc)inList.get(i); + getParameterFromMessage(inParamList, paramDesc, soapBodyElement); } + + Object[] invArgs = new Object[inParamList.size()]; + inParamList.toArray(invArgs); + invocation.setArguments(invArgs); } else { @@ -272,21 +182,22 @@ int argOffset = 0; Object[] args = result.getArguments(); + // Add the return to the message ParameterDesc retDesc = opDesc.getReturnType(); if (retDesc != null) { Object value = args[0]; - addSOAPElementForParameter(retDesc, value, null, soapBodyElement); + addParameterToMessage(retDesc, value, null, soapBodyElement); argOffset++; } + // Add the out parameters to the message List output = opDesc.getOutputParameters(); for (int i = 0; i < output.size(); i++) { ParameterDesc paramDesc = (ParameterDesc)output.get(i); Object value = args[i + argOffset]; - - addSOAPElementForParameter(paramDesc, value, soapHeader, soapBodyElement); + addParameterToMessage(paramDesc, value, soapHeader, soapBodyElement); argOffset++; } } @@ -308,95 +219,42 @@ { try { - ArrayList retList = new ArrayList(); - // Read the SOAPEnvelope from the reqMessage SOAPEnvelope soapEnvelope = resMessage.getSOAPPart().getEnvelope(); - SOAPHeader soapHeader = soapEnvelope.getHeader(); SOAPBody soapBody = soapEnvelope.getBody(); - // Get the JAXB unmarshaller for complex objects - JAXBContext context = JAXBContext.newInstance("org.jboss.jaxb"); - Unmarshaller complexUnmarshaller = context.createUnmarshaller(); - - // Get the unmarshaller for simple XMLSchema objects - SimpleTypeUnmarshaller simpleUnmarshaller = new SimpleTypeUnmarshaller(); Style style = opDesc.getStyle(); if (style == Style.RPC) { SOAPBodyElement soapBodyElement = (SOAPBodyElement)soapBody.getChildElements().next(); Name elName = soapBodyElement.getElementName(); + QName elQName = new QName(elName.getURI(), elName.getLocalName()); QName rpcQName = opDesc.getXmlResponseName(); - Name rpcName = new NameImpl(rpcQName.getLocalPart(), PREFIX, rpcQName.getNamespaceURI()); - - if (elName.equals(rpcName) == false) - throw new BindingException("SOAPBodyElement name mismatch, exp[" + rpcName + "] was[" + elName + "]"); + if (elQName.equals(rpcQName) == false) + throw new BindingException("SOAPBodyElement name mismatch, exp[" + rpcQName + "] was[" + elQName + "]"); + ArrayList outParamList = new ArrayList(); ParameterDesc returnDesc = opDesc.getReturnType(); if (returnDesc != null) { - QName pQName = returnDesc.getXmlName(); - QName xmlType = returnDesc.getXmlType(); - - Name pName = new NameImpl(pQName.getLocalPart(), PREFIX, pQName.getNamespaceURI()); - - // The parameters are expected to be lazy - SOAPLazyElement soapElement = (SOAPLazyElement)soapBodyElement.getChildElements(pName).next(); - - Object value = null; - if (DefaultTypeMapping.isRegisteredType(xmlType)) - { - String content = soapElement.getValue(); - value = simpleUnmarshaller.unmarshal(xmlType, content); - } - else - { - String content = soapElement.getLazyContent(); - value = complexUnmarshaller.unmarshal(new ByteArrayInputStream(content.getBytes())); - } - - retList.add(value); + getParameterFromMessage(outParamList, returnDesc, soapBodyElement); } List output = opDesc.getOutputParameters(); for (int i = 0; i < output.size(); i++) { ParameterDesc paramDesc = (ParameterDesc)output.get(i); - QName pQName = paramDesc.getXmlName(); - QName xmlType = paramDesc.getXmlType(); - - Name pName = new NameImpl(pQName.getLocalPart(), PREFIX, pQName.getNamespaceURI()); - - // The parameters are expected to be lazy - SOAPLazyElement soapElement = null; - if (paramDesc.isInHeader()) - soapElement = (SOAPLazyElement)soapHeader.getChildElements(pName).next(); - else - soapElement = (SOAPLazyElement)soapBodyElement.getChildElements(pName).next(); - - Object value = null; - if (DefaultTypeMapping.isRegisteredType(xmlType)) - { - String content = soapElement.getValue(); - value = simpleUnmarshaller.unmarshal(xmlType, content); - } - else - { - String content = soapElement.getLazyContent(); - value = complexUnmarshaller.unmarshal(new ByteArrayInputStream(content.getBytes())); - } - - retList.add(value); + getParameterFromMessage(outParamList, paramDesc, soapBodyElement); } + + return outParamList.toArray(); } else { throw new IllegalStateException("Unsupported encoding style: " + style); } - - return retList.toArray(); } catch (BindingException e) { @@ -407,4 +265,139 @@ throw new BindingException(e); } } + + /** Marshall the given parameter and add it to the SOAPMessage */ + private void addParameterToMessage(ParameterDesc paramDesc, Object value, SOAPHeader soapHeader, SOAPBodyElement soapBodyElement) + throws SOAPException, JAXBException, BindingException + { + SOAPFactory factory = new SOAPFactoryImpl(); + + // Get the JAXB marshaller for complex objects + JAXBContext context = JAXBContext.newInstance("org.jboss.jaxb"); + Marshaller jaxbMarshaller = context.createMarshaller(); + + // Get the marshaller for simple XMLSchema objects + SimpleTypeMarshaller simpleMarshaller = new SimpleTypeMarshaller(); + + QName pQName = paramDesc.getXmlName(); + QName xmlType = paramDesc.getXmlType(); + + // [TODO] when do we add prefixes + //Name pName = new NameImpl(pQName.getLocalPart(), PREFIX, pQName.getNamespaceURI()); + Name pName = new NameImpl(pQName.getLocalPart()); + + // The SOAPElement to be created + SOAPElement soapElement = null; + + // Handle the JAXRPC default types + if (DefaultTypeMapping.isRegisteredType(xmlType)) + { + // Create the new SOAPElement + soapElement = factory.createElement(pName); + + // Do the marshalling + String strValue = simpleMarshaller.marshal(xmlType, value); + + // Create a TextNode + soapElement.addTextNode(strValue); + } + else + { + // Generate the xsdSchema for the given type + if (value != null) + { + URL xsdURL = generateXSDSchema(xmlType, value.getClass()); + jaxbMarshaller.setProperty(MarshallerImpl.JAXB_XSD_URL, xsdURL); + } + + // A complex type needs to be marshalled with JAXB + StringWriter strwr = new StringWriter(); + jaxbMarshaller.marshal(value, strwr); + + String strValue = strwr.toString(); + + // The string representation of the complexType is the content + soapElement = new SOAPLazyElement(pName, strValue); + } + + // Add element either as header or as body element + if (paramDesc.isInHeader()) + { + log.debug("Add header element: " + soapElement); + soapElement = soapHeader.addChildElement(soapElement); + } + else + { + log.debug("Add body element: " + soapElement); + soapElement = soapBodyElement.addChildElement(soapElement); + } + } + + /** Unmarshall a message element and add it to the parameter list */ + private void getParameterFromMessage(List paramList, ParameterDesc paramDesc, SOAPBodyElement soapBodyElement) + throws JAXBException + { + // Get the JAXB unmarshaller for complex objects + JAXBContext context = JAXBContext.newInstance("org.jboss.jaxb"); + Unmarshaller complexUnmarshaller = context.createUnmarshaller(); + + // Get the unmarshaller for simple XMLSchema objects + SimpleTypeUnmarshaller simpleUnmarshaller = new SimpleTypeUnmarshaller(); + + QName pQName = paramDesc.getXmlName(); + QName xmlType = paramDesc.getXmlType(); + + Name pName = new NameImpl(pQName.getLocalPart(), PREFIX, pQName.getNamespaceURI()); + + // The parameters are expected to be lazy + SOAPLazyElement soapElement = (SOAPLazyElement)soapBodyElement.getChildElements(pName).next(); + + Object value = null; + if (DefaultTypeMapping.isRegisteredType(xmlType)) + { + String content = soapElement.getValue(); + value = simpleUnmarshaller.unmarshal(xmlType, content); + } + else + { + String content = soapElement.getLazyContent(); + value = complexUnmarshaller.unmarshal(new ByteArrayInputStream(content.getBytes())); + } + + paramList.add(value); + } + + /** Generate the xsdSchema for a given type + * [TODO] do some caching + */ + private URL generateXSDSchema(QName xmlType, Class javaType) throws BindingException + { + try + { + Configuration config = new Configuration(); + config.setTargetNS(xmlType.getNamespaceURI()); + JavaToWSDL javaToWSDL = new jbossws(config).getJavaToWSDL(); + javaToWSDL.generateXSDType(javaType); + + StringWriter strw = new StringWriter(); + javaToWSDL.writeXSDSchema(strw); + + log.debug("xsdSchema for type: " + javaType + "\n" + strw); + + File tmpFile = File.createTempFile("complexType", ".xsd"); + FileWriter writer = new FileWriter(tmpFile); + writer.write(strw.toString()); + writer.close(); + + return tmpFile.toURL(); + } + catch (RuntimeException e) + { + throw e; + } + catch (Exception e) + { + throw new BindingException("Cannot generate xsdSchema for: " + javaType.getName()); + } + } } |