Skip to content

Commit 94dfc6a

Browse files
birklandemetsger
authored andcommitted
Expose loader as an extension
Self-load and expose as a repository-scoped service, bound to the repository root resource. Resolves fcrepo4-labs#84
1 parent 254723f commit 94dfc6a

File tree

5 files changed

+88
-23
lines changed

5 files changed

+88
-23
lines changed

fcrepo-api-x-binding/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@
3636
<groupId>org.fcrepo.client</groupId>
3737
<artifactId>fcrepo-java-client</artifactId>
3838
</dependency>
39+
40+
<dependency>
41+
<groupId>commons-io</groupId>
42+
<artifactId>commons-io</artifactId>
43+
</dependency>
3944

4045
<dependency>
4146
<groupId>org.slf4j</groupId>

fcrepo-api-x-binding/src/main/java/org/fcrepo/apix/binding/impl/RuntimeExtensionBinding.java

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818

1919
package org.fcrepo.apix.binding.impl;
2020

21+
import java.io.ByteArrayInputStream;
22+
import java.io.IOException;
23+
import java.io.InputStream;
2124
import java.net.URI;
2225
import java.util.Collection;
2326
import java.util.Collections;
@@ -34,6 +37,7 @@
3437
import org.fcrepo.client.FcrepoClient;
3538
import org.fcrepo.client.FcrepoResponse;
3639

40+
import org.apache.commons.io.IOUtils;
3741
import org.osgi.service.component.annotations.Component;
3842
import org.osgi.service.component.annotations.ConfigurationPolicy;
3943
import org.osgi.service.component.annotations.Reference;
@@ -118,20 +122,32 @@ public Collection<Extension> getExtensionsFor(final WebResource resource) {
118122
public Collection<Extension> getExtensionsFor(final WebResource resource,
119123
final Collection<Extension> extensions) {
120124

121-
final Set<URI> rdfTypes = extensions.stream()
122-
.map(Extension::getResource)
123-
.peek(r -> LOG.debug("Examinining the ontology closure of extension {}", r.uri()))
124-
.map(ontologySvc::parseOntology)
125-
.flatMap(o -> ontologySvc.inferClasses(resource.uri(), resource, o).stream())
126-
.peek(rdfType -> LOG.debug("Instance {} is of class {}", resource.uri(), rdfType))
127-
.collect(Collectors.toSet());
128-
129-
return extensions.stream()
130-
.peek(e -> LOG.debug("Extension {} binds to instances of {}", e.uri(), e.bindingClass()))
131-
.filter(e -> rdfTypes.contains(e.bindingClass()))
132-
.peek(e -> LOG.debug("Extension {} bound to instance {} via {}", e.uri(), resource.uri(), e
133-
.bindingClass()))
134-
.collect(Collectors.toList());
125+
try (final InputStream resourceContent = resource.representation()) {
126+
127+
final byte[] content = IOUtils.toByteArray(resourceContent);
128+
129+
final Set<URI> rdfTypes = extensions.stream()
130+
.map(Extension::getResource)
131+
.peek(r -> LOG.debug("Examinining the ontology closure of extension {}", r.uri()))
132+
.map(ontologySvc::parseOntology)
133+
.flatMap(o -> ontologySvc.inferClasses(resource.uri(), cached(resource, content), o).stream())
134+
.peek(rdfType -> LOG.debug("Instance {} is of class {}", resource.uri(), rdfType))
135+
.collect(Collectors.toSet());
136+
137+
return extensions.stream()
138+
.peek(e -> LOG.debug("Extension {} binds to instances of {}", e.uri(), e.bindingClass()))
139+
.filter(e -> rdfTypes.contains(e.bindingClass()))
140+
.peek(e -> LOG.debug("Extension {} bound to instance {} via {}", e.uri(), resource.uri(), e
141+
.bindingClass()))
142+
.collect(Collectors.toList());
143+
} catch (final IOException e) {
144+
throw new RuntimeException(e);
145+
}
146+
}
147+
148+
private WebResource cached(final WebResource initial, final byte[] content) {
149+
return WebResource.of(new ByteArrayInputStream(content), initial.contentType(), initial.uri(), initial
150+
.name());
135151
}
136152

137153
/** Just does a dumb dereference and lookup */

fcrepo-api-x-loader/src/main/java/org/fcrepo/apix/loader/impl/LoaderRoutes.java

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
package org.fcrepo.apix.loader.impl;
2020

21+
import static org.apache.camel.Exchange.CONTENT_TYPE;
2122
import static org.apache.camel.Exchange.HTTP_RESPONSE_CODE;
2223

2324
import java.io.InputStream;
@@ -44,6 +45,8 @@ public class LoaderRoutes extends RouteBuilder {
4445

4546
private static final String ROUTE_NO_SERVICE = "direct:no_service";
4647

48+
private static final String ROUTE_OPTIONS = "direct:options";
49+
4750
LoaderService loaderService;
4851

4952
/**
@@ -57,14 +60,26 @@ public void setLoaderService(final LoaderService svc) {
5760

5861
@Override
5962
public void configure() throws Exception {
60-
restConfiguration().component("jetty").host("0.0.0.0").port("{{loader.port}}");
6163

62-
rest("/load")
63-
.get()
64-
.produces("text/html").to("language:simple:resource:classpath:form.html")
64+
from("jetty:http://0.0.0.0:{{loader.port}}/load" +
65+
"?matchOnUriPrefix=true&sendServerVersion=false&httpMethodRestrict=GET,OPTIONS,POST")
66+
.id("loader-http")
67+
.choice()
68+
69+
.when(header(Exchange.HTTP_METHOD).isEqualTo("GET"))
70+
.setHeader("Content-Type", constant("text/html"))
71+
.to("language:simple:resource:classpath:form.html")
72+
73+
.when(header(Exchange.HTTP_METHOD).isEqualTo("POST"))
74+
.to(ROUTE_PREPARE_LOAD)
75+
76+
.otherwise().to(ROUTE_OPTIONS);
6577

66-
.post().consumes("application/x-www-form-urlencoded, text/plain")
67-
.to(ROUTE_PREPARE_LOAD);
78+
from(ROUTE_OPTIONS).id("respond-options")
79+
.setHeader(CONTENT_TYPE).constant("text/turtle")
80+
.setHeader("Allow").constant("GET,OPTIONS,POST")
81+
.setHeader("Accept-Post").constant("application/x-www-form-urlencoded,text/plain")
82+
.to("language:simple:resource:classpath:options.ttl");
6883

6984
from(ROUTE_PREPARE_LOAD).id("load-prepare")
7085
.choice().when(header("Content-Type").isEqualTo("text/plain"))

fcrepo-api-x-loader/src/main/resources/OSGI-INF/blueprint/blueprint.xml

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,26 @@
3737
<property name="loaderService" ref="loaderService" />
3838
</bean>
3939

40-
<camel:camelContext id="apix-loader">
41-
<camel:routeBuilder ref="loaderRoutes" />
42-
</camel:camelContext>
40+
41+
<camelContext id="apix-loader"
42+
xmlns="http://camel.apache.org/schema/blueprint">
43+
<routeBuilder ref="loaderRoutes" />
44+
45+
<!-- Self-register the loader service as an extension -->
46+
<route id="load-extension">
47+
<from uri="timer:register?repeatCount=1" />
48+
<onException>
49+
<exception>java.lang.Exception</exception>
50+
<redeliveryPolicy maximumRedeliveries="10" logRetryAttempted="true" retryAttemptedLogLevel="INFO"/>
51+
</onException>
52+
<setHeader headerName="Content-Type">
53+
<constant>text/plain</constant>
54+
</setHeader>
55+
<setBody>
56+
<simple>http://localhost:{{loader.port}}/load</simple>
57+
</setBody>
58+
<to
59+
uri="jetty:http://localhost:{{loader.port}}/load?okStatusCodeRange=200-399" />
60+
</route>
61+
</camelContext>
4362
</blueprint>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@prefix apix:<http://fedora.info/definitions/v4/api-extension#> .
2+
@prefix fedora:<http://fedora.info/definitions/v4/repository#> .
3+
@prefix rdfs:<http://www.w3.org/2000/01/rdf-schema#> .
4+
5+
<> a apix:Extension;
6+
rdfs:label "Extension loader service";
7+
rdfs:comment "A service that automates loading and registration of extensions and services";
8+
apix:exposesService apix:LoaderService;
9+
apix:exposesServiceAt "/apix:load";
10+
apix:bindsTo fedora:RepositoryRoot .

0 commit comments

Comments
 (0)