get rid of ObjectFactory.java

This commit is contained in:
Andreas Penski (init) 2020-04-29 16:57:15 +02:00
parent 5b1d0cd467
commit d0000fc698
20 changed files with 494 additions and 445 deletions

View file

@ -0,0 +1,34 @@
package de.kosit.validationtool.daemon;
import java.io.IOException;
import java.io.OutputStream;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
/**
* Simple base implemenation for http handlers. Doing I/O stuff.
*
* @author Andreas Penski
*/
public abstract class BaseHandler implements HttpHandler {
protected static final String APPLICATION_XML = "application/xml";
protected static void write(final HttpExchange exchange, final byte[] content, final String contentType) throws IOException {
final OutputStream os = exchange.getResponseBody();
exchange.getResponseHeaders().add("Content-Type", contentType);
exchange.sendResponseHeaders(200, content.length);
os.write(content);
os.close();
}
protected static void error(final HttpExchange httpExchange, final int statusCode, final String message) throws IOException {
final byte[] bytes = message.getBytes();
httpExchange.sendResponseHeaders(statusCode, bytes.length);
final OutputStream os = httpExchange.getResponseBody();
os.write(bytes);
os.close();
}
}

View file

@ -1,32 +1,37 @@
package de.kosit.validationtool.daemon;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.atomic.AtomicLong;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import de.kosit.validationtool.api.Check;
import de.kosit.validationtool.api.InputFactory;
import de.kosit.validationtool.api.Result;
import de.kosit.validationtool.impl.input.SourceInput;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.Serializer;
/**
* Wir benötigen einen Handler, der zur Verarbeitung von HTTP-Anforderungen aufgerufen wird um hier die Verarbeitung des
* POST Request zu realisieren.
*/
@Slf4j
class HttpServerHandler implements HttpHandler {
@RequiredArgsConstructor
class CheckHandler extends BaseHandler {
private static final AtomicLong counter = new AtomicLong(0);
private final Check implemenation;
HttpServerHandler(final Check check) {
this.implemenation = check;
}
private final Processor processor;
/**
* Methode, die eine gegebene Anforderung verarbeitet und eine entsprechende Antwort generiert
@ -41,20 +46,31 @@ class HttpServerHandler implements HttpHandler {
final String requestMethod = httpExchange.getRequestMethod();
if (requestMethod.equals("POST")) {
final InputStream inputStream = httpExchange.getRequestBody();
if (inputStream.available() > 0) {
final SourceInput serverInput = (SourceInput) InputFactory.read(inputStream, "Prüfling" + counter.incrementAndGet());
Daemon.writeOutputstreamArray(httpExchange, this.implemenation.check(serverInput));
final SourceInput serverInput = (SourceInput) InputFactory.read(inputStream,
"supplied_instance_" + counter.incrementAndGet());
final Result result = this.implemenation.checkInput(serverInput);
write(httpExchange, serialize(result), APPLICATION_XML);
} else {
Daemon.writeError(httpExchange, 400, "XML-Inhalt erforderlich!");
error(httpExchange, 400, "No content supplied");
}
} else {
Daemon.writeError(httpExchange, 405, "Es ist nur die POST-Methode erlaubt!");
error(httpExchange, 405, "Method not supported");
}
} catch (final Exception e) {
Daemon.writeError(httpExchange, 500, "Interner Fehler bei der Verarbeitung des Requests: " + e.getMessage());
log.error("Es ist ein Fehler aufgetreten. Das Dokument kann nicht geprüft werden", e);
error(httpExchange, 500, "Internal error: " + e.getMessage());
}
}
private byte[] serialize(final Result result) {
try ( final ByteArrayOutputStream out = new ByteArrayOutputStream() ) {
final Serializer serializer = this.processor.newSerializer(out);
serializer.serializeNode(result.getReport());
return out.toByteArray();
} catch (final SaxonApiException | IOException e) {
log.error("Error serializing result", e);
throw new IllegalStateException("Can not serialize result", e);
}
}

View file

@ -0,0 +1,77 @@
package de.kosit.validationtool.daemon;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.net.URI;
import java.util.Optional;
import org.apache.commons.io.IOUtils;
import com.sun.net.httpserver.HttpExchange;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import de.kosit.validationtool.api.Configuration;
import de.kosit.validationtool.config.Keys;
import de.kosit.validationtool.impl.ConversionService;
import de.kosit.validationtool.model.scenarios.Scenarios;
/**
* Handler that returns the actual configuration used for this daemon instance.
*
* @author Andreas Penski
*/
@Slf4j
@RequiredArgsConstructor
public class ConfigHandler extends BaseHandler {
private final Configuration configuration;
private final ConversionService conversionService;
@Override
public void handle(final HttpExchange exchange) throws IOException {
try {
final Optional<String> xml = getSource();
if (xml.isPresent()) {
write(exchange, xml.get().getBytes(), APPLICATION_XML);
} else {
error(exchange, 404, "No configuration found");
}
} catch (final Exception e) {
log.error("Error grabbing configuration", e);
error(exchange, 500, "Error grabbing configuration: " + e.getMessage());
}
}
private Optional<String> getSource() {
final URI fileUri = (URI) this.configuration.getAdditionalParameters().get(Keys.SCENARIOS_FILE);
return fileUri != null ? loadFile(fileUri) : loadFromConfig();
}
private static Optional<String> loadFile(final URI fileUri) {
try ( final Reader in = new InputStreamReader(fileUri.toURL().openStream());
final StringWriter out = new StringWriter() ) {
IOUtils.copy(in, out);
return Optional.of(out.toString());
} catch (final IOException e) {
return Optional.empty();
}
}
private Optional<String> loadFromConfig() {
final Optional<String> result;
final Scenarios scenarios = (Scenarios) this.configuration.getAdditionalParameters().get(Keys.SCENARIO_DEFINITION);
if (scenarios != null) {
final String s = this.conversionService.writeXml(scenarios);
result = Optional.of(s);
} else {
result = Optional.empty();
}
return result;
}
}

View file

@ -1,19 +1,9 @@
package de.kosit.validationtool.daemon;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpServer;
import lombok.Getter;
@ -22,8 +12,9 @@ import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import de.kosit.validationtool.api.Configuration;
import de.kosit.validationtool.impl.ConversionService;
import de.kosit.validationtool.impl.DefaultCheck;
import de.kosit.validationtool.impl.ObjectFactory;
import de.kosit.validationtool.model.daemon.HealthType;
/**
* HTTP-Daemon für die Bereitstellung der Prüf-Funktionalität via http.
@ -42,56 +33,6 @@ public class Daemon {
private final int threadCount;
/**
* Methode, die die Antwort als String-Text schreibt
*
* @param httpExchange um den Antwort Body zu erhalten
* @param rCode der Code-Status
* @param response die String antwort, die ich anzeigen möchte
*/
static void writeError(final HttpExchange httpExchange, final int rCode, final String response) throws IOException {
httpExchange.sendResponseHeaders(rCode, response.length());
final OutputStream os = httpExchange.getResponseBody();
os.write(response.getBytes());
os.close();
}
/**
* Methode, die die Antwort als String-Text schreibt
*
* @param httpExchange um den Antwort Body zu erhalten
* @param doc der Report
*/
static void writeOutputstreamArray(final HttpExchange httpExchange, final Document doc)
throws IOException, TransformerException {
final byte[] bytes = serialize(doc);
final OutputStream os = httpExchange.getResponseBody();
httpExchange.getResponseHeaders().add("Content-Type", "application/xml");
httpExchange.sendResponseHeaders(200, bytes.length);
os.write(bytes);
os.close();
log.debug("Xml File erzeugen ist Fertig ");
}
/**
* Methode zum Serialisieren des Dokuments.
*
* @param report Vom Typ Dokument, aka Report .
*/
static byte[] serialize(final Document report) throws TransformerException {
try ( final ByteArrayOutputStream bArrayOS = new ByteArrayOutputStream() ) {
final DOMSource source = new DOMSource(report);
final StreamResult streamResult = new StreamResult(bArrayOS);
final Transformer transformer = ObjectFactory.createTransformer(true);
transformer.transform(source, streamResult);
return bArrayOS.toByteArray();
} catch (final IOException e) {
log.error("Report {}", e.getMessage(), e);
throw new IllegalStateException(e);
}
}
/**
* Methode zum Starten des Servers
*
@ -100,10 +41,14 @@ public class Daemon {
public void startServer(final Configuration config) {
HttpServer server = null;
try {
final ConversionService converter = new ConversionService();
converter.initialize(HealthType.class.getPackage());
server = HttpServer.create(new InetSocketAddress(this.hostName, this.port), 0);
final DefaultCheck check = new DefaultCheck(config);
server.createContext("/", new HttpServerHandler(check));
server.createContext("/health", new HealthHandler(config));
server.createContext("/", new CheckHandler(check, config.getContentRepository().getProcessor()));
server.createContext("/server/health", new HealthHandler(config, converter));
server.createContext("/server/config", new ConfigHandler(config, new ConversionService()));
server.setExecutor(Executors.newFixedThreadPool(this.threadCount));
server.start();
log.info("Server unter Port {} ist erfolgreich gestartet", this.port);

View file

@ -2,140 +2,50 @@ package de.kosit.validationtool.daemon;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.TransformerException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import de.kosit.validationtool.api.Configuration;
import de.kosit.validationtool.impl.ObjectFactory;
import de.kosit.validationtool.impl.ConversionService;
import de.kosit.validationtool.model.daemon.HealthType;
import de.kosit.validationtool.model.daemon.MemoryType;
/**
* Wir benötigen einen Handler, der zur Verarbeitung von HTTP-Anforderungen aufgerufen wird , und hier für Verarbeitung
* das GET Request um Health-Endpunkt zu erstellen. Die Klasse HealthHandler implementiert diese Schnittstelle
* Handler that implements a simple health check. Useful for monitoring the service.
*
* @author Andreas Penski`
*/
@Slf4j
class HealthHandler implements HttpHandler {
@RequiredArgsConstructor
class HealthHandler extends BaseHandler {
/**
* Klasse zur Erzeugung Health Xml , die optiamle Status.
*
* @author Roula Antoun
*/
@Slf4j
static class Health {
private final long freeMemory;
private final long maxMemory;
private final long totalMemory;
private final Configuration config;
Health(final Configuration config) {
final Runtime runtime = Runtime.getRuntime();
this.freeMemory = runtime.freeMemory();
this.maxMemory = runtime.maxMemory();
this.totalMemory = runtime.totalMemory();
this.config = config;
}
/**
* Methode, die schreibt das Health Xml für optimale Status
*
*/
Document writeHealthXml() {
final DocumentBuilder dBuilder = ObjectFactory.createDocumentBuilder(false);
final Document doc = dBuilder.newDocument();
final Element rootElement = doc.createElementNS("https://localhost:8080/Health", "Health");
doc.appendChild(rootElement);
rootElement.appendChild(getMemory(doc, this.freeMemory, this.maxMemory, this.totalMemory));
rootElement.appendChild(getState(doc));
rootElement.appendChild(getScenario(doc, this.config));
return doc;
}
/**
* Methode, die schreibt das System Status Node im Xml File
*
* @param doc Vom Typ Dokument.
*
*/
private static Node getState(final Document doc) {
final Element state = doc.createElement("state");
state.setAttribute("indicator", "OK");
final Element stateNode = doc.createElement("message");
stateNode.appendChild(doc.createTextNode("System is up and running normally"));
state.appendChild(stateNode);
return state;
}
/**
* Methode, die schreibt das Scnarios Information Node im Xml File
*
* @param doc Vom Typ Dokument .
* @param config Vom Typ {@link Configuration} das verwendete scenario.
*
*/
private static Node getScenario(final Document doc, final Configuration config) {
final Element scenario = doc.createElement("scenario");
final Element scenarioNameNode = doc.createElement("name");
scenarioNameNode.appendChild(doc.createTextNode(config.getName()));
scenario.appendChild(scenarioNameNode);
return scenario;
}
/**
* Methode, die schreibt das Scnarios Information Node im Xml File
*
* @param doc Vom Typ Dokument .
* @param freeMemory Vom Typ long , der freier Speicher.
* @param maxMemory Vom Typ long , der maximaler Speicher
* @param totalMemory Vom Typ long , der Gesamte speicher.
*
*/
private static Node getMemory(final Document doc, final long freeMemory, final long maxMemory, final long totalMemory) {
final Element memory = doc.createElement("memoryState");
final String freeM = Long.toString(freeMemory);
final Element freeMNode = doc.createElement("freeMemory");
freeMNode.appendChild(doc.createTextNode(freeM));
memory.appendChild(freeMNode);
final String maxM = Long.toString(maxMemory);
final Element maxMNode = doc.createElement("maxMemory");
maxMNode.appendChild(doc.createTextNode(maxM));
memory.appendChild(maxMNode);
final String totalM = Long.toString(totalMemory);
final Element totalMNode = doc.createElement("totalMemory");
totalMNode.appendChild(doc.createTextNode(totalM));
memory.appendChild(totalMNode);
return memory;
}
}
private final Configuration scenarios;
HealthHandler(final Configuration config) {
this.scenarios = config;
}
private final ConversionService conversionService;
@Override
public void handle(final HttpExchange httpExchange) throws IOException {
final Health health = new Health(this.scenarios);
final Document doc = health.writeHealthXml();
try {
Daemon.writeOutputstreamArray(httpExchange, doc);
} catch (final TransformerException e) {
Daemon.writeError(httpExchange, 500, e.getMessage());
log.error("Fehler beim Erzeugen der Status-Information", e);
}
final HealthType health = createHealth();
final String xml = this.conversionService.writeXml(health);
write(httpExchange, xml.getBytes(), APPLICATION_XML);
}
private static HealthType createHealth() {
final HealthType h = new HealthType();
h.setMemory(createMemory());
return h;
}
private static MemoryType createMemory() {
final MemoryType m = new MemoryType();
final Runtime runtime = Runtime.getRuntime();
m.setFreeMemory(runtime.freeMemory());
m.setMaxMemory(runtime.maxMemory());
m.setTotalMemory(runtime.totalMemory());
return m;
}
}