Skip to content
Browse files

support for using soap 1.1 and 1.2 together. fixes #130

refactored out HttpClients to its own file and
renamed one of the Fault classes so soap 1.1 and
soap 1.2 can be used side by side.
  • Loading branch information...
1 parent d3c37f3 commit 4e87c03756c8bbcf396afc8ec313d806876f7b62 @eed3si9n committed Dec 10, 2011
View
9 cli/src/main/resources/httpclients.scala.template
@@ -0,0 +1,9 @@
+package scalaxb
+
+trait HttpClients {
+ val httpClient: HttpClient
+
+ trait HttpClient {
+ def request(in: String, address: java.net.URI, headers: Map[String, String]): String
+ }
+}
View
23 cli/src/main/resources/soap11.scala.template
@@ -1,15 +1,7 @@
package scalaxb
-trait HttpClients {
- val httpClient: HttpClient
-
- trait HttpClient {
- def request(in: String, address: java.net.URI, headers: Map[String, String]): String
- }
-}
-
-case class Fault[+A](original: Any, detail: Option[A], headers: scala.xml.NodeSeq) {
- def asFault[B: scalaxb.XMLFormat] = Fault(original, detail map {
+case class Soap11Fault[+A](original: Any, detail: Option[A], headers: scala.xml.NodeSeq) {
+ def asFault[B: scalaxb.XMLFormat] = Soap11Fault(original, detail map {
case x: soapenvelope11.Detail => x.any.head.value match {
case node: scala.xml.Node => scalaxb.fromXML[B](node)
case _ => error("unsupported fault: " + toString)
@@ -19,12 +11,11 @@ case class Fault[+A](original: Any, detail: Option[A], headers: scala.xml.NodeSe
}
trait Soap11Clients { this: HttpClients =>
- import soapenvelope11.{Envelope, Body, Detail, Header}
-
lazy val soapClient: Soap11Client = new Soap11Client {}
val baseAddress: java.net.URI
trait Soap11Client {
+ import soapenvelope11._
val SOAP_ENVELOPE11_URI = "http://schemas.xmlsoap.org/soap/envelope/"
def soapRequest(in: Option[Envelope], scope: scala.xml.NamespaceBinding,
@@ -51,7 +42,7 @@ trait Soap11Clients { this: HttpClients =>
def requestResponse(body: scala.xml.NodeSeq, headers: scala.xml.NodeSeq, scope: scala.xml.NamespaceBinding,
address: java.net.URI, webMethod: String, action: Option[java.net.URI]):
- Either[Fault[Detail], (scala.xml.NodeSeq, scala.xml.NodeSeq)] = {
+ Either[Soap11Fault[Detail], (scala.xml.NodeSeq, scala.xml.NodeSeq)] = {
val bodyRecords = body.toSeq map { DataRecord(None, None, _) }
val headerOption = headers.toSeq.headOption map { _ =>
Header(headers.toSeq map {DataRecord(None, None, _)}, Map())
@@ -62,12 +53,12 @@ trait Soap11Clients { this: HttpClients =>
def soapResponse(location: Option[String], params: Map[String, Any],
address: java.net.URI, webMethod: String, action: Option[java.net.URI]):
- Either[Fault[Detail], (scala.xml.NodeSeq, scala.xml.NodeSeq)] = {
+ Either[Soap11Fault[Detail], (scala.xml.NodeSeq, scala.xml.NodeSeq)] = {
buildResponse(soapRequest(None, scala.xml.TopScope, address, webMethod, action))
}
def buildResponse(soapResponse: Envelope):
- Either[Fault[Detail], (scala.xml.NodeSeq, scala.xml.NodeSeq)] = {
+ Either[Soap11Fault[Detail], (scala.xml.NodeSeq, scala.xml.NodeSeq)] = {
val header: scala.xml.NodeSeq =
soapResponse.Header.toSeq flatMap { header =>
header.any collect {
@@ -78,7 +69,7 @@ trait Soap11Clients { this: HttpClients =>
case Some(DataRecord(_, _, x: scala.xml.Elem)) if (x.label == "Fault") &&
(x.scope.getURI(x.prefix) == SOAP_ENVELOPE11_URI) =>
val fault = scalaxb.fromXML[soapenvelope11.Fault](x)
- Left(Fault(fault, fault.detail, header))
+ Left(Soap11Fault(fault, fault.detail, header))
case _ =>
Right(header, soapResponse.Body.any collect {
case DataRecord(_, _, x: scala.xml.Node) => x
View
81 cli/src/main/resources/soap12.scala.template
@@ -0,0 +1,81 @@
+package scalaxb
+
+case class Fault[+A](original: Any, detail: Option[A], headers: scala.xml.NodeSeq) {
+ def asFault[B: scalaxb.XMLFormat] = Fault(original, detail map {
+ case x: soapenvelope12.Detail => x.any.head.value match {
+ case node: scala.xml.Node => scalaxb.fromXML[B](node)
+ case _ => error("unsupported fault: " + toString)
+ }
+ case _ => error("unsupported fault: " + toString)
+ }, headers)
+}
+
+trait SoapClients { this: HttpClients =>
+ lazy val soapClient: SoapClient = new SoapClient {}
+ val baseAddress: java.net.URI
+
+ trait SoapClient {
+ import soapenvelope12.{Fault => _, _}
+ val SOAP_ENVELOPE_URI = "http://www.w3.org/2003/05/soap-envelope"
+
+ def soapRequest(in: Option[Envelope], scope: scala.xml.NamespaceBinding,
+ address: java.net.URI, webMethod: String, action: Option[java.net.URI]): Envelope = {
+ val merged = scalaxb.toScope(((Some("soap12") -> "http://www.w3.org/2003/05/soap-envelope") ::
+ scalaxb.fromScope(scope)).distinct: _*)
+ val r = in map { scalaxb.toXML(_, Some(SOAP_ENVELOPE_URI), Some("Envelope"), merged) match {
+ case elem: scala.xml.Elem => elem
+ case x => error("unexpected non-elem: " + x.toString)
+ }}
+ val contentType = "application/soap+xml; charset=utf-8" +
+ (action map {"""; action="%s"""" format(_)} getOrElse {""})
+ val headers = Map[String, String]("Content-Type" -> contentType)
+ val s = httpClient.request(r map {_.toString} getOrElse {""}, address, headers)
+
+ try {
+ val response = scala.xml.XML.loadString(s)
+ scalaxb.fromXML[Envelope](response)
+ }
+ catch {
+ case e: Exception => error(e.toString + ": " + s)
+ }
+ }
+
+ def requestResponse(body: scala.xml.NodeSeq, headers: scala.xml.NodeSeq, scope: scala.xml.NamespaceBinding,
+ address: java.net.URI, webMethod: String, action: Option[java.net.URI]):
+ Either[Fault[Detail], (scala.xml.NodeSeq, scala.xml.NodeSeq)] = {
+ val bodyRecords = body.toSeq map {DataRecord(None, None, _)}
+ val headerOption = headers.toSeq.headOption map { _ =>
+ Header(headers.toSeq map {DataRecord(None, None, _)}, Map())
+ }
+ val envelope = Envelope(headerOption, Body(bodyRecords, Map()), Map())
+ buildResponse(soapRequest(Some(envelope), scope, address, webMethod, action))
+ }
+
+ def soapResponse(location: Option[String], params: Map[String, Any],
+ address: java.net.URI, webMethod: String, action: Option[java.net.URI]):
+ Either[Fault[Detail], (scala.xml.NodeSeq, scala.xml.NodeSeq)]= {
+ buildResponse(soapRequest(None, scala.xml.TopScope, address, webMethod, action))
+ }
+
+ def buildResponse(soapResponse: Envelope):
+ Either[Fault[Detail], (scala.xml.NodeSeq, scala.xml.NodeSeq)] = {
+ val header: scala.xml.NodeSeq =
+ soapResponse.Header.toSeq flatMap { header =>
+ header.any collect {
+ case DataRecord(_, _, x: scala.xml.Node) => x
+ }
+ }
+ soapResponse.Body.any.headOption match {
+ case Some(DataRecord(_, _, x: scala.xml.Elem)) if (x.label == "Fault") &&
+ (x.scope.getURI(x.prefix) == SOAP_ENVELOPE_URI) =>
+ val fault = scalaxb.fromXML[soapenvelope12.Fault](x)
+ Left(Fault(fault, fault.Detail, header))
+ case _ =>
+ Right(header, soapResponse.Body.any collect {
+ case DataRecord(_, _, x: scala.xml.Node) => x
+ })
+ }
+ }
+
+ }
+}
View
13 cli/src/main/scala/scalaxb/compiler/wsdl11/Driver.scala
@@ -95,7 +95,8 @@ class Driver extends Module { driver =>
val wsdlgenerated: Seq[(Option[String], Snippet, String)] = pair.definition.toList map { wsdl =>
val pkg = packageName(wsdl.targetNamespace map {_.toString}, cntxt)
- cntxt.soap11 = !generator.soap11Bindings(wsdl).isEmpty
+ generator.soap11Bindings(wsdl) foreach { _ => cntxt.soap11 = true }
+ generator.soap12Bindings(wsdl) foreach { _ => cntxt.soap12 = true }
(pkg, Snippet(headerSnippet(pkg), generator.generate(wsdl)), part)
}
@@ -171,17 +172,20 @@ class Driver extends Module { driver =>
def generateRuntimeFiles[To](cntxt: Context)(implicit evTo: CanBeWriter[To]): List[To] =
List(generateFromResource[To](Some("scalaxb"), "scalaxb.scala", "/scalaxb.scala.template"),
+ generateFromResource[To](Some("scalaxb"), "httpclients.scala", "/httpclients.scala.template"),
generateFromResource[To](Some("scalaxb"), "httpclients_dispatch.scala",
"/httpclients_dispatch.scala.template")) ++
(if (cntxt.soap11) List(generateFromResource[To](Some("scalaxb"), "soap11.scala", "/soap11.scala.template"),
generateFromResource[To](Some("soapenvelope11"), "soapenvelope11.scala",
"/soapenvelope11.scala.template"),
generateFromResource[To](Some("soapenvelope11"), "soapenvelope11_xmlprotocol.scala",
"/soapenvelope11_xmlprotocol.scala.template"))
- else List(generateFromResource[To](Some("scalaxb"), "soap.scala", "/soap.scala.template"),
+ else Nil) ++
+ (if (cntxt.soap12) List(generateFromResource[To](Some("scalaxb"), "soap12.scala", "/soap12.scala.template"),
generateFromResource[To](Some("soapenvelope12"), "soapenvelope12.scala", "/soapenvelope12.scala.template"),
generateFromResource[To](Some("soapenvelope12"), "soapenvelope12_xmlprotocol.scala",
- "/soapenvelope12_xmlprotocol.scala.template")))
+ "/soapenvelope12_xmlprotocol.scala.template"))
+ else Nil)
}
case class WsdlPair(definition: Option[XDefinitionsType], schemas: Seq[SchemaDecl], scope: scala.xml.NamespaceBinding)
@@ -193,4 +197,5 @@ case class WsdlContext(xsdcontext: XsdContext = XsdContext(),
services: mutable.ListMap[(Option[String], String), XServiceType] = mutable.ListMap(),
faults: mutable.ListMap[(Option[String], String), XFaultType] = mutable.ListMap(),
messages: mutable.ListMap[(Option[String], String), XMessageType] = mutable.ListMap(),
- var soap11: Boolean = false )
+ var soap11: Boolean = false,
+ var soap12: Boolean = false)
View
53 cli/src/main/scala/scalaxb/compiler/wsdl11/GenSource.scala
@@ -76,7 +76,8 @@ trait GenSource {
paramMessage(param).part.isEmpty && headerBindings(bindingOption).isEmpty
// generate method signature
- def makeOperation(binding: XBinding_operationType, intf: XPortTypeType, defaultDocument: Boolean): String = {
+ def makeOperation(binding: XBinding_operationType, intf: XPortTypeType,
+ defaultDocument: Boolean, soap12: Boolean): String = {
val op = boundOperation(binding, intf)
val document = isDocument(binding, defaultDocument)
@@ -95,11 +96,11 @@ trait GenSource {
case DataRecord(_, _, XOnewayoperationSequence(input)) =>
"def %s(%s): Unit".format(name, arg(input))
case DataRecord(_, _, XRequestresponseoperationSequence(input, output, faults)) =>
- "def %s(%s): Either[scalaxb.Fault[%s], %s]".format(name, arg(input),
- faultsToTypeName(faults), outputTypeName(binding, op, output, document))
+ "def %s(%s): Either[%s, %s]".format(name, arg(input),
+ faultsToTypeName(faults, soap12), outputTypeName(binding, op, output, document))
case DataRecord(_, _, XSolicitresponseoperationSequence(output, input, faults)) =>
- "def %s(%s): Either[scalaxb.Fault[%s], %s]".format(name, arg(input),
- faultsToTypeName(faults), outputTypeName(binding, op, output, document))
+ "def %s(%s): Either[%s, %s]".format(name, arg(input),
+ faultsToTypeName(faults, soap12), outputTypeName(binding, op, output, document))
case DataRecord(_, _, XNotificationoperationSequence(output)) =>
"def %s: %s".format(name, outputTypeName(binding, op, output, document))
case _ => error("unsupported.")
@@ -181,8 +182,8 @@ trait GenSource {
}
// generate method impl
- def makeSoap12OpBinding(binding: XBinding_operationType, intf: XPortTypeType,
- defaultDocument: Boolean): String = {
+ def makeSoapOpBinding(binding: XBinding_operationType, intf: XPortTypeType,
+ defaultDocument: Boolean, soap12: Boolean): String = {
val op = boundOperation(binding, intf)
logger.debug("makeSoap12OpBinding: " + op.name)
@@ -195,9 +196,9 @@ trait GenSource {
val document = isDocument(binding, defaultDocument)
val actionString = action map {"Some(new java.net.URI(\"%s\"))".format(_)} getOrElse {"None"}
- def faultString(faults: Seq[XFaultType]): String = faultsToTypeName(faults) match {
+ def faultString(faults: Seq[XFaultType]): String = faultsToFaultParamTypeName(faults) match {
case "Any" => "x"
- case x => "x.asFault[%s]".format(x)
+ case x => "x.asFault[%s]".format(x)
}
val opImpl = op.xoperationtypeoption match {
@@ -241,7 +242,7 @@ trait GenSource {
case _ => error("unsupported.")
}
- val retval = makeOperation(binding, intf, defaultDocument) + " = " + NL +
+ val retval = makeOperation(binding, intf, defaultDocument, soap12) + " = " + NL +
" " + opImpl
logger.debug(retval)
retval
@@ -525,15 +526,21 @@ trait GenSource {
} getOrElse {None}
else None
- def faultsToTypeName(faults: Seq[XFaultType]): String = faults.toList match {
- case x :: xs =>
- val msg = context.messages(splitTypeName(x.message))
- msg.part.headOption map { part =>
- val symbol = toTypeSymbol(part)
- xsdgenerator.buildTypeName(symbol, true)
- } getOrElse {"Any"}
- case _ => "Any"
- }
+ def faultsToTypeName(faults: Seq[XFaultType], soap12: Boolean): String =
+ "%s[%s]" format (if (soap12) "scalaxb.Fault"
+ else "scalaxb.Soap11Fault",
+ faultsToFaultParamTypeName(faults))
+
+ def faultsToFaultParamTypeName(faults: Seq[XFaultType]): String =
+ faults.toList match {
+ case x :: xs =>
+ val msg = context.messages(splitTypeName(x.message))
+ msg.part.headOption map { part =>
+ val symbol = toTypeSymbol(part)
+ xsdgenerator.buildTypeName(symbol, true)
+ } getOrElse {"Any"}
+ case _ => "Any"
+ }
def makeBindingName(binding: XBindingType): String = {
val name = xsdgenerator.makeTypeName(binding.name)
@@ -563,8 +570,8 @@ trait GenSource {
val addressString = address map {"""lazy val baseAddress = new java.net.URI("%s")""".format(_)} getOrElse {""}
val operationOutputs = binding.operation flatMap { makeOperationOutput(_, interfaceType) }
- val operations = binding.operation map { opBinding => makeOperation(opBinding, interfaceType, document) }
- val bindingOps = binding.operation map { opBinding => makeSoap12OpBinding(opBinding, interfaceType, document) }
+ val operations = binding.operation map { opBinding => makeOperation(opBinding, interfaceType, document, false) }
+ val bindingOps = binding.operation map { opBinding => makeSoapOpBinding(opBinding, interfaceType, document, false) }
val interfaceTrait = <source>
trait {interfaceTypeName} {{
@@ -609,8 +616,8 @@ trait {interfaceTypeName} {{
val addressString = address map {"""lazy val baseAddress = new java.net.URI("%s")""".format(_)} getOrElse {""}
- val operations = binding.operation map { opBinding => makeOperation(opBinding, interfaceType, document) }
- val bindingOps = binding.operation map { opBinding => makeSoap12OpBinding(opBinding, interfaceType, document) }
+ val operations = binding.operation map { opBinding => makeOperation(opBinding, interfaceType, document, true) }
+ val bindingOps = binding.operation map { opBinding => makeSoapOpBinding(opBinding, interfaceType, document, true) }
val interfaceTrait = <source>
trait {interfaceTypeName} {{
View
2 integration/src/test/scala/Wsdl11Soap11Test.scala
@@ -17,7 +17,7 @@ object Wsdl11Soap11Test extends TestBase {
"""val service = (new BarCodeSoapBindings with scalaxb.Soap11Clients with scalaxb.DispatchHttpClients {}).service
val data = BarCodeData(120, 120, 0, 1, 1, 20, 20, true, None, None, None, 10.0f, Both, CodeEAN128B, NoneType, BottomCenter, PNG)
println(scalaxb.toXML(data, "BarCodeParam", defaultScope))
- val response = service.generateBarCode(data, Some("1234")).right.get.get
+ val response = service.generateBarCode(data, Some("1234")).right.get
println(response)""",
"""response.toString.contains("iVB")"""), generated) must evaluateTo(true,
outdir = "./tmp", usecurrentcp = true)

0 comments on commit 4e87c03

Please sign in to comment.
Something went wrong with that request. Please try again.