Skip to content

Commit

Permalink
Polish StoragePolicy API and tests
Browse files Browse the repository at this point in the history
Resolves: https://www.pivotaltracker.com/story/show/55399322
* Change REST API endpoint to use {path}/fcr:storagepolicy
* Add API for GET-ing a specific storage policy
* Add more unit and integration tests
* Add @timed annotations
* Stop stacktraces from reaching the user
  • Loading branch information
Andrew Woods committed Aug 20, 2013
1 parent 124149e commit 00cc96e
Show file tree
Hide file tree
Showing 8 changed files with 500 additions and 221 deletions.
6 changes: 3 additions & 3 deletions fcrepo-storage-policy/pom.xml
Expand Up @@ -27,10 +27,10 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.fcrepo</groupId>
<artifactId>fcrepo-http-api</artifactId>
<groupId>org.fcrepo</groupId>
<artifactId>fcrepo-http-api</artifactId>
<version>${project.version}</version>
</dependency>
</dependency>
<!-- test gear -->
<dependency>
<groupId>junit</groupId>
Expand Down
Expand Up @@ -93,7 +93,7 @@ public void removeAll() {
/**
* For now: simple contains implementation
*
* @param propertyType
* @param p
*/
@Override
public boolean contains(Policy p) {
Expand All @@ -115,7 +115,7 @@ public void setPolicies(final List<Policy> policies) {
*/
@Override
public String toString() {
return "PolicyDecisionPoint [policies=" + policies + "]";
return "policies=" + policies;
}

/**
Expand Down
Expand Up @@ -20,6 +20,7 @@
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.slf4j.LoggerFactory.getLogger;

import com.codahale.metrics.annotation.Timed;
import org.apache.commons.lang.StringUtils;
import org.fcrepo.http.commons.AbstractResource;
import org.fcrepo.kernel.services.policy.Policy;
Expand All @@ -30,14 +31,14 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
//import org.springframework.validation.annotation.Validated;



import javax.annotation.PostConstruct;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.nodetype.NodeType;
import javax.servlet.http.HttpServletRequest;
Expand All @@ -50,6 +51,7 @@
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import java.io.IOException;

Expand All @@ -63,19 +65,23 @@

@Component
@Scope("prototype")
@Path("/storagepolicy")
public class PolicyGenerator extends AbstractResource {
@Path("/{path: .*}/fcr:storagepolicy")
public class StoragePolicy extends AbstractResource {

@InjectedSession
protected Session session;

@Context
private HttpServletRequest request;
protected HttpServletRequest request;

@Autowired(required = true)
StoragePolicyDecisionPoint storagePolicyDecisionPoint;
protected StoragePolicyDecisionPoint storagePolicyDecisionPoint;

private JcrTools jcrTools;

private static final Logger LOGGER = getLogger(PolicyGenerator.class);
public static final String POLICY_RESOURCE = "policies";

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

/**
* Initialize
Expand All @@ -86,7 +92,7 @@ public class PolicyGenerator extends AbstractResource {
@PostConstruct
public void setUpRepositoryConfiguration() throws RepositoryException,
IOException {
final JcrTools jcrTools = new JcrTools(true);
final JcrTools jcrTools = getJcrTools();
Session session = null;
try {
session = sessions.getSession();
Expand All @@ -113,9 +119,21 @@ public void setUpRepositoryConfiguration() throws RepositoryException,

@POST
@Consumes(APPLICATION_FORM_URLENCODED)
public Response post(final String request) throws Exception {
@Timed
public Response post(final @PathParam("path") String path,
final String request) throws Exception {
LOGGER.debug("POST Received request param: {}", request);
final JcrTools jcrTools = new JcrTools(true);
Response.ResponseBuilder response;

if (!path.equalsIgnoreCase(POLICY_RESOURCE)) {
response = Response.status(405);
return response.entity(
"POST method not allowed on " + getUriInfo().getAbsolutePath() +
", try /policies/fcr:storagepolicy")
.build();
}

final JcrTools jcrTools = getJcrTools();
final String[] str = StringUtils.split(request); // simple split for now
validateArgs(str.length);
try {
Expand All @@ -135,30 +153,36 @@ public Response post(final String request) throws Exception {
storagePolicyDecisionPoint.addPolicy(policy);
session.save();
LOGGER.debug("Saved PDS hint {}", request);
return Response.ok().build();

response = Response.created(getUriInfo().getBaseUriBuilder()
.path(str[0])
.path("fcr:storagepolicy")
.build());
} else {
throw new PolicyTypeException(
"Invalid property type specified.");
"Invalid property type specified: " + str[0]);
}
} catch (final Exception e) {
throw e;
response = Response.serverError().entity(e.getMessage());
} finally {
session.logout();
}

return response.build();
}

/**
* For nodeType n or runtime property p get org.fcrepo.binary.Policy
* implementation. Note: Signature might need to change, or a more
* sophisticated method used, as implementation evolves.
*
* @param nodeType
* @param propertyType
* @param itemType
* @param value
* @return
* @throws PolicyTypeException
*/
public Policy newPolicyInstance(final String propertyType,
protected Policy newPolicyInstance(final String propertyType,
final String itemType, final String value) throws PolicyTypeException {

switch (propertyType) {
Expand All @@ -175,9 +199,9 @@ public Policy newPolicyInstance(final String propertyType,
* the design of how things are stored will need to change.
*/
@DELETE
@Path("/{id}")
public Response deleteNodeType(@PathParam("id")
final String nodeType) throws RepositoryException {
@Timed
public Response deleteNodeType(@PathParam("path") final String nodeType)
throws RepositoryException {
try {
// final String[] str = StringUtils.split(request);
// validateArgs(str.length);
Expand All @@ -194,7 +218,7 @@ public Response deleteNodeType(@PathParam("id")
// TODO Once Policy is updated to display Policy type, this
// would change
storagePolicyDecisionPoint.removeAll();
return Response.ok().build();
return Response.noContent().build();
} else {
throw new RepositoryException(
"Invalid property type specified.");
Expand All @@ -206,21 +230,61 @@ public Response deleteNodeType(@PathParam("id")

/**
* TODO (for now) prints org.fcrepo.binary.PolicyDecisionPoint
*
* @param policyType
*
* @return
* @throws RepositoryException
*/
@GET
@Produces(APPLICATION_JSON)
public Response printActiveStoragePolicies() throws Exception {
@Timed
public Response get(final @PathParam("path") String path) throws Exception {
if (POLICY_RESOURCE.equalsIgnoreCase(path)) {
return getAllStoragePolicies();
} else {
return getStoragePolicy(path);
}
}

private Response getAllStoragePolicies() throws Exception {
if (storagePolicyDecisionPoint == null ||
storagePolicyDecisionPoint.size() == 0) {
return Response.ok("No Policies Found").build();
}
return Response.ok(storagePolicyDecisionPoint.toString()).build();
}

private Response getStoragePolicy(final String nodeType) {
LOGGER.debug("Get storage policy for: {}", nodeType);
Response.ResponseBuilder response;
try {
final Node node =
jcrTools.findOrCreateNode(session,
"/fedora:system/fedora:storage_policy",
"test");

Property prop = node.getProperty(nodeType);
if (null == prop) {
throw new PathNotFoundException("Policy not found: " + nodeType);
}

Value[] values = prop.getValues();
if (values != null && values.length > 0) {
response = Response.ok(values[0].getString());
} else {
throw new PathNotFoundException("Policy not found: " + nodeType);
}

} catch (PathNotFoundException e) {
response = Response.status(404).entity(e.getMessage());
} catch (Exception e) {
response = Response.serverError().entity(e.getMessage());

} finally {
session.logout();
}
return response.build();
}

/**
* Verifies whether node type is valid
*
Expand Down Expand Up @@ -276,4 +340,31 @@ private InputPattern(int l) {
requiredLength = l;
}
}

private JcrTools getJcrTools() {
if (null == jcrTools) {
this.jcrTools = new JcrTools(true);
}
return jcrTools;
}

/**
* Only for UNIT TESTING
* @param jcrTools
*/
public void setJcrTools(JcrTools jcrTools) {
this.jcrTools = jcrTools;
}

private UriInfo getUriInfo() {
return this.uriInfo;
}

/**
* Only for UNIT TESTING
* @param uriInfo
*/
public void setUriInfo(UriInfo uriInfo) {
this.uriInfo = uriInfo;
}
}
Expand Up @@ -19,7 +19,6 @@
import static org.slf4j.LoggerFactory.getLogger;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
Expand All @@ -43,8 +42,6 @@ public abstract class AbstractResourceIT {

protected Logger logger;

protected String OBJECT_PATH = "storagepolicy";

@Before
public void setLogger() {
logger = getLogger(this.getClass());
Expand All @@ -55,10 +52,10 @@ public void setLogger() {

protected static final String HOSTNAME = "localhost";

protected static final String WEBAPP = "storagepolicy";
protected static final String SUFFIX = "fcr:storagepolicy";

protected static final String serverAddress = "http://" + HOSTNAME + ":" +
SERVER_PORT + "/rest/" + WEBAPP;
SERVER_PORT + "/rest/";

protected final PoolingClientConnectionManager connectionManager =
new PoolingClientConnectionManager();
Expand All @@ -72,27 +69,33 @@ public AbstractResourceIT() {
client = new DefaultHttpClient(connectionManager);
}

protected static HttpGet HttpGetObjMethod(final String param) {
return new HttpGet(serverAddress);
protected HttpGet HttpGetObjMethod(final String param) {
HttpGet get = new HttpGet(serverAddress + param + "/" + SUFFIX);
logger.debug("GET: {}", get.getURI());
return get;
}

protected static HttpPost HttpPostObjMethod() {
return new HttpPost(serverAddress);
protected HttpPost HttpPostObjMethod(String param) {
HttpPost post = new HttpPost(serverAddress + param + "/" + SUFFIX);
logger.debug("POST: {}", post.getURI());
return post;
}

protected static HttpDelete HttpDeleteObjMethod(final String param) {
return new HttpDelete(serverAddress + "/" + param);
protected HttpDelete HttpDeleteObjMethod(final String param) {
HttpDelete delete = new HttpDelete(serverAddress + param + "/" + SUFFIX);
logger.debug("DELETE: {}", delete.getURI());
return delete;
}

protected HttpResponse execute(final HttpUriRequest method)
throws ClientProtocolException, IOException {
throws IOException {
logger.debug("Executing: " + method.getMethod() + " to " +
method.getURI());
return client.execute(method);
}

protected int getStatus(final HttpUriRequest method)
throws ClientProtocolException, IOException {
throws IOException {
HttpResponse response = execute(method);
int result = response.getStatusLine().getStatusCode();
if (!(result > 199) || !(result < 400)) {
Expand Down

0 comments on commit 00cc96e

Please sign in to comment.