From 63fcf226fc65456971144670428e56a8b4cf3145 Mon Sep 17 00:00:00 2001 From: Andrew Woods Date: Thu, 7 Jul 2016 15:03:48 -0400 Subject: [PATCH] Allow resources that are referenced by other versioned resources to be deleted Resolves: https://jira.duraspace.org/browse/FCREPO-2074 --- .../kernel/modeshape/FedoraResourceImpl.java | 12 ++++-- .../modeshape/FedoraResourceImplIT.java | 39 +++++++++++++++++++ 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/fcrepo-kernel-modeshape/src/main/java/org/fcrepo/kernel/modeshape/FedoraResourceImpl.java b/fcrepo-kernel-modeshape/src/main/java/org/fcrepo/kernel/modeshape/FedoraResourceImpl.java index 7d7bd2a466..ddbb93f42e 100644 --- a/fcrepo-kernel-modeshape/src/main/java/org/fcrepo/kernel/modeshape/FedoraResourceImpl.java +++ b/fcrepo-kernel-modeshape/src/main/java/org/fcrepo/kernel/modeshape/FedoraResourceImpl.java @@ -26,8 +26,6 @@ import static java.util.stream.Stream.empty; import static java.util.stream.Stream.of; import static org.apache.commons.codec.digest.DigestUtils.shaHex; -import static org.fcrepo.kernel.api.FedoraTypes.FEDORA_LASTMODIFIED; -import static org.fcrepo.kernel.api.FedoraTypes.FEDORA_REPOSITORY_ROOT; import static org.fcrepo.kernel.api.RdfLexicon.LAST_MODIFIED_DATE; import static org.fcrepo.kernel.api.RdfLexicon.REPOSITORY_NAMESPACE; import static org.fcrepo.kernel.api.RdfLexicon.isManagedNamespace; @@ -157,6 +155,7 @@ public class FedoraResourceImpl extends JcrTools implements FedoraTypes, FedoraR private static final String JCR_CHILD_VERSION_HISTORY = "jcr:childVersionHistory"; private static final String JCR_VERSIONABLE_UUID = "jcr:versionableUuid"; private static final String JCR_FROZEN_UUID = "jcr:frozenUuid"; + private static final String JCR_VERSION_STORAGE = "jcr:versionStorage"; private static final PropertyConverter propertyConverter = new PropertyConverter(); @@ -378,7 +377,14 @@ public void delete() { prop.setValue(newVals.toArray(new Value[newVals.size()])); } } catch (final RepositoryException ex) { - throw new RepositoryRuntimeException(ex); + // Ignore error from trying to update properties on versioned resources + if (ex instanceof javax.jcr.nodetype.ConstraintViolationException && + ex.getMessage().contains(JCR_VERSION_STORAGE)) { + LOGGER.debug("Ignoring exception trying to remove property from versioned resource: {}", + ex.getMessage()); + } else { + throw new RepositoryRuntimeException(ex); + } } }); diff --git a/fcrepo-kernel-modeshape/src/test/java/org/fcrepo/integration/kernel/modeshape/FedoraResourceImplIT.java b/fcrepo-kernel-modeshape/src/test/java/org/fcrepo/integration/kernel/modeshape/FedoraResourceImplIT.java index a2227756f0..b08fa227c6 100644 --- a/fcrepo-kernel-modeshape/src/test/java/org/fcrepo/integration/kernel/modeshape/FedoraResourceImplIT.java +++ b/fcrepo-kernel-modeshape/src/test/java/org/fcrepo/integration/kernel/modeshape/FedoraResourceImplIT.java @@ -1005,6 +1005,45 @@ public void testVersionedChildBinaryDeleted() throws RepositoryException, Invali } } + @Test + public void testDeleteLinkedVersionedResources() throws RepositoryException { + final Container object1 = containerService.findOrCreate(session, "/" + getRandomPid()); + final Container object2 = containerService.findOrCreate(session, "/" + getRandomPid()); + + // Create a link between objects 1 and 2 + object2.updateProperties(subjects, "PREFIX example: \n" + + "INSERT { <> " + "<" + createGraphSubjectNode(object1).getURI() + ">" + + " } WHERE {} ", + object2.getTriples(subjects, emptySet())); + + // Create version of object2 + versionService.createVersion(session, object2.getPath(), "obj2-v0"); + + // Verify that the objects exist + assertTrue("object1 should exist!", exists(object1)); + assertTrue("object2 should exist!", exists(object2)); + + // This is the test: verify successful deletion of the objects + object2.delete(); + session.save(); + + object1.delete(); + session.save(); + + // Double-verify that the objects are gone + assertFalse("/object2 should NOT exist!", exists(object2)); + assertFalse("/object1 should NOT exist!", exists(object1)); + } + + private boolean exists(final Container resource) { + try { + resource.getPath(); + return true; + } catch (RepositoryRuntimeException e) { + return false; + } + } + @Test (expected = RepositoryRuntimeException.class) public void testNullBaseVersion() throws RepositoryException { final String pid = getRandomPid();