com.googlecode.fascinator.common.storage.StorageUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.googlecode.fascinator.common.storage.StorageUtils.java

Source

/* 
 * The Fascinator - Common Library
 * Copyright (C) 2008 University of Southern Queensland
 * Copyright (C) 2013 Queensland Cyber Infrastructure Foundation (http://www.qcif.edu.au/)
 *  
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
package com.googlecode.fascinator.common.storage;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Properties;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.googlecode.fascinator.api.storage.DigitalObject;
import com.googlecode.fascinator.api.storage.Payload;
import com.googlecode.fascinator.api.storage.Storage;
import com.googlecode.fascinator.api.storage.StorageException;

/**
 * Storage API utility methods.
 * 
 * @author Oliver Lucido
 * @author Andrew Brazzatti
 * @author Jianfeng Li
 */

public class StorageUtils {

    /** Default host name */
    public static final String DEFAULT_HOSTNAME = "localhost";

    /** Logging */
    @SuppressWarnings("unused")
    private static final Logger log = LoggerFactory.getLogger(StorageUtils.class);

    /**
     * Generates a Object identifier for a given file
     * 
     * @param file the File to store
     * @return a String object id
     */
    public static String generateOid(File file) {
        // MD5 hash the file path,
        String path = FilenameUtils.separatorsToUnix(file.getAbsolutePath());
        String hostname = "localhost";
        try {
            hostname = InetAddress.getLocalHost().getCanonicalHostName();
        } catch (UnknownHostException uhe) {
        }
        String username = System.getProperty("user.name", "anonymous");
        // log.debug("Generating OID path:'{}' hostname:'{}' username:'{}'",
        // new String[] { path, hostname, username });
        return DigestUtils.md5Hex(path + hostname + username);
    }

    /**
     * Hash the internal contents of a file.
     * 
     * @param file The File to hash
     * @return String Hash of the file's contents
     * @throws IOException If there was an error accessing the file
     */
    private static String hashFile(File file) throws IOException {
        return DigestUtils.md5Hex(FileUtils.readFileToString(file));
    }

    /**
     * Generates a Payload identifier for a given file
     * 
     * @param file the File to store
     * @return a String payload id
     */
    public static String generatePid(File file) {
        return FilenameUtils.separatorsToUnix(file.getName());
    }

    /**
     * This method stores a copy of a File as a DigitalObject into the specified
     * Storage
     * 
     * @param storage a Storage instance
     * @param file the File to store
     * @return a DigitalObject
     * @throws StorageException if there was an error storing the file
     */
    public static DigitalObject storeFile(Storage storage, File file) throws StorageException {
        return storeFile(storage, file, false);
    }

    /**
     * This method stores a link to a File as a DigitalObject into the specified
     * Storage
     * 
     * @param storage a Storage instance
     * @param file the File to store
     * @return a DigitalObject
     * @throws StorageException if there was an error storing the file
     */
    public static DigitalObject linkFile(Storage storage, File file) throws StorageException {
        return storeFile(storage, file, true);
    }

    /**
     * This method stores a File as a DigitalObject into the specified Storage.
     * The File can be stored as a linked Payload if specified.
     * 
     * @param storage a Storage instance
     * @param file the File to store
     * @param linked set true to link to the original file, false to copy
     * @return a DigitalObject
     * @throws StorageException if there was an error storing the file
     */
    public static DigitalObject storeFile(Storage storage, File file, boolean linked) throws StorageException {
        DigitalObject object = null;
        Payload payload = null;
        String oid = generateOid(file);
        String pid = generatePid(file);
        try {
            try {
                object = getDigitalObject(storage, oid);
                if (linked) {
                    try {
                        String path = FilenameUtils.separatorsToUnix(file.getAbsolutePath());
                        payload = createLinkedPayload(object, pid, path);
                    } catch (StorageException se) {
                        payload = object.getPayload(pid);
                    }
                } else {
                    payload = createOrUpdatePayload(object, pid, new FileInputStream(file));
                }
            } catch (StorageException se) {
                throw se;
            }
        } catch (FileNotFoundException fnfe) {
            throw new StorageException("File not found '" + oid + "'");
        } finally {
            if (payload != null) {
                payload.close();
            }
        }
        return object;
    }

    /**
     * Gets a DigitalObject from the specified Storage instance. If the object
     * does not exist, this method will attempt to create it.
     * 
     * @param storage a Storage instance
     * @param oid the object identifier to get (or create)
     * @return a DigitalObject
     * @throws StorageException if the object could not be retrieved or created
     */
    public static DigitalObject getDigitalObject(Storage storage, String oid) throws StorageException {
        DigitalObject object = null;
        try {
            // try to create a new object
            object = storage.createObject(oid);
        } catch (StorageException ex) {
            // object exists, try and get it
            try {
                object = storage.getObject(oid);
            } catch (StorageException ex1) {
                // could not be created and not found
                throw new StorageException(ex1);
            }
        }
        return object;
    }

    /**
     * Get a payload object in the specified Storage instance by its object ID
     * and the name of payload
     * 
     * @param storage : Storage object
     * @param oid : ID of a Digital object
     * @param payloadName : name of payload
     * @return a Payload object
     * @throws StorageException
     */
    public static Payload getPayload(Storage storage, String oid, String payloadName) throws StorageException {
        DigitalObject digitalObject = getDigitalObject(storage, oid);

        Payload payload = digitalObject.getPayload(payloadName);
        return payload;
    }

    /**
     * Ensure the provided harvest file is up-to-date in storage.
     * 
     * @param storage a Storage instance
     * @param file to check in storage
     * @return a DigitalObject
     * @throws StorageException if the object could not be retrieved or created
     */
    public static DigitalObject checkHarvestFile(Storage storage, File file) throws StorageException {
        String oid = generateOid(file);
        String lastMod = String.valueOf(file.lastModified());
        DigitalObject object;
        Properties metadata;

        try {
            // Get the object from storage
            object = storage.getObject(oid);
            try {
                // Check when it was last saved
                metadata = object.getMetadata();
                String oldMod = metadata.getProperty("lastModified");

                // Quick test - has it been changed?
                if (oldMod == null || !oldMod.equals(lastMod)) {
                    // Hash the file contents
                    String oldHash = metadata.getProperty("fileHash");
                    String fileHash = hashFile(file);
                    // Thorough test - have the contents changed?
                    if (oldHash == null || !oldHash.equals(fileHash)) {
                        // Update the file
                        FileInputStream in = new FileInputStream(file);
                        object.updatePayload(object.getSourceId(), in);
                        // Update the metadata
                        metadata.setProperty("lastModified", lastMod);
                        metadata.setProperty("fileHash", fileHash);
                        // Close and return
                        object.close();
                        return object;
                    }
                }
            } catch (FileNotFoundException ex1) {
                throw new StorageException("Harvest file not found: ", ex1);
            } catch (IOException ex1) {
                throw new StorageException("Error reading harvest file: ", ex1);
            } catch (StorageException ex1) {
                throw new StorageException("Error storing harvest file: ", ex1);
            }

        } catch (StorageException ex) {
            // It wasn't found in storage
            try {
                // Store it
                object = storeFile(storage, file);
                // Update its metadata
                metadata = object.getMetadata();
                metadata.setProperty("lastModified", lastMod);
                metadata.setProperty("fileHash", hashFile(file));
                // Close and return
                object.close();
                return object;
            } catch (IOException ex1) {
                throw new StorageException("Error reading harvest file: ", ex1);
            } catch (StorageException ex1) {
                throw new StorageException("Error storing harvest file: ", ex1);
            }
        }
        return null;
    }

    /**
     * Create or update a stored Payload in the specified DigitalObject
     * 
     * @param object the DigitalObject to create the Payload in
     * @param pid the Payload ID
     * @param in the InputStream for the Payload's data
     * @return a Payload
     * @throws StorageException if the Payload could not be created
     */
    public static Payload createOrUpdatePayload(DigitalObject object, String pid, InputStream in)
            throws StorageException {
        return createOrUpdatePayload(object, pid, in, null);
    }

    public static Payload createOrUpdatePayload(DigitalObject object, String pid, InputStream in, String filePath)
            throws StorageException {
        Payload payload = null;
        try {
            if (filePath == null) {
                payload = object.createStoredPayload(pid, in);
            } else {
                payload = object.createLinkedPayload(pid, filePath);
            }
        } catch (StorageException ex) {
            try {
                payload = object.updatePayload(pid, in);
            } catch (StorageException ex1) {
                throw ex1;
            }
        }
        return payload;
    }

    /**
     * Creates a linked Payload in the specified DigitalObject
     * 
     * @param object the DigitalObject to create the Payload in
     * @param pid the Payload ID
     * @param path the absolute path to the file the Payload links to
     * @return a Payload
     * @throws StorageException if the Payload could not be created
     */
    public static Payload createLinkedPayload(DigitalObject object, String pid, String path)
            throws StorageException {
        Payload payload = null;
        try {
            payload = object.createLinkedPayload(pid, path);
        } catch (StorageException ex) {
            throw ex;
        }
        return payload;
    }
}