/*
* Licensed to DuraSpace under one or more contributor license agreements.
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership.
*
* DuraSpace licenses this file to you 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.integration.kernel.modeshape;
import static java.util.Arrays.asList;
import static org.apache.jena.rdf.model.ResourceFactory.createResource;
import static java.util.UUID.randomUUID;
import static org.fcrepo.kernel.api.FedoraTypes.FEDORA_BINARY;
import static org.fcrepo.kernel.api.FedoraTypes.FEDORA_NON_RDF_SOURCE_DESCRIPTION;
import static org.fcrepo.kernel.api.RdfLexicon.HAS_MESSAGE_DIGEST;
import static org.fcrepo.kernel.api.RdfCollectors.toModel;
import static org.fcrepo.kernel.api.RequiredRdfContext.PROPERTIES;
import static org.fcrepo.kernel.api.utils.ContentDigest.DIGEST_ALGORITHM.SHA1;
import static org.fcrepo.kernel.api.utils.ContentDigest.asURI;
import static org.fcrepo.kernel.modeshape.FedoraSessionImpl.getJcrSession;
import static org.fcrepo.kernel.modeshape.utils.FedoraTypesUtils.getJcrNode;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.modeshape.jcr.api.JcrConstants.JCR_CONTENT;
import static org.modeshape.jcr.api.JcrConstants.JCR_DATA;
import static org.modeshape.jcr.api.JcrConstants.NT_FILE;
import static org.modeshape.jcr.api.JcrConstants.NT_RESOURCE;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.time.Instant;
import java.util.HashSet;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.ValueFactory;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.Resource;
import org.apache.commons.io.IOUtils;
import org.fcrepo.kernel.api.FedoraRepository;
import org.fcrepo.kernel.api.FedoraSession;
import org.fcrepo.kernel.api.exception.InvalidChecksumException;
import org.fcrepo.kernel.api.identifiers.IdentifierConverter;
import org.fcrepo.kernel.api.models.Container;
import org.fcrepo.kernel.api.models.FedoraBinary;
import org.fcrepo.kernel.api.models.FedoraResource;
import org.fcrepo.kernel.api.services.BinaryService;
import org.fcrepo.kernel.api.services.ContainerService;
import org.fcrepo.kernel.modeshape.rdf.impl.DefaultIdentifierTranslator;
import org.junit.Before;
import org.junit.Test;
import org.springframework.test.context.ContextConfiguration;
/**
* <p>{@link org.fcrepo.integration.kernel.modeshape.FedoraBinaryImplIT} class.</p>
*
* @author ksclarke
* @author ajs6f
*/
@ContextConfiguration({"/spring-test/repo.xml"})
public class FedoraBinaryImplIT extends AbstractIT {
@Inject
FedoraRepository repo;
@Inject
BinaryService binaryService;
@Inject
ContainerService containerService;
private IdentifierConverter<Resource, FedoraResource> idTranslator;
@Before
public void setUp() throws RepositoryException {
idTranslator = new DefaultIdentifierTranslator(getJcrSession(repo.login()));
}
@Test
public void testCreatedDate() throws RepositoryException, InvalidChecksumException {
FedoraSession session = repo.login();
containerService.findOrCreate(session, "/testDatastreamObject");
binaryService.findOrCreate(session, "/testDatastreamObject/testDatastreamNode1").setContent(
new ByteArrayInputStream("asdf".getBytes()),
"application/octet-stream",
null,
null,
null
);
session.commit();
session.expire();
session = repo.login();
final FedoraBinary ds = binaryService.findOrCreate(session,
"/testDatastreamObject/testDatastreamNode1");
assertNotNull("Couldn't find created date on datastream!", ds
.getCreatedDate());
}
@Test
public void testDatastreamContent() throws IOException,
RepositoryException,
InvalidChecksumException {
final FedoraSession session = repo.login();
containerService.findOrCreate(session, "/testDatastreamObject");
binaryService.findOrCreate(session, "/testDatastreamObject/testDatastreamNode1").setContent(
new ByteArrayInputStream("asdf".getBytes()),
"application/octet-stream",
null,
null,
null
);
session.commit();
final FedoraBinary ds = binaryService.findOrCreate(session,
"/testDatastreamObject/testDatastreamNode1");
final String contentString = IOUtils.toString(ds.getContent(), "ASCII");
assertEquals("asdf", contentString);
}
@Test
public void testDatastreamContentType() throws RepositoryException, InvalidChecksumException {
final FedoraSession session = repo.login();
try {
containerService.findOrCreate(session, "/testDatastreamObject");
binaryService.findOrCreate(session, "/testDatastreamObject/testDatastreamNode1").setContent(
new ByteArrayInputStream("asdf".getBytes()),
"some/mime-type; with=params",
null,
null,
null
);
session.commit();
final FedoraBinary ds = binaryService.findOrCreate(session,
"/testDatastreamObject/testDatastreamNode1");
assertEquals("some/mime-type; with=params", ds.getMimeType());
} finally {
session.expire();
}
}
@Test
public void testDatastreamContentDigestAndLength() throws IOException, RepositoryException,
InvalidChecksumException {
final FedoraSession session = repo.login();
try {
containerService.findOrCreate(session, "/testDatastreamObject");
binaryService.findOrCreate(session, "/testDatastreamObject/testDatastreamNode2").setContent(
new ByteArrayInputStream("asdf".getBytes()),
"application/octet-stream",
null,
null,
null
);
session.commit();
final FedoraBinary ds = binaryService.findOrCreate(session,
"/testDatastreamObject/testDatastreamNode2");
assertEquals("urn:sha1:3da541559918a808c2402bba5012f6c60b27661c", ds
.getContentDigest().toString());
assertEquals(4L, ds.getContentSize());
final String contentString = IOUtils.toString(ds.getContent(), "ASCII");
assertEquals("asdf", contentString);
} finally {
session.expire();
}
}
@Test
public void
testModifyDatastreamContentDigestAndLength() throws IOException, RepositoryException, InvalidChecksumException {
final FedoraSession session = repo.login();
try {
containerService.findOrCreate(session, "/testDatastreamObject");
final FedoraBinary orig = binaryService.findOrCreate(session, "/testDatastreamObject/testDatastreamNode3");
orig.setContent(new ByteArrayInputStream("asdf".getBytes()), "application/octet-stream", null, null, null);
session.commit();
final Instant origMod = orig.getLastModifiedDate();
final FedoraBinary ds = binaryService.findOrCreate(session,
"/testDatastreamObject/testDatastreamNode3");
ds.setContent(new ByteArrayInputStream("0123456789".getBytes()), null, null, null, null);
assertEquals("urn:sha1:87acec17cd9dcd20a716cc2cf67417b71c8a7016", ds
.getContentDigest().toString());
assertEquals(10L, ds.getContentSize());
final String contentString = IOUtils.toString(ds.getContent(), "ASCII");
assertEquals("0123456789", contentString);
assertTrue("Last-modified should be updated", ds.getLastModifiedDate().isAfter(origMod));
} finally {
session.expire();
}
}
@Test
public void testDatastreamContentWithChecksum() throws IOException, RepositoryException, InvalidChecksumException {
final FedoraSession session = repo.login();
try {
containerService.findOrCreate(session, "/testDatastreamObject");
binaryService.findOrCreate(session, "/testDatastreamObject/testDatastreamNode4").setContent(
new ByteArrayInputStream("asdf".getBytes()),
"application/octet-stream",
new HashSet<>(asList(asURI(SHA1.algorithm, "3da541559918a808c2402bba5012f6c60b27661c"))),
null,
null
);
session.commit();
final FedoraBinary ds = binaryService.findOrCreate(session,
"/testDatastreamObject/testDatastreamNode4");
assertEquals("urn:sha1:3da541559918a808c2402bba5012f6c60b27661c", ds
.getContentDigest().toString());
final String contentString = IOUtils.toString(ds.getContent(), "ASCII");
assertEquals("asdf", contentString);
} finally {
session.expire();
}
}
@Test
public void testDatastreamFileName() throws RepositoryException, InvalidChecksumException {
final FedoraSession session = repo.login();
try {
containerService.findOrCreate(session, "/testDatastreamObject");
binaryService.findOrCreate(session, "/testDatastreamObject/testDatastreamNode5").setContent(
new ByteArrayInputStream("asdf".getBytes()),
"application/octet-stream",
null,
"xyz.jpg",
null
);
session.commit();
final FedoraBinary ds = binaryService.findOrCreate(session,
"/testDatastreamObject/testDatastreamNode5");
final String filename = ds.getFilename();
assertEquals("xyz.jpg", filename);
} finally {
session.expire();
}
}
@Test
public void testChecksumBlobs() throws RepositoryException, InvalidChecksumException {
final String pid = "testChecksumBlobs-" + randomUUID();
final FedoraSession session = repo.login();
try {
containerService.findOrCreate(session, pid);
binaryService.findOrCreate(session, pid + "/testRepositoryContent").setContent(
new ByteArrayInputStream("01234567890123456789012345678901234567890123456789".getBytes()),
"text/plain",
null,
"numbers.txt",
null
);
session.commit();
final FedoraBinary ds = binaryService.findOrCreate(session, pid + "/testRepositoryContent");
final Model fixityResults = ds.getFixity(idTranslator).collect(toModel());
assertNotEquals(0, fixityResults.size());
assertTrue("Expected to find checksum",
fixityResults.contains(null,
HAS_MESSAGE_DIGEST,
createResource("urn:sha1:9578f951955d37f20b601c26591e260c1e5389bf")));
assertEquals("Expected to find mime type",
getJcrNode(ds).getProperty("ebucore:hasMimeType").getString(), "text/plain");
assertEquals("Expected to find file name",
getJcrNode(ds).getProperty("ebucore:filename").getString(), "numbers.txt");
} finally {
session.expire();
}
}
@Test
public void testChecksumBlobsForInMemoryValues() throws RepositoryException, InvalidChecksumException {
final FedoraSession session = repo.login();
try {
containerService.findOrCreate(session, "/testLLObject");
binaryService.findOrCreate(session, "/testLLObject/testMemoryContent").setContent(
new ByteArrayInputStream("0123456789".getBytes()),
"application/octet-stream",
null,
null,
null
);
session.commit();
final FedoraBinary ds = binaryService.findOrCreate(session, "/testLLObject/testMemoryContent");
final Model fixityResults = ds.getFixity(idTranslator).collect(toModel());
assertNotEquals(0, fixityResults.size());
assertTrue("Expected to find checksum",
fixityResults.contains(null,
HAS_MESSAGE_DIGEST,
createResource("urn:sha1:87acec17cd9dcd20a716cc2cf67417b71c8a7016")));
} finally {
session.expire();
}
}
@Test
public void testChecksumBlobsForValuesWithoutChecksums() throws RepositoryException {
final FedoraSession session = repo.login();
final Session jcrSession = getJcrSession(session);
try {
final ValueFactory factory = jcrSession.getValueFactory();
final Container object = containerService.findOrCreate(session, "/testLLObject");
final Node testRandomContentNode = getJcrNode(object).addNode("testRandomContent", NT_FILE);
testRandomContentNode.addMixin(FEDORA_NON_RDF_SOURCE_DESCRIPTION);
final Node testRandomContent = testRandomContentNode.addNode(JCR_CONTENT, NT_RESOURCE);
testRandomContent.addMixin(FEDORA_BINARY);
testRandomContent.setProperty(JCR_DATA,
factory.createBinary(new ByteArrayInputStream("0123456789".getBytes())));
session.commit();
final FedoraBinary ds = binaryService.findOrCreate(session, "/testLLObject/testRandomContent");
final Model fixityResults = ds.getFixity(idTranslator).collect(toModel());
assertNotEquals(0, fixityResults.size());
assertTrue("Expected to find checksum",
fixityResults.contains(null,
HAS_MESSAGE_DIGEST,
createResource("urn:sha1:87acec17cd9dcd20a716cc2cf67417b71c8a7016")));
} finally {
session.expire();
}
}
@Test
public void testModifyDatastreamDescriptionLastMod() throws RepositoryException, InvalidChecksumException {
final FedoraSession session = repo.login();
try {
containerService.findOrCreate(session, "/testDatastreamObject");
final FedoraBinary orig = binaryService.findOrCreate(session, "/testDatastreamObject/testDatastreamNode6");
orig.setContent(new ByteArrayInputStream("asdf".getBytes()), "application/octet-stream", null, null, null);
session.commit();
final FedoraResource description = orig.getDescription();
final Instant origMod = orig.getLastModifiedDate();
final Instant origDescriptionMod = description.getLastModifiedDate();
description.updateProperties(idTranslator, "INSERT { <> <info:fcrepo/foo> \"b\" } WHERE {}",
description.getTriples(idTranslator, PROPERTIES));
session.commit();
final FedoraBinary ds = binaryService.findOrCreate(session, "/testDatastreamObject/testDatastreamNode6");
final Instant modMod = ds.getLastModifiedDate();
final Instant modDescMod = ds.getDescription().getLastModifiedDate();
assertEquals("Last-modified on the binary should be the same", modMod, origMod);
assertNotEquals("Last-modified on the description should not be the same", modDescMod, origDescriptionMod);
ds.setContent(new ByteArrayInputStream("0123456789".getBytes()), null, null, null, null);
assertNotEquals("Last-modified on the binary should have changed", ds.getLastModifiedDate(), modMod);
assertNotEquals("Last-modified on the description should have changed",
ds.getDescription().getLastModifiedDate(), modDescMod);
} finally {
session.expire();
}
}
}