diff --git a/fcrepo-client-impl/src/main/java/org/fcrepo/client/impl/FedoraObjectImpl.java b/fcrepo-client-impl/src/main/java/org/fcrepo/client/impl/FedoraObjectImpl.java index 41779db..d5faccf 100644 --- a/fcrepo-client-impl/src/main/java/org/fcrepo/client/impl/FedoraObjectImpl.java +++ b/fcrepo-client-impl/src/main/java/org/fcrepo/client/impl/FedoraObjectImpl.java @@ -40,7 +40,7 @@ * @since 2014-08-11 */ public class FedoraObjectImpl extends FedoraResourceImpl implements FedoraObject { - private final static Node binaryType = NodeFactory.createLiteral("fedora:binary"); + private final static Node binaryType = NodeFactory.createLiteral("fedora:Binary"); /** * Constructor for FedoraObjectImpl diff --git a/fcrepo-client-impl/src/main/java/org/fcrepo/client/impl/FedoraRepositoryImpl.java b/fcrepo-client-impl/src/main/java/org/fcrepo/client/impl/FedoraRepositoryImpl.java index 2612237..95cacc8 100644 --- a/fcrepo-client-impl/src/main/java/org/fcrepo/client/impl/FedoraRepositoryImpl.java +++ b/fcrepo-client-impl/src/main/java/org/fcrepo/client/impl/FedoraRepositoryImpl.java @@ -16,12 +16,14 @@ package org.fcrepo.client.impl; import com.hp.hpl.jena.graph.Triple; + import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpHead; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; +import org.fcrepo.client.AlreadyExistsException; import org.fcrepo.client.FedoraContent; import org.fcrepo.client.FedoraDatastream; import org.fcrepo.client.FedoraException; @@ -147,7 +149,7 @@ public FedoraDatastream createDatastream(final String path, final FedoraContent throw new ForbiddenException("request to create resource " + uri + " is not authorized."); } else if (statusCode == SC_CONFLICT) { LOGGER.error("resource {} already exists", uri); - throw new FedoraException("resource " + uri + " already exists"); + throw new AlreadyExistsException("resource " + uri + " already exists"); } else { LOGGER.error("error creating resource {}: {} {}", uri, statusCode, status.getReasonPhrase()); throw new FedoraException("error retrieving resource " + uri + ": " + statusCode + " " + @@ -206,7 +208,7 @@ public FedoraObject createObject(final String path) throws FedoraException { throw new ForbiddenException("request to create resource " + uri + " is not authorized."); } else if (statusCode == SC_CONFLICT) { LOGGER.error("resource {} already exists", uri); - throw new FedoraException("resource " + uri + " already exists"); + throw new AlreadyExistsException("resource " + uri + " already exists"); } else { LOGGER.error("error creating resource {}: {} {}", uri, statusCode, status.getReasonPhrase()); throw new FedoraException("error retrieving resource " + uri + ": " + statusCode + " " + diff --git a/fcrepo-client-impl/src/main/java/org/fcrepo/client/impl/FedoraResourceImpl.java b/fcrepo-client-impl/src/main/java/org/fcrepo/client/impl/FedoraResourceImpl.java index 55575e4..2a43c31 100644 --- a/fcrepo-client-impl/src/main/java/org/fcrepo/client/impl/FedoraResourceImpl.java +++ b/fcrepo-client-impl/src/main/java/org/fcrepo/client/impl/FedoraResourceImpl.java @@ -19,7 +19,6 @@ import static org.apache.http.HttpStatus.SC_FORBIDDEN; import static org.apache.http.HttpStatus.SC_NO_CONTENT; import static org.apache.http.HttpStatus.SC_NOT_FOUND; - import static org.slf4j.LoggerFactory.getLogger; import java.io.IOException; @@ -32,23 +31,22 @@ import java.util.Iterator; import java.util.Set; -import org.apache.http.client.methods.HttpPost; -import org.apache.jena.atlas.lib.NotImplemented; - import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; import org.apache.http.StatusLine; +import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpPatch; +import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; - import org.fcrepo.client.FedoraException; import org.fcrepo.client.FedoraRepository; import org.fcrepo.client.FedoraResource; import org.fcrepo.client.ForbiddenException; import org.fcrepo.client.NotFoundException; -import org.fcrepo.client.ReadOnlyException; +import org.fcrepo.client.utils.HttpCopy; import org.fcrepo.client.utils.HttpHelper; +import org.fcrepo.client.utils.HttpMove; import org.fcrepo.kernel.RdfLexicon; - import org.slf4j.Logger; import com.hp.hpl.jena.graph.Graph; @@ -76,6 +74,8 @@ public class FedoraResourceImpl implements FedoraResource { protected String path = null; + protected String oldPath = null; + protected Node subject = null; protected Graph graph; @@ -97,15 +97,118 @@ public FedoraResourceImpl(final FedoraRepository repository, final HttpHelper ht } @Override - public void copy(final String destination) throws ReadOnlyException { - // TODO Auto-generated method stub - throw new NotImplemented("Method copy(final String destination) is not implemented."); + public void copy(final String destination) throws FedoraException { + + final HttpCopy copy = httpHelper.createCopyMethod(path,destination); + + try { + final HttpResponse response = httpHelper.execute( copy ); + final StatusLine status = response.getStatusLine(); + final String uri = copy.getURI().toString(); + + if (status.getStatusCode() == HttpStatus.SC_CREATED) { // Created + LOGGER.debug("resource successfully copied from " + path + " to " + destination, uri); + } else if (status.getStatusCode() == HttpStatus.SC_CONFLICT) { // Source path doesn't exists + LOGGER.error("error copying resource {}: {} {}", uri, status.getStatusCode(), + status.getReasonPhrase()); + throw new FedoraException("error copying resource " + uri + ": " + status.getStatusCode() + " " + + status.getReasonPhrase()); + } else if (status.getStatusCode() == HttpStatus.SC_PRECONDITION_FAILED) { // Destination path already exists + LOGGER.error("error copying resource {}: {} {}", uri, status.getStatusCode(), + status.getReasonPhrase()); + throw new FedoraException("error copying resource " + uri + ": " + status.getStatusCode() + " " + + status.getReasonPhrase()); + } else if (status.getStatusCode() == HttpStatus.SC_BAD_GATEWAY) { + // Destination URI isn't a valid resource path + LOGGER.error("error copying resource {}: {} {}", uri, status.getStatusCode(), + status.getReasonPhrase()); + throw new FedoraException("error copying resource " + uri + ": " + status.getStatusCode() + " " + + status.getReasonPhrase()); + } + } catch (final FedoraException e) { + throw e; + } catch (final Exception e) { + LOGGER.error("could not encode URI parameter", e); + throw new FedoraException(e); + } finally { + copy.releaseConnection(); + } + } + + @Override + public void delete() throws FedoraException { + final HttpDelete delete = httpHelper.createDeleteMethod(path); + + try { + final HttpResponse response = httpHelper.execute( delete ); + final StatusLine status = response.getStatusLine(); + final String uri = delete.getURI().toString(); + + if ( status.getStatusCode() == SC_NO_CONTENT) { + LOGGER.debug("triples updated successfully for resource {}", uri); + } else if ( status.getStatusCode() == SC_NOT_FOUND) { + LOGGER.error("resource {} does not exist, cannot update", uri); + throw new NotFoundException("resource " + uri + " does not exist, cannot update"); + } else { + LOGGER.error("error updating resource {}: {} {}", uri, status.getStatusCode(), + status.getReasonPhrase()); + throw new FedoraException("error updating resource " + uri + ": " + status.getStatusCode() + " " + + status.getReasonPhrase()); + } + } catch (final FedoraException e) { + throw e; + } catch (final Exception e) { + LOGGER.error("Error executing request", e); + throw new FedoraException(e); + } finally { + delete.releaseConnection(); + } } @Override - public void delete() throws ReadOnlyException { - // TODO Auto-generated method stub - throw new NotImplemented("Method delete() is not implemented."); + public void forceDelete() throws FedoraException { + delete(); + removeTombstone(); + } + + /** + * Remove tombstone (for the current path) + */ + public void removeTombstone() throws FedoraException { + removeTombstone(path); + } + + + /** + * Remove tombstone located at given path + */ + public void removeTombstone(final String path) throws FedoraException { + final HttpDelete delete = httpHelper.createDeleteMethod(path + "/fcr:tombstone"); + + try { + final HttpResponse response = httpHelper.execute( delete ); + final StatusLine status = response.getStatusLine(); + final String uri = delete.getURI().toString(); + + if ( status.getStatusCode() == SC_NO_CONTENT) { + LOGGER.debug("triples updated successfully for resource {}", uri); + } else if ( status.getStatusCode() == SC_NOT_FOUND) { + LOGGER.error("resource {} does not exist, cannot update", uri); + throw new NotFoundException("resource " + uri + " does not exist, cannot update"); + } else { + LOGGER.error("error updating resource {}: {} {}", uri, status.getStatusCode(), + status.getReasonPhrase()); + throw new FedoraException("error updating resource " + uri + ": " + status.getStatusCode() + " " + + status.getReasonPhrase()); + } + } catch (final FedoraException e) { + throw e; + } catch (final Exception e) { + LOGGER.error("Error executing request", e); + throw new FedoraException(e); + } finally { + delete.releaseConnection(); + } } @Override @@ -160,9 +263,52 @@ public Long getSize() { } @Override - public void move(final String destination) throws ReadOnlyException { - // TODO Auto-generated method stub - throw new NotImplemented("Method move(final String destination) is not implemented."); + public void move(final String destination) throws FedoraException { + final HttpMove move = httpHelper.createMoveMethod(path,destination); + + try { + final HttpResponse response = httpHelper.execute( move ); + final StatusLine status = response.getStatusLine(); + final String uri = move.getURI().toString(); + + if (status.getStatusCode() == HttpStatus.SC_CREATED) { // Created + LOGGER.debug("resource successfully moved from " + path + " to " + destination, uri); + oldPath = path; + path = destination; + subject = NodeFactory.createURI(repository.getRepositoryUrl() + path); + } else if (status.getStatusCode() == HttpStatus.SC_CONFLICT) { // Source path doesn't exists + LOGGER.error("error moving resource {}: {} {}", uri, status.getStatusCode(), + status.getReasonPhrase()); + throw new FedoraException("error moving resource " + uri + ": " + status.getStatusCode() + + " " + status.getReasonPhrase()); + } else if (status.getStatusCode() == HttpStatus.SC_PRECONDITION_FAILED) { + // Destination path already exists + LOGGER.error("error moving resource {}: {} {}", uri, status.getStatusCode(), + status.getReasonPhrase()); + throw new FedoraException("error moving resource " + uri + ": " + status.getStatusCode() + " " + + status.getReasonPhrase()); + } else if (status.getStatusCode() == HttpStatus.SC_BAD_GATEWAY) { + // Destination URI isn't a valid resource path + LOGGER.error("error moving resource {}: {} {}", uri, status.getStatusCode(), + status.getReasonPhrase()); + throw new FedoraException("error moving resource " + uri + ": " + status.getStatusCode() + " " + + status.getReasonPhrase()); + } + } catch (final FedoraException e) { + oldPath = null; + throw e; + } catch (final Exception e) { + LOGGER.error("could not encode URI parameter", e); + throw new FedoraException(e); + } finally { + move.releaseConnection(); + } + } + + @Override + public void forceMove(final String destination) throws FedoraException { + move(destination); + removeTombstone(oldPath); } @Override diff --git a/fcrepo-client-impl/src/main/java/org/fcrepo/client/utils/HttpCopy.java b/fcrepo-client-impl/src/main/java/org/fcrepo/client/utils/HttpCopy.java new file mode 100644 index 0000000..ac87415 --- /dev/null +++ b/fcrepo-client-impl/src/main/java/org/fcrepo/client/utils/HttpCopy.java @@ -0,0 +1,63 @@ +/** + * Copyright 2015 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.client.utils; + +import java.net.URI; + +import org.apache.http.HttpHeaders; +import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; + +/** + * HTTP copy + * + * @author sleroux + * @since 2015-06-03 + **/ +public class HttpCopy extends HttpEntityEnclosingRequestBase { + + /** + * Create an HTTP COPY request. + * + * @param source + * Source URL. + * @param destination + * Destination URL. + **/ + public HttpCopy(final URI source, final URI destination) { + this.setHeader(HttpHeaders.DESTINATION, destination.toASCIIString()); + this.setURI(source); + } + + /** + * Create an HTTP COPY request. + * + * @param source + * Source String URL. + * @param destination + * Destination String URL. + **/ + public HttpCopy(final String source, final String destination) { + this(URI.create(source), URI.create(destination)); + } + + /** + * Returns the request method. + **/ + @Override + public String getMethod() { + return "COPY"; + } +} diff --git a/fcrepo-client-impl/src/main/java/org/fcrepo/client/utils/HttpHelper.java b/fcrepo-client-impl/src/main/java/org/fcrepo/client/utils/HttpHelper.java index 6f44f59..ec8d2a5 100644 --- a/fcrepo-client-impl/src/main/java/org/fcrepo/client/utils/HttpHelper.java +++ b/fcrepo-client-impl/src/main/java/org/fcrepo/client/utils/HttpHelper.java @@ -50,6 +50,7 @@ import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpHead; import org.apache.http.client.methods.HttpPatch; @@ -201,6 +202,15 @@ public HttpGet createGetMethod(final String path, final Map return new HttpGet(repositoryURL + path + queryString(params)); } + /** + * Create DELETE method + * @param path Resource path, relative to repository baseURL + * @return DELETE method + **/ + public HttpDelete createDeleteMethod(final String path) { + return new HttpDelete(repositoryURL + path); + } + /** * Create a request to update triples with SPARQL Update. * @param path The datastream path. @@ -359,4 +369,24 @@ public FedoraResourceImpl loadProperties( final FedoraResourceImpl resource ) th } } + /** + * Create COPY method + * @param sourcePath Source path, relative to repository baseURL + * @param destinationPath Destination path, relative to repository baseURL + * @return COPY method + **/ + public HttpCopy createCopyMethod(final String sourcePath, final String destinationPath) { + return new HttpCopy(repositoryURL + sourcePath, repositoryURL + destinationPath); + } + + /** + * Create MOVE method + * @param sourcePath Source path, relative to repository baseURL + * @param destinationPath Destination path, relative to repository baseURL + * @return MOVE method + **/ + public HttpMove createMoveMethod(final String sourcePath, final String destinationPath) { + return new HttpMove(repositoryURL + sourcePath, repositoryURL + destinationPath); + } + } diff --git a/fcrepo-client-impl/src/main/java/org/fcrepo/client/utils/HttpMove.java b/fcrepo-client-impl/src/main/java/org/fcrepo/client/utils/HttpMove.java new file mode 100644 index 0000000..5c97c35 --- /dev/null +++ b/fcrepo-client-impl/src/main/java/org/fcrepo/client/utils/HttpMove.java @@ -0,0 +1,63 @@ +/** + * Copyright 2015 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.client.utils; + +import java.net.URI; + +import org.apache.http.HttpHeaders; +import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; + +/** + * HTTP move + * + * @author sleroux + * @since 2015-06-03 + **/ +public class HttpMove extends HttpEntityEnclosingRequestBase { + + /** + * Create an HTTP MOVE request. + * + * @param source + * Source String URL. + * @param destination + * Destination String URL. + **/ + public HttpMove(final String source, final String destination) { + this(URI.create(source), URI.create(destination)); + } + + /** + * Create an HTTP MOVE request. + * + * @param source + * Source URL. + * @param destination + * Destination URL. + **/ + public HttpMove(final URI source, final URI destination) { + this.setHeader(HttpHeaders.DESTINATION, destination.toASCIIString()); + this.setURI(source); + } + + /** + * Returns the request method. + **/ + @Override + public String getMethod() { + return "MOVE"; + } +} diff --git a/fcrepo-client-impl/src/test/java/org/fcrepo/client/impl/FedoraObjectImplTest.java b/fcrepo-client-impl/src/test/java/org/fcrepo/client/impl/FedoraObjectImplTest.java index afbb65c..acbbd6d 100644 --- a/fcrepo-client-impl/src/test/java/org/fcrepo/client/impl/FedoraObjectImplTest.java +++ b/fcrepo-client-impl/src/test/java/org/fcrepo/client/impl/FedoraObjectImplTest.java @@ -80,6 +80,11 @@ public class FedoraObjectImplTest { private FedoraObject customChild; private FedoraDatastream datastreamChild; + private static String BINARY = "fedora:Binary"; + private static String CONTAINER = "fedora:Container"; + private static String CUSTOM = "fedora:Custom"; + private static String BOGUS_MIXIN = "bogus:mixin"; + @Before public void setUp() throws FedoraException { initMocks(this); @@ -94,9 +99,9 @@ public void setUp() throws FedoraException { graph.add( create(objectSubj, CONTAINS.asNode(), datastreamChildSubj) ); graph.add( create(objectSubj, CONTAINS.asNode(), objectChildSubj) ); graph.add( create(objectSubj, CONTAINS.asNode(), customChildSubj) ); - graph.add( create(datastreamChildSubj, HAS_MIXIN_TYPE.asNode(), createLiteral("fedora:binary")) ); - graph.add( create(objectChildSubj, HAS_MIXIN_TYPE.asNode(), createLiteral("fedora:object")) ); - graph.add( create(customChildSubj, HAS_MIXIN_TYPE.asNode(), createLiteral("fedora:custom")) ); + graph.add( create(datastreamChildSubj, HAS_MIXIN_TYPE.asNode(), createLiteral(BINARY)) ); + graph.add( create(objectChildSubj, HAS_MIXIN_TYPE.asNode(), createLiteral(CONTAINER)) ); + graph.add( create(customChildSubj, HAS_MIXIN_TYPE.asNode(), createLiteral(CUSTOM)) ); objectWithChildren.setGraph( graph ); objectWithoutChildren.setGraph( createDefaultGraph() ); @@ -120,7 +125,7 @@ public void testGetChildren() throws FedoraException { @Test public void testGetChildrenObjects() throws FedoraException { - final Collection children = objectWithChildren.getChildren("fedora:object"); + final Collection children = objectWithChildren.getChildren(CONTAINER); verify(mockRepository).getObject(objectChildPath); verify(mockRepository, never()).getObject(customChildPath); verify(mockRepository, never()).getDatastream(datastreamChildPath); @@ -131,7 +136,7 @@ public void testGetChildrenObjects() throws FedoraException { @Test public void testGetChildrenCustom() throws FedoraException { - final Collection children = objectWithChildren.getChildren("fedora:custom"); + final Collection children = objectWithChildren.getChildren(CUSTOM); verify(mockRepository, never()).getObject(objectChildPath); verify(mockRepository).getObject(customChildPath); verify(mockRepository, never()).getDatastream(datastreamChildPath); @@ -142,7 +147,7 @@ public void testGetChildrenCustom() throws FedoraException { @Test public void testGetChildrenDatastreams() throws FedoraException { - final Collection children = objectWithChildren.getChildren("fedora:binary"); + final Collection children = objectWithChildren.getChildren(BINARY); verify(mockRepository, never()).getObject(objectChildPath); verify(mockRepository, never()).getObject(customChildPath); verify(mockRepository).getDatastream(datastreamChildPath); @@ -161,7 +166,7 @@ public void testGetChildrenNoChildren() throws FedoraException { @Test public void testGetChildrenNoMatch() throws FedoraException { - final Collection children = objectWithChildren.getChildren("bogus:mixin"); + final Collection children = objectWithChildren.getChildren(BOGUS_MIXIN); verify(mockRepository, never()).getObject(anyString()); verify(mockRepository, never()).getDatastream(anyString()); assertEquals( 0, children.size() ); diff --git a/fcrepo-client-impl/src/test/java/org/fcrepo/client/impl/FedoraRepositoryImplIT.java b/fcrepo-client-impl/src/test/java/org/fcrepo/client/impl/FedoraRepositoryImplIT.java index 2f8f1f9..7ced3b4 100644 --- a/fcrepo-client-impl/src/test/java/org/fcrepo/client/impl/FedoraRepositoryImplIT.java +++ b/fcrepo-client-impl/src/test/java/org/fcrepo/client/impl/FedoraRepositoryImplIT.java @@ -17,14 +17,17 @@ import com.hp.hpl.jena.graph.NodeFactory; import com.hp.hpl.jena.graph.Triple; -import junit.framework.Assert; + import org.apache.commons.io.IOUtils; import org.fcrepo.client.FedoraContent; import org.fcrepo.client.FedoraDatastream; import org.fcrepo.client.FedoraException; import org.fcrepo.client.FedoraObject; import org.fcrepo.client.FedoraRepository; +import org.fcrepo.client.FedoraResource; +import org.fcrepo.client.NotFoundException; import org.fcrepo.kernel.RdfLexicon; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; @@ -33,6 +36,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.util.Collection; import java.util.Iterator; import java.util.UUID; @@ -40,6 +44,7 @@ /** * @author Mike Durbin + * @author Hélder Silva */ public class FedoraRepositoryImplIT { @@ -57,7 +62,7 @@ private static String getFedoraBaseUrl() { @Before public void setUp() throws FedoraException { - repo = new FedoraRepositoryImpl("http://localhost:" + CARGO_PORT + "/" + FEDORA_CONTEXT + "/rest/"); + repo = new FedoraRepositoryImpl(getFedoraBaseUrl() + "/rest/"); } @Test @@ -154,6 +159,119 @@ public void testCreateOrUpdateRedirectDatastream() throws FedoraException, IOExc } + @Test + public void testMoveResource() throws FedoraException { + final String originResourcePath = getRandomUniqueId(); + final String destinyResourcePath = getRandomUniqueId(); + + // create origin resource + FedoraObject originResource = repo.createObject(originResourcePath); + Assert.assertNotNull(originResource); + Assert.assertEquals(originResourcePath, originResource.getPath()); + + // move resource to another location + originResource.move(destinyResourcePath); + final FedoraObject destinyResource = repo.getObject(destinyResourcePath); + Assert.assertNotNull(destinyResource); + + // try to obtain, from origin, the object that was moved + try { + originResource = repo.getObject(originResourcePath); + Assert.fail("An exception was expected but it didn't happened!"); + } catch (FedoraException e) { + Assert.assertTrue(e.getMessage().contains("410 Gone")); + } + } + + @Test + public void testForceMoveResource() throws FedoraException { + final String originResourcePath = getRandomUniqueId(); + final String destinyResourcePath = getRandomUniqueId(); + + // create origin resource + FedoraObject originResource = repo.createObject(originResourcePath); + Assert.assertNotNull(originResource); + Assert.assertEquals(originResourcePath, originResource.getPath()); + + // move resource to another location and remove tombstone + originResource.forceMove(destinyResourcePath); + final FedoraObject destinyResource = repo.getObject(destinyResourcePath); + Assert.assertNotNull(destinyResource); + + // try to obtain, from origin, the object that was moved and doesn't have a tombstone because it was removed + try { + originResource = repo.getObject(originResourcePath); + Assert.fail("An exception was expected but it didn't happened!"); + } catch (FedoraException e) { + Assert.assertTrue(e.getClass() == NotFoundException.class); + } + } + + @Test + public void testCopyResource() throws FedoraException { + final String originResourcePath = getRandomUniqueId(); + final String originChildResourcePath = originResourcePath + "/" + getRandomUniqueId(); + final String destinyResourcePath = getRandomUniqueId(); + + // create origin resource + FedoraObject originResource = repo.createObject(originResourcePath); + Assert.assertNotNull(originResource); + Assert.assertEquals(originResourcePath, originResource.getPath()); + + // create child origin resource + final FedoraObject originChildResource = repo.createObject(originChildResourcePath); + Assert.assertNotNull(originChildResource); + Assert.assertEquals(originChildResourcePath, originChildResource.getPath()); + + // copy resource to another location + originResource.copy(destinyResourcePath); + final FedoraObject destinyResource = repo.getObject(destinyResourcePath); + Assert.assertNotNull(destinyResource); + Assert.assertEquals(destinyResourcePath, destinyResource.getPath()); + + // ensure that copied resource has the same number of child resources + originResource = repo.getObject(originResourcePath); + final Collection originChildren = originResource.getChildren(null); + final Collection destinyChildren = destinyResource.getChildren(null); + Assert.assertEquals(originChildren.size(),destinyChildren.size()); + } + + @Test + public void testDeleteResource() throws FedoraException { + final String resourcePath = getRandomUniqueId(); + // create resource + FedoraObject resource = repo.createObject(resourcePath); + Assert.assertNotNull(resource); + Assert.assertEquals(resourcePath, resource.getPath()); + + // delete resource + resource.delete(); + + try { + resource = repo.getObject(resourcePath); + } catch (FedoraException e) { + Assert.assertTrue(e.getMessage().contains("410 Gone")); + } + } + + @Test + public void testForceDeleteResource() throws FedoraException { + final String resourcePath = getRandomUniqueId(); + // create resource + FedoraObject resource = repo.createObject(resourcePath); + Assert.assertNotNull(resource); + Assert.assertEquals(resourcePath, resource.getPath()); + + // delete resource and remove tombstone + resource.forceDelete(); + + try { + resource = repo.getObject(resourcePath); + } catch (FedoraException e) { + Assert.assertTrue(e.getClass() == NotFoundException.class); + } + } + private FedoraContent getStringTextContent(final String value) throws UnsupportedEncodingException { return new FedoraContent().setContent(new ByteArrayInputStream(value.getBytes("UTF-8"))) .setContentType("text/plain"); diff --git a/fcrepo-client/src/main/java/org/fcrepo/client/AlreadyExistsException.java b/fcrepo-client/src/main/java/org/fcrepo/client/AlreadyExistsException.java new file mode 100644 index 0000000..f82e872 --- /dev/null +++ b/fcrepo-client/src/main/java/org/fcrepo/client/AlreadyExistsException.java @@ -0,0 +1,59 @@ +/** + * Copyright 2015 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.client; + +/** + * Fedora exception indicating the resource cannot be created because + * it already exists (HTTP Status Code 409). + * @author hsilva@keep.pt + * @since 2015-05-28 +**/ +public class AlreadyExistsException extends FedoraException { + + private static final long serialVersionUID = 8377918196578302965L; + + /** + * Default constructor. + **/ + public AlreadyExistsException() { + super(); + } + + /** + * Constructor with reason. + * @param message Exception message. + **/ + public AlreadyExistsException( final String message ) { + super( message ); + } + + /** + * Constructor with reason and cause. + * @param message Exception message. + * @param cause Exception cause. + **/ + public AlreadyExistsException( final String message, final Throwable cause ) { + super( message, cause ); + } + + /** + * Constructor with cause. + * @param cause Exception cause. + **/ + public AlreadyExistsException( final Throwable cause ) { + super( cause ); + } +} diff --git a/fcrepo-client/src/main/java/org/fcrepo/client/FedoraResource.java b/fcrepo-client/src/main/java/org/fcrepo/client/FedoraResource.java index 611e9f6..51a9436 100644 --- a/fcrepo-client/src/main/java/org/fcrepo/client/FedoraResource.java +++ b/fcrepo-client/src/main/java/org/fcrepo/client/FedoraResource.java @@ -40,6 +40,11 @@ public interface FedoraResource { **/ public void delete() throws FedoraException; + /** + * Remove this Resource and respective tombstone. + **/ + public void forceDelete() throws FedoraException; + /** * Get the creation date of this Resource. **/ @@ -86,6 +91,12 @@ public interface FedoraResource { **/ public void move( String destination ) throws FedoraException; + /** + * Move this Resource to a new path and removes the tombstone created in the old path. + * @param destination The path of the new copy. + **/ + public void forceMove( String destination ) throws FedoraException; + /** * Update the properties of this Resource using SPARQL Update. * @param sparqlUpdate SPARQL Update command. @@ -114,4 +125,14 @@ public void updateProperties( InputStream updatedProperties, **/ public void createVersionSnapshot( String label ) throws FedoraException; + /** + * Remove tombstone (for the current path) + */ + public void removeTombstone() throws FedoraException; + + /** + * Remove tombstone located at given path + */ + public void removeTombstone(final String path) throws FedoraException; + }