Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented delete resource method; Several fixes and other improvements #22

Closed
wants to merge 9 commits into from
Expand Up @@ -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
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -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 + " " +
Expand Down Expand Up @@ -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 + " " +
Expand Down
Expand Up @@ -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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please back out the whitespace/ordering changes on otherwise unmodified code.


import java.io.IOException;
Expand All @@ -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;
Expand Down Expand Up @@ -76,6 +74,8 @@ public class FedoraResourceImpl implements FedoraResource {

protected String path = null;

protected String oldPath = null;

protected Node subject = null;

protected Graph graph;
Expand All @@ -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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please create a new integration test minimally for your new operations: copy, delete, move (and ideally for the other public methods on this class).
This integration test will be very similar to FedoraRepositoryImplIT.


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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add removeTombstone to the FedoraResource interface, or make the method private.

removeTombstone(path);
}


/**
* Remove tombstone located at given path
*/
public void removeTombstone(final String path) throws FedoraException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add removeTombstone to the FedoraResource interface, or make the method private.

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
Expand Down Expand Up @@ -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
Expand Down
@@ -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";
}
}
Expand Up @@ -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;
Expand Down Expand Up @@ -201,6 +202,15 @@ public HttpGet createGetMethod(final String path, final Map<String, List<String>
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.
Expand Down Expand Up @@ -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);
}

}