Skip to content

Commit

Permalink
Refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
predic8 committed Aug 30, 2023
1 parent 63b9ec2 commit 1fea4f1
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 159 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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 "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
" <soapenv:Body>\n" +
" <soapenv:Fault>\n" +
" <faultcode>soapenv:Client</faultcode>\n" +
" <faultstring>Resource Not Found</faultstring>\n" +
" <detail>\n" +
" <errorcode>404</errorcode>\n" +
" <errormessage>" + error + "</errormessage>\n" +
" </detail>\n" +
" </soapenv:Fault>\n" +
" </soapenv:Body>\n" +
"</soapenv:Envelope>";
}


// 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<String,City>
// 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";
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.*;


/**
Expand Down Expand Up @@ -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) {
Expand Down
17 changes: 6 additions & 11 deletions core/src/main/java/com/predic8/membrane/core/util/SOAPUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
29 changes: 29 additions & 0 deletions core/src/main/java/com/predic8/membrane/core/util/XMLUtil.java
Original file line number Diff line number Diff line change
@@ -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();
}
}
Loading

0 comments on commit 1fea4f1

Please sign in to comment.