Hi David and Matt
Many thanx for your answers. I could solve my issue by myself in the meanwhile. What I needed was a collection of IdentificationResults for a file; however this collection should include all available IdentificationResults: binary signatures, container signatures, and extension matches; i.e. their "method" is one of "SIGNATURE", "CONTAINER", or "EXTENSION".
To accomplish this, I had to do quite some programming. I find it's a pity that DROID doesn't offer a simple external interface like
<code>
List<IdentificationResult> getIdentificationResults(String filePath);
List<IdentificationResult> getIdentificationResults(File file);
</code>
to retrieve the relevant informations easily.
This is my implementation. It is an abstract class that offers only static methods because I don't need several different instances.
<code>
/**
* Copyright (C) 2011-2013 Docuteam GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3
* as published by the Free Software Foundation.
*
* 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
*/
package ch.docuteam.docutools.file;
import java.io.*;
import java.util.List;
import uk.gov.nationalarchives.droid.command.action.CommandExecutionException;
import uk.gov.nationalarchives.droid.command.container.Ole2ContainerContentIdentifier;
import uk.gov.nationalarchives.droid.command.container.ZipContainerContentIdentifier;
import uk.gov.nationalarchives.droid.container.*;
import uk.gov.nationalarchives.droid.container.ole2.Ole2IdentifierEngine;
import uk.gov.nationalarchives.droid.container.zip.ZipIdentifierEngine;
import uk.gov.nationalarchives.droid.core.BinarySignatureIdentifier_Extended;
import uk.gov.nationalarchives.droid.core.interfaces.*;
import uk.gov.nationalarchives.droid.core.interfaces.archive.IdentificationRequestFactory;
import uk.gov.nationalarchives.droid.core.interfaces.resource.FileSystemIdentificationRequest;
import uk.gov.nationalarchives.droid.core.interfaces.resource.RequestMetaData;
import uk.gov.nationalarchives.droid.core.signature.FileFormat;
import ch.docuteam.docutools.file.exception.*;
import ch.docuteam.docutools.out.Logger;
/**
* This is an abstract class for getting file format information using DROID.
* <br>
* The DROID subsystem requires the signature file "config/DROID_SignatureFile_V66.xml" to be in the folder "config" in the working directory.
*
* @author denis
*
*/
public abstract class MetadataProviderDROID
{
// ===========================================================================================
// ======== Structure =======================================================
// ===========================================================================================
// ======== Static Final Public =======================================================
// ======== Static Final Private =======================================================
static private final String DefaultSignatureFile = "config/DROID_SignatureFile_V66.xml";
static private final String DefaultContainerSignatureFile = "config/container-signature-20121218.xml";
// ======== Static Public =======================================================
// ======== Static Private =======================================================
static private String SignatureFile = DefaultSignatureFile;
static private String ContainerSignatureFile = DefaultContainerSignatureFile;
static private BinarySignatureIdentifier_Extended SignatureIdentificator = null;
static private ContainerSignatureDefinitions ContainerSignatureDefs = null;
static private List<TriggerPuid> ContainerSignatureTriggerPuids = null;
private static Boolean IsInitialized = false;
// ===========================================================================================
// ======== Methods =======================================================
// ===========================================================================================
// ======== Static Public =======================================================
// -------- Initializing -------------------------------------------------------
static public void setSignatureFile(String newSignatureFile)
{
SignatureFile = newSignatureFile;
IsInitialized = false;
// I will (re-)initialize myself the next time I am used.
}
static public void setContainerSignatureFile(String newContainerSignatureFile)
{
ContainerSignatureFile = newContainerSignatureFile;
IsInitialized = false;
// I will (re-)initialize myself the next time I am used.
}
/**
* Deprecated - use method setSignatureFile() instead.
* @throws DROIDCouldNotInitializeException
*/
@Deprecated
static public void setConfigFile(String newSignatureFile)
{
setSignatureFile(newSignatureFile);
}
// -------- Accessing -------------------------------------------------------
static public IdentificationResult getIdentificationResult(String filePath) throws DROIDCouldNotInitializeException, DROIDNoIdentificationFoundException, DROIDMultipleIdentificationsFoundException, FileNotFoundException
{
List<IdentificationResult> resultList = getIdentificationResults(filePath);
if (resultList == null || resultList.isEmpty()) throw new DROIDNoIdentificationFoundException();
if (resultList.size() != 1) throw new DROIDMultipleIdentificationsFoundException(resultList);
return resultList.get(0);
}
// The following are convenience methods (shortcuts for retrieving specific metadata directly):
static public String getFileFormatPUID(String fileName) throws DROIDCouldNotInitializeException, DROIDNoIdentificationFoundException, DROIDMultipleIdentificationsFoundException, FileNotFoundException
{
IdentificationResult result = getIdentificationResult(fileName);
return (result == null)? null: result.getPuid();
}
static public String getMimeType(String fileName) throws DROIDCouldNotInitializeException, DROIDNoIdentificationFoundException, DROIDMultipleIdentificationsFoundException, FileNotFoundException
{
IdentificationResult result = getIdentificationResult(fileName);
return (result == null)? null: result.getMimeType();
}
static public String getFileFormatName(String fileName) throws DROIDCouldNotInitializeException, DROIDNoIdentificationFoundException, DROIDMultipleIdentificationsFoundException, FileNotFoundException
{
IdentificationResult result = getIdentificationResult(fileName);
return (result == null)? null: result.getName();
}
static public String getFileFormatVersion(String fileName) throws DROIDCouldNotInitializeException, DROIDNoIdentificationFoundException, DROIDMultipleIdentificationsFoundException, FileNotFoundException
{
IdentificationResult result = getIdentificationResult(fileName);
return (result == null)? null: result.getVersion();
}
static public String getFileFormatMethod(String fileName) throws DROIDCouldNotInitializeException, DROIDNoIdentificationFoundException, DROIDMultipleIdentificationsFoundException, FileNotFoundException
{
IdentificationResult result = getIdentificationResult(fileName);
return (result == null)? null: result.getMethod().getMethod();
}
// ======== Static Private =======================================================
// -------- Initializing -------------------------------------------------------
static private void initializeIfNecessary() throws DROIDCouldNotInitializeException
{
if (IsInitialized) return;
try
{
Logger.debug("Initializing DROID...");
SignatureIdentificator = new BinarySignatureIdentifier_Extended();
SignatureIdentificator.setSignatureFile(SignatureFile);
SignatureIdentificator.init();
ContainerSignatureDefs = new ContainerSignatureSaxParser().parse(new FileInputStream(ContainerSignatureFile));
ContainerSignatureTriggerPuids = ContainerSignatureDefs.getTiggerPuids();
IsInitialized = true;
Logger.debug("...OK");
}
catch (java.lang.Exception ex)
{
Logger.debug("...NOK!");
throw new DROIDCouldNotInitializeException(ex);
}
}
// -------- Calculating -------------------------------------------------------
static private List<IdentificationResult> getIdentificationResults(String filePath) throws DROIDCouldNotInitializeException, FileNotFoundException
{
initializeIfNecessary();
if (!new File(filePath).exists()) throw new FileNotFoundException(filePath);
File file = new File(filePath);
RequestMetaData metadata = new RequestMetaData(file.length(), file.lastModified(), file.getName());
RequestIdentifier id = new RequestIdentifier(file.toURI());
IdentificationRequest request = new FileSystemIdentificationRequest(metadata, id);
FileInputStream fis = null;
try
{
fis = new FileInputStream(file);
request.open(fis);
// Identify the file. Try 3 different systems: first container, then binary (= signature), and finally file extension:
// (NOTE: To get the container identifications, I need the binary identifications)
IdentificationResultCollection signatureResultCollection = SignatureIdentificator.matchBinarySignatures(request);
IdentificationResultCollection containerResultCollection = getContainerResults(request, signatureResultCollection);
IdentificationResultCollection finalResultCollection;
if (containerResultCollection.getResults().size() > 0) finalResultCollection = containerResultCollection;
else if (signatureResultCollection.getResults().size() > 0) finalResultCollection = signatureResultCollection;
else finalResultCollection = SignatureIdentificator.matchExtensions(request, false);
SignatureIdentificator.removeLowerPriorityHits(finalResultCollection);
return finalResultCollection.getResults();
}
catch (Exception ex)
{
ex.printStackTrace();
return null;
}
finally
{
try
{
request.close();
if (fis != null) fis.close();
}
catch(IOException ex){};
}
}
private static IdentificationResultCollection getContainerResults(IdentificationRequest request, IdentificationResultCollection results) throws CommandExecutionException
{
IdentificationResultCollection containerResults = new IdentificationResultCollection(request);
for (IdentificationResult identResult: results.getResults())
{
String filePuid = identResult.getPuid();
if (filePuid == null) continue;
TriggerPuid containerPuid = null;
for (TriggerPuid tp: ContainerSignatureTriggerPuids)
{
if (tp.getPuid().equals(filePuid))
{
containerPuid = tp;
break;
}
}
if (containerPuid == null) continue;
IdentificationRequestFactory requestFactory = new ContainerFileIdentificationRequestFactory();
String containerType = containerPuid.getContainerType();
if ("OLE2".equals(containerType))
{
try
{
Ole2ContainerContentIdentifier ole2Identifier = new Ole2ContainerContentIdentifier();
ole2Identifier.init(ContainerSignatureDefs, containerType);
Ole2IdentifierEngine ole2IdentifierEngine = new Ole2IdentifierEngine();
ole2IdentifierEngine.setRequestFactory(requestFactory);
ole2Identifier.setIdentifierEngine(ole2IdentifierEngine);
ole2Identifier.process(request.getSourceInputStream(), containerResults);
}
catch (IOException e)
{
e.printStackTrace();
}
}
else if ("ZIP".equals(containerType))
{
try
{
ZipContainerContentIdentifier zipIdentifier = new ZipContainerContentIdentifier();
zipIdentifier.init(ContainerSignatureDefs, containerType);
ZipIdentifierEngine zipIdentifierEngine = new ZipIdentifierEngine();
zipIdentifierEngine.setRequestFactory(requestFactory);
zipIdentifier.setIdentifierEngine(zipIdentifierEngine);
zipIdentifier.process(request.getSourceInputStream(), containerResults);
}
catch (IOException e)
{
e.printStackTrace();
}
}
else
{
throw new CommandExecutionException("Unknown container type: " + containerPuid);
}
}
IdentificationResultCollection finalContainerResults = new IdentificationResultCollection(request);
for (IdentificationResult r: containerResults.getResults())
{
FileFormat ff = SignatureIdentificator.getFileFormatForPuid(r.getPuid());
finalContainerResults.addResult(new MetadataProviderDROID_IdentificationResult(r, ff));
}
return finalContainerResults;
}
}
</code>