⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bitstreamstoragemanager.java

📁 dspace 用j2ee架构的一个数字图书馆.开源程序
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* * BitstreamStorageManager.java * * Version: $Revision: 1.17 $ * * Date: $Date: 2006/01/20 16:13:19 $ * * Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts * Institute of Technology.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of the Hewlett-Packard Company nor the name of the * Massachusetts Institute of Technology nor the names of their * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */package org.dspace.storage.bitstore;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.security.DigestInputStream;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.sql.SQLException;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import org.apache.log4j.Logger;import org.dspace.checker.BitstreamInfoDAO;import org.dspace.core.ConfigurationManager;import org.dspace.core.Context;import org.dspace.core.Utils;import org.dspace.storage.rdbms.DatabaseManager;import org.dspace.storage.rdbms.TableRow;import edu.sdsc.grid.io.FileFactory;import edu.sdsc.grid.io.GeneralFile;import edu.sdsc.grid.io.GeneralFileOutputStream;import edu.sdsc.grid.io.local.LocalFile;import edu.sdsc.grid.io.srb.SRBAccount;import edu.sdsc.grid.io.srb.SRBFile;import edu.sdsc.grid.io.srb.SRBFileSystem;/** * <P> * Stores, retrieves and deletes bitstreams. * </P> *  * <P> * Presently, asset stores are specified in <code>dspace.cfg</code>. Since * Java does not offer a way of detecting free disk space, the asset store to * use for new bitstreams is also specified in a configuration property. The * drawbacks to this are that the administrators are responsible for monitoring * available space in the asset stores, and DSpace (Tomcat) has to be restarted * when the asset store for new ('incoming') bitstreams is changed. * </P> *  * <P> * Mods by David Little, UCSD Libraries 12/21/04 to allow the registration of * files (bitstreams) into DSpace. * </P> *  * <p>Cleanup integration with checker package by Nate Sarr 2006-01. N.B. The  * dependency on the checker package isn't ideal - a Listener pattern would be  * better but was considered overkill for the purposes of integrating the checker. * It would be worth re-considering a Listener pattern if another package needs to  * be notified of BitstreamStorageManager actions.</p>  * * @author Peter Breton, Robert Tansley, David Little, Nathan Sarr * @version $Revision: 1.17 $ */public class BitstreamStorageManager{    /** log4j log */    private static Logger log = Logger.getLogger(BitstreamStorageManager.class);	/**	 * The asset store locations. The information for each GeneralFile in the	 * array comes from dspace.cfg, so see the comments in that file.	 *	 * If an array element refers to a conventional (non_SRB) asset store, the	 * element will be a LocalFile object (similar to a java.io.File object)	 * referencing a local directory under which the bitstreams are stored.	 *	 * If an array element refers to an SRB asset store, the element will be an	 * SRBFile object referencing an SRB 'collection' (directory) under which	 * the bitstreams are stored.	 *	 * An SRBFile object is obtained by (1) using dspace.cfg properties to	 * create an SRBAccount object (2) using the account to create an	 * SRBFileSystem object (similar to a connection) (3) using the	 * SRBFileSystem object to create an SRBFile object	 */	private static GeneralFile[] assetStores;    /** The asset store to use for new bitstreams */    private static int incoming;    // These settings control the way an identifier is hashed into    // directory and file names    //    // With digitsPerLevel 2 and directoryLevels 3, an identifier    // like 12345678901234567890 turns into the relative name    // /12/34/56/12345678901234567890.    //    // You should not change these settings if you have data in the    // asset store, as the BitstreamStorageManager will be unable    // to find your existing data.    private static final int digitsPerLevel = 2;    private static final int directoryLevels = 3;	/**	 * This prefix string marks registered bitstreams in internal_id	 */	private static final String REGISTERED_FLAG = "-R";    /* Read in the asset stores from the config. */    static    {        ArrayList stores = new ArrayList();		// 'assetstore.dir' is always store number 0		String sAssetstoreDir = ConfigurationManager				.getProperty("assetstore.dir"); 		// see if conventional assetstore or srb		if (sAssetstoreDir != null) {			stores.add(sAssetstoreDir); // conventional (non-srb)		} else if (ConfigurationManager.getProperty("srb.host") != null) {			stores.add(new SRBAccount( // srb					ConfigurationManager.getProperty("srb.host"),					ConfigurationManager.getIntProperty("srb.port"),					ConfigurationManager.getProperty("srb.username"),					ConfigurationManager.getProperty("srb.password"),					ConfigurationManager.getProperty("srb.homedirectory"),					ConfigurationManager.getProperty("srb.mdasdomainname"),					ConfigurationManager							.getProperty("srb.defaultstorageresource"),					ConfigurationManager.getProperty("srb.mcatzone")));		} else {			log.error("No default assetstore");		}		// read in assetstores .1, .2, ....		for (int i = 1;; i++) { // i == 0 is default above			sAssetstoreDir = ConfigurationManager.getProperty("assetstore.dir."					+ i);			// see if 'i' conventional assetstore or srb			if (sAssetstoreDir != null) { 		// conventional (non-srb)				stores.add(sAssetstoreDir);			} else if (ConfigurationManager.getProperty("srb.host." + i)					!= null) { // srb				stores.add(new SRBAccount(						ConfigurationManager.getProperty("srb.host." + i),						ConfigurationManager.getIntProperty("srb.port." + i),						ConfigurationManager.getProperty("srb.username." + i),						ConfigurationManager.getProperty("srb.password." + i),						ConfigurationManager								.getProperty("srb.homedirectory." + i),						ConfigurationManager								.getProperty("srb.mdasdomainname." + i),						ConfigurationManager								.getProperty("srb.defaultstorageresource." + i),						ConfigurationManager.getProperty("srb.mcatzone." + i)));			} else {				break; // must be at the end of the assetstores			}		}		// convert list to array		// the elements (objects) in the list are class		//   (1) String - conventional non-srb assetstore		//   (2) SRBAccount - srb assetstore		assetStores = new GeneralFile[stores.size()];		for (int i = 0; i < stores.size(); i++) {			Object o = stores.get(i);			if (o == null) { // I don't know if this can occur				log.error("Problem with assetstore " + i);			}			if (o instanceof String) {				assetStores[i] = new LocalFile((String) o);			} else if (o instanceof SRBAccount) {				SRBFileSystem srbFileSystem = null;				try {					srbFileSystem = new SRBFileSystem((SRBAccount) o);				} catch (NullPointerException e) {					log.error("No SRBAccount for assetstore " + i);				} catch (IOException e) {					log.error("Problem getting SRBFileSystem for assetstore"							+ i);				}				if (srbFileSystem == null) {					log.error("SRB FileSystem is null for assetstore " + i);				}				String sSRBAssetstore = null;				if (i == 0) { // the zero (default) assetstore has no suffix					sSRBAssetstore = ConfigurationManager							.getProperty("srb.parentdir");				} else {					sSRBAssetstore = ConfigurationManager							.getProperty("srb.parentdir." + i);				}				if (sSRBAssetstore == null) {					log.error("srb.parentdir is undefined for assetstore " + i);				}				assetStores[i] = new SRBFile(srbFileSystem, sSRBAssetstore);			} else {				log.error("Unexpected " + o.getClass().toString()						+ " with assetstore " + i);			}		}        // Read asset store to put new files in. Default is 0.        incoming = ConfigurationManager.getIntProperty("assetstore.incoming");    }    /**     * Store a stream of bits.     *      * <p>     * If this method returns successfully, the bits have been stored, and RDBMS     * metadata entries are in place (the context still needs to be completed to     * finalize the transaction).     * </p>     *      * <p>     * If this method returns successfully and the context is aborted, then the     * bits will be stored in the asset store and the RDBMS metadata entries     * will exist, but with the deleted flag set.     * </p>     *      * If this method throws an exception, then any of the following may be     * true:     *      * <ul>     * <li>Neither bits nor RDBMS metadata entries have been stored.     * <li>RDBMS metadata entries with the deleted flag set have been stored,     * but no bits.     * <li>RDBMS metadata entries with the deleted flag set have been stored,     * and some or all of the bits have also been stored.     * </ul>     *      * @param context     *            The current context     * @param is     *            The stream of bits to store     * @exception IOException     *                If a problem occurs while storing the bits     * @exception SQLException     *                If a problem occurs accessing the RDBMS     *      * @return The ID of the stored bitstream     */    public static int store(Context context, InputStream is)            throws SQLException, IOException    {        // Create internal ID        String id = Utils.generateKey();        // Create a deleted bitstream row, using a separate DB connection        TableRow bitstream;        Context tempContext = null;        try        {            tempContext = new Context();            bitstream = DatabaseManager.create(tempContext, "Bitstream");            bitstream.setColumn("deleted", true);            bitstream.setColumn("internal_id", id);            /*             * Set the store number of the new bitstream If you want to use some             * other method of working out where to put a new bitstream, here's             * where it should go             */            bitstream.setColumn("store_number", incoming);            DatabaseManager.update(tempContext, bitstream);            tempContext.complete();        }        catch (SQLException sqle)        {            if (tempContext != null)            {                tempContext.abort();            }            throw sqle;        }        // Where on the file system will this new bitstream go?		GeneralFile file = getFile(bitstream);        // Make the parent dirs if necessary		GeneralFile parent = file.getParentFile();        if (!parent.exists())        {            parent.mkdirs();        }        //Create the corresponding file and open it        file.createNewFile();		GeneralFileOutputStream fos = FileFactory.newFileOutputStream(file);		// Read through a digest input stream that will work out the MD5        DigestInputStream dis = null;        try        {            dis = new DigestInputStream(is, MessageDigest.getInstance("MD5"));        }        // Should never happen        catch (NoSuchAlgorithmException nsae)        {            log.warn("Caught NoSuchAlgorithmException", nsae);        }        Utils.bufferedCopy(dis, fos);        fos.close();        is.close();        bitstream.setColumn("size_bytes", file.length());        bitstream.setColumn("checksum", Utils.toHex(dis.getMessageDigest()                .digest()));        bitstream.setColumn("checksum_algorithm", "MD5");        bitstream.setColumn("deleted", false);        DatabaseManager.update(context, bitstream);        int bitstream_id = bitstream.getIntColumn("bitstream_id");        if (log.isDebugEnabled())        {            log.debug("Stored bitstream " + bitstream_id + " in file "                    + file.getAbsolutePath());        }        return bitstream_id;    }	/**	 * Register a bitstream already in storage.	 *	 * @param context	 *            The current context	 * @param assetstore The assetstore number for the bitstream to be	 * 			registered	 * @param bitstreamPath The relative path of the bitstream to be registered.	 * 		The path is relative to the path of ths assetstore.	 * @return The ID of the registered bitstream	 * @exception SQLException	 *                If a problem occurs accessing the RDBMS	 * @throws IOExeption	 */	public static int register(Context context, int assetstore,				String bitstreamPath) throws SQLException, IOException {		// mark this bitstream as a registered bitstream		String sInternalId = REGISTERED_FLAG + bitstreamPath;		// Create a deleted bitstream row, using a separate DB connection		TableRow bitstream;		Context tempContext = null;		try {			tempContext = new Context();			bitstream = DatabaseManager.create(tempContext, "Bitstream");			bitstream.setColumn("deleted", true);			bitstream.setColumn("internal_id", sInternalId);			bitstream.setColumn("store_number", assetstore);			DatabaseManager.update(tempContext, bitstream);			tempContext.complete();		} catch (SQLException sqle) {			if (tempContext != null) {				tempContext.abort();			}			throw sqle;		}		// get a reference to the file		GeneralFile file = getFile(bitstream);		// read through a DigestInputStream that will work out the MD5		//		// DSpace refers to checksum, writes it in METS, and uses it as an		// AIP filename (!), but never seems to validate with it. Furthermore,		// DSpace appears to hardcode the algorithm to MD5 in some places--see 		// METSExport.java.		//

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -