Skip to content

Commit

Permalink
feat: new validator processor, fix: load class files
Browse files Browse the repository at this point in the history
  • Loading branch information
jenspots committed May 24, 2024
1 parent 2db38c4 commit da61e50
Show file tree
Hide file tree
Showing 12 changed files with 283 additions and 27 deletions.
3 changes: 3 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ repositories { mavenCentral() }
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")

// Guava
implementation("com.google.guava:guava:33.2.0-jre")

// K2JVM Compiler.
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.22")
implementation("org.jetbrains.kotlin:kotlin-compiler-embeddable:1.9.22")
Expand Down
3 changes: 3 additions & 0 deletions src/main/kotlin/exception/RunnerException.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package technology.idlab.exception

open class RunnerException : Exception()
38 changes: 31 additions & 7 deletions src/main/kotlin/extensions/File.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package technology.idlab.extensions

import com.google.common.reflect.ClassPath
import java.io.File
import java.net.URLClassLoader
import org.apache.jena.ontology.OntModelSpec
import org.apache.jena.rdf.model.Model
import org.apache.jena.rdf.model.ModelFactory
import org.apache.jena.rdf.model.Resource
import org.apache.jena.vocabulary.OWL
import org.jetbrains.kotlin.incremental.isClassFile
import org.jetbrains.kotlin.incremental.isJavaFile
import org.jetbrains.kotlin.incremental.isKotlinFile
import technology.idlab.compiler.Compiler
import technology.idlab.compiler.MemoryClassLoader
import technology.idlab.logging.Log
Expand Down Expand Up @@ -54,13 +59,32 @@ internal fun File.readModelRecursively(): Model {
* Parse a file as a JVM processor by loading the class file from disk or compiling the source code.
*/
internal fun File.loadIntoJVM(): Class<*> {
val bytes =
when (extension) {
"kt" -> Compiler.compileKotlin(this)
"java" -> Compiler.compileJava(this)
"class" -> readBytes()
else -> Log.shared.fatal("Unsupported file extension: $extension")
if (this.isClassFile()) {
// Load the class file using a custom class loader.
val loader = URLClassLoader(arrayOf(toURI().toURL()))
val classPath = ClassPath.from(loader)
val classes = classPath.allClasses

// Find the class which corresponds to this file.
for (clazz in classes) {
// TODO: this is a hack, we should use a better way to find the class.
if (clazz.name.endsWith(this.nameWithoutExtension)) {
return clazz.load()
}
}

Log.shared.fatal("Failed to load class ${this.nameWithoutExtension}")
}

if (this.isKotlinFile(listOf("kt"))) {
val bytes = Compiler.compileKotlin(this)
return MemoryClassLoader().fromBytes(bytes, nameWithoutExtension)
}

if (this.isJavaFile()) {
val bytes = Compiler.compileJava(this)
return MemoryClassLoader().fromBytes(bytes, nameWithoutExtension)
}

return MemoryClassLoader().fromBytes(bytes, nameWithoutExtension)
Log.shared.fatal("Unsupported file type: $extension")
}
11 changes: 4 additions & 7 deletions src/main/kotlin/logging/Log.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import java.time.format.DateTimeFormatter
import java.util.Date
import java.util.TimeZone
import kotlin.Exception
import kotlin.system.exitProcess
import technology.idlab.exception.RunnerException

class Log private constructor() {
init {
Expand Down Expand Up @@ -64,20 +64,17 @@ class Log private constructor() {

fun fatal(message: String): Nothing {
print(message, "FATAL")
print(Throwable().stackTraceToString())
exitProcess(1)
throw RunnerException()
}

fun fatal(exception: Exception): Nothing {
print(exception.message.toString(), "FATAL")
print(Throwable().stackTraceToString())
exitProcess(1)
throw RunnerException()
}

fun fatal(message: String, exception: Exception) {
print("$message - ${exception.message}")
print(Throwable().stackTraceToString())
exitProcess(1)
throw RunnerException()
}

fun debug(message: String) {
Expand Down
27 changes: 21 additions & 6 deletions src/main/kotlin/std/RDFValidator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import java.io.ByteArrayOutputStream
import java.io.File
import org.apache.jena.graph.Graph
import org.apache.jena.rdf.model.ModelFactory
import org.apache.jena.riot.RiotException
import org.apache.jena.shacl.ShaclValidator
import technology.idlab.extensions.readModelRecursively
import technology.idlab.logging.Log
Expand All @@ -31,7 +32,14 @@ class RDFValidator(args: Map<String, Any>) : Processor(args) {
init {
val path = this.getArgument<String>("shapes")
val file = File(path)
val shapesModel = file.readModelRecursively()

val shapesModel =
try {
file.readModelRecursively()
} catch (e: RiotException) {
Log.shared.fatal("Failed to read SHACL shapes from file://$path")
}

this.shapes = shapesModel.graph
}

Expand All @@ -46,27 +54,34 @@ class RDFValidator(args: Map<String, Any>) : Processor(args) {

// Parse as a model.
Log.shared.assert(model.isEmpty, "Model should be empty.")
model.read(res.value.toString())
try {
model.read(res.value.inputStream(), null, "TURTLE")
} catch (e: RiotException) {
Log.shared.fatal("Failed to read incoming RDF data.")
}

// Validate the model.
val report = validator.validate(shapes, model.graph)
if (!report.conforms()) {

if (report.conforms()) {
// Propagate to the output.
output.pushSync(res.value)
} else {
// Print the report if required.
if (printReport.orElse(printReportDefault)) {
val out = ByteArrayOutputStream()
report.model.write(out, "TURTLE")
Log.shared.info(out.toString())
}

// Check if we can continue after an error.
if (errorIsFatal.orElse(errorIsFatalDefault)) {
Log.shared.fatal("Validation error is fatal.")
}
}

// Reset model for next invocation.
model.removeAll(null, null, null)

// Propagate to the output.
output.pushSync(res.value)
}

// Close the output.
Expand Down
11 changes: 8 additions & 3 deletions src/main/resources/pipeline.ttl
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
@prefix jvm: <https://w3id.org/conn/jvm#>.
@prefix fno: <https://w3id.org/function/ontology#>.
@prefix fnom: <https://w3id.org/function/vocabulary/mapping#>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
@prefix : <https://w3id.org/conn#>.
@prefix sh: <http://www.w3.org/ns/shacl#>.
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix owl: <http://www.w3.org/2002/07/owl#>.

# Include the Standard Processor Library
<> owl:imports
<./std/file_reader.ttl>,
<./std/file_writer.ttl>,
<./std/http_fetch.ttl>,
<./std/rdf_validator.ttl>.

# Definition of a Processor.
[]
Expand Down
3 changes: 2 additions & 1 deletion src/main/resources/std/file_reader.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
@prefix owl: <http://www.w3.org/2002/07/owl#>.
@prefix sh: <http://www.w3.org/ns/shacl#>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.

<> owl:imports <../pipeline.ttl>.

jvm:FileReader a jvm:Processor;
jvm:file <../../kotlin/std/FileReader.kt>;
jvm:file <../../../classes/kotlin/main/technology/idlab/std/FileReader.class>;
jvm:language "Kotlin".

[] a sh:NodeShape;
Expand Down
3 changes: 2 additions & 1 deletion src/main/resources/std/file_writer.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
@prefix owl: <http://www.w3.org/2002/07/owl#>.
@prefix sh: <http://www.w3.org/ns/shacl#>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.

<> owl:imports <../pipeline.ttl>.

jvm:FileWriter a jvm:Processor;
jvm:file <../../kotlin/std/FileWriter.kt>;
jvm:file <../../../classes/kotlin/main/technology/idlab/std/FileWriter.class>;
jvm:language "Kotlin".

[] a sh:NodeShape;
Expand Down
3 changes: 2 additions & 1 deletion src/main/resources/std/http_fetch.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
@prefix owl: <http://www.w3.org/2002/07/owl#>.
@prefix sh: <http://www.w3.org/ns/shacl#>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.

<> owl:imports <../pipeline.ttl>.

jvm:HttpFetch a jvm:Processor;
jvm:file <../../kotlin/std/HttpFetch.kt>;
jvm:file <../../../classes/kotlin/main/technology/idlab/std//HttpFetch.class>;
jvm:language "Kotlin".

[] a sh:NodeShape;
Expand Down
3 changes: 2 additions & 1 deletion src/main/resources/std/rdf_validator.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
@prefix owl: <http://www.w3.org/2002/07/owl#>.
@prefix sh: <http://www.w3.org/ns/shacl#>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.

<> owl:imports <../pipeline.ttl>.

jvm:RDFValidator a jvm:Processor;
jvm:file <../../kotlin/std/RDFValidator.kt>;
jvm:file <../../../classes/kotlin/main/technology/idlab/std/RDFValidator.class>;
jvm:language "Kotlin".

[] a sh:NodeShape;
Expand Down
Loading

0 comments on commit da61e50

Please sign in to comment.