diff --git a/Backend-libXML/main.py b/Backend-libXML/main.py index abb78f9..88550a8 100644 --- a/Backend-libXML/main.py +++ b/Backend-libXML/main.py @@ -29,13 +29,13 @@ def process_xml(request: request, type: str) -> str: try: request_data = json.loads(request.get_data(as_text=True)) data = request_data['data'] - process = request_data['process'] + processorData = request_data['processorData'] if (type == "xsd"): - response_json['result'] = Parser.xsd(data, process) + response_json['result'] = Parser.xsd(data, processorData) elif (type == "xslt"): - response_json['result'] = Parser.xslt(data, process) + response_json['result'] = Parser.xslt(data, processorData) elif (type == "xpath"): - response_json['result'], response_json['type'] = Parser.xpath(data, process) + response_json['result'], response_json['type'] = Parser.xpath(data, processorData) elif (type == "prettify"): response_json['result'] = Parser.formatXML(data, True) elif (type == "minimize"): @@ -45,7 +45,7 @@ def process_xml(request: request, type: str) -> str: elif (type == "minimizeHtml"): response_json['result'] = Parser.formatHTML(data, False) elif (type == "convertHTML"): - response_json['result'] = Parser.convertHTML(data, process) + response_json['result'] = Parser.convertHTML(data, processorData) else: raise ValueError("Valid operation types are: xsd, xslt, xpath") diff --git a/Backend/mocked-services/src/main/resources/application.properties b/Backend/mocked-services/src/main/resources/application.properties index cc5394a..c2a44a8 100644 --- a/Backend/mocked-services/src/main/resources/application.properties +++ b/Backend/mocked-services/src/main/resources/application.properties @@ -11,6 +11,6 @@ spring.redis.host=redis spring.redis.port=6379 #retention -retention.minutes-to-delete-message=120 +retention.minutes-to-delete-message=1440 retention.minutes-to-delete-history-record=1440 retention.retention-cooldown=1440 diff --git a/Backend/tools-services/src/main/java/com/r11/tools/SparkApplication.java b/Backend/tools-services/src/main/java/com/r11/tools/SparkApplication.java index 4908e9b..ce40a6b 100644 --- a/Backend/tools-services/src/main/java/com/r11/tools/SparkApplication.java +++ b/Backend/tools-services/src/main/java/com/r11/tools/SparkApplication.java @@ -40,11 +40,10 @@ public class SparkApplication { RestControllerRegistry registry = new RestControllerRegistry(); registry.registerController(new ProcessorInfoController(logger, saxon, xalan)); - registry.registerController(new XsdController(gson, logger, xalan)); - registry.registerController(new XPathController(gson, logger, saxon, xalan)); - registry.registerController(new XsltController(gson, logger, saxon, xalan)); + + registry.registerController(new XmlController(gson, logger, saxon, xalan)); + registry.registerController(new MultipleXMLController(gson,logger, saxon)); registry.registerController(new JsonController(gson, jsongson, logger)); - registry.registerController(new XQueryController(gson, logger, saxon)); registry.register(); diff --git a/Backend/tools-services/src/main/java/com/r11/tools/controller/JsonController.java b/Backend/tools-services/src/main/java/com/r11/tools/controller/JsonController.java index e42f277..5d72a74 100644 --- a/Backend/tools-services/src/main/java/com/r11/tools/controller/JsonController.java +++ b/Backend/tools-services/src/main/java/com/r11/tools/controller/JsonController.java @@ -36,7 +36,7 @@ public class JsonController implements RestController { try { Object requestJson = this.gson.fromJson(request.body(), Object.class); - responseJson.addProperty("data", this.prettyGson.toJson(requestJson)); + responseJson.addProperty("result", this.prettyGson.toJson(requestJson)); responseJson.addProperty("time", System.currentTimeMillis() - startProcess); @@ -46,7 +46,7 @@ public class JsonController implements RestController { response.status(400); - responseJson.addProperty("data", cause == null ? e.getMessage() : cause.getMessage()); + responseJson.addProperty("result", cause == null ? e.getMessage() : cause.getMessage()); responseJson.addProperty("time", System.currentTimeMillis() - startProcess); @@ -65,17 +65,17 @@ public class JsonController implements RestController { response.status(200); - responseJson.addProperty("data", this.gson.toJson(requestJson)); + responseJson.addProperty("result", this.gson.toJson(requestJson)); responseJson.addProperty("time", System.currentTimeMillis() - startProcess); response.body(this.gson.toJson(responseJson)); } catch (Exception e) { - this.logger.error("Error on minimizeing Json " + e); + this.logger.error("Error on minimizing Json " + e); Throwable cause = e.getCause(); response.status(400); - responseJson.addProperty("data", cause == null ? e.getMessage() : cause.getMessage()); + responseJson.addProperty("result", cause == null ? e.getMessage() : cause.getMessage()); responseJson.addProperty("time", System.currentTimeMillis() - startProcess); response.body(this.prettyGson.toJson(responseJson)); diff --git a/Backend/tools-services/src/main/java/com/r11/tools/controller/MultipleXMLController.java b/Backend/tools-services/src/main/java/com/r11/tools/controller/MultipleXMLController.java new file mode 100644 index 0000000..b6c24bb --- /dev/null +++ b/Backend/tools-services/src/main/java/com/r11/tools/controller/MultipleXMLController.java @@ -0,0 +1,96 @@ +package com.r11.tools.controller; + +import com.google.gson.Gson; +import com.r11.tools.controller.internal.*; +import com.r11.tools.model.XMLMultipleFilesBody; +import com.r11.tools.model.XMLResponseBody; +import com.r11.tools.xml.XmlEngine; +import org.apache.logging.log4j.Logger; +import spark.Request; +import spark.Response; + +@GlobalControllerManifest +public class MultipleXMLController implements RestController { + + private final Gson gson; + private final Logger logger; + + private final XmlEngine engine; + + public MultipleXMLController(Gson gson, Logger logger, XmlEngine engine) { + this.gson = gson; + this.logger = logger; + this.engine = engine; + } + + @ScopedControllerManifest(method = HandlerType.POST, path = "/multiple/xslt") + public void acceptRequestXslt(Request request, Response response) { + acceptRequest(request, response, XmlJobType.XSLT); + } + + private void acceptRequest(Request request, Response response, XmlJobType xmlJobType) { + XMLMultipleFilesBody requestBody; + try { + requestBody = this.gson.fromJson(request.body(), XMLMultipleFilesBody.class); + } catch (Exception e) { + requestErrorResponse(response, e); + return; + } + processRequest(new MultipleXmlJob(response, requestBody, engine, xmlJobType)); + } + + private void processRequest(MultipleXmlJob xmlJob) { + XMLResponseBody responseBody = null; + long timeStart = System.currentTimeMillis(); + long duration; + + try { + responseBody = processData(xmlJob); + + duration = System.currentTimeMillis() - timeStart; + responseBody.setDuration(duration); + + xmlJob.getResponse().status(200); + + this.logger.info("Request (" + xmlJob.getXmlJobType() + ", " + + xmlJob.getEngine().getVersion() + + ") processed in " + duration + " ms."); + + } catch (Exception ex) { + responseBody = processingErrorResponse(ex, xmlJob); + + } finally { + xmlJob.getResponse().body(this.gson.toJson(responseBody)); + } + + } + + private XMLResponseBody processData(MultipleXmlJob xmlJob) throws Exception { + XmlEngine engine = xmlJob.getEngine(); + XMLMultipleFilesBody requestBody = xmlJob.getRequestBody(); + String result = engine.processXSLT(requestBody.getData(), requestBody.getProcessorData()); + return new XMLResponseBody(result, "OK", requestBody.getVersion()); + } + + + private XMLResponseBody processingErrorResponse(Exception ex, MultipleXmlJob xmlJob) { + XmlEngine engine = xmlJob.getEngine(); + XmlJobType xmlJobType = xmlJob.getXmlJobType(); + Response response = xmlJob.getResponse(); + + XMLResponseBody responseBody = + new XMLResponseBody(ex.getMessage(), "ERR", engine.getVersion(), -1); + + response.status(400); + this.logger.error("Error on processing " + xmlJobType + " using " + engine.getVersion() + ". " + ex); + + return responseBody; + } + + private void requestErrorResponse(Response response, Exception ex) { + XMLResponseBody responseBody = new XMLResponseBody(ex.getMessage(), "ERR", "N/A", -1); + response.status(400); + response.body(this.gson.toJson(responseBody)); + } + +} diff --git a/Backend/tools-services/src/main/java/com/r11/tools/controller/XPathController.java b/Backend/tools-services/src/main/java/com/r11/tools/controller/XPathController.java deleted file mode 100644 index dbf3840..0000000 --- a/Backend/tools-services/src/main/java/com/r11/tools/controller/XPathController.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.r11.tools.controller; - -import com.google.gson.Gson; -import com.r11.tools.controller.internal.*; -import com.r11.tools.model.XMLRequestBody; -import com.r11.tools.model.XMLResponseBody; -import com.r11.tools.model.XPathQueryResult; -import com.r11.tools.xml.XmlEngine; -import org.apache.logging.log4j.Logger; -import spark.Request; -import spark.Response; - -@GlobalControllerManifest -public class XPathController implements RestController { - - private final Gson gson; - private final Logger logger; - - private final XmlEngine saxon; - private final XmlEngine xalan; - - public XPathController(Gson gson, Logger logger, XmlEngine saxon, XmlEngine xalan) { - this.gson = gson; - this.logger = logger; - this.saxon = saxon; - this.xalan = xalan; - } - - private XMLResponseBody errorResponse(String message, String processor) { - return new XMLResponseBody(message, "ERR", processor, -1); - } - - private void nonValidEngineSelectedResponse(Response response) { - XMLResponseBody responseBody = - errorResponse("Valid engines are: saxon, xalan", "N/A"); - response.body(this.gson.toJson(responseBody)); - response.status(400); - } - - @ScopedControllerManifest(method = HandlerType.POST, path = "/xpath") - public void acceptRequest(Request request, Response response) { - XMLRequestBody requestBody; - try { - requestBody = this.gson.fromJson(request.body(), XMLRequestBody.class); - } catch (Exception e) { - XMLResponseBody responseBody = errorResponse(e.getMessage(), "N/A"); - response.status(400); - response.body(this.gson.toJson(responseBody)); - return; - } - - if (requestBody.getProcessor() == null) { - nonValidEngineSelectedResponse(response); - return; - } - - switch (requestBody.getProcessor()) { - case "saxon": - process(response, requestBody, saxon); - break; - case "xalan": - process(response, requestBody, xalan); - break; - default: - nonValidEngineSelectedResponse(response); - } - } - - private void process(Response response, XMLRequestBody requestBody, XmlEngine engine) { - long timeStart = System.currentTimeMillis(); - XMLResponseBody responseBody = null; - try { - XPathQueryResult xPathQueryResult = - engine.processXPath(requestBody.getData(), requestBody.getProcess(), requestBody.getVersion()); - - response.status(200); - long duration = System.currentTimeMillis() - timeStart; - responseBody = new XMLResponseBody(xPathQueryResult.getData().trim(), - "OK", engine.getVersion(),duration); - - responseBody.setType(xPathQueryResult.getType()); - this.logger.info("Request (XPath, " + engine.getVersion() + ") processed in " + duration + " ms."); - } catch (Exception ex) { - responseBody = errorResponse(ex.getMessage(), engine.getVersion()); - response.status(400); - - this.logger.error("Error on processing XPath using " + engine.getVersion() + ". " + ex); - } finally { - response.body(this.gson.toJson(responseBody)); - } - - } - -} diff --git a/Backend/tools-services/src/main/java/com/r11/tools/controller/XQueryController.java b/Backend/tools-services/src/main/java/com/r11/tools/controller/XQueryController.java deleted file mode 100644 index 59bec6a..0000000 --- a/Backend/tools-services/src/main/java/com/r11/tools/controller/XQueryController.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.r11.tools.controller; - -import com.google.gson.Gson; -import com.r11.tools.controller.internal.*; -import com.r11.tools.model.XMLRequestBody; -import com.r11.tools.model.XMLResponseBody; -import com.r11.tools.xml.XmlEngine; -import org.apache.logging.log4j.Logger; -import spark.Request; -import spark.Response; - -/** - * Controller used to handle XQuery tool. Currently, it supports Saxon engine - * @author Adam Bem - */ -@GlobalControllerManifest -public class XQueryController implements RestController { - - private final Gson gson; - private final Logger logger; - private final XmlEngine saxon; - - public XQueryController(Gson gson, Logger logger, XmlEngine saxon) { - this.gson = gson; - this.logger = logger; - this.saxon = saxon; - } - - private XMLResponseBody prepareErrorResponse(String message, String processor) { - return new XMLResponseBody(message, "ERR", processor, -1); - } - - private void nonValidEngineSelectedResponse(Response response) { - XMLResponseBody responseBody = - prepareErrorResponse("Valid engines are: saxon", "N/A"); - response.body(this.gson.toJson(responseBody)); - response.status(400); - } - - @ScopedControllerManifest(method = HandlerType.POST, path = "/xquery") - public void acceptRequest(Request request, Response response) { - XMLRequestBody requestBody; - try { - requestBody = this.gson.fromJson(request.body(), XMLRequestBody.class); - } catch (Exception e) { - XMLResponseBody responseBody = prepareErrorResponse(e.getMessage(), "N/A"); - - response.status(400); - response.body(this.gson.toJson(responseBody)); - return; - } - if (requestBody.getProcessor() == null) { - nonValidEngineSelectedResponse(response); - return; - } - - if (requestBody.getProcessor().equalsIgnoreCase("saxon")) - process(response, requestBody, saxon); - else - nonValidEngineSelectedResponse(response); - } - - private void process(Response response, XMLRequestBody requestBody, XmlEngine engine) { - XMLResponseBody responseBody = null; - long timeStart = System.currentTimeMillis(); - try { - String result = engine.executeXQuery(requestBody.getData(), requestBody.getProcess(), requestBody.getVersion()); - - response.status(200); - - long duration = System.currentTimeMillis() - timeStart; - responseBody = new XMLResponseBody(result, "OK", engine.getVersion(), duration); - - this.logger.info("Request (XQuery, " + engine.getVersion() + ") processed in " + duration + " ms."); - } catch (Exception ex) { - response.status(400); - responseBody = prepareErrorResponse(ex.getMessage(), engine.getVersion()); - - this.logger.error("Error on processing XQuery using " + engine.getVersion() + ". " + ex); - } - finally { - response.body(this.gson.toJson(responseBody)); - } - - } - -} diff --git a/Backend/tools-services/src/main/java/com/r11/tools/controller/XmlController.java b/Backend/tools-services/src/main/java/com/r11/tools/controller/XmlController.java new file mode 100644 index 0000000..7759a62 --- /dev/null +++ b/Backend/tools-services/src/main/java/com/r11/tools/controller/XmlController.java @@ -0,0 +1,173 @@ +package com.r11.tools.controller; + +import com.google.gson.Gson; +import com.r11.tools.controller.internal.*; +import com.r11.tools.model.XMLRequestBody; +import com.r11.tools.model.XMLResponseBody; +import com.r11.tools.model.XPathQueryResult; +import com.r11.tools.xml.XmlEngine; +import org.apache.logging.log4j.Logger; +import spark.Request; +import spark.Response; + +/** + * Controller used to handle XML tools: XPath, XSD validation, XQuery and XSLT + * @author Adam Bem + */ +@GlobalControllerManifest +public class XmlController implements RestController { + + private final Gson gson; + private final Logger logger; + + private final XmlEngine saxon; + private final XmlEngine xalan; + + public XmlController(Gson gson, Logger logger, XmlEngine saxon, XmlEngine xalan) { + this.gson = gson; + this.logger = logger; + this.saxon = saxon; + this.xalan = xalan; + } + + @ScopedControllerManifest(method = HandlerType.POST, path = "/xpath") + public void acceptRequestXPath(Request request, Response response) { + acceptRequest(request, response, XmlJobType.XPath); + } + + @ScopedControllerManifest(method = HandlerType.POST, path = "/xquery") + public void acceptRequestXQuery(Request request, Response response) { + acceptRequest(request, response, XmlJobType.XQuery); + } + + @ScopedControllerManifest(method = HandlerType.POST, path = "/xsd") + public void acceptRequestXsd(Request request, Response response) { + acceptRequest(request, response, XmlJobType.XSD); + + } + + @ScopedControllerManifest(method = HandlerType.POST, path = "/xslt") + public void acceptRequestXslt(Request request, Response response) { + acceptRequest(request, response, XmlJobType.XSLT); + } + + private void acceptRequest(Request request, Response response, XmlJobType xmlJobType) { + XMLRequestBody requestBody; + try { + requestBody = this.gson.fromJson(request.body(), XMLRequestBody.class); + } catch (Exception e) { + requestErrorResponse(response, e); + return; + } + + if (requestBody.getProcessor() == null) { + invalidEngineSelectedResponse(response); + return; + } + + switch (requestBody.getProcessor().toLowerCase()) { + case "saxon": + processRequest(new XmlJob(response, requestBody, saxon, xmlJobType)); + return; + + case "xalan": + processRequest(new XmlJob(response, requestBody, xalan, xmlJobType)); + return; + + default: + invalidEngineSelectedResponse(response); + } + } + + private void processRequest(XmlJob xmlJob) { + XMLResponseBody responseBody = null; + long timeStart = System.currentTimeMillis(); + long duration; + + try { + responseBody = processData(xmlJob); + + duration = System.currentTimeMillis() - timeStart; + responseBody.setDuration(duration); + + xmlJob.getResponse().status(200); + + this.logger.info("Request (" + xmlJob.getXmlJobType() + ", " + + xmlJob.getEngine().getVersion() + + ") processed in " + duration + " ms."); + + } catch (Exception ex) { + responseBody = processingErrorResponse(ex, xmlJob); + + } finally { + xmlJob.getResponse().body(this.gson.toJson(responseBody)); + } + + } + + private XMLResponseBody processData(XmlJob xmlJob) throws Exception { + if (xmlJob.getXmlJobType() == XmlJobType.XPath) + return processXPath(xmlJob); + else + return processOther(xmlJob); + } + + private XMLResponseBody processXPath(XmlJob xmlJob) throws Exception { + XmlEngine engine = xmlJob.getEngine(); + XMLRequestBody requestBody = xmlJob.getRequestBody(); + + XPathQueryResult xPathQueryResult = + engine.processXPath(requestBody.getData(), requestBody.getProcessorData(), requestBody.getVersion()); + + return new XMLResponseBody(xPathQueryResult.getData().trim(), + "OK", engine.getVersion(), xPathQueryResult.getType()); + } + + private XMLResponseBody processOther(XmlJob xmlJob) throws Exception { + XmlEngine engine = xmlJob.getEngine(); + XMLRequestBody requestBody = xmlJob.getRequestBody(); + + String result = null; + switch (xmlJob.getXmlJobType()) { + case XSLT: + result = engine.processXSLT(requestBody.getData(), requestBody.getProcessorData()); + break; + case XSD: + result = engine.validate(requestBody.getData(), requestBody.getProcessorData()).trim(); + break; + case XQuery: + result = engine.executeXQuery(requestBody.getData(), + requestBody.getProcessorData(), + requestBody.getVersion()); + break; + } + return new XMLResponseBody(result, "OK", requestBody.getVersion()); + } + + private XMLResponseBody processingErrorResponse(Exception ex, XmlJob xmlJob) { + XmlEngine engine = xmlJob.getEngine(); + XmlJobType xmlJobType = xmlJob.getXmlJobType(); + Response response = xmlJob.getResponse(); + + XMLResponseBody responseBody = + new XMLResponseBody(ex.getMessage(), "ERR", engine.getVersion(), -1); + + response.status(400); + this.logger.error("Error on processing " + xmlJobType + " using " + engine.getVersion() + ". " + ex); + + return responseBody; + } + + private void invalidEngineSelectedResponse(Response response) { + XMLResponseBody responseBody = + new XMLResponseBody("Valid engines are: saxon, xalan", "ERR", "N/A", -1); + response.body(this.gson.toJson(responseBody)); + response.status(400); + } + + private void requestErrorResponse(Response response, Exception ex) { + XMLResponseBody responseBody = new XMLResponseBody(ex.getMessage(), "ERR", "N/A", -1); + response.status(400); + response.body(this.gson.toJson(responseBody)); + } +} diff --git a/Backend/tools-services/src/main/java/com/r11/tools/controller/XsdController.java b/Backend/tools-services/src/main/java/com/r11/tools/controller/XsdController.java deleted file mode 100644 index 294c6dc..0000000 --- a/Backend/tools-services/src/main/java/com/r11/tools/controller/XsdController.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.r11.tools.controller; - -import com.google.gson.Gson; -import com.r11.tools.controller.internal.*; -import com.r11.tools.model.XMLRequestBody; -import com.r11.tools.model.XMLResponseBody; -import com.r11.tools.xml.XmlEngine; -import org.apache.logging.log4j.Logger; -import spark.Request; -import spark.Response; - -@GlobalControllerManifest -public class XsdController implements RestController { - - private final Gson gson; - private final Logger logger; - - private final XmlEngine xalan; - - public XsdController(Gson gson, Logger logger, XmlEngine xalan) { - this.gson = gson; - this.logger = logger; - this.xalan = xalan; - } - - private XMLResponseBody prepareErrorResponse(String message, String processor) { - return new XMLResponseBody(message, "ERR", processor, -1); - } - - private void nonValidEngineSelectedResponse(Response response) { - XMLResponseBody responseBody = - prepareErrorResponse("Valid engines is: xalan", "N/A"); - response.body(this.gson.toJson(responseBody)); - response.status(400); - } - @ScopedControllerManifest(method = HandlerType.POST, path = "/xsd") - public void acceptRequest(Request request, Response response) { - XMLRequestBody requestBody; - try { - requestBody = this.gson.fromJson(request.body(), XMLRequestBody.class); - } catch (Exception e) { - XMLResponseBody responseBody = prepareErrorResponse(e.getMessage(), "N/A"); - - response.status(400); - response.body(this.gson.toJson(responseBody)); - return; - } - - if (requestBody.getProcessor() == null) { - nonValidEngineSelectedResponse(response); - return; - } - if (requestBody.getProcessor().equalsIgnoreCase("xalan")) - process(response, requestBody, xalan); - else - nonValidEngineSelectedResponse(response); - - } - - private void process(Response response, XMLRequestBody requestBody, XmlEngine engine) { - XMLResponseBody responseBody = null; - try { - long timeStart = System.currentTimeMillis(); - String result = engine.validate(requestBody.getData(), requestBody.getProcess()).trim(); - - response.status(200); - - long duration = System.currentTimeMillis() - timeStart; - responseBody = new XMLResponseBody(result, "OK", engine.getVersion(), duration); - - this.logger.info("Request (XSD, " + engine.getVersion() + ") processed in " + duration + " ms."); - } catch (Exception ex) { - responseBody = prepareErrorResponse(ex.getMessage(), engine.getVersion()); - response.status(400); - - this.logger.error("Error on validation against XSD using " + engine.getVersion() + ". " + ex); - } - finally { - response.body(this.gson.toJson(responseBody)); - } - - - } - -} diff --git a/Backend/tools-services/src/main/java/com/r11/tools/controller/XsltController.java b/Backend/tools-services/src/main/java/com/r11/tools/controller/XsltController.java deleted file mode 100644 index a2b7e95..0000000 --- a/Backend/tools-services/src/main/java/com/r11/tools/controller/XsltController.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.r11.tools.controller; - -import com.google.gson.Gson; -import com.r11.tools.controller.internal.*; -import com.r11.tools.model.XMLRequestBody; -import com.r11.tools.model.XMLResponseBody; -import com.r11.tools.xml.XmlEngine; -import org.apache.logging.log4j.Logger; -import spark.Request; -import spark.Response; - -@GlobalControllerManifest -public class XsltController implements RestController { - - private final Gson gson; - private final Logger logger; - - private final XmlEngine saxon; - private final XmlEngine xalan; - - public XsltController(Gson gson, Logger logger, XmlEngine saxon, XmlEngine xalan) { - this.gson = gson; - this.logger = logger; - this.saxon = saxon; - this.xalan = xalan; - } - - private XMLResponseBody prepareErrorResponse(String message, String processor) { - return new XMLResponseBody(message, "ERR", processor, -1); - } - - private void nonValidEngineSelectedResponse(Response response) { - XMLResponseBody responseBody = - prepareErrorResponse("Valid engines are: saxon, xalan", "N/A"); - response.body(this.gson.toJson(responseBody)); - response.status(400); - } - - @ScopedControllerManifest(method = HandlerType.POST, path = "/xslt") - public void acceptRequest(Request request, Response response) { - XMLRequestBody requestBody; - try { - requestBody = this.gson.fromJson(request.body(), XMLRequestBody.class); - } catch (Exception e) { - XMLResponseBody responseBody = prepareErrorResponse(e.getMessage(), "N/A"); - - response.status(400); - response.body(this.gson.toJson(responseBody)); - return; - } - - if (requestBody.getProcessor() == null) { - nonValidEngineSelectedResponse(response); - return; - } - - switch (requestBody.getProcessor()) { - case "saxon": - process(response, requestBody, saxon); - return; - - case "xalan": - process(response, requestBody, xalan); - return; - - default: - nonValidEngineSelectedResponse(response); - } - } - - private void process(Response response, XMLRequestBody requestBody, XmlEngine engine) { - XMLResponseBody responseBody = null; - long timeStart = System.currentTimeMillis(); - try { - String result = engine.processXSLT(requestBody.getData(), requestBody.getProcess()); - response.status(200); - - long duration = System.currentTimeMillis() - timeStart; - responseBody = new XMLResponseBody(result, "OK", engine.getVersion(), duration); - - this.logger.info("Request (XSLT, " + engine.getVersion() + ") processed in " + duration + " ms."); - } catch (Exception ex) { - responseBody = prepareErrorResponse(ex.getMessage(), engine.getVersion()); - response.status(400); - this.logger.error("Error on processing XSLT using " + engine.getVersion() + ". " + ex); - - } finally { - response.body(this.gson.toJson(responseBody)); - } - - } - -} diff --git a/Backend/tools-services/src/main/java/com/r11/tools/controller/internal/MultipleXmlJob.java b/Backend/tools-services/src/main/java/com/r11/tools/controller/internal/MultipleXmlJob.java new file mode 100644 index 0000000..c896188 --- /dev/null +++ b/Backend/tools-services/src/main/java/com/r11/tools/controller/internal/MultipleXmlJob.java @@ -0,0 +1,36 @@ +package com.r11.tools.controller.internal; + +import com.r11.tools.model.XMLMultipleFilesBody; +import com.r11.tools.xml.XmlEngine; +import spark.Response; + +public class MultipleXmlJob { + + private final Response response; + private final XMLMultipleFilesBody requestBody; + private final XmlEngine engine; + private final XmlJobType xmlJobType; + + public MultipleXmlJob(Response response, XMLMultipleFilesBody requestBody, XmlEngine engine, XmlJobType xmlJobType) { + this.response = response; + this.requestBody = requestBody; + this.engine = engine; + this.xmlJobType = xmlJobType; + } + + public Response getResponse() { + return response; + } + + public XMLMultipleFilesBody getRequestBody() { + return requestBody; + } + + public XmlEngine getEngine() { + return engine; + } + + public XmlJobType getXmlJobType() { + return xmlJobType; + } +} diff --git a/Backend/tools-services/src/main/java/com/r11/tools/controller/internal/XmlJob.java b/Backend/tools-services/src/main/java/com/r11/tools/controller/internal/XmlJob.java new file mode 100644 index 0000000..3537d2c --- /dev/null +++ b/Backend/tools-services/src/main/java/com/r11/tools/controller/internal/XmlJob.java @@ -0,0 +1,35 @@ +package com.r11.tools.controller.internal; + +import com.r11.tools.model.XMLRequestBody; +import com.r11.tools.xml.XmlEngine; +import spark.Response; + +public class XmlJob { + private final Response response; + private final XMLRequestBody requestBody; + private final XmlEngine engine; + private final XmlJobType xmlJobType; + + public XmlJob(Response response, XMLRequestBody requestBody, XmlEngine engine, XmlJobType xmlJobType) { + this.response = response; + this.requestBody = requestBody; + this.engine = engine; + this.xmlJobType = xmlJobType; + } + + public Response getResponse() { + return response; + } + + public XMLRequestBody getRequestBody() { + return requestBody; + } + + public XmlEngine getEngine() { + return engine; + } + + public XmlJobType getXmlJobType() { + return xmlJobType; + } +} diff --git a/Backend/tools-services/src/main/java/com/r11/tools/controller/internal/XmlJobType.java b/Backend/tools-services/src/main/java/com/r11/tools/controller/internal/XmlJobType.java new file mode 100644 index 0000000..0967e42 --- /dev/null +++ b/Backend/tools-services/src/main/java/com/r11/tools/controller/internal/XmlJobType.java @@ -0,0 +1,8 @@ +package com.r11.tools.controller.internal; + +public enum XmlJobType { + XPath("XPath"), XSD("XSD"), XQuery("XQuery"), XSLT("XSLT"); + + XmlJobType(String type) { + } +} diff --git a/Backend/tools-services/src/main/java/com/r11/tools/model/XMLMultipleFilesBody.java b/Backend/tools-services/src/main/java/com/r11/tools/model/XMLMultipleFilesBody.java new file mode 100644 index 0000000..67291a4 --- /dev/null +++ b/Backend/tools-services/src/main/java/com/r11/tools/model/XMLMultipleFilesBody.java @@ -0,0 +1,32 @@ +package com.r11.tools.model; + +import com.google.gson.annotations.SerializedName; + +public class XMLMultipleFilesBody { + + @SerializedName("data") + private XMLMultipleFilesData[] data; + @SerializedName("processorData") + private String processorData; + @SerializedName("processor") + private String processor; + @SerializedName("version") + private String version; + + + public String getProcessorData() { + return processorData; + } + + public String getProcessor() { + return processor; + } + + public String getVersion() { + return version; + } + + public XMLMultipleFilesData[] getData() { + return data; + } +} diff --git a/Backend/tools-services/src/main/java/com/r11/tools/model/XMLMultipleFilesData.java b/Backend/tools-services/src/main/java/com/r11/tools/model/XMLMultipleFilesData.java new file mode 100644 index 0000000..9dd4743 --- /dev/null +++ b/Backend/tools-services/src/main/java/com/r11/tools/model/XMLMultipleFilesData.java @@ -0,0 +1,18 @@ +package com.r11.tools.model; + +import com.google.gson.annotations.SerializedName; + +public class XMLMultipleFilesData { + @SerializedName("fileName") + private String filename; + @SerializedName("fileData") + private String data; + + public String getFilename() { + return filename; + } + + public String getData() { + return data; + } +} diff --git a/Backend/tools-services/src/main/java/com/r11/tools/model/XMLRequestBody.java b/Backend/tools-services/src/main/java/com/r11/tools/model/XMLRequestBody.java index 52e89eb..e7b06aa 100644 --- a/Backend/tools-services/src/main/java/com/r11/tools/model/XMLRequestBody.java +++ b/Backend/tools-services/src/main/java/com/r11/tools/model/XMLRequestBody.java @@ -4,13 +4,13 @@ import com.google.gson.annotations.SerializedName; /** * POJO class used to contain body of XML related requests - * @author Adam + * @author Adam Bem */ public class XMLRequestBody { @SerializedName("data") private String data; - @SerializedName("process") - private String process; + @SerializedName("processorData") + private String processorData; @SerializedName("processor") private String processor; @SerializedName("version") @@ -20,8 +20,8 @@ public class XMLRequestBody { return data; } - public String getProcess() { - return process; + public String getProcessorData() { + return processorData; } public String getProcessor() { diff --git a/Backend/tools-services/src/main/java/com/r11/tools/model/XMLResponseBody.java b/Backend/tools-services/src/main/java/com/r11/tools/model/XMLResponseBody.java index 42e52c1..81f8d73 100644 --- a/Backend/tools-services/src/main/java/com/r11/tools/model/XMLResponseBody.java +++ b/Backend/tools-services/src/main/java/com/r11/tools/model/XMLResponseBody.java @@ -10,6 +10,11 @@ public class XMLResponseBody { // Optional private String type; + public XMLResponseBody(String result, String status, String processor) { + this.result = result; + this.status = status; + this.processor = processor; + } public XMLResponseBody(String result, String status, String processor, long duration) { this.result = result; this.status = status; @@ -17,6 +22,13 @@ public class XMLResponseBody { this.duration = duration; } + public XMLResponseBody(String result, String status, String processor, String type) { + this.result = result; + this.status = status; + this.processor = processor; + this.type = type; + } + public String getResult() { return result; } diff --git a/Backend/tools-services/src/main/java/com/r11/tools/xml/Saxon.java b/Backend/tools-services/src/main/java/com/r11/tools/xml/Saxon.java index 897da0b..f610a9e 100644 --- a/Backend/tools-services/src/main/java/com/r11/tools/xml/Saxon.java +++ b/Backend/tools-services/src/main/java/com/r11/tools/xml/Saxon.java @@ -1,11 +1,16 @@ package com.r11.tools.xml; +import com.r11.tools.model.XMLMultipleFilesData; import com.r11.tools.model.XPathQueryResult; import net.sf.saxon.s9api.*; import javax.xml.transform.stream.StreamSource; -import java.io.StringReader; -import java.io.StringWriter; +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Comparator; +import java.util.UUID; /** * Handler for Saxon engine @@ -13,6 +18,64 @@ import java.io.StringWriter; */ public class Saxon implements XmlEngine{ + /** + * Transforms many XML documents via XSLT. + * @param data XML Files to be transformed. + * @param transform XSLT + * @return transformed xml + * @throws SaxonApiException thrown on stylesheet or transformation error + * @throws IOException thrown when file does not exist, or cannot be read. + */ + public String processXSLT(XMLMultipleFilesData[] data, String transform) throws SaxonApiException, IOException{ + Processor processor = new Processor(false); + XsltCompiler compiler = processor.newXsltCompiler(); + + String filesPath = "/tmp/"+UUID.randomUUID()+"/"; + try{ + createXMLFilesFromData(data, filesPath); + Path transformPath = createXSLTFileAndReturnPath(transform,filesPath); + XsltExecutable stylesheet = compiler.compile( new StreamSource( transformPath.toFile() )); + + StringWriter sw = new StringWriter(); + Serializer out = processor.newSerializer(sw); + out.setOutputProperty(Serializer.Property.METHOD, "xml"); + out.setOutputProperty(Serializer.Property.INDENT, "yes"); + Xslt30Transformer transformer = stylesheet.load30(); + transformer.transform( new StreamSource( new File(filesPath+data[0].getFilename()) ) , out ); + return sw.toString(); + } finally { + deleteTemporaryFiles(filesPath); + } + + } + + private void createXMLFilesFromData( XMLMultipleFilesData[] data , String filesPath ) throws IOException { + Files.createDirectories(Paths.get(filesPath)); + for (XMLMultipleFilesData fileData : data) { + Path filePath = Files.createFile( Paths.get(filesPath + fileData.getFilename() ) ); + try (FileWriter writer = new FileWriter(filePath.toFile())) { + writer.write(fileData.getData()); + } + } + } + + private Path createXSLTFileAndReturnPath( String xsltTransform, String filesPath ) throws IOException { + Path transformPath = Files.createFile( Paths.get(filesPath + "transform.xsl") ); + FileWriter writer = new FileWriter(transformPath.toFile()); + writer.write(xsltTransform); + writer.close(); + + return transformPath; + } + + private void deleteTemporaryFiles(String filesPath) throws IOException { + Files + .walk( Paths.get(filesPath) ) + .sorted(Comparator.reverseOrder()) + .map(Path::toFile) + .forEach(File::delete); + } + /** * Transforms string containing xml document via xslt * @param data xml to be transformed @@ -40,7 +103,7 @@ public class Saxon implements XmlEngine{ } /** - * This method evaluates XQuery exporession on given xml + * This method evaluates XQuery expression on given xml * @param data xml * @param xquery expression * @return @@ -64,8 +127,8 @@ public class Saxon implements XmlEngine{ /** * Process xpath and return either node or wrapped atomic value - * @param data xml to be querried - * @param query xpath queryy + * @param data xml to be processed + * @param query xpath query * @param version processor version * @return string xml representation of the node * @throws Exception thrown on node building errors or invalid xpath diff --git a/Backend/tools-services/src/main/java/com/r11/tools/xml/Xalan.java b/Backend/tools-services/src/main/java/com/r11/tools/xml/Xalan.java index befbe23..5c64093 100644 --- a/Backend/tools-services/src/main/java/com/r11/tools/xml/Xalan.java +++ b/Backend/tools-services/src/main/java/com/r11/tools/xml/Xalan.java @@ -1,5 +1,6 @@ package com.r11.tools.xml; +import com.r11.tools.model.XMLMultipleFilesData; import com.r11.tools.model.XPathQueryResult; import org.apache.xpath.XPathAPI; import org.w3c.dom.Document; @@ -17,7 +18,10 @@ import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; -import java.io.*; +import java.io.ByteArrayOutputStream; +import java.io.OutputStreamWriter; +import java.io.StringReader; +import java.io.StringWriter; /** * Handler for Xalan engine @@ -57,6 +61,11 @@ public class Xalan implements XmlEngine{ return nodeType == Node.CDATA_SECTION_NODE || nodeType == Node.TEXT_NODE; } + @Override + public String processXSLT(XMLMultipleFilesData[] data, String transform) throws Exception { + throw new UnsupportedOperationException("Xalan does not support multiple files XSLT processing"); + } + /** * Process xpath and return either node or wrapped atomic value * @param data xml diff --git a/Backend/tools-services/src/main/java/com/r11/tools/xml/XmlEngine.java b/Backend/tools-services/src/main/java/com/r11/tools/xml/XmlEngine.java index 132c9d4..7e7b8db 100644 --- a/Backend/tools-services/src/main/java/com/r11/tools/xml/XmlEngine.java +++ b/Backend/tools-services/src/main/java/com/r11/tools/xml/XmlEngine.java @@ -1,8 +1,11 @@ package com.r11.tools.xml; +import com.r11.tools.model.XMLMultipleFilesData; import com.r11.tools.model.XPathQueryResult; public interface XmlEngine { + + String processXSLT(XMLMultipleFilesData[] data, String transform) throws Exception; XPathQueryResult processXPath(String data, String query, String version) throws Exception; String processXSLT(String data, String transform) throws Exception; String validate(String data, String xsd) throws Exception; diff --git a/Frontend/Dockerfile b/Frontend/Dockerfile index 0b44b57..278b4e0 100644 --- a/Frontend/Dockerfile +++ b/Frontend/Dockerfile @@ -1,4 +1,4 @@ -FROM node:latest as build-stage +FROM node:20.9.0-bullseye-slim as build-stage WORKDIR /app COPY package*.json ./ RUN npm install @@ -7,7 +7,7 @@ RUN npm run build -FROM nginx:stable-alpine as production-stage +FROM nginx:stable-alpine3.17-slim as production-stage RUN mkdir /app RUN apk add --no-cache tzdata @@ -20,7 +20,7 @@ EXPOSE 80 EXPOSE 443 -FROM node:latest as dev +FROM node:20.9.0-bullseye-slim as dev WORKDIR /app COPY package*.json ./ RUN npm install diff --git a/Frontend/package-lock.json b/Frontend/package-lock.json index 1734b18..839da8b 100644 --- a/Frontend/package-lock.json +++ b/Frontend/package-lock.json @@ -13,6 +13,7 @@ "@codemirror/lang-xml": "^6.0.2", "@codemirror/theme-one-dark": "^6.1.2", "codemirror": "^6.0.1", + "thememirror": "^2.0.1", "vue": "^3.3.4", "vue-codemirror": "^6.1.1", "vue-router": "^4.2.2" @@ -3190,9 +3191,9 @@ } }, "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "bin": { "semver": "bin/semver" @@ -3326,9 +3327,9 @@ } }, "node_modules/npm-run-all/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "bin": { "semver": "bin/semver" @@ -3616,9 +3617,9 @@ } }, "node_modules/postcss": { - "version": "8.4.24", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz", - "integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "funding": [ { "type": "opencollective", @@ -4305,6 +4306,16 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/thememirror": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/thememirror/-/thememirror-2.0.1.tgz", + "integrity": "sha512-d5i6FVvWWPkwrm4cHLI3t9AT1OrkAt7Ig8dtdYSofgF7C/eiyNuq6zQzSTusWTde3jpW9WLvA9J/fzNKMUsd0w==", + "peerDependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + } + }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -6994,9 +7005,9 @@ }, "dependencies": { "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true } } @@ -7097,9 +7108,9 @@ "dev": true }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true }, "shebang-command": { @@ -7302,9 +7313,9 @@ "dev": true }, "postcss": { - "version": "8.4.24", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz", - "integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "requires": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", @@ -7756,6 +7767,12 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "thememirror": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/thememirror/-/thememirror-2.0.1.tgz", + "integrity": "sha512-d5i6FVvWWPkwrm4cHLI3t9AT1OrkAt7Ig8dtdYSofgF7C/eiyNuq6zQzSTusWTde3jpW9WLvA9J/fzNKMUsd0w==", + "requires": {} + }, "thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", diff --git a/Frontend/package.json b/Frontend/package.json index a6ecef8..7663195 100644 --- a/Frontend/package.json +++ b/Frontend/package.json @@ -17,6 +17,7 @@ "@codemirror/lang-xml": "^6.0.2", "@codemirror/theme-one-dark": "^6.1.2", "codemirror": "^6.0.1", + "thememirror": "^2.0.1", "vue": "^3.3.4", "vue-codemirror": "^6.1.1", "vue-router": "^4.2.2" diff --git a/Frontend/src/App.vue b/Frontend/src/App.vue index f61c09b..d425cc9 100644 --- a/Frontend/src/App.vue +++ b/Frontend/src/App.vue @@ -1,14 +1,53 @@