Skip to content

Commit

Permalink
aggregate fixity
Browse files Browse the repository at this point in the history
  • Loading branch information
barmintor committed Mar 12, 2013
1 parent a0fe429 commit e9d6ec0
Show file tree
Hide file tree
Showing 12 changed files with 233 additions and 41 deletions.
2 changes: 2 additions & 0 deletions fcrepo-generator-dc/src/test/resources/spring-test/repo.xml
Expand Up @@ -18,5 +18,7 @@
<bean class="org.modeshape.jcr.JcrRepositoryFactory"/>

<bean class="org.fcrepo.services.ObjectService"/>
<bean class="org.fcrepo.services.LowLevelStorageService"/>
<bean class="org.fcrepo.services.DatastreamService"/>

</beans>
2 changes: 2 additions & 0 deletions fcrepo-generator-rdf/src/test/resources/spring-test/repo.xml
Expand Up @@ -18,5 +18,7 @@
<bean class="org.modeshape.jcr.JcrRepositoryFactory"/>

<bean class="org.fcrepo.services.ObjectService"/>
<bean class="org.fcrepo.services.LowLevelStorageService"/>
<bean class="org.fcrepo.services.DatastreamService"/>

</beans>
7 changes: 7 additions & 0 deletions fcrepo-http-api/pom.xml
Expand Up @@ -96,6 +96,13 @@
<version>1.7</version>
</dependency>

<dependency>
<groupId>org.fcrepo</groupId>
<artifactId>fcrepo-kernel</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>

<!-- test gear -->
<dependency>
<groupId>org.fcrepo</groupId>
Expand Down
81 changes: 60 additions & 21 deletions fcrepo-http-api/src/main/java/org/fcrepo/api/FedoraDatastreams.java
Expand Up @@ -10,6 +10,7 @@
import static org.fcrepo.api.FedoraObjects.getObjectSize;
import static org.fcrepo.jaxb.responses.management.DatastreamProfile.DatastreamStates.A;
import static org.fcrepo.services.DatastreamService.createDatastreamNode;
import static org.fcrepo.services.LowLevelStorageService.getBlobs;
import static org.fcrepo.services.ObjectService.getObjectNode;
import static org.fcrepo.services.PathService.getDatastreamJcrNodePath;
import static org.fcrepo.services.PathService.getObjectJcrNodePath;
Expand All @@ -19,18 +20,21 @@
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Calendar;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.ValueFormatException;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
Expand Down Expand Up @@ -59,8 +63,12 @@
import org.fcrepo.jaxb.responses.management.DatastreamFixity;
import org.fcrepo.jaxb.responses.management.DatastreamHistory;
import org.fcrepo.jaxb.responses.management.DatastreamProfile;
import org.fcrepo.jaxb.responses.management.FixityStatus;
import org.fcrepo.services.DatastreamService;
import org.fcrepo.services.LowLevelStorageService;
import org.fcrepo.utils.ContentDigest;
import org.fcrepo.utils.LowLevelCacheStore;
import org.modeshape.common.util.StringUtil;
import org.modeshape.jcr.api.Binary;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -72,6 +80,9 @@ public class FedoraDatastreams extends AbstractResource {

final private Logger logger = LoggerFactory
.getLogger(FedoraDatastreams.class);

@Inject
private LowLevelStorageService llStorageService;

/**
* Returns a list of datastreams for the object
Expand Down Expand Up @@ -456,32 +467,60 @@ public DatastreamFixity getDatastreamFixity(@PathParam("pid")
*/
private DatastreamFixity validatedDatastreamFixity(Datastream ds) throws RepositoryException {
Node node = ds.getNode();
Binary binary =
(Binary) node.getSession().getValueFactory().createBinary(
ds.getContent());
Map<LowLevelCacheStore, InputStream> blobs = getBlobs(node);
//compute size and checksum
String compChecksum = binary.getHexHash();
long compSize = binary.getSize();
//get properties for comparison
URI dsChecksum = ds.getContentDigest();
long dsSize = ds.getContentSize();
String dsChecksumStr = ContentDigest.asChecksumString(dsChecksum);

DatastreamFixity dsf = new DatastreamFixity();
dsf.validChecksum = false;
dsf.validSize = false;
dsf.dsChecksumType = ds.getContentDigestType();
dsf.dsChecksum = dsChecksum;
dsf.dsSize = dsSize;

logger.debug("Validated checksum: " + compChecksum);
logger.debug("Validated size is " + compSize);

if (compChecksum.equals(dsChecksumStr)) {
dsf.validChecksum = true;
}
if (compSize == dsSize) {
dsf.validSize = true;
dsf.statuses = new ArrayList<FixityStatus>(blobs.size());
MessageDigest digest = null;
try {
digest = MessageDigest.getInstance("SHA1");
} catch (NoSuchAlgorithmException e) {
logger.error("Could not locate a SHA1 provider: Everything is ruined.",e);
throw new RepositoryException(e.getMessage(),e);
}
for (LowLevelCacheStore key: blobs.keySet()){
FixityStatus status = new FixityStatus();
status.validChecksum = false;
status.validSize = false;
status.dsChecksumType = ds.getContentDigestType();
status.dsChecksum = dsChecksum;
status.dsSize = dsSize;
InputStream in = blobs.get(key);
byte [] buf = new byte[1024];
int len = -1;
int read = 0;
digest.reset();
try {
while ((len = in.read(buf)) > -1){
digest.update(buf, 0, len);
read += len;
}
in.close();
} catch (IOException e) {
logger.error("Could not read blobs for datastream: Everything is ruined,", e);
throw new RepositoryException(e.getMessage(),e);
}

byte [] digestBytes = digest.digest();
String compChecksum = StringUtil.getHexString(digestBytes);
long compSize = read;
status.computedSize = compSize;
status.computedChecksum = compChecksum.toString();
logger.debug("Computed checksum: " + compChecksum);
logger.debug("Computed size is " + compSize);

if (compChecksum.toString().equals(dsChecksumStr)) {
status.validChecksum = true;
}
if (compSize == dsSize) {
status.validSize = true;
}
dsf.statuses.add(status);
}
return dsf;
}
Expand Down
94 changes: 94 additions & 0 deletions fcrepo-http-api/src/main/resources/fedora-node-types.cnd
@@ -0,0 +1,94 @@

/*
* JCR node types for use with Fedora
*/
<jcr = 'http://www.jcp.org/jcr/1.0'>
<nt = 'http://www.jcp.org/jcr/nt/1.0'>
<mix = 'http://www.jcp.org/jcr/mix/1.0'>

/*
* Friend-of-a-Friend
*/
<foaf = 'http://xmlns.com/foaf/0.1/'>

/*
* Generic Fedora namespace
*/
<fedora = 'info:fedora'>

/*
* Dublin Core. See:
*
* http://dublincore.org/documents/dcmi-namespace/
*/
<dc = 'http://purl.org/dc/terms/'>


/*
* Any Fedora resource.
*/
[fedora:resource] > mix:created, mix:lastModified, mix:lockable, mix:versionable mixin abstract

/*
* Temporary for us until we better understand the use of jcr:created.
*/
- fedora:created (STRING) COPY

/*
* See: http://dublincore.org/documents/dcmi-terms/#elements-identifier
*/
- dc:identifier (STRING) multiple COPY
- dc:title (STRING) COPY


/*
* A Fedora object.
*/
[fedora:object] > fedora:resource, nt:folder mixin


/*
* A Fedora datastream.
*/
[fedora:datastream] > fedora:resource, nt:file mixin

/*
* The MIMEtype of this datastream.
*/
- fedora:contentType (STRING) COPY


/*
* Indicates that this resource is owned.
*/
[fedora:owned] mixin noquery

/*
* The owner of this owned resource.
*/
- fedora:owner (REFERENCE) COPY

/*
* For use for when the owner-entities are not managed in the repository.
*/
- fedora:ownerId (STRING) COPY


/*
* Some entity that owns a Fedora resource.
*/
[fedora:owner] primaryitem foaf:name

/*
* The name of this owner.
*/
- foaf:name (STRING) multiple COPY


/*
* Some content that can have a checksum
*/
[fedora:checksum] mixin
- fedora:size (LONG) COPY
- fedora:digest (STRING) COPY
- fedora:digestAlgorithm (STRING) COPY
Expand Up @@ -5,6 +5,7 @@
import java.io.UnsupportedEncodingException;
import java.util.concurrent.TimeUnit;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
Expand Down Expand Up @@ -68,12 +69,17 @@ protected static HttpPut putDSMethod(final String pid, final String ds) {
return new HttpPut(serverAddress + "objects/" + pid + "/datastreams/" +
ds);
}

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

protected int getStatus(HttpUriRequest method)
throws ClientProtocolException, IOException {
return execute(method).getStatusLine().getStatusCode();
}

}
Expand Up @@ -10,6 +10,10 @@
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
Expand All @@ -19,6 +23,8 @@
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.util.EntityUtils;
import org.fcrepo.jaxb.responses.management.DatastreamFixity;
import org.fcrepo.jaxb.responses.management.FixityStatus;
import org.junit.Test;

public class FedoraDatastreamsTest extends AbstractResourceTest {
Expand Down Expand Up @@ -296,6 +302,21 @@ public void testCheckDatastreamFixity() throws Exception {
final HttpGet method2 =
new HttpGet(serverAddress +
"objects/FedoraDatastreamsTest10/datastreams/zxc/fixity");
assertEquals(200, getStatus(method2));
HttpResponse response = execute(method2);
assertEquals(200, response.getStatusLine().getStatusCode());
HttpEntity entity = response.getEntity();
String content = EntityUtils.toString(entity);
JAXBContext context = JAXBContext.newInstance(DatastreamFixity.class);
Unmarshaller um = context.createUnmarshaller();
DatastreamFixity fixity =
(DatastreamFixity) um.unmarshal(new java.io.StringReader(content));
int cache = 0;
for (FixityStatus status:fixity.statuses){
logger.debug("Verifying cache {} :", cache++);
assertTrue(status.validChecksum);
logger.debug("Checksum matched");
assertTrue(status.validSize);
logger.debug("DS size matched");
}
}
}
1 change: 1 addition & 0 deletions fcrepo-http-api/src/test/resources/spring-test/repo.xml
Expand Up @@ -19,6 +19,7 @@


<bean class="org.fcrepo.services.ObjectService"/>
<bean class="org.fcrepo.services.LowLevelStorageService"/>
<bean class="org.fcrepo.services.DatastreamService"/>

</beans>
@@ -1,25 +1,14 @@
package org.fcrepo.jaxb.responses.management;

import java.net.URI;
import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "DatastreamFixity")
public class DatastreamFixity {

@XmlElement
public long dsSize;
@XmlElement(name = "DatastreamFixityStatus")
public List<FixityStatus> statuses;

@XmlElement
public String dsChecksumType;

@XmlElement
public URI dsChecksum;

@XmlElement
public boolean validChecksum;

@XmlElement
public boolean validSize;
}

0 comments on commit e9d6ec0

Please sign in to comment.