fedora.test.integration.TestLargeDatastreams.java Source code

Java tutorial

Introduction

Here is the source code for fedora.test.integration.TestLargeDatastreams.java

Source

/* 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 fedora.test.integration;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

import java.util.Random;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.PartSource;

import org.junit.Test;

import junit.framework.JUnit4TestAdapter;

import fedora.client.FedoraClient;

import fedora.server.access.FedoraAPIA;
import fedora.server.management.FedoraAPIM;
import fedora.server.types.gen.MIMETypedStream;

import fedora.test.FedoraTestCase;

/**
 * Performs ingest and export tests using large datastreams.
 * This test creates and moves very large files and as such
 * takes significant time to run.
 *
 * Non-SSL transports *MUST* be available for all APIs in order
 * for this test to run properly.
 *
 * @author Bill Branan
 */
public class TestLargeDatastreams extends FedoraTestCase {

    private FedoraClient fedoraClient;

    private FedoraAPIM apim;

    private FedoraAPIA apia;

    private static final String pid = "demo:LargeDatastreams";

    private static byte[] DEMO_FOXML;

    private static long gigabyte = 1073741824;
    private long fileSize = gigabyte * 5;

    static {
        // Test FOXML object
        StringBuilder sb = new StringBuilder();
        sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        sb.append("<foxml:digitalObject VERSION=\"1.1\" PID=\"" + pid + "\" ");
        sb.append("  xmlns:foxml=\"info:fedora/fedora-system:def/foxml#\" ");
        sb.append("  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ");
        sb.append("  xsi:schemaLocation=\"info:fedora/fedora-system:def/foxml# ");
        sb.append("  http://www.fedora.info/definitions/1/0/foxml1-1.xsd\">");
        sb.append("  <foxml:objectProperties>");
        sb.append("    <foxml:property NAME=\"info:fedora/fedora-system:def/model#state\" VALUE=\"A\"/>");
        sb.append("  </foxml:objectProperties>");
        sb.append("</foxml:digitalObject>");

        try {
            DEMO_FOXML = sb.toString().getBytes("UTF-8");
        } catch (UnsupportedEncodingException uee) {
        }
    }

    @Override
    public void setUp() throws Exception {
        fedoraClient = getFedoraClient();
        apim = fedoraClient.getAPIM();
        apia = fedoraClient.getAPIA();
    }

    @Test
    public void testLargeDatastreamIO() throws Exception {
        System.out.println("Running testLargeDatastreams...");

        // Create the object, add the datastream
        System.out.println("  Uploading a file of size " + fileSize + " bytes...");
        String uploadId = upload();
        System.out.println("  Creating data object...");
        apim.ingest(DEMO_FOXML, FOXML1_1.uri, "new foxml object");
        System.out.println("  Adding uploaded file as a datastream...");
        apim.addDatastream(pid, "DS1", null, "Large Datastream", false, "text/plain", null, uploadId, "M", "A",
                null, null, "Adding Large Datastream");

        // Export the datastream via API-A-Lite
        System.out.println("  Exporting datastream via API-A-Lite...");
        long exportFileAPIALiteSize = exportAPIALite("DS1");

        // Check the file size to make sure the entire file was retrieved
        assertEquals(fileSize, exportFileAPIALiteSize);

        // Export the datastream via API-A
        System.out.println("  Exporting datastream via API-A...");
        long exportFileAPIASize = exportAPIA("DS1");

        // If file was small enough to transfer via API-A
        if (exportFileAPIASize >= 0) {
            assertEquals(fileSize, exportFileAPIASize);
        }

        // Clean up
        apim.purgeObject(pid, "Removing Test Object", false);
        System.out.println("  Test Complete.");
    }

    private String upload() throws Exception {
        String url = fedoraClient.getUploadURL();
        EntityEnclosingMethod httpMethod = new PostMethod(url);
        httpMethod.setDoAuthentication(true);
        httpMethod.getParams().setParameter("Connection", "Keep-Alive");
        httpMethod.setContentChunked(true);
        Part[] parts = { new FilePart("file", new SizedPartSource()) };
        httpMethod.setRequestEntity(new MultipartRequestEntity(parts, httpMethod.getParams()));
        HttpClient client = fedoraClient.getHttpClient();
        try {

            int status = client.executeMethod(httpMethod);
            String response = new String(httpMethod.getResponseBody());

            if (status != HttpStatus.SC_CREATED) {
                throw new IOException("Upload failed: " + HttpStatus.getStatusText(status) + ": "
                        + replaceNewlines(response, " "));
            } else {
                response = response.replaceAll("\r", "").replaceAll("\n", "");
                return response;
            }
        } finally {
            httpMethod.releaseConnection();
        }
    }

    private long exportAPIALite(String dsId) throws Exception {
        String url = apia.describeRepository().getRepositoryBaseURL() + "/get/" + pid + "/" + dsId;
        HttpMethod httpMethod = new GetMethod(url);
        httpMethod.setDoAuthentication(true);
        httpMethod.getParams().setParameter("Connection", "Keep-Alive");

        HttpClient client = fedoraClient.getHttpClient();
        client.executeMethod(httpMethod);
        BufferedInputStream dataStream = new BufferedInputStream(httpMethod.getResponseBodyAsStream());

        long bytesRead = 0;
        while (dataStream.read() >= 0) {
            ++bytesRead;
        }

        return bytesRead;
    }

    private long exportAPIA(String dsId) throws Exception {
        MIMETypedStream fileStream = null;
        try {
            fileStream = apia.getDatastreamDissemination(pid, dsId, null);
        } catch (Exception e) {
            if (e.getMessage().indexOf("The datastream you are attempting " + "to retrieve is too large") > 0) {
                System.out.println("  Expected error generated in API-A export:");
                System.out.println("    Error text: " + e.getMessage());
                return -1;
            } else {
                fail("  Unexpected exception encountered in exportAPIA: " + e.getMessage());
            }
        }

        return fileStream.getStream().length;
    }

    /**
     * Replace newlines with the given string.
     */
    private static String replaceNewlines(String in, String replaceWith) {
        return in.replaceAll("\r", replaceWith).replaceAll("\n", replaceWith);
    }

    public static junit.framework.Test suite() {
        return new JUnit4TestAdapter(TestLargeDatastreams.class);
    }

    private class SizedPartSource implements PartSource {

        public InputStream createInputStream() throws IOException {
            return new SizedInputStream();
        }

        public String getFileName() {
            return "file";
        }

        public long getLength() {
            return fileSize;
        }
    }

    private class SizedInputStream extends InputStream {

        private long bytesRead = 0;
        Random generator = new Random(System.currentTimeMillis());

        @Override
        public int available() throws IOException {
            return (int) (fileSize - bytesRead);
        }

        @Override
        public int read() throws IOException {
            if (bytesRead < fileSize) {
                ++bytesRead;
                return generator.nextInt(100);
            } else {
                return -1;
            }
        }
    }
}