Skip to content

Commit

Permalink
Add support for tx calls
Browse files Browse the repository at this point in the history
  • Loading branch information
gushakov authored and Andrew Woods committed Dec 30, 2015
1 parent 39923a4 commit 6da86ac
Show file tree
Hide file tree
Showing 6 changed files with 257 additions and 18 deletions.
147 changes: 134 additions & 13 deletions fcrepo-client-impl/src/main/java/org/fcrepo/client/impl/FedoraRepositoryImpl.java 100644 → 100755
Expand Up @@ -16,7 +16,6 @@
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;
Expand All @@ -43,6 +42,7 @@
import static org.apache.http.HttpStatus.SC_CREATED;
import static org.apache.http.HttpStatus.SC_FORBIDDEN;
import static org.apache.http.HttpStatus.SC_NOT_FOUND;
import static org.apache.http.HttpStatus.SC_NO_CONTENT;
import static org.apache.http.HttpStatus.SC_OK;
import static org.slf4j.LoggerFactory.getLogger;

Expand All @@ -51,11 +51,19 @@
*
* @author lsitu
* @author escowles
* @author gushakov
* @since 2014-08-11
*/
public class FedoraRepositoryImpl implements FedoraRepository {
private static final Logger LOGGER = getLogger(FedoraRepositoryImpl.class);

private static final ThreadLocal<String> TX_ID = new ThreadLocal<>();

private static final String TX = "tx:";
private static final String FCR_TX = "/fcr:tx";
private static final String FCR_COMMIT = "/fcr:commit";
private static final String FCR_ROLLBACK = "/fcr:rollback";

protected HttpHelper httpHelper;
protected String repositoryURL;

Expand Down Expand Up @@ -97,7 +105,7 @@ public FedoraRepositoryImpl(final String repositoryURL, final HttpClient httpCli

@Override
public boolean exists(final String path) throws FedoraException, ForbiddenException {
final HttpHead head = httpHelper.createHeadMethod(path);
final HttpHead head = httpHelper.createHeadMethod(prependTransactionId(path));
try {
final HttpResponse response = httpHelper.execute(head);
final StatusLine status = response.getStatusLine();
Expand All @@ -116,7 +124,7 @@ public boolean exists(final String path) throws FedoraException, ForbiddenExcept
status.getReasonPhrase());
}
} catch (final Exception e) {
LOGGER.error("could not encode URI parameter", e);
LOGGER.error("Could not encode URI parameter: {}", e.getMessage());
throw new FedoraException(e);
} finally {
head.releaseConnection();
Expand All @@ -125,17 +133,19 @@ public boolean exists(final String path) throws FedoraException, ForbiddenExcept

@Override
public FedoraDatastream getDatastream(final String path) throws FedoraException {
return (FedoraDatastream)httpHelper.loadProperties(new FedoraDatastreamImpl(this, httpHelper, path));
return (FedoraDatastream) httpHelper
.loadProperties(new FedoraDatastreamImpl(this, httpHelper, prependTransactionId(path)));
}

@Override
public FedoraObject getObject(final String path) throws FedoraException {
return (FedoraObject)httpHelper.loadProperties(new FedoraObjectImpl(this, httpHelper, path));
return (FedoraObject) httpHelper
.loadProperties(new FedoraObjectImpl(this, httpHelper, prependTransactionId(path)));
}

@Override
public FedoraDatastream createDatastream(final String path, final FedoraContent content) throws FedoraException {
final HttpPut put = httpHelper.createContentPutMethod(path, null, content);
final HttpPut put = httpHelper.createContentPutMethod(prependTransactionId(path), null, content);
try {
final HttpResponse response = httpHelper.execute(put);
final String uri = put.getURI().toString();
Expand All @@ -156,7 +166,7 @@ public FedoraDatastream createDatastream(final String path, final FedoraContent
status.getReasonPhrase());
}
} catch (final Exception e) {
LOGGER.error("could not encode URI parameter", e);
LOGGER.error("Could not encode URI parameter: {}", e.getMessage());
throw new FedoraException(e);
} finally {
put.releaseConnection();
Expand All @@ -166,7 +176,7 @@ public FedoraDatastream createDatastream(final String path, final FedoraContent
@Override
public FedoraDatastream createOrUpdateRedirectDatastream(final String path, final String url)
throws FedoraException {
final HttpPut put = httpHelper.createContentPutMethod(path, null, null);
final HttpPut put = httpHelper.createContentPutMethod(prependTransactionId(path), null, null);
try {
put.setHeader("Content-Type", "message/external-body; access-type=URL; URL=\"" + url + "\"");
final HttpResponse response = httpHelper.execute(put);
Expand All @@ -185,7 +195,7 @@ public FedoraDatastream createOrUpdateRedirectDatastream(final String path, fina
status.getReasonPhrase());
}
} catch (final Exception e) {
LOGGER.error("Error making or building PUT request.", e);
LOGGER.error("Error making or building PUT request: {}", e.getMessage());
throw new FedoraException(e);
} finally {
put.releaseConnection();
Expand All @@ -194,7 +204,7 @@ public FedoraDatastream createOrUpdateRedirectDatastream(final String path, fina

@Override
public FedoraObject createObject(final String path) throws FedoraException {
final HttpPut put = httpHelper.createPutMethod(path, null);
final HttpPut put = httpHelper.createPutMethod(prependTransactionId(path), null);
try {
final HttpResponse response = httpHelper.execute(put);
final String uri = put.getURI().toString();
Expand All @@ -215,7 +225,7 @@ public FedoraObject createObject(final String path) throws FedoraException {
status.getReasonPhrase());
}
} catch (final Exception e) {
LOGGER.error("could not encode URI parameter", e);
LOGGER.error("Could not encode URI parameter: {}", e.getMessage());
throw new FedoraException(e);
} finally {
put.releaseConnection();
Expand All @@ -224,7 +234,9 @@ public FedoraObject createObject(final String path) throws FedoraException {

@Override
public FedoraObject createResource(final String containerPath) throws FedoraException {
final HttpPost post = httpHelper.createPostMethod(containerPath == null ? "" : containerPath, null);
final HttpPost post = httpHelper
.createPostMethod(containerPath == null
? prependTransactionId("") : prependTransactionId(containerPath), null);
try {
final HttpResponse response = httpHelper.execute(post);
final String uri = post.getURI().toString();
Expand All @@ -242,7 +254,7 @@ public FedoraObject createResource(final String containerPath) throws FedoraExce
status.getReasonPhrase());
}
} catch (final Exception e) {
LOGGER.error("could not encode URI parameter", e);
LOGGER.error("Could not encode URI parameter: {}", e.getMessage());
throw new FedoraException(e);
} finally {
post.releaseConnection();
Expand Down Expand Up @@ -314,9 +326,118 @@ public boolean isWritable() {
return true;
}

@Override
public String startTransaction() throws FedoraException {
final HttpPost post = httpHelper.createPostMethod(FCR_TX, null);
try {

final HttpResponse response = httpHelper.execute(post);
final String uri = post.getURI().toString();
final StatusLine status = response.getStatusLine();
final int statusCode = status.getStatusCode();

if (statusCode == SC_CREATED) {
final String txId = response.getFirstHeader("Location").getValue().substring(repositoryURL.length());
TX_ID.set(txId);
LOGGER.debug("Started transaction {}", txId);
return txId;
} else if (statusCode == SC_FORBIDDEN) {
LOGGER.error("request to start new transaction {} is not authorized.", uri);
throw new ForbiddenException("request to start new transaction " + uri + " is not authorized.");
} else {
LOGGER.error("error start new transaction {}: {} {}", uri, statusCode, status.getReasonPhrase());
throw new FedoraException("error start new transaction " + uri + ": " + statusCode + " " +
status.getReasonPhrase());
}

} catch (final Exception e) {
LOGGER.error("Could not encode URI parameter: ", e.getMessage());
throw new FedoraException(e);
} finally {
post.releaseConnection();
}

}

@Override
public void commitTransaction() throws FedoraException {
final HttpPost post = httpHelper.createPostMethod(TX_ID.get()
+ FCR_TX + FCR_COMMIT, null);
try {
final HttpResponse response = httpHelper.execute(post);
final String uri = post.getURI().toString();
final StatusLine status = response.getStatusLine();
final int statusCode = status.getStatusCode();

if (statusCode == SC_FORBIDDEN) {
LOGGER.error("request to commit transaction {} is not authorized.", uri);
throw new ForbiddenException("request to commit transaction " + uri + " is not authorized.");
} else {
if (statusCode != SC_NO_CONTENT) {
LOGGER.error("error committing back transaction {}: {} {}", uri,
statusCode, status.getReasonPhrase());
throw new FedoraException("error committing transaction " + uri + ": " + statusCode + " " +
status.getReasonPhrase());
}
}
LOGGER.debug("Committed transaction {}", TX_ID.get());
} catch (final Exception e) {
LOGGER.error("Could not encode URI parameter: {}", e.getMessage());
throw new FedoraException(e);
} finally {
post.releaseConnection();
TX_ID.remove();
}
}

@Override
public void rollbackTransaction() throws FedoraException {
final HttpPost post = httpHelper.createPostMethod(TX_ID.get()
+ FCR_TX + FCR_ROLLBACK, null);
try {
final HttpResponse response = httpHelper.execute(post);
final String uri = post.getURI().toString();
final StatusLine status = response.getStatusLine();
final int statusCode = status.getStatusCode();

if (statusCode == SC_FORBIDDEN) {
LOGGER.error("request to rollback transaction {} is not authorized.", uri);
throw new ForbiddenException("request to rollback transaction " + uri + " is not authorized.");
} else {
if (statusCode != SC_NO_CONTENT) {
LOGGER.error("error rolling back transaction {}: {} {}", uri, statusCode, status.getReasonPhrase());
throw new FedoraException("error rolling back transaction " + uri + ": " + statusCode + " " +
status.getReasonPhrase());
}
}

LOGGER.debug("Rolled back transaction {}", TX_ID.get());
} catch (final Exception e) {
LOGGER.error("Could not encode URI parameter: {}", e.getMessage());
throw new FedoraException(e);
} finally {
post.releaseConnection();
TX_ID.remove();
}
}

@Override
public String getRepositoryUrl() {
return repositoryURL;
}

private String prependTransactionId(final String path) {
final String txId = TX_ID.get();
// append (if needed) tx id to the path if a transaction has been started for this thread
if (txId == null || path.contains(TX)) {
return path;
} else {
// respect the slash (if present) in the original path
if (path.startsWith("/")) {
return "/" + txId + path;
} else {
return txId + "/" + path;
}
}
}
}
Expand Up @@ -129,7 +129,7 @@ public void copy(final String destination) throws FedoraException {
} catch (final FedoraException e) {
throw e;
} catch (final Exception e) {
LOGGER.error("could not encode URI parameter", e);
LOGGER.error("Could not encode URI parameter: {}", e.getMessage());
throw new FedoraException(e);
} finally {
copy.releaseConnection();
Expand Down Expand Up @@ -299,7 +299,7 @@ public void move(final String destination) throws FedoraException {
oldPath = null;
throw e;
} catch (final Exception e) {
LOGGER.error("could not encode URI parameter", e);
LOGGER.error("Could not encode URI parameter: {}", e.getMessage());
throw new FedoraException(e);
} finally {
move.releaseConnection();
Expand Down Expand Up @@ -345,7 +345,7 @@ public void updateProperties(final String sparqlUpdate) throws FedoraException {
} catch (final FedoraException e) {
throw e;
} catch (final Exception e) {
LOGGER.error("could not encode URI parameter", e);
LOGGER.error("Could not encode URI parameter: {}", e.getMessage());
throw new FedoraException(e);
} finally {
patch.releaseConnection();
Expand Down
19 changes: 19 additions & 0 deletions fcrepo-client-impl/src/main/java/org/fcrepo/client/impl/ReadOnlyFedoraRepositoryImpl.java 100644 → 100755
Expand Up @@ -41,6 +41,7 @@
public class ReadOnlyFedoraRepositoryImpl extends FedoraRepositoryImpl implements FedoraRepository {
private static final Logger LOGGER = getLogger(ReadOnlyFedoraRepositoryImpl.class);
private static final String msg = "Write operation attempted using read-only repository";
private static final String txMsg = "Transaction operation attempted using read-only repository";

/**
* Constructor that takes the repository url
Expand Down Expand Up @@ -129,4 +130,22 @@ public void removeNamespace(final String prefix) throws ReadOnlyException {
public boolean isWritable() {
return false;
}

@Override
public String startTransaction() throws FedoraException {
LOGGER.warn(txMsg);
throw new ReadOnlyException();
}

@Override
public void commitTransaction() throws FedoraException {
LOGGER.warn(txMsg);
throw new ReadOnlyException();
}

@Override
public void rollbackTransaction() throws FedoraException {
LOGGER.warn(txMsg);
throw new ReadOnlyException();
}
}
Expand Up @@ -385,7 +385,7 @@ public FedoraResourceImpl loadProperties( final FedoraResourceImpl resource ) th
throw e;
} catch (final Exception e) {
e.printStackTrace();
LOGGER.info("could not encode URI parameter", e);
LOGGER.info("Could not encode URI parameter: {}", e.getMessage());
throw new FedoraException(e);
} finally {
get.releaseConnection();
Expand Down

0 comments on commit 6da86ac

Please sign in to comment.