From 94dfc6af52dfebaef63485141364d7c32e370c08 Mon Sep 17 00:00:00 2001 From: Aaron Birkland Date: Sun, 6 Nov 2016 19:57:41 -0500 Subject: [PATCH] Expose loader as an extension Self-load and expose as a repository-scoped service, bound to the repository root resource. Resolves #84 --- fcrepo-api-x-binding/pom.xml | 5 +++ .../binding/impl/RuntimeExtensionBinding.java | 44 +++++++++++++------ .../fcrepo/apix/loader/impl/LoaderRoutes.java | 27 +++++++++--- .../OSGI-INF/blueprint/blueprint.xml | 25 +++++++++-- .../src/main/resources/options.ttl | 10 +++++ 5 files changed, 88 insertions(+), 23 deletions(-) create mode 100644 fcrepo-api-x-loader/src/main/resources/options.ttl diff --git a/fcrepo-api-x-binding/pom.xml b/fcrepo-api-x-binding/pom.xml index 38839b0..2410d0a 100644 --- a/fcrepo-api-x-binding/pom.xml +++ b/fcrepo-api-x-binding/pom.xml @@ -36,6 +36,11 @@ org.fcrepo.client fcrepo-java-client + + + commons-io + commons-io + org.slf4j diff --git a/fcrepo-api-x-binding/src/main/java/org/fcrepo/apix/binding/impl/RuntimeExtensionBinding.java b/fcrepo-api-x-binding/src/main/java/org/fcrepo/apix/binding/impl/RuntimeExtensionBinding.java index 2896121..4f5cdc5 100644 --- a/fcrepo-api-x-binding/src/main/java/org/fcrepo/apix/binding/impl/RuntimeExtensionBinding.java +++ b/fcrepo-api-x-binding/src/main/java/org/fcrepo/apix/binding/impl/RuntimeExtensionBinding.java @@ -18,6 +18,9 @@ package org.fcrepo.apix.binding.impl; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; import java.net.URI; import java.util.Collection; import java.util.Collections; @@ -34,6 +37,7 @@ import org.fcrepo.client.FcrepoClient; import org.fcrepo.client.FcrepoResponse; +import org.apache.commons.io.IOUtils; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.ConfigurationPolicy; import org.osgi.service.component.annotations.Reference; @@ -118,20 +122,32 @@ public Collection getExtensionsFor(final WebResource resource) { public Collection getExtensionsFor(final WebResource resource, final Collection extensions) { - final Set rdfTypes = extensions.stream() - .map(Extension::getResource) - .peek(r -> LOG.debug("Examinining the ontology closure of extension {}", r.uri())) - .map(ontologySvc::parseOntology) - .flatMap(o -> ontologySvc.inferClasses(resource.uri(), resource, o).stream()) - .peek(rdfType -> LOG.debug("Instance {} is of class {}", resource.uri(), rdfType)) - .collect(Collectors.toSet()); - - return extensions.stream() - .peek(e -> LOG.debug("Extension {} binds to instances of {}", e.uri(), e.bindingClass())) - .filter(e -> rdfTypes.contains(e.bindingClass())) - .peek(e -> LOG.debug("Extension {} bound to instance {} via {}", e.uri(), resource.uri(), e - .bindingClass())) - .collect(Collectors.toList()); + try (final InputStream resourceContent = resource.representation()) { + + final byte[] content = IOUtils.toByteArray(resourceContent); + + final Set rdfTypes = extensions.stream() + .map(Extension::getResource) + .peek(r -> LOG.debug("Examinining the ontology closure of extension {}", r.uri())) + .map(ontologySvc::parseOntology) + .flatMap(o -> ontologySvc.inferClasses(resource.uri(), cached(resource, content), o).stream()) + .peek(rdfType -> LOG.debug("Instance {} is of class {}", resource.uri(), rdfType)) + .collect(Collectors.toSet()); + + return extensions.stream() + .peek(e -> LOG.debug("Extension {} binds to instances of {}", e.uri(), e.bindingClass())) + .filter(e -> rdfTypes.contains(e.bindingClass())) + .peek(e -> LOG.debug("Extension {} bound to instance {} via {}", e.uri(), resource.uri(), e + .bindingClass())) + .collect(Collectors.toList()); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } + + private WebResource cached(final WebResource initial, final byte[] content) { + return WebResource.of(new ByteArrayInputStream(content), initial.contentType(), initial.uri(), initial + .name()); } /** Just does a dumb dereference and lookup */ diff --git a/fcrepo-api-x-loader/src/main/java/org/fcrepo/apix/loader/impl/LoaderRoutes.java b/fcrepo-api-x-loader/src/main/java/org/fcrepo/apix/loader/impl/LoaderRoutes.java index fcfb4d8..fbaecaf 100644 --- a/fcrepo-api-x-loader/src/main/java/org/fcrepo/apix/loader/impl/LoaderRoutes.java +++ b/fcrepo-api-x-loader/src/main/java/org/fcrepo/apix/loader/impl/LoaderRoutes.java @@ -18,6 +18,7 @@ package org.fcrepo.apix.loader.impl; +import static org.apache.camel.Exchange.CONTENT_TYPE; import static org.apache.camel.Exchange.HTTP_RESPONSE_CODE; import java.io.InputStream; @@ -44,6 +45,8 @@ public class LoaderRoutes extends RouteBuilder { private static final String ROUTE_NO_SERVICE = "direct:no_service"; + private static final String ROUTE_OPTIONS = "direct:options"; + LoaderService loaderService; /** @@ -57,14 +60,26 @@ public void setLoaderService(final LoaderService svc) { @Override public void configure() throws Exception { - restConfiguration().component("jetty").host("0.0.0.0").port("{{loader.port}}"); - rest("/load") - .get() - .produces("text/html").to("language:simple:resource:classpath:form.html") + from("jetty:http://0.0.0.0:{{loader.port}}/load" + + "?matchOnUriPrefix=true&sendServerVersion=false&httpMethodRestrict=GET,OPTIONS,POST") + .id("loader-http") + .choice() + + .when(header(Exchange.HTTP_METHOD).isEqualTo("GET")) + .setHeader("Content-Type", constant("text/html")) + .to("language:simple:resource:classpath:form.html") + + .when(header(Exchange.HTTP_METHOD).isEqualTo("POST")) + .to(ROUTE_PREPARE_LOAD) + + .otherwise().to(ROUTE_OPTIONS); - .post().consumes("application/x-www-form-urlencoded, text/plain") - .to(ROUTE_PREPARE_LOAD); + from(ROUTE_OPTIONS).id("respond-options") + .setHeader(CONTENT_TYPE).constant("text/turtle") + .setHeader("Allow").constant("GET,OPTIONS,POST") + .setHeader("Accept-Post").constant("application/x-www-form-urlencoded,text/plain") + .to("language:simple:resource:classpath:options.ttl"); from(ROUTE_PREPARE_LOAD).id("load-prepare") .choice().when(header("Content-Type").isEqualTo("text/plain")) diff --git a/fcrepo-api-x-loader/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/fcrepo-api-x-loader/src/main/resources/OSGI-INF/blueprint/blueprint.xml index a4a67c5..019c3ff 100644 --- a/fcrepo-api-x-loader/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/fcrepo-api-x-loader/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -37,7 +37,26 @@ - - - + + + + + + + + + java.lang.Exception + + + + text/plain + + + http://localhost:{{loader.port}}/load + + + + \ No newline at end of file diff --git a/fcrepo-api-x-loader/src/main/resources/options.ttl b/fcrepo-api-x-loader/src/main/resources/options.ttl new file mode 100644 index 0000000..559440f --- /dev/null +++ b/fcrepo-api-x-loader/src/main/resources/options.ttl @@ -0,0 +1,10 @@ +@prefix apix: . +@prefix fedora: . +@prefix rdfs: . + +<> a apix:Extension; + rdfs:label "Extension loader service"; + rdfs:comment "A service that automates loading and registration of extensions and services"; + apix:exposesService apix:LoaderService; + apix:exposesServiceAt "/apix:load"; + apix:bindsTo fedora:RepositoryRoot . \ No newline at end of file