/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package org.fcrepo.server.storage.translation;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Date;
import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.apache.commons.codec.digest.DigestUtils;
import org.custommonkey.xmlunit.XMLTestCase;
import org.jrdf.graph.URIReference;
import org.fcrepo.common.PID;
import org.fcrepo.server.Context;
import org.fcrepo.server.errors.StreamIOException;
import org.fcrepo.server.storage.types.BasicDigitalObject;
import org.fcrepo.server.storage.types.DSBinding;
import org.fcrepo.server.storage.types.DSBindingMap;
import org.fcrepo.server.storage.types.DatastreamManagedContent;
import org.fcrepo.server.storage.types.DatastreamReferencedContent;
import org.fcrepo.server.storage.types.DatastreamXMLMetadata;
import org.fcrepo.server.storage.types.DigitalObject;
import org.fcrepo.server.storage.types.Disseminator;
/**
* Convenience superclass for serializer and deserializer tests.
*
* @author Chris Wilper
*/
@SuppressWarnings("deprecation")
public abstract class TranslationTest
extends XMLTestCase {
protected static final String TEST_PID = "test:pid";
//---
// Static helpers
//---
protected static DOTranslationUtility translationUtility() {
Properties transProps = new Properties(System.getProperties());
if (transProps.getProperty("fedora.hostname") == null) {
transProps.setProperty("fedora.hostname","localhost");
}
if (transProps.getProperty("fedora.port") == null) {
transProps.setProperty("fedora.port","1024");
}
if (transProps.getProperty("fedora.appServerContext") == null) {
transProps.setProperty("fedora.appServerContext","fedora");
}
return new DOTranslationUtility.Impl(transProps, true);
}
protected static DigitalObject createTestObject(URIReference... contentModelURIs) {
DigitalObject obj = new BasicDigitalObject();
obj.setPid(TEST_PID);
DatastreamXMLMetadata ds = createXDatastream("RELS-EXT");
StringBuilder rdf = new StringBuilder();
rdf
.append("<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" "
+ "xmlns:fedora-model=\"info:fedora/fedora-system:def/model#\">\n"
+ "<rdf:Description rdf:about=\"");
rdf.append(PID.getInstance(TEST_PID).toURI() + "\">\n");
for (URIReference model : contentModelURIs) {
rdf.append("<fedora-model:hasModel rdf:resource=\""
+ model.getURI().toString()
+ "\"></fedora-model:hasModel>\n");
}
rdf.append("</rdf:Description></rdf:RDF>");
ds.xmlContent = rdf.toString().getBytes();
obj.addDatastreamVersion(ds, false);
obj.setCreateDate(new Date());
obj.setLastModDate(new Date());
obj.setCreateDate(new Date());
obj.setLastModDate(new Date());
return obj;
}
protected static DatastreamXMLMetadata createXDatastream(String id) {
DatastreamXMLMetadata ds = new DatastreamXMLMetadata();
ds.DatastreamID = id;
ds.DSVersionID = id + ".0";
ds.DSControlGrp = "X";
ds.xmlContent = "<doc/>".getBytes();
ds.DSCreateDT = new Date();
return ds;
}
protected static DatastreamReferencedContent createRDatastream(String id,
String url) {
DatastreamReferencedContent ds = new DatastreamReferencedContent();
ds.DatastreamID = id;
ds.DSVersionID = id + ".0";
ds.DSControlGrp = "R";
ds.DSLocation = url;
return ds;
}
protected static DatastreamManagedContent createMDatastream(String id, final byte [] content) {
DatastreamManagedContent dmc = new DatastreamManagedContent(){
public InputStream getContentStream(Context ctx) throws StreamIOException {
return new ByteArrayInputStream(content);
}
};
dmc.DatastreamID = id;
dmc.DSVersionID = id + ".0";
dmc.DSControlGrp = "M";
dmc.DSChecksumType = "MD5";
dmc.DSChecksum = DigestUtils.md5Hex(content);
return dmc;
}
protected static Disseminator createDisseminator(String id, int numBindings) {
Disseminator diss = new Disseminator();
diss.dissID = id;
diss.dissVersionID = id + ".0";
diss.bDefID = TEST_PID + "bdef";
diss.sDepID = TEST_PID + "bmech";
diss.dsBindMap = new DSBindingMap();
// the following is only needed for METS
diss.dsBindMapID = id + "bindMap";
DSBinding[] dsBindings = new DSBinding[numBindings];
for (int i = 1; i <= numBindings; i++) {
dsBindings[i - 1] = new DSBinding();
dsBindings[i - 1].bindKeyName = "KEY" + i;
dsBindings[i - 1].datastreamID = "DS" + i;
}
diss.dsBindMap.dsBindings = dsBindings;
return diss;
}
protected void runConcurrent(Callable<?>[] callables) throws Exception {
final int numThreads = callables.length;
final ExecutorService threadPool = Executors.newFixedThreadPool(numThreads);
try {
final CountDownLatch allExecutorThreadsReady = new CountDownLatch(numThreads);
final CountDownLatch afterInitBlocker = new CountDownLatch(1);
final CountDownLatch allDone = new CountDownLatch(numThreads);
for (final Callable<?> submittedTestCallable : callables) {
threadPool.submit(new Callable<Object>() {
public Object call() throws Exception {
allExecutorThreadsReady.countDown();
try {
afterInitBlocker.await();
return submittedTestCallable.call();
} finally {
allDone.countDown();
}
}
});
}
// wait until all threads are ready
assertTrue("Timeout initializing threads! Perform long lasting initializations before passing runnables to assertConcurrent", allExecutorThreadsReady.await(callables.length * 10, TimeUnit.MILLISECONDS));
// start all test runners
afterInitBlocker.countDown();
assertTrue("Thread timeout! More than 5 seconds", allDone.await(5, TimeUnit.SECONDS));
} finally {
threadPool.shutdownNow();
}
}
}