/** * JHOVE2 - Next-generation architecture for format-aware characterization * * Copyright (c) 2009 by The Regents of the University of California, * Ithaka Harbors, Inc., and The Board of Trustees of the Leland Stanford * Junior University. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * o Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * o 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. * * o Neither the name of the University of California/California Digital * Library, Ithaka Harbors/Portico, or Stanford University, nor the names of * its 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 OWNER 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.jhove2.core.source; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import org.jhove2.core.Invocation; import org.jhove2.core.JHOVE2; import org.jhove2.core.JHOVE2Exception; import com.sleepycat.persist.model.Persistent; /** JHOVE2 byte stream source. A byte stream source is always a child of * some other source unit. * * @author mstrong, slabrams */ @Persistent public class ByteStreamSource extends AbstractSource implements MeasurableSource { /** The backing file of the parent source unit. If parent is itself a * ByteStreamSource, then the backing file of the parent's parent, and * so on. */ protected File parentFile; /** Buffer size (for creating temporary file). */ protected int bufferSize; /** Starting offset relative to parent source. */ protected long endingOffset; /** Backing file. */ protected File file; /** Name, if known. */ protected String name; /** Size of the byte stream, in bytes. */ protected long size; /** Starting offset relative to parent source. */ protected long startingOffset; /** Temporary directory. */ protected File tmpDirectory; /** Temporary file prefix. */ protected String tmpPrefix; /** Temporary file suffix. */ protected String tmpSuffix; @SuppressWarnings("unused") private ByteStreamSource() throws IOException, JHOVE2Exception { super(); } /** Instantiate a new <code>ByteStreamSource</code>. The new byte stream * is automatically added as a child reportable of its parent source unit. * @param jhove2 JHOVE2 framework * @param parent Parent source * @param offset Starting offset relative to parent * @param size Size of the byte stream * @param name Byte stream name, if known * @throws IOException * @throws JHOVE2Exception */ protected ByteStreamSource(JHOVE2 jhove2, Source parent, long offset, long size, String name) throws IOException, JHOVE2Exception { super(jhove2); if (parent instanceof ByteStreamSource) { this.parentFile = ((ByteStreamSource) parent).getParentFile(); } else { this.parentFile = parent.getFile(); } this.size = size; this.startingOffset = offset; this.endingOffset = offset + size; if (size > 0L) { this.endingOffset--; } this.name = name; /* Keep a copy of the temporary file prefix and suffix and I/O buffer * size in case we have to create a temporary backing file. */ Invocation inv = jhove2.getInvocation(); this.tmpDirectory = inv.getTempDirectoryFile(); this.tmpPrefix = inv.getTempPrefix(); this.tmpSuffix = inv.getTempSuffix(); this.bufferSize = inv.getBufferSize(); this.deleteTempFileOnClose = inv.getDeleteTempFilesOnClose(); //this.setSourceAccessor(sourceFactory.createSourceAccessor(this)); /* will update parentSourceId and sourceId fields automatically. */ parent.addChildSource(this); } /** * Close the source unit and release all underlying system I/O resources, * including a temporary backing file, if one exists.. */ @Override public void close() { super.close(); if (this.file != null && this.isTemp && this.deleteTempFileOnClose) { this.file.delete(); this.file = null; } } /** Get ending offset of the byte stream, relative to its parent. * @return Ending offset */ @Override public long getEndingOffset() { return this.endingOffset; } /** * Get {@link java.io.File} backing byte stream subset of its * parent source. Note that this File is not created until * actually required, and will be deleted on close(). * * @return File backing the byte stream; or null if the backing * file cannot be created successfully */ @Override public File getFile() { if (this.file == null) { /* Get format extension from name. */ String ext = this.tmpSuffix; int in = name.lastIndexOf('.'); if (in > -1) { ext = name.substring(in); } try { this.file = createTempFile(this.parentFile, this.startingOffset, this.size, this.tmpDirectory, this.tmpPrefix, ext, this.bufferSize); this.isTemp = true; } catch (IOException e) { /* Can't do anything more than return a null value. */ } } return this.file; } /** * Get {@link java.io.InputStream} backing the source unit. * If this method is called explicitly, then the corresponding * InputStream.close() method must be called to avoid a resource leak. * * @return Input stream backing the source unit * @throws FileNotFoundException Backing file not found * @throws IOException Backing file could not be created * @see org.jhove2.core.source.Source#getInputStream() */ @Override public InputStream getInputStream() throws IOException { InputStream stream = null; stream = new FileInputStream(this.getFile()); return stream; } /** Get parent file. This is the file associated with the parent source * unit, unless the parent is also a ByteStreamSource, in which case it * is the file that parent source's parent, and so on. * @return Parent file */ public File getParentFile() { return this.parentFile; } /** Get byte stream size, in bytes. * @return Byte stream size */ @Override public long getSize() { return this.size; } /** Get starting offset of the source unit, in bytes, relative to its * parent. * @return Starting offset of the source unit */ @Override public long getStartingOffset() { return this.startingOffset; } }