Skip to content

Commit

Permalink
Move Fuseki integration to a Jena module
Browse files Browse the repository at this point in the history
Follow-up from #136

Fuseki modules are not supported in all Fuseki distributions, so it makes more sense to move the functionality to a Jena module. The only disadvantage is that the module loads regardless of whether we are in a Fuseki instance or not, but that can be solved with some exception catching...
  • Loading branch information
Ostrzyciel committed Oct 15, 2024
1 parent 4ad7b2f commit 453099a
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 27 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
eu.ostrzyciel.jelly.convert.jena.riot.JellySubsystemLifecycle
eu.ostrzyciel.jelly.convert.jena.fuseki.JellyFusekiLifecycle
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,46 @@ package eu.ostrzyciel.jelly.convert.jena.fuseki
import eu.ostrzyciel.jelly.core.Constants
import org.apache.jena.atlas.web.{AcceptList, MediaRange}
import org.apache.jena.fuseki.{DEF, Fuseki}
import org.apache.jena.fuseki.main.FusekiServer
import org.apache.jena.fuseki.main.sys.FusekiAutoModule
import org.apache.jena.rdf.model.Model
import org.apache.jena.riot.WebContent
import org.apache.jena.sys.JenaSubsystemLifecycle

import java.util

object JellyFusekiModule:
object JellyFusekiLifecycle:
val mediaRangeJelly: MediaRange = new MediaRange(Constants.jellyContentType)

/**
* A Fuseki module that adds Jelly content type to the list of accepted content types.
* A Jena module that adds Jelly content type to the list of accepted content types in Fuseki.
* This isn't a Fuseki module, because Fuseki modules are not supported in all distributions of Fuseki, see:
* https://github.com/apache/jena/issues/2774
*
* This allows users to use the Accept header set to application/x-jelly-rdf to request Jelly RDF responses.
* It works for SPARQL CONSTRUCT queries and for the Graph Store Protocol.
*
* More info on Fuseki modules: https://jena.apache.org/documentation/fuseki2/fuseki-modules.html
*/
final class JellyFusekiModule extends FusekiAutoModule:
import JellyFusekiModule.*

override def name(): String = "Jelly"
final class JellyFusekiLifecycle extends JenaSubsystemLifecycle:
import JellyFusekiLifecycle.*

override def start(): Unit =
try {
maybeAddJellyToList(DEF.constructOffer).foreach(offer => DEF.constructOffer = offer)
maybeAddJellyToList(DEF.rdfOffer).foreach(offer => DEF.rdfOffer = offer)
maybeAddJellyToList(DEF.quadsOffer).foreach(offer => {
DEF.quadsOffer = offer
Fuseki.serverLog.info(s"Added ${Constants.jellyContentType} to the list of accepted content types")
Fuseki.serverLog.info(s"Jelly: Added ${Constants.jellyContentType} to the list of accepted content types")
})
} catch {
case e: NoClassDefFoundError => // ignore, we are not running Fuseki
case e: IllegalAccessError => Fuseki.serverLog.warn(
s"Cannot register the ${Constants.jellyContentType} content type, because you are running an Apache Jena " +
s"Fuseki version that doesn't support content type registration. " +
s"Jelly: Cannot register the ${Constants.jellyContentType} content type, because you are running an " +
s"Apache Jena Fuseki version that doesn't support content type registration. " +
s"Update to Fuseki 5.2.0 or newer for this to work."
)
}

override def stop(): Unit = ()

// Initialize after JellySubsystemLifecycle
override def level(): Int = 502

/**
* Adds the Jelly content type to the list of accepted content types if it is not already present.
* @param list current list of accepted content types
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,38 @@ import scala.jdk.CollectionConverters.*
class JellyFusekiModuleSpec extends AnyWordSpec, Matchers:
"JellyFusekiModule" should {
"have a name" in {
JellyFusekiModule().name() should be ("Jelly")
JellyFusekiLifecycle().name() should be ("Jelly")
}

"use the correct content type for Jelly" in {
JellyFusekiModule.mediaRangeJelly.getContentTypeStr should be ("application/x-jelly-rdf")
JellyFusekiLifecycle.mediaRangeJelly.getContentTypeStr should be ("application/x-jelly-rdf")
}

"register the Jelly content type in the lists of accepted content types" in {
val oldLists = List(DEF.constructOffer, DEF.rdfOffer, DEF.quadsOffer)
for list <- oldLists do
list.entries().asScala should not contain JellyFusekiModule.mediaRangeJelly
DEF.constructOffer.entries().asScala should not contain JellyFusekiModule.mediaRangeJelly
DEF.rdfOffer.entries().asScala should not contain JellyFusekiModule.mediaRangeJelly
DEF.quadsOffer.entries().asScala should not contain JellyFusekiModule.mediaRangeJelly
list.entries().asScala should not contain JellyFusekiLifecycle.mediaRangeJelly
DEF.constructOffer.entries().asScala should not contain JellyFusekiLifecycle.mediaRangeJelly
DEF.rdfOffer.entries().asScala should not contain JellyFusekiLifecycle.mediaRangeJelly
DEF.quadsOffer.entries().asScala should not contain JellyFusekiLifecycle.mediaRangeJelly

val module = JellyFusekiModule()
val module = JellyFusekiLifecycle()
module.start()

val lists = List(DEF.constructOffer, DEF.rdfOffer, DEF.quadsOffer)
for (list, oldList) <- lists.zip(oldLists) do
list.entries().asScala should contain (JellyFusekiModule.mediaRangeJelly)
list.entries().asScala should contain (JellyFusekiLifecycle.mediaRangeJelly)
list.entries().size() should be (oldList.entries().size() + 1)
}

"not register the Jelly content type if it's already registered" in {
val module = JellyFusekiModule()
val module = JellyFusekiLifecycle()
module.start()
DEF.rdfOffer.entries().asScala should contain (JellyFusekiModule.mediaRangeJelly)
DEF.rdfOffer.entries().asScala should contain (JellyFusekiLifecycle.mediaRangeJelly)
val size1 = DEF.rdfOffer.entries().size()

module.start()
DEF.rdfOffer.entries().asScala should contain (JellyFusekiModule.mediaRangeJelly)
DEF.rdfOffer.entries().asScala should contain (JellyFusekiLifecycle.mediaRangeJelly)
val size2 = DEF.rdfOffer.entries().size()
size2 should be (size1)
}
Expand Down

0 comments on commit 453099a

Please sign in to comment.