From 9fed20a4dc884a4b26338e724e141e79b1e61182 Mon Sep 17 00:00:00 2001 From: Sander Van Dooren Date: Thu, 28 Jul 2022 13:18:38 +0200 Subject: [PATCH] SPARQL Shell tool. --- Makefile | 18 +++++ README.md | 38 +++++++++ pom.xml | 80 +++++++++++++++++++ .../java/eu/europa/ec/sparql/shell/Exec.java | 48 +++++++++++ src/main/main.iml | 12 +++ .../eu/europa/ec/sparql/shell/ExecTest.java | 20 +++++ src/test/test.iml | 11 +++ test/test-query | 7 ++ test/test-query-1 | 7 ++ 9 files changed, 241 insertions(+) create mode 100644 Makefile create mode 100644 README.md create mode 100644 pom.xml create mode 100644 src/main/java/eu/europa/ec/sparql/shell/Exec.java create mode 100644 src/main/main.iml create mode 100644 src/test/java/eu/europa/ec/sparql/shell/ExecTest.java create mode 100644 src/test/test.iml create mode 100644 test/test-query create mode 100644 test/test-query-1 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e7e4ff6 --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ +test: tools/apache-jena/lib/sparql-shell-1.0-SNAPSHOT.jar test/test-query + ./tools/apache-jena/bin/sparql --query=test/test-query-1 + + +tools/apache-jena/lib/sparql-shell-1.0-SNAPSHOT.jar: src/main/java/eu/europa/ec/sparql/shell/Exec.java + mvn package + cp target/sparql-shell-1.0-SNAPSHOT.jar tools/apache-jena/lib + + +tools/apache-jena: + mkdir -p tools + rm -rf tools/apache-jena + wget https://dlcdn.apache.org/jena/binaries/apache-jena-4.5.0.zip -O tools/apache-jena.zip + unzip tools/apache-jena.zip -d tools + rm tools/apache-jena.zip + cd tools; ln -s apache-jena-4.5.0 apache-jena + +.PHONY: test diff --git a/README.md b/README.md new file mode 100644 index 0000000..80fb652 --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +# SPARQL Shell +SPARQL shell is an Apache Jena plugin, that allows executing shell commands as a SPARQL function. + +## Setup +Build the jar: +``` +mvn package +``` +Copy the resulting package to the 'lib' folder of your Jena installation. + +Alternatively grab the JAR from the release on GitHub. + +## Example usage +To convert Markdown to HTML, we can use the following query: +``` +PREFIX f: +SELECT ?s +{ + BIND("# Title\n - Item 1\n - Item 2" as ?t) + BIND(f:Exec("pandoc -f markdown -t html", ?t) as ?s) + +} +``` +This will execute the pandoc tool to do the convertion. + +The output of this query is: +``` +-------------------------------------------------------------------------------- +| s | +================================================================================ +| "

Title

\n" | +-------------------------------------------------------------------------------- +``` + +## Security consideration +The executed process runs as a subprocess of the Jena SPARQL/Fuseki process. +This is a serious security risk. It should not be used in a public endpoint or where the data is untrusted. + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..9cb2449 --- /dev/null +++ b/pom.xml @@ -0,0 +1,80 @@ + + + + 4.0.0 + + eu.europa.ec.sparql.shell + sparql-shell + 1.0-SNAPSHOT + + sparql-shell + github.com/sandervd/sparql-shell + + + UTF-8 + 1.7 + 1.7 + 4.5.0 + + + + + junit + junit + 4.11 + test + + + org.apache.jena + jena-tdb + ${jena.version} + + + + + + + + + maven-clean-plugin + 3.1.0 + + + + maven-resources-plugin + 3.0.2 + + + maven-compiler-plugin + 3.8.0 + + + maven-surefire-plugin + 2.22.1 + + + maven-jar-plugin + 3.0.2 + + + maven-install-plugin + 2.5.2 + + + maven-deploy-plugin + 2.8.2 + + + + maven-site-plugin + 3.7.1 + + + maven-project-info-reports-plugin + 3.0.0 + + + + + diff --git a/src/main/java/eu/europa/ec/sparql/shell/Exec.java b/src/main/java/eu/europa/ec/sparql/shell/Exec.java new file mode 100644 index 0000000..e24bb39 --- /dev/null +++ b/src/main/java/eu/europa/ec/sparql/shell/Exec.java @@ -0,0 +1,48 @@ +package eu.europa.ec.sparql.shell; + +import org.apache.jena.sparql.expr.NodeValue; +import org.apache.jena.sparql.function.FunctionBase2; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; + +/** + * SPARQL function to execute a shell. + */ +public class Exec extends FunctionBase2 +{ + + @Override + public NodeValue exec(NodeValue cmd, NodeValue pipe) { + try { + Process p = Runtime.getRuntime().exec(cmd.asString()); + OutputStream outputStream = p.getOutputStream(); + outputStream.write(pipe.asString().getBytes()); + outputStream.close(); + BufferedReader output = new BufferedReader(new InputStreamReader(p.getInputStream())); + BufferedReader error = new BufferedReader(new InputStreamReader(p.getErrorStream())); + p.waitFor(); + StringBuilder result = new StringBuilder(); + if (p.exitValue() != 0) { + result.append("Error while executing ").append(cmd.asString()).append(":\n"); + dump(error, result); + throw new RuntimeException(error.toString()); + } + dump(output,result); + return NodeValue.makeString(result.toString().trim()); + + } catch (IOException | InterruptedException e ) { + throw new RuntimeException(e); + } + } + + private static StringBuilder dump(BufferedReader reader, StringBuilder builder) throws IOException { + String line; + while ((line = reader.readLine()) != null) { + builder.append(line).append("\n"); + } + reader.close(); + return builder; + } +} diff --git a/src/main/main.iml b/src/main/main.iml new file mode 100644 index 0000000..d4a312b --- /dev/null +++ b/src/main/main.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/java/eu/europa/ec/sparql/shell/ExecTest.java b/src/test/java/eu/europa/ec/sparql/shell/ExecTest.java new file mode 100644 index 0000000..19dd59b --- /dev/null +++ b/src/test/java/eu/europa/ec/sparql/shell/ExecTest.java @@ -0,0 +1,20 @@ +package eu.europa.ec.sparql.shell; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +/** + * Unit test for simple App. + */ +public class ExecTest +{ + /** + * Rigorous Test :-) + */ + @Test + public void shouldAnswerWithTrue() + { + assertTrue( true ); + } +} diff --git a/src/test/test.iml b/src/test/test.iml new file mode 100644 index 0000000..a0e49a3 --- /dev/null +++ b/src/test/test.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/test/test-query b/test/test-query new file mode 100644 index 0000000..b511932 --- /dev/null +++ b/test/test-query @@ -0,0 +1,7 @@ +PREFIX f: +SELECT ?s +{ + BIND("Some test" as ?t) + BIND(f:Exec("cat -", ?t) as ?s) + +} diff --git a/test/test-query-1 b/test/test-query-1 new file mode 100644 index 0000000..b66dbb6 --- /dev/null +++ b/test/test-query-1 @@ -0,0 +1,7 @@ +PREFIX f: +SELECT ?s +{ + BIND("# Title\n - Item 1\n - Item 2" as ?t) + BIND(f:Exec("pandoc -f markdown -t html", ?t) as ?s) + +}