diff --git a/core/src/main/java/com/predic8/membrane/core/interceptor/soap/SampleSoapService.java b/core/src/main/java/com/predic8/membrane/core/interceptor/soap/SampleSoapService.java
deleted file mode 100644
index f98f1a606..000000000
--- a/core/src/main/java/com/predic8/membrane/core/interceptor/soap/SampleSoapService.java
+++ /dev/null
@@ -1,139 +0,0 @@
-package com.predic8.membrane.core.interceptor.soap;
-
-import com.predic8.membrane.annot.MCElement;
-import com.predic8.membrane.core.exchange.Exchange;
-import com.predic8.membrane.core.http.Response;
-import com.predic8.membrane.core.interceptor.AbstractInterceptor;
-import com.predic8.membrane.core.interceptor.Outcome;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import javax.xml.namespace.QName;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamReader;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import java.io.InputStream;
-import java.io.StringWriter;
-
-import static com.predic8.membrane.core.interceptor.Outcome.CONTINUE;
-import static com.predic8.membrane.core.interceptor.Outcome.RETURN;
-import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
-
-@MCElement(name="sampleSoapService")
-public class SampleSoapService extends AbstractInterceptor {
-
- public SampleSoapService() {
- name = "SampleSoapService";
- }
-
- @Override
- public Outcome handleRequest(Exchange exc) throws Exception {
- try {
- String cityName = getElementAsString(exc.getRequest().getBodyAsStream(), "city");
- exc.setResponse(Response.ok(getResponse(cityName)).header("Content-Type", "application/xml").build());
- } catch (Exception e) {
- exc.setResponse(Response.ok(getSoapFault("city element not found")).header("Content-Type", "application/xml").build());
- }
- return RETURN;
- }
-
- public static String getSoapFault(String error) {
- return "\n" +
- " \n" +
- " \n" +
- " soapenv:Client\n" +
- " Resource Not Found\n" +
- " \n" +
- " 404\n" +
- " " + error + "\n" +
- " \n" +
- " \n" +
- " \n" +
- "";
- }
-
- public static String getElementAsString(InputStream is, String localName) throws Exception {
- XMLInputFactory factory = XMLInputFactory.newInstance();
- XMLStreamReader reader = factory.createXMLStreamReader(is);
-
- while (reader.hasNext()) {
- int event = reader.next();
- if (event == START_ELEMENT) {
- QName startElementName = reader.getName();
- if (startElementName.getLocalPart().equals(localName)) {
- return reader.getElementText();
- }
- }
- }
- throw new Exception();
- }
-
- public static String getResponse(String result) throws ParserConfigurationException, TransformerException {
- if(result.equals("Bonn") || result.equals("London") || result.equals("New York")) {
- // DocumentBuilderFactory is not guaranteed to be thread safe
- // https://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.5/api/javax/xml/parsers/DocumentBuilderFactory.html
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- DocumentBuilder builder = factory.newDocumentBuilder();
- Document responseDoc = builder.newDocument();
- Element envElement = responseDoc.createElementNS("http://schemas.xmlsoap.org/soap/envelope/", "s:Envelope");
- envElement.setAttribute("xmlns:s", "http://schemas.xmlsoap.org/soap/envelope/");
- envElement.setAttribute("xmlns:cs", "https://predic8.de/city-service");
- Element body = responseDoc.createElement("s:Body");
- Element cityDetailsRes = responseDoc.createElement("cs:cityDetails");
- Element country = responseDoc.createElement("cs:country");
- Element population = responseDoc.createElement("cs:population");
- country.appendChild(responseDoc.createTextNode(getCountry(result)));
- population.appendChild(responseDoc.createTextNode(String.valueOf(getPopulation(result))));
- cityDetailsRes.appendChild(country);
- cityDetailsRes.appendChild(population);
- body.appendChild(cityDetailsRes);
- envElement.appendChild(body);
- responseDoc.appendChild(envElement);
- return getString(responseDoc);
- }else{
- return getSoapFault("No city data available. Try Bonn, London or new York");
- }
- }
-
- private static String getString(Document responseDoc) throws TransformerException {
- TransformerFactory tfFactory = TransformerFactory.newInstance();
- Transformer tf = tfFactory.newTransformer();
- tf.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
- tf.setOutputProperty(OutputKeys.INDENT, "yes");
- tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
- DOMSource source = new DOMSource(responseDoc);
- StringWriter writer = new StringWriter();
- StreamResult reswr = new StreamResult(writer);
- tf.transform(source, reswr);
- return writer.toString();
- }
-
- private static int getPopulation(String city) {
- return switch (city) {
- case "Bonn" -> 84000000;
- case "London" -> 56000000;
- case "New York" -> 332000000;
- default -> 0;
- };
- }
-
- private static String getCountry(String city) {
- return switch (city) {
- case "Bonn" -> "Germany";
- case "London" -> "England";
- case "New York" -> "USA";
- default -> "Unknown";
- };
- }
-}
\ No newline at end of file
diff --git a/core/src/main/java/com/predic8/membrane/core/interceptor/soap/SampleSoapServiceInterceptor.java b/core/src/main/java/com/predic8/membrane/core/interceptor/soap/SampleSoapServiceInterceptor.java
new file mode 100644
index 000000000..ba9cb0055
--- /dev/null
+++ b/core/src/main/java/com/predic8/membrane/core/interceptor/soap/SampleSoapServiceInterceptor.java
@@ -0,0 +1,151 @@
+package com.predic8.membrane.core.interceptor.soap;
+
+import com.predic8.membrane.annot.*;
+import com.predic8.membrane.core.exchange.*;
+import com.predic8.membrane.core.interceptor.*;
+import org.w3c.dom.*;
+
+import javax.xml.parsers.*;
+import javax.xml.stream.*;
+import javax.xml.transform.*;
+import java.io.*;
+
+import static com.predic8.membrane.core.Constants.*;
+import static com.predic8.membrane.core.http.MimeType.*;
+import static com.predic8.membrane.core.http.Response.*;
+import static com.predic8.membrane.core.interceptor.Outcome.*;
+import static com.predic8.membrane.core.util.XMLUtil.*;
+import static javax.xml.stream.XMLStreamConstants.*;
+
+@MCElement(name = "sampleSoapService")
+public class SampleSoapServiceInterceptor extends AbstractInterceptor {
+
+ public static final String CITY_SERVICE_NS = "https://predic8.de/city-service";
+
+ public SampleSoapServiceInterceptor() {
+ name = "SampleSoapService";
+ }
+
+ @Override
+ public Outcome handleRequest(Exchange exc) throws Exception {
+ try {
+ exc.setResponse(ok(getResponse(getCity(exc))).contentType(APPLICATION_XML).build());
+ } catch (Exception e) {
+ exc.setResponse(ok(getSoapFault("Cannot parse SOAP message")).contentType(APPLICATION_XML).build());
+ }
+ return RETURN;
+ }
+
+ private static String getCity(Exchange exc) throws Exception {
+ return getElementAsString(exc.getRequest().getBodyAsStream(), "city");
+ }
+
+ public static String getSoapFault(String error) {
+ // Multiline String """ ... """
+ // soapenv => s11
+ return "\n" +
+ " \n" +
+ " \n" +
+ " soapenv:Client\n" +
+ " Resource Not Found\n" +
+ " \n" +
+ " 404\n" +
+ " " + error + "\n" +
+ " \n" +
+ " \n" +
+ " \n" +
+ "";
+ }
+
+
+ // Test: Make String => InputStream
+ public static String getElementAsString(InputStream is, String localName) throws Exception {
+ XMLInputFactory factory = XMLInputFactory.newInstance(); // TODO Comment about Threadsafe
+ XMLStreamReader reader = factory.createXMLStreamReader(is);
+
+ while (reader.hasNext()) {
+ if (reader.next() == START_ELEMENT) {
+ if (reader.getName().getLocalPart().equals(localName)) {
+ return reader.getElementText();
+ }
+ }
+ }
+ throw new Exception();
+ }
+
+ public static String getResponse(String city) throws ParserConfigurationException, TransformerException {
+ try {
+ return xml2string(createResponse(city));
+ } catch (Exception e) {
+ return getSoapFault("Do not know %s. Try Bonn, London or new York".formatted(city)); // Todo abgleichen
+ }
+ }
+
+ private static Document createResponse(String city) throws Exception {
+ // DocumentBuilderFactory is not guaranteed to be thread safe
+ // https://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.5/api/javax/xml/parsers/DocumentBuilderFactory.html
+ Document res = createDocumentBuilder().newDocument();
+ res.appendChild(createResponseEnvelope(city, res));
+ return res;
+ }
+
+ private static Element createResponseEnvelope(String city, Document res) throws Exception {
+ Element env = res.createElementNS(SOAP11_NS, "s:Envelope");
+ env.setAttribute("xmlns:s", SOAP11_NS);
+ env.setAttribute("xmlns:cs", CITY_SERVICE_NS);
+ env.appendChild(createBody(city, res));
+ return env;
+ }
+
+ private static Element createBody(String city, Document res) throws Exception {
+ Element body = res.createElement("s:Body");
+ body.appendChild(createCityDetails(city, res));
+ return body;
+ }
+
+ private static Element createCityDetails(String city, Document res) throws Exception {
+ Element details = res.createElement("cs:cityDetails");
+ details.appendChild(createCountry(city, res));
+ details.appendChild(createPopulation(city, res));
+ return details;
+ }
+
+ private static Element createPopulation(String city, Document res) throws Exception {
+ Element pop = res.createElement("cs:population");
+ pop.appendChild(res.createTextNode(String.valueOf(getPopulation(city))));
+ return pop;
+ }
+
+ private static Element createCountry(String city, Document res) {
+ Element country = res.createElement("cs:country");
+ country.appendChild(res.createTextNode(getCountry(city)));
+ return country;
+ }
+
+ private static DocumentBuilder createDocumentBuilder() throws ParserConfigurationException {
+ return DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ }
+
+ // Todo Put cities in Map
+ // record City(Name,Pop,Country)
+ private static int getPopulation(String city) throws Exception {
+ return switch (city) {
+ case "Bonn" -> 300_000;
+ case "Manila" -> 1000;
+ case "Da Nang" -> 1100;
+ case "Bielefeld" -> 1222;
+ case "London" -> 56_000_000;
+ case "New York" -> 332000000;
+ default -> throw new Exception("What city?");
+ };
+ }
+
+ private static String getCountry(String city) {
+ return switch (city) {
+ case "Bonn" -> "Germany";
+ case "London" -> "England";
+ case "New York" -> "USA";
+ default -> "Unknown";
+ };
+ }
+}
\ No newline at end of file
diff --git a/core/src/main/java/com/predic8/membrane/core/interceptor/xml/Xml2JsonInterceptor.java b/core/src/main/java/com/predic8/membrane/core/interceptor/xml/Xml2JsonInterceptor.java
index a9a55e93b..f3af18991 100644
--- a/core/src/main/java/com/predic8/membrane/core/interceptor/xml/Xml2JsonInterceptor.java
+++ b/core/src/main/java/com/predic8/membrane/core/interceptor/xml/Xml2JsonInterceptor.java
@@ -33,6 +33,7 @@
import static com.predic8.membrane.core.interceptor.Outcome.CONTINUE;
import static java.nio.charset.StandardCharsets.UTF_8;
+import static javax.xml.transform.OutputKeys.*;
/**
@@ -92,10 +93,10 @@ public static String documentToString(Document doc) {
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
Transformer transformer = tf.newTransformer();
- transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
- transformer.setOutputProperty(OutputKeys.METHOD, "xml");
- transformer.setOutputProperty(OutputKeys.INDENT, "no");
- transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+ transformer.setOutputProperty(OMIT_XML_DECLARATION, "no");
+ transformer.setOutputProperty(METHOD, "xml");
+ transformer.setOutputProperty(INDENT, "no");
+ transformer.setOutputProperty(ENCODING, "UTF-8");
transformer.transform(new DOMSource(doc), new StreamResult(sw));
return sw.toString();
} catch (Exception ex) {
diff --git a/core/src/main/java/com/predic8/membrane/core/util/SOAPUtil.java b/core/src/main/java/com/predic8/membrane/core/util/SOAPUtil.java
index 20532a532..43599d2c0 100644
--- a/core/src/main/java/com/predic8/membrane/core/util/SOAPUtil.java
+++ b/core/src/main/java/com/predic8/membrane/core/util/SOAPUtil.java
@@ -94,17 +94,12 @@ public static boolean isFault(XMLInputFactory xmlInputFactory, XOPReconstitutor
String expected;
switch (state) {
- case 0:
- expected = "Envelope";
- break;
- case 1:
- expected = "Body";
- break;
- case 2:
- expected = "Fault";
- break;
- default:
- return false;
+ case 0 -> expected = "Envelope";
+ case 1 -> expected = "Body";
+ case 2 -> expected = "Fault";
+ default -> {
+ return false;
+ }
}
if (expected.equals(name.getLocalPart())) {
if (state == 2)
diff --git a/core/src/main/java/com/predic8/membrane/core/util/XMLUtil.java b/core/src/main/java/com/predic8/membrane/core/util/XMLUtil.java
new file mode 100644
index 000000000..0151bcee7
--- /dev/null
+++ b/core/src/main/java/com/predic8/membrane/core/util/XMLUtil.java
@@ -0,0 +1,29 @@
+package com.predic8.membrane.core.util;
+
+import org.w3c.dom.*;
+
+import javax.xml.transform.*;
+import javax.xml.transform.dom.*;
+import javax.xml.transform.stream.*;
+import java.io.*;
+
+import static javax.xml.transform.OutputKeys.INDENT;
+import static javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION;
+
+public class XMLUtil {
+
+ // TODO 2. param boolean indent
+ // Write Test
+ public static String xml2string(Document doc) throws TransformerException {
+ TransformerFactory tfFactory = TransformerFactory.newInstance(); // Comment ThreadSafe? with URL
+ Transformer tf = tfFactory.newTransformer();
+ tf.setOutputProperty(OMIT_XML_DECLARATION, "yes");
+
+ tf.setOutputProperty(INDENT, "yes");
+ tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
+
+ StringWriter writer = new StringWriter();
+ tf.transform(new DOMSource(doc), new StreamResult(writer));
+ return writer.toString();
+ }
+}
diff --git a/core/src/test/java/com/predic8/membrane/core/interceptor/soap/SampleSoapInterceptorTest.java b/core/src/test/java/com/predic8/membrane/core/interceptor/soap/SampleSoapInterceptorTest.java
index a85c22429..7a12e4341 100644
--- a/core/src/test/java/com/predic8/membrane/core/interceptor/soap/SampleSoapInterceptorTest.java
+++ b/core/src/test/java/com/predic8/membrane/core/interceptor/soap/SampleSoapInterceptorTest.java
@@ -7,9 +7,7 @@
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.w3c.dom.Document;
-import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import javax.xml.namespace.NamespaceContext;
@@ -29,11 +27,11 @@
public class SampleSoapInterceptorTest {
- private static SampleSoapService service;
+ private static SampleSoapServiceInterceptor service;
private static Exchange exc = new Exchange(null);
@BeforeAll
public static void setUp() throws IOException {
- service = new SampleSoapService();
+ service = new SampleSoapServiceInterceptor();
}
@Test
@@ -41,7 +39,7 @@ public void notFoundTest() throws Exception {
exc.setRequest(new Request.Builder().contentType(MimeType.TEXT_XML)
.body(IOUtils.toByteArray(Objects.requireNonNull(this.getClass().getResourceAsStream("/soap-sample/wrongRequest.xml")))).build());
service.handleRequest(exc);
- assertEquals(SampleSoapService.getSoapFault("city element not found"), exc.getResponse().getBody().toString());
+ assertEquals(SampleSoapServiceInterceptor.getSoapFault("city element not found"), exc.getResponse().getBody().toString());
// System.out.println(exc.getResponse().getBody().toString());
}