Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Daylight is seen. FedoraVersions is now fully streaming, HTTP to JCR
  • Loading branch information
ajs6f committed Oct 30, 2013
1 parent f4fede9 commit fd9bf12
Show file tree
Hide file tree
Showing 7 changed files with 260 additions and 40 deletions.
Expand Up @@ -16,7 +16,9 @@

package org.fcrepo.http.api;

import static com.google.common.util.concurrent.Futures.addCallback;
import static javax.ws.rs.core.Response.noContent;
import static javax.ws.rs.core.Response.ok;
import static javax.ws.rs.core.Response.status;
import static javax.ws.rs.core.Response.Status.NOT_FOUND;
import static org.fcrepo.http.commons.domain.RDFMediaType.N3;
Expand Down Expand Up @@ -49,15 +51,14 @@

import org.fcrepo.http.commons.AbstractResource;
import org.fcrepo.http.commons.api.rdf.HttpGraphSubjects;
import org.fcrepo.http.commons.responses.GraphStoreStreamingOutput;
import org.fcrepo.http.commons.responses.RdfStreamStreamingOutput;
import org.fcrepo.http.commons.session.InjectedSession;
import org.fcrepo.kernel.FedoraResource;
import org.fcrepo.kernel.utils.LogoutCallback;
import org.slf4j.Logger;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.hp.hpl.jena.query.Dataset;

/**
* Endpoint for retrieving previous versions of nodes
*
Expand Down Expand Up @@ -97,21 +98,17 @@ public Response getVersionList(@PathParam("path")
final Variant bestPossibleResponse =
request.selectVariant(POSSIBLE_RDF_VARIANTS);

try {
final FedoraResource resource =
nodeService.getObject(session, path);
final FedoraResource resource = nodeService.getObject(session, path);

return Response.ok(
new GraphStoreStreamingOutput(resource
.getVersionTriples(new HttpGraphSubjects(session,
FedoraNodes.class,
uriInfo)),
bestPossibleResponse.getMediaType())).build();
final RdfStreamStreamingOutput streamOutput =
new RdfStreamStreamingOutput(resource
.getVersionTriples(new HttpGraphSubjects(session,
FedoraVersions.class, uriInfo)),
bestPossibleResponse.getMediaType(), session);

} finally {
session.logout();
}
addCallback(streamOutput, new LogoutCallback(session));

return ok(streamOutput).build();
}

/**
Expand Down Expand Up @@ -153,31 +150,37 @@ public Response addVersionLabel(@PathParam("path")
@Path("/{versionLabel}")
@GET
@Produces({TURTLE, N3, N3_ALT1, N3_ALT2, RDF_XML, RDF_JSON, NTRIPLES})
public Dataset getVersion(@PathParam("path")
public Response getVersion(@PathParam("path")
final List<PathSegment> pathList,
@PathParam("versionLabel")
final String versionLabel,
@Context
final Request request,
@Context
final UriInfo uriInfo) throws RepositoryException, IOException {
final String path = toPath(pathList);
LOGGER.trace("getting version profile for {} at version {}", path,
versionLabel);

try {
final FedoraResource resource =
nodeService.getObject(session, path, versionLabel);
final FedoraResource resource =
nodeService.getObject(session, path, versionLabel);

if (resource == null) {
throw new WebApplicationException(status(NOT_FOUND).build());
} else {
if (resource == null) {
throw new WebApplicationException(status(NOT_FOUND).build());
} else {

return resource.getPropertiesDataset(new HttpGraphSubjects(
session, FedoraNodes.class, uriInfo), 0, -1);
}
final Variant bestPossibleResponse =
request.selectVariant(POSSIBLE_RDF_VARIANTS);

} finally {
session.logout();
}
final RdfStreamStreamingOutput streamOutput =
new RdfStreamStreamingOutput(resource
.getTriples(new HttpGraphSubjects(session,
FedoraVersions.class, uriInfo)),
bestPossibleResponse.getMediaType(), session);

addCallback(streamOutput, new LogoutCallback(session));

return ok(streamOutput).build();
}
}
}
Expand Up @@ -24,7 +24,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
Expand Down Expand Up @@ -120,10 +119,13 @@ public void testGetVersion() throws RepositoryException, IOException {
when(
mockNodes.getObject(any(Session.class), any(String.class),
any(String.class))).thenReturn(mockResource);
testObj.getVersion(createPathList(pid), versionLabel, TestHelpers
when(mockRequest.selectVariant(POSSIBLE_RDF_VARIANTS)).thenReturn(
mockVariant);
when(mockVariant.getMediaType()).thenReturn(
new MediaType("text", "turtle"));
testObj.getVersion(createPathList(pid), versionLabel, mockRequest, TestHelpers
.getUriInfoImpl());
verify(mockResource).getPropertiesDataset(any(HttpGraphSubjects.class),
anyInt(), anyInt());
verify(mockResource).getTriples(any(HttpGraphSubjects.class));
}

}
Expand Up @@ -18,10 +18,10 @@

import static org.junit.Assert.assertEquals;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.util.EntityUtils;
import org.junit.Test;

public class FedoraVersionsIT extends AbstractResourceIT {
Expand All @@ -32,7 +32,10 @@ public void testGetObjectVersionProfile() throws Exception {
final HttpGet method =
new HttpGet(serverAddress + "FedoraDatastreamsTest1/fcr:versions");
final HttpResponse resp = execute(method);
assertEquals(200, resp.getStatusLine().getStatusCode());
final String profile = EntityUtils.toString(resp.getEntity());
assertEquals("Failed to retrieve version profile!\n" + profile, 200,
resp.getStatusLine().getStatusCode());
logger.debug("Retrieved version profile: \n{}", profile);
}

@Test
Expand All @@ -48,9 +51,10 @@ public void testAddVersion() throws Exception {
new HttpGet(serverAddress
+ "FedoraVersioningTest2/fcr:versions/v0.0.1");
final HttpResponse resp = execute(getVersion);
assertEquals(200, resp.getStatusLine().getStatusCode());
logger.info("Got version profile: {}", IOUtils.toString(resp
.getEntity().getContent()));
final String version = EntityUtils.toString(resp.getEntity());
assertEquals("Failed to retrieve new version!\n" + version, 200, resp
.getStatusLine().getStatusCode());
logger.info("Got version profile: {}", version);
}

@Test
Expand Down
16 changes: 16 additions & 0 deletions fcrepo-http-commons/pom.xml
Expand Up @@ -215,6 +215,22 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.openrdf.sesame</groupId>
<artifactId>sesame-rio-api</artifactId>
</dependency>
<dependency>
<groupId>org.openrdf.sesame</groupId>
<artifactId>sesame-rio-ntriples</artifactId>
</dependency>
<dependency>
<groupId>org.openrdf.sesame</groupId>
<artifactId>sesame-rio-rdfxml</artifactId>
</dependency>
<dependency>
<groupId>org.openrdf.sesame</groupId>
<artifactId>sesame-rio-turtle</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
Expand Up @@ -78,9 +78,8 @@ public abstract class RDFMediaType extends MediaType {
public static final MediaType NQUADS_TYPE = typeFromString(NQUADS);

public static final List<Variant> POSSIBLE_RDF_VARIANTS = mediaTypes(
N3_TYPE, N3_ALT1_TYPE, N3_ALT2_TYPE, TURTLE_TYPE, RDF_XML_TYPE,
RDF_JSON_TYPE, NTRIPLES_TYPE, TRI_G_TYPE, NQUADS_TYPE).add()
.build();
RDF_XML_TYPE, NTRIPLES_TYPE, TURTLE_TYPE, RDF_JSON_TYPE, N3_TYPE,
N3_ALT1_TYPE, N3_ALT2_TYPE, TRI_G_TYPE, NQUADS_TYPE).add().build();

private static MediaType typeFromString(final String type) {
return new MediaType(type.split("/")[0], type.split("/")[1]);
Expand Down
@@ -0,0 +1,138 @@
/**
* Copyright 2013 DuraSpace, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.fcrepo.http.commons.responses;

import static org.openrdf.model.impl.ValueFactoryImpl.getInstance;
import static org.openrdf.model.util.Literals.createLiteral;
import static org.openrdf.rio.RDFFormat.RDFXML;
import static org.openrdf.rio.RDFFormat.forMIMEType;
import static org.slf4j.LoggerFactory.getLogger;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;

import javax.jcr.Session;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.StreamingOutput;

import org.fcrepo.kernel.utils.iterators.RdfStream;
import org.openrdf.model.Statement;
import org.openrdf.model.Value;
import org.openrdf.model.ValueFactory;
import org.openrdf.rio.RDFFormat;
import org.openrdf.rio.RDFHandlerException;
import org.openrdf.rio.Rio;
import org.openrdf.rio.WriterConfig;
import org.slf4j.Logger;

import com.google.common.base.Function;
import com.google.common.util.concurrent.AbstractFuture;
import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.graph.Triple;

/**
* Serializes an {@link RdfStream}.
*
* @author ajs6f
* @date Oct 30, 2013
*/
public class RdfStreamStreamingOutput extends AbstractFuture<Session> implements
StreamingOutput {

private static final Logger LOGGER =
getLogger(RdfStreamStreamingOutput.class);

private static ValueFactory vfactory = getInstance();

private final RDFFormat format;

private final RdfStream rdfStream;

/**
* This should be passed in as the {@link Session} in which the
* {@link RdfStream} to be serialized is rooted. It will be made available
* again after serialization for further operation via the {@link Future}
* methods.
*/
private final Session session;

/**
* Normal constructor
*
* @param rdfStream
* @param mediaType
*/
public RdfStreamStreamingOutput(final RdfStream rdfStream,
final MediaType mediaType, final Session session) {
super();
this.format = forMIMEType(mediaType.toString(), RDFXML);
this.rdfStream = rdfStream;
this.session = session;
}

@Override
public void write(final OutputStream output) throws IOException,
WebApplicationException {
LOGGER.debug("Serializing RDF stream in: {}", format);
try {
Rio.write(asStatements(), output, format, new WriterConfig());
} catch (final RDFHandlerException e) {
setException(e);
} finally {
// we're done.
set(session);
}
}

private Iterable<Statement> asStatements() {
return new Iterable<Statement>() {

@Override
public Iterator<Statement> iterator() {
return rdfStream.transform(toStatement);
}
};
}

protected static final Function<? super Triple, Statement> toStatement =
new Function<Triple, Statement>() {

@Override
public Statement apply(final Triple t) {
final Value object = getValueForObject(t.getObject());
return vfactory.createStatement(vfactory.createURI(t
.getSubject().getURI()), vfactory.createURI(t
.getPredicate().getURI()), object);
}

};

protected static Value getValueForObject(final Node object) {
if (object.isURI()) {
return vfactory.createURI(object.getURI());
} else {
if (object.isLiteral()) {
return createLiteral(vfactory, object.getLiteralValue());
}
}
throw new UnsupportedOperationException(
"We do not serialize blank nodes!");

}

}

0 comments on commit fd9bf12

Please sign in to comment.