/** * 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; import java.io.IOException; import java.util.List; import org.jhove2.annotation.ReportableProperty; import org.jhove2.config.ConfigInfo; import org.jhove2.core.Message.Context; import org.jhove2.core.Message.Severity; import org.jhove2.core.io.Input; import org.jhove2.core.source.FileSystemProperties; import org.jhove2.core.source.NamedSource; import org.jhove2.core.source.Source; import org.jhove2.core.source.SourceCounter; import org.jhove2.core.source.SourceFactory; import org.jhove2.module.AbstractModule; import org.jhove2.module.Command; import org.jhove2.persist.FrameworkAccessor; import com.sleepycat.persist.model.Persistent; /** * Singleton object that drives the characterization process. Widely referred to throughout the * framework. * * @author mstrong, slabrams, smorrissey */ @Persistent public class JHOVE2 extends AbstractModule { /** Framework version identifier. */ public static final String VERSION = "2.0.0"; /** Framework release date. */ public static final String RELEASE = "2010-09-10"; /** Framework rights statement. */ public static final String RIGHTS = "Copyright 2010 by The Regents of the University of California, " + "Ithaka Harbors, Inc., and The Board of Trustees of the Leland " + "Stanford Junior University. " + "Available under the terms of the BSD license."; /** Counter to track number and scope of sources processed by framework */ protected SourceCounter sourceCounter; /** Invocation settings for framework. If not configured, default values will be used */ protected Invocation invocation; /** Installation settings for framework. */ protected Installation installation; /** Configuration settings for framework. If not configured, default values will be used */ protected ConfigInfo configInfo; /** Factory class for creating new Sources for characterization */ protected SourceFactory sourceFactory; /** * Instantiate a new <code>JHOVE2</code> core framework with a default * configuration. * * @throws JHOVE2Exception */ public JHOVE2() throws JHOVE2Exception { this(null); } /** * Instantiate a new <code>JHOVE2</code> core framework with a default * configuration and a specified FrameworkAccessor * @param frameworkAccessor FrameworkAccessor to manage access to list of Commands * @throws JHOVE2Exception */ public JHOVE2(FrameworkAccessor frameworkAccessor) throws JHOVE2Exception{ this(new Invocation(), frameworkAccessor); } /** * Instantiate a new <code>JHOVE2</code> core framework with a specific * configuration. * @param invocation Configuration settings for this instance of the * JHOVE2 framework * @param frameworkAccessor * framework persistence manager * @throws JHOVE2Exception */ public JHOVE2(Invocation invocation, FrameworkAccessor frameworkAccessor) throws JHOVE2Exception { super(VERSION, RELEASE, RIGHTS, Scope.Generic, frameworkAccessor); this.invocation = invocation; this.sourceCounter = new SourceCounter(); } /** * Characterize a {@link org.jhove2.core.source.Source} unit by parsing its * {@link org.jhove2.core.io.Input}, without performing an identification * step. * This method will be used as a call-back by any format module that must * recursively characterize components of a format instance. * * @param source * Source unit * @param input * Source input * @return source which has been characterized * @throws JHOVE2Exception * @throws IOException */ public Source characterize(Source source, Input input) throws IOException, JHOVE2Exception { source = source.startTimer(); /* Update summary counts of source units, by scope. */ try { this.sourceCounter.incrementSourceCounter(source); this.getModuleAccessor().persistModule(this); /* Characterize the source unit. */ boolean tryIt = true; /* Check to see if this is a file system source unit, that is, a * physical file or directory on the file system, and if so, * that it exists and is readable. */ FileSystemProperties properties = source.getFileSystemProperties(); if (properties != null) { String name = ((NamedSource) source).getSourceName(); if (!properties.isExtant()) { source = source.addMessage(new Message(Severity.ERROR, Context.PROCESS, "org.jhove2.core.JHOVE2.FileNotFoundMessage", new Object[]{name}, this.getConfigInfo())); tryIt = false; } else if (!properties.isReadable()) { source = source.addMessage(new Message(Severity.ERROR, Context.PROCESS, "org.jhove2.core.JHOVE2.FileNotReadableMessage", new Object[]{name}, this.getConfigInfo())); tryIt = false; } } if (tryIt) { for (Command command : this.getCommands()){ command = (Command) command.getModuleAccessor().resetTimerInfo(command); try { command.execute(this, source, input); } finally { try{ command = (Command) command.getModuleAccessor().endTimerInfo(command); } catch(JHOVE2Exception j){ throw j; } } } } } catch (JHOVE2Exception e){ throw e; } catch (Exception e1){ String sourceName = ""; if (source instanceof NamedSource){ sourceName = ((NamedSource)source).getSourceName(); } throw new JHOVE2Exception ("Exception characterizing source " + sourceName, e1); } finally { source.close(); source = source.endTimer(); // this will commit source } return source; } /** * Determine if the fail fast limit has been exceeded. * * @param numErrors * Number of errors * @return True if the fail fast limit has been exceeded */ public boolean failFast(int numErrors) { if (this.invocation.getFailFastLimit() > 0 && numErrors > this.invocation.getFailFastLimit()) { return true; } return false; } /** * Get list of commands to be executed in sequence to characterize * a source unit. * @return List of command to be executed * @throws JHOVE2Exception */ @ReportableProperty(order = 3, value = "Configured commands.") public List<Command> getCommands() throws JHOVE2Exception { if (this.getModuleAccessor()==null){ throw new JHOVE2Exception("FrameworkAccessor is null"); } FrameworkAccessor fa = (FrameworkAccessor) this.getModuleAccessor(); return fa.getCommands(this); } /** * Get framework invocation properties. * @return Framework invocation properties */ @ReportableProperty(order = 2, value="Framework invocation properties.") public Invocation getInvocation() { return invocation; } /** Get framework {@link org.jhove2.core.Installation} properties. * @return Framework installation properties */ @ReportableProperty(order = 1, value = "Framework installation properties.") public Installation getInstallation() { return installation; } /** * Get framework memory usage. This is calculated naively as the Java * {@link java.lang.Runtime}'s total memory minus free memory at the time of * method abstractApplication. * * @return Memory usage, in bytes */ @ReportableProperty(order = 6, value = "Framework memory usage, in bytes.") public long getMemoryUsage() { Runtime rt = Runtime.getRuntime(); long use = rt.totalMemory() - rt.freeMemory(); return use; } /** * Get counter to track number and scope of source units processed * by the JHOVE2 framework. * @return Source unit counter */ @ReportableProperty(order = 5, value = "Source unit counter, by scope.") public SourceCounter getSourceCounter() { return sourceCounter; } /** * Set commands to be executed in sequence to characterize * {@link org.jhove2.core.source.Source} units. * @param commands Commands to be executed * @return List<Commands> added to JHOVE2 * @throws JHOVE2Exception */ public List<Command> setCommands(List<Command> commands) throws JHOVE2Exception { if (this.getModuleAccessor()==null){ throw new JHOVE2Exception("FrameworkAccessor is null"); } FrameworkAccessor fa = (FrameworkAccessor)this.getModuleAccessor(); return fa.setCommands(this, commands); } /** * Set framework invocation properties. * @param invocation Framework invocation properties */ public void setInvocation(Invocation invocation) { this.invocation = invocation; } /** * Set framework installation properties. * @param installation Framework installation properties */ public void setInstallation(Installation installation) { this.installation = installation; } /** * Set counter to track number and scope of * {@link org.jhove2.core.source.Source}s processed by * the JHOVE2 framework. * @param sourceCounter Source unit counter */ public void setSourceCounter(SourceCounter sourceCounter) { this.sourceCounter = sourceCounter; } /** * @return the configInfo */ public ConfigInfo getConfigInfo() { return configInfo; } /** * @param configInfo the configInfo to set */ public void setConfigInfo(ConfigInfo configInfo) { this.configInfo = configInfo; } /** * @return the sourceFactory */ public SourceFactory getSourceFactory() { return sourceFactory; } /** * @param sourceFactory the sourceFactory to set */ public void setSourceFactory(SourceFactory sourceFactory) { this.sourceFactory = sourceFactory; } }