Skip to content

Commit

Permalink
Merge pull request #568 from fcrepo4/ldp-constraints
Browse files Browse the repository at this point in the history
Ldp constraints
  • Loading branch information
Andrew Woods committed Oct 22, 2014
2 parents 40bf251 + 32018ab commit 14f4fe0
Show file tree
Hide file tree
Showing 13 changed files with 183 additions and 29 deletions.
Expand Up @@ -32,6 +32,7 @@
import org.fcrepo.kernel.FedoraBinary;
import org.fcrepo.kernel.FedoraResource;
import org.fcrepo.kernel.exception.InvalidChecksumException;
import org.fcrepo.kernel.exception.MalformedRdfException;
import org.fcrepo.kernel.exception.RepositoryRuntimeException;
import org.fcrepo.kernel.impl.rdf.ManagedRdf;
import org.fcrepo.kernel.impl.rdf.impl.AclRdfContext;
Expand Down Expand Up @@ -513,7 +514,7 @@ protected void replaceResourceBinaryWithStream(final FedoraBinary result,
protected void replaceResourceWithStream(final FedoraResource resource,
final InputStream requestBodyStream,
final MediaType contentType,
final RdfStream resourceTriples) {
final RdfStream resourceTriples) throws MalformedRdfException {
final Lang format = contentTypeToLang(contentType.toString());

final Model inputModel = createDefaultModel()
Expand All @@ -524,7 +525,7 @@ protected void replaceResourceWithStream(final FedoraResource resource,

protected void patchResourcewithSparql(final FedoraResource resource,
final String requestBody,
final RdfStream resourceTriples) {
final RdfStream resourceTriples) throws MalformedRdfException {
resource.updateProperties(translator(), requestBody, resourceTriples);
}

Expand Down
Expand Up @@ -28,6 +28,7 @@
import org.fcrepo.kernel.FedoraObject;
import org.fcrepo.kernel.FedoraResource;
import org.fcrepo.kernel.exception.InvalidChecksumException;
import org.fcrepo.kernel.exception.MalformedRdfException;
import org.fcrepo.kernel.exception.RepositoryRuntimeException;
import org.fcrepo.kernel.utils.iterators.RdfStream;
import org.glassfish.jersey.media.multipart.ContentDisposition;
Expand Down Expand Up @@ -222,7 +223,7 @@ public Response createOrReplaceObjectRdf(
@QueryParam("checksum") final String checksum,
@HeaderParam("Content-Disposition") final ContentDisposition contentDisposition,
@HeaderParam("If-Match") final String ifMatch)
throws InvalidChecksumException, IOException {
throws InvalidChecksumException, IOException, MalformedRdfException {

final FedoraResource resource;
final Response.ResponseBuilder response;
Expand Down Expand Up @@ -300,7 +301,8 @@ && isRdfContentType(contentType.toString())) {
@PATCH
@Consumes({contentTypeSPARQLUpdate})
@Timed
public Response updateSparql(@ContentLocation final InputStream requestBodyStream) throws IOException {
public Response updateSparql(@ContentLocation final InputStream requestBodyStream)
throws IOException, MalformedRdfException {

if (null == requestBodyStream) {
throw new BadRequestException("SPARQL-UPDATE requests must have content!");
Expand Down Expand Up @@ -365,7 +367,7 @@ public Response createObject(@QueryParam("mixin") final String mixin,
@HeaderParam("Content-Type") final MediaType requestContentType,
@HeaderParam("Slug") final String slug,
@ContentLocation final InputStream requestBodyStream)
throws InvalidChecksumException, IOException {
throws InvalidChecksumException, IOException, MalformedRdfException {

if (!(resource() instanceof FedoraObject)) {
throw new ClientErrorException("Object cannot have child nodes", CONFLICT);
Expand Down
Expand Up @@ -15,14 +15,17 @@
*/
package org.fcrepo.http.commons.exceptionhandlers;

import org.apache.commons.codec.binary.Base64;
import org.fcrepo.kernel.exception.MalformedRdfException;

import javax.ws.rs.core.Link;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

import static javax.ws.rs.core.Response.Status.CONFLICT;
import static javax.ws.rs.core.Response.status;
import static org.fcrepo.kernel.RdfLexicon.CONSTRAINED_BY;

/**
* @author cabeer
Expand All @@ -33,6 +36,11 @@ public class MalformedRdfExceptionMapper implements ExceptionMapper<MalformedRdf

@Override
public Response toResponse(final MalformedRdfException e) {
return status(CONFLICT).entity(e.getMessage()).build();
final Link link = Link.fromUri(getConstraintUri(e)).rel(CONSTRAINED_BY.getURI()).build();
return status(CONFLICT).entity(e.getMessage()).links(link).build();
}

private static String getConstraintUri(final MalformedRdfException e) {
return "data:text/plain;base64," + Base64.encodeBase64String(e.getMessage().getBytes());
}
}
@@ -0,0 +1,55 @@
/**
* Copyright 2014 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.exceptionhandlers;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.fcrepo.kernel.exception.MalformedRdfException;
import org.junit.Before;
import org.junit.Test;

import javax.ws.rs.core.Link;
import javax.ws.rs.core.Response;

import java.io.IOException;

import static org.fcrepo.kernel.RdfLexicon.CONSTRAINED_BY;
import static org.junit.Assert.assertEquals;

/**
* @author cabeer
*/
public class MalformedRdfExceptionMapperTest {

private MalformedRdfExceptionMapper testObj;

@Before
public void setUp() {
testObj = new MalformedRdfExceptionMapper();

}
@Test
public void testToResponse() throws IOException {
final Response response = testObj.toResponse(new MalformedRdfException("xyz"));

final Link link = response.getLink(CONSTRAINED_BY.getURI());
assertEquals(CONSTRAINED_BY.getURI(), link.getRel());
assertEquals("data", link.getUri().getScheme());
final String[] split = link.getUri().toString().split(",", 2);
assertEquals("Constraint data appears malformed", 2, split.length);
assertEquals("xyz", IOUtils.toString(Base64.decodeBase64(split[1].getBytes()), "UTF-8"));
}
}
Expand Up @@ -72,6 +72,7 @@ public void runLDPTestSuite() throws IOException {
options.put("server", serverAddress + pid);
options.put("direct", "true");
options.put("non-rdf", "true");
options.put("read-only-prop", "http://fedora.info/definitions/v4/repository#uuid");
final LdpTestSuite testSuite = new LdpTestSuite(options);
testSuite.run();
assertTrue("The LDP test suite is only informational", true);
Expand Down
Expand Up @@ -58,6 +58,7 @@
import org.fcrepo.kernel.Datastream;
import org.fcrepo.kernel.FedoraBinary;
import org.fcrepo.kernel.FedoraResource;
import org.fcrepo.kernel.exception.MalformedRdfException;
import org.fcrepo.kernel.exception.PathNotFoundRuntimeException;
import org.fcrepo.kernel.exception.RepositoryRuntimeException;
import org.fcrepo.kernel.identifiers.IdentifierConverter;
Expand Down Expand Up @@ -360,7 +361,8 @@ public boolean hasType(final String type) {
*/
@Override
public void updateProperties(final IdentifierConverter<Resource, FedoraResource> subjects,
final String sparqlUpdateStatement, final RdfStream originalTriples) {
final String sparqlUpdateStatement, final RdfStream originalTriples)
throws MalformedRdfException {

final Model model = originalTriples.asModel();

Expand Down Expand Up @@ -465,21 +467,31 @@ public Boolean isNew() {
*/
@Override
public void replaceProperties(final IdentifierConverter<Resource, FedoraResource> graphSubjects,
final Model inputModel, final RdfStream originalTriples) {
final Model inputModel, final RdfStream originalTriples) throws MalformedRdfException {

final RdfStream replacementStream = new RdfStream().namespaces(inputModel.getNsPrefixMap());

final GraphDifferencingIterator differencer =
new GraphDifferencingIterator(inputModel, originalTriples);

final StringBuilder exceptions = new StringBuilder();
try {
new RdfRemover(graphSubjects, getSession(), replacementStream
.withThisContext(differencer)).consume();
} catch (final MalformedRdfException e) {
exceptions.append(e.getMessage());
exceptions.append("\n");
}

try {
new RdfAdder(graphSubjects, getSession(), replacementStream
.withThisContext(differencer.notCommon())).consume();
} catch (final RepositoryException e) {
throw new RepositoryRuntimeException(e);
} catch (final MalformedRdfException e) {
exceptions.append(e.getMessage());
}

if (exceptions.length() > 0) {
throw new MalformedRdfException(exceptions.toString());
}
}

Expand Down
Expand Up @@ -23,6 +23,7 @@
import com.google.common.base.Joiner;
import org.fcrepo.kernel.FedoraResource;
import org.fcrepo.kernel.exception.MalformedRdfException;
import org.fcrepo.kernel.exception.RepositoryRuntimeException;
import org.fcrepo.kernel.identifiers.IdentifierConverter;
import org.fcrepo.kernel.impl.rdf.JcrRdfTools;
import org.slf4j.Logger;
Expand Down Expand Up @@ -110,7 +111,7 @@ public void addedStatement(final Statement input) {
}

jcrRdfTools.addProperty(resource, property, objectNode, input.getModel().getNsPrefixMap());
} catch (final RepositoryException e) {
} catch (final RepositoryException | RepositoryRuntimeException e) {
exceptions.add(e.getMessage());
}

Expand Down Expand Up @@ -153,7 +154,7 @@ public void removedStatement(final Statement s) {

jcrRdfTools.removeProperty(resource, property, objectNode, s.getModel().getNsPrefixMap());

} catch (final RepositoryException e) {
} catch (final RepositoryException | RepositoryRuntimeException e) {
exceptions.add(e.getMessage());
}

Expand All @@ -162,7 +163,7 @@ public void removedStatement(final Statement s) {
/**
* Assert that no exceptions were thrown while this listener was processing change
*/
public void assertNoExceptions() {
public void assertNoExceptions() throws MalformedRdfException {
if (!exceptions.isEmpty()) {
throw new MalformedRdfException(Joiner.on("\n").join(exceptions));
}
Expand Down
Expand Up @@ -20,6 +20,7 @@
import static org.fcrepo.kernel.impl.rdf.ManagedRdf.isManagedMixin;
import static org.slf4j.LoggerFactory.getLogger;

import com.google.common.base.Joiner;
import org.fcrepo.kernel.FedoraResource;
import org.fcrepo.kernel.exception.MalformedRdfException;
import org.fcrepo.kernel.exception.RepositoryRuntimeException;
Expand All @@ -41,6 +42,9 @@
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;

import java.util.ArrayList;
import java.util.List;

/**
* @author ajs6f
* @since Oct 24, 2013
Expand All @@ -62,6 +66,8 @@ public abstract class PersistingRdfStreamConsumer implements RdfStreamConsumer {

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

private final List<String> exceptions;

/**
* Ordinary constructor.
*
Expand Down Expand Up @@ -95,20 +101,29 @@ public boolean apply(final Triple t) {
this.stream =
stream.withThisContext(stream.filter(isFedoraSubjectTriple));
this.session = session;

this.exceptions = new ArrayList<>();
}

@Override
public void consume() throws RepositoryException {
public void consume() throws MalformedRdfException {
while (stream.hasNext()) {
final Statement t = m.asStatement(stream.next());
LOGGER.debug("Operating triple {}.", t);

operateOnTriple(t);
try {
operateOnTriple(t);
} catch (final MalformedRdfException e) {
exceptions.add(e.getMessage());
}
}

if (!exceptions.isEmpty()) {
throw new MalformedRdfException(Joiner.on("\n").join(exceptions));
}
}

protected void operateOnTriple(final Statement input) {
protected void operateOnTriple(final Statement input) throws MalformedRdfException {
try {

final Statement t = jcrRdfTools.skolemize(idTranslator, input);
Expand Down

0 comments on commit 14f4fe0

Please sign in to comment.