fr.gouv.culture.vitam.digest.DigestCompute.java Source code

Java tutorial

Introduction

Here is the source code for fr.gouv.culture.vitam.digest.DigestCompute.java

Source

/**
 * This file is part of Vitam Project.
 * 
 * Copyright 2010, Frederic Bregier, and individual contributors by the @author
 * tags. See the COPYRIGHT.txt in the distribution for a full listing of individual contributors.
 * 
 * All Vitam Project 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 3 of
 * the License, or (at your option) any later version.
 * 
 * Vitam 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 Vitam. If not, see
 * <http://www.gnu.org/licenses/>.
 */
package fr.gouv.culture.vitam.digest;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.FileUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;

import uk.gov.nationalarchives.droid.command.action.CommandExecutionException;

import fr.gouv.culture.vitam.droid.DroidFileFormat;
import fr.gouv.culture.vitam.droid.DroidHandler;
import fr.gouv.culture.vitam.utils.ConfigLoader;
import fr.gouv.culture.vitam.utils.StaticValues;
import fr.gouv.culture.vitam.utils.VitamArgument;
import fr.gouv.culture.vitam.utils.XmlDom;

/**
 * Digest compute
 * 
 * @author Frederic Bregier
 *
 */
public class DigestCompute {

    /**
     * @param file
     * @param algorithm
     * @return the Hashcode according to the algorithm
     * @throws Exception
     */
    public final static String getHashCode(File file, String algorithm) throws Exception {
        FileInputStream fis = new FileInputStream(file);
        return DigestCompute.getHashCode(fis, algorithm);
    }

    /**
     * @param base
     * @param filename
     * @param algorithm
     * @return the Hashcode according to the algorithm
     * @throws Exception
     */
    public final static String getHashCode(File base, String filename, String algorithm) throws Exception {
        FileInputStream fis = new FileInputStream(new File(base, filename));
        return DigestCompute.getHashCode(fis, algorithm);
    }

    /**
     * 
     * @param fis
     * @param algorithm
     * @return the Hashcode according to the algorithm
     * @throws Exception
     */
    public final static String getHashCode(FileInputStream fis, String algorithm) throws Exception {
        MessageDigest md = MessageDigest.getInstance(algorithm);
        DigestInputStream dis = null;
        try {
            dis = new DigestInputStream(fis, md);
            byte[] buffer = new byte[8192];
            while (dis.read(buffer) != -1)
                ;
        } finally {
            if (dis != null) {
                dis.close();
            }
        }
        byte[] bDigest = md.digest();
        return Base64.encode(bDigest, false);
    }

    /**
     * Add the various Digest as specified in the argument to the droidFileFormat
     * 
     * @param droidFileFormat
     * @param argument
     */
    public final static void computeDroidFileFormatDigest(DroidFileFormat droidFileFormat, VitamArgument argument) {
        if (argument == null)
            return;
        if (argument.sha1 || argument.sha256 || argument.sha512) {
            String filename = droidFileFormat.getFilename();
            boolean ignoreNotFound = false;
            if (filename.startsWith("tar:") || filename.startsWith("bzip2:") || filename.startsWith("gzip:")
                    || filename.startsWith("zip:")) {
                ignoreNotFound = true;
            }
            FileInputStream in;
            try {
                in = new FileInputStream(filename);
            } catch (FileNotFoundException e1) {
                if (!ignoreNotFound) {
                    System.err.println(StaticValues.LBL.error_filenotfile.get() + e1);
                }
                return;
            }
            String[] result = computeDigest(in, argument);
            if (argument.sha1)
                droidFileFormat.setSha1(result[0]);
            if (argument.sha256)
                droidFileFormat.setSha256(result[1]);
            if (argument.sha512)
                droidFileFormat.setSha512(result[2]);
        }
    }

    /**
     * Compute the various Digest as specified in the argument 
     * 
     * @param inputstream
     * @param argument
     * @return Array of String in order of SHA-1/SHA-256/SHA-512 as required by argument
     */
    public final static String[] computeDigest(InputStream inputstream, VitamArgument argument) {
        String[] result = new String[3];
        result[0] = result[1] = result[2] = null;
        if (argument == null) {
            return result;
        }
        if (argument.sha1 || argument.sha256 || argument.sha512) {
            MessageDigest md1 = null, md256 = null, md512 = null;
            if (argument.sha1) {
                try {
                    md1 = MessageDigest.getInstance("SHA-1");
                } catch (NoSuchAlgorithmException e) {
                    System.err.println(StaticValues.LBL.error_computedigest.get() + e);
                }
            }
            if (argument.sha256) {
                try {
                    md256 = MessageDigest.getInstance("SHA-256");
                } catch (NoSuchAlgorithmException e) {
                    System.err.println(StaticValues.LBL.error_computedigest.get() + e);
                }
            }
            if (argument.sha512) {
                try {
                    md512 = MessageDigest.getInstance("SHA-512");
                } catch (NoSuchAlgorithmException e) {
                    System.err.println(StaticValues.LBL.error_computedigest.get() + e);
                }
            }
            int size = 0;
            byte[] buf = new byte[8192];
            try {
                while ((size = inputstream.read(buf)) >= 0) {
                    if (md1 != null)
                        md1.update(buf, 0, size);
                    if (md256 != null)
                        md256.update(buf, 0, size);
                    if (md512 != null)
                        md512.update(buf, 0, size);
                }
            } catch (IOException e) {
                System.err.println(StaticValues.LBL.error_computedigest.get() + e);
            } finally {
                try {
                    inputstream.close();
                } catch (IOException e) {
                }
            }
            if (md1 != null)
                result[0] = Base64.encode(md1.digest(), false);
            if (md256 != null)
                result[1] = Base64.encode(md256.digest(), false);
            if (md512 != null)
                result[2] = Base64.encode(md512.digest(), false);
            return result;
        }
        return result;
    }

    /**
     * 
     * @param config
     * @param src
     * @param file
     * @return Null in case of error, else return the Element config.DOCUMENT_FIELD
     */
    public static Element checkDigest(ConfigLoader config, File src, File file) {
        String shortname = StaticValues.getSubPath(file, src);
        FileInputStream inputstream;
        try {
            inputstream = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            System.err.println(StaticValues.LBL.error_computedigest.get() + ": " + shortname);
            return null;
        }
        String[] shas = DigestCompute.computeDigest(inputstream, config.argument);
        //SEDA type since already configured
        Element result = XmlDom.factory.createElement(config.DOCUMENT_FIELD);
        Element attachment = XmlDom.factory.createElement(config.ATTACHMENT_FIELD);
        attachment.addAttribute(config.FILENAME_ATTRIBUTE.substring(1), shortname);
        result.add(attachment);
        if (shas[0] != null) {
            Element integrity = XmlDom.factory.createElement(config.INTEGRITY_FIELD);
            integrity.addAttribute(config.ALGORITHME_ATTRIBUTE.substring(1), StaticValues.XML_SHA1);
            integrity.setText(shas[0]);
            result.add(integrity);
        }
        if (shas[1] != null) {
            Element integrity = XmlDom.factory.createElement(config.INTEGRITY_FIELD);
            integrity.addAttribute(config.ALGORITHME_ATTRIBUTE.substring(1), StaticValues.XML_SHA256);
            integrity.setText(shas[1]);
            result.add(integrity);
        }
        if (shas[2] != null) {
            Element integrity = XmlDom.factory.createElement(config.INTEGRITY_FIELD);
            integrity.addAttribute(config.ALGORITHME_ATTRIBUTE.substring(1), StaticValues.XML_SHA512);
            integrity.setText(shas[2]);
            result.add(integrity);
        }
        String status = "ok";
        if ((shas[0] == null && config.argument.sha1) || (shas[1] == null && config.argument.sha256)
                || (shas[2] == null && config.argument.sha512)) {
            status = "error";
        }
        result.addAttribute("status", status);
        XmlDom.addDate(VitamArgument.ONEXML, config, result);
        return result;
    }

    public static int createDigest(File src, File dst, File ftar, File fglobal, boolean oneDigestPerFile,
            String[] extensions, String mask, boolean prefix) {
        if (mask == null) {
            return createDigest(src, dst, ftar, fglobal, oneDigestPerFile, extensions);
        }
        try {
            if (prefix) {
                // fix mask
                List<File> filesToScan = new ArrayList<File>();
                File dirToSearch = src;
                if (!dirToSearch.isDirectory()) {
                    if (dirToSearch.canRead() && dirToSearch.getName().startsWith(mask)) {
                        filesToScan.add(dirToSearch);
                    } else {
                        throw new CommandExecutionException("Resources not found");
                    }
                } else {
                    Collection<File> temp = FileUtils.listFiles(dirToSearch, extensions,
                            StaticValues.config.argument.recursive);
                    for (File file : temp) {
                        if (file.getName().startsWith(mask)) {
                            filesToScan.add(file);
                        }
                    }
                    temp.clear();
                }
                return createDigest(src, dst, ftar, fglobal, oneDigestPerFile, filesToScan);
            } else {
                // RegEx mask
                File dirToSearch = src;
                if (!dirToSearch.isDirectory()) {
                    List<File> filesToScan = new ArrayList<File>();
                    if (dirToSearch.canRead() && dirToSearch.getName().matches(mask + ".*")) {
                        filesToScan.add(dirToSearch);
                        String global = dirToSearch.getName().replaceAll("[^" + mask + "].*", "")
                                + "_all_digests.xml";
                        fglobal = new File(fglobal, global);
                    } else {
                        throw new CommandExecutionException("Resources not found");
                    }
                    return createDigest(src, dst, ftar, fglobal, oneDigestPerFile, filesToScan);
                } else {
                    HashMap<String, List<File>> hashmap = new HashMap<String, List<File>>();
                    Collection<File> temp = FileUtils.listFiles(dirToSearch, extensions,
                            StaticValues.config.argument.recursive);
                    List<File> filesToScan = null;
                    Pattern pattern = Pattern.compile(mask + ".*");
                    Pattern pattern2 = Pattern.compile(mask);
                    for (File file : temp) {
                        String filename = file.getName();
                        Matcher matcher = pattern.matcher(filename);
                        if (matcher.matches()) {
                            String end = pattern2.matcher(filename).replaceFirst("");
                            int pos = filename.indexOf(end);
                            if (pos <= 0) {
                                System.err.println("Cannot find : " + end + " in " + filename);
                                continue;
                            }
                            String global = filename.substring(0, pos);
                            if (global.charAt(global.length() - 1) != '_') {
                                global += "_";
                            }
                            global += "all_digests.xml";
                            filesToScan = hashmap.get(global);
                            if (filesToScan == null) {
                                filesToScan = new ArrayList<File>();
                                hashmap.put(global, filesToScan);
                            }
                            filesToScan.add(file);
                        }
                    }
                    temp.clear();
                    int res = 0;
                    for (String global : hashmap.keySet()) {
                        File fglobalnew = new File(fglobal, global);
                        res += createDigest(src, dst, ftar, fglobalnew, oneDigestPerFile, hashmap.get(global));
                    }
                    hashmap.clear();
                    return res;
                }
            }
        } catch (CommandExecutionException e1) {
            System.err.println(StaticValues.LBL.error_error.get() + " " + e1.toString());
            return -1;
        }
    }

    public static int createDigest(File src, File dst, File ftar, File fglobal, boolean oneDigestPerFile,
            String[] extensions) {
        try {
            List<File> filesToScan = DroidHandler.matchedFiled(new File[] { src }, extensions,
                    StaticValues.config.argument.recursive);
            if (src.isFile()) {
                src = src.getParentFile();
            }
            return createDigest(src, dst, ftar, fglobal, oneDigestPerFile, filesToScan);
        } catch (CommandExecutionException e1) {
            System.err.println(StaticValues.LBL.error_error.get() + " " + e1.toString());
            return -1;
        }
    }

    public static int createDigest(File src, File dst, File ftar, File fglobal, boolean oneDigestPerFile,
            List<File> filesToScan) {
        try {
            Element global = null;
            Document globalDoc = null;
            if (fglobal != null) {
                global = XmlDom.factory.createElement("digests");
                global.addAttribute("source", src.getAbsolutePath());
                globalDoc = XmlDom.factory.createDocument(global);
            }
            OutputFormat format = OutputFormat.createPrettyPrint();
            format.setEncoding(StaticValues.CURRENT_OUTPUT_ENCODING);
            XMLWriter writer = new XMLWriter(format);
            int error = 0;
            int currank = 0;
            for (File file : filesToScan) {
                currank++;
                Element result = DigestCompute.checkDigest(StaticValues.config, src, file);
                if (result.selectSingleNode(".[@status='ok']") == null) {
                    System.err.println(StaticValues.LBL.error_error.get()
                            + StaticValues.LBL.error_computedigest.get() + StaticValues.getSubPath(file, src));
                    error++;
                } else if (oneDigestPerFile) {
                    Element rootElement = XmlDom.factory.createElement("digest");
                    Document unique = XmlDom.factory.createDocument(rootElement);
                    rootElement.add(result);
                    FileOutputStream out = null;
                    String shortname = StaticValues.getSubPath(file, src);
                    String shortnameWithoutFilename = shortname.substring(0, shortname.lastIndexOf(file.getName()));
                    File fdirout = new File(dst, shortnameWithoutFilename);
                    fdirout.mkdirs();
                    File fout = new File(fdirout, file.getName() + "_digest.xml");
                    try {
                        out = new FileOutputStream(fout);
                        writer.setOutputStream(out);
                        writer.write(unique);
                        writer.close();
                    } catch (FileNotFoundException e) {
                        System.err.println(
                                StaticValues.LBL.error_error.get() + fout.getAbsolutePath() + " " + e.toString());
                        error++;
                    } catch (IOException e) {
                        System.err.println(
                                StaticValues.LBL.error_error.get() + fout.getAbsolutePath() + " " + e.toString());
                        if (out != null) {
                            try {
                                out.close();
                            } catch (IOException e1) {
                            }
                        }
                        error++;
                    }
                    result.detach();
                }
                if (fglobal != null) {
                    global.add(result);
                }
            }
            if (ftar != null) {
                currank++;
                Element result = DigestCompute.checkDigest(StaticValues.config, src, ftar);
                if (result.selectSingleNode(".[@status='ok']") == null) {
                    System.err.println(StaticValues.LBL.error_error.get()
                            + StaticValues.LBL.error_computedigest.get() + ftar.getAbsolutePath());
                    error++;
                } else if (oneDigestPerFile) {
                    Element rootElement = XmlDom.factory.createElement("digest");
                    Document unique = XmlDom.factory.createDocument(rootElement);
                    rootElement.add(result);
                    FileOutputStream out = null;
                    File fout = new File(dst, ftar.getName() + "_tar_digest.xml");
                    try {
                        out = new FileOutputStream(fout);
                        writer.setOutputStream(out);
                        writer.write(unique);
                        writer.close();
                    } catch (FileNotFoundException e) {
                        System.err.println(
                                StaticValues.LBL.error_error.get() + fout.getAbsolutePath() + " " + e.toString());
                        error++;
                    } catch (IOException e) {
                        System.err.println(
                                StaticValues.LBL.error_error.get() + fout.getAbsolutePath() + " " + e.toString());
                        if (out != null) {
                            try {
                                out.close();
                            } catch (IOException e1) {
                            }
                        }
                        error++;
                    }
                    result.detach();
                }
                if (fglobal != null) {
                    global.add(result);
                }
            }
            if (fglobal != null) {
                if (error > 0) {
                    global.addAttribute("status", "error");
                } else {
                    global.addAttribute("status", "ok");
                }
                XmlDom.addDate(VitamArgument.ONEXML, StaticValues.config, global);
                FileOutputStream out;
                try {
                    out = new FileOutputStream(fglobal);
                    writer.setOutputStream(out);
                    writer.write(globalDoc);
                    writer.close();
                } catch (FileNotFoundException e) {
                    System.err.println(
                            StaticValues.LBL.error_error.get() + fglobal.getAbsolutePath() + " " + e.toString());
                    error++;
                } catch (IOException e) {
                    System.err.println(
                            StaticValues.LBL.error_error.get() + fglobal.getAbsolutePath() + " " + e.toString());
                    error++;
                }
            }
            if (error > 0) {
                System.err.println(StaticValues.LBL.error_error.get() + " Digest" + " [ " + currank
                        + (error > 0 ? " (" + StaticValues.LBL.error_error.get() + error + " ) " : "") + " ]");
                return -error;
            }
            return currank;
        } catch (UnsupportedEncodingException e) {
            System.err.println(StaticValues.LBL.error_error.get() + " " + e.toString());
            return -1;
        }

    }
}