es.mityc.firmaJava.libreria.utilidades.CopiaFicherosManager.java Source code

Java tutorial

Introduction

Here is the source code for es.mityc.firmaJava.libreria.utilidades.CopiaFicherosManager.java

Source

/**
 * LICENCIA LGPL:
 * 
 * Esta librera es Software Libre; Usted puede redistribuirlo y/o modificarlo
 * bajo los trminos de la GNU Lesser General Public License (LGPL)
 * tal y como ha sido publicada por la Free Software Foundation; o
 * bien la versin 2.1 de la Licencia, o (a su eleccin) cualquier versin posterior.
 * 
 * Esta librera se distribuye con la esperanza de que sea til, pero SIN NINGUNA
 * GARANT?A; tampoco las implcitas garantas de MERCANTILIDAD o ADECUACIN A UN
 * PROPSITO PARTICULAR. Consulte la GNU Lesser General Public License (LGPL) para ms
 * detalles
 * 
 * Usted debe recibir una copia de la GNU Lesser General Public License (LGPL)
 * junto con esta librera; si no es as, escriba a la Free Software Foundation Inc.
 * 51 Franklin Street, 5 Piso, Boston, MA 02110-1301, USA o consulte
 * <http://www.gnu.org/licenses/>.
 *
 * Copyright 2008 Ministerio de Industria, Turismo y Comercio
 * 
 */

package es.mityc.firmaJava.libreria.utilidades;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
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.OutputStream;
import java.lang.reflect.Field;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.StringTokenizer;
import java.util.zip.Adler32;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import es.mityc.firmaJava.configuracion.Configuracion;
import es.mityc.firmaJava.libreria.ConstantesXADES;
import es.mityc.firmaJava.libreria.excepciones.FilesNotAvalaibleException;
import es.mityc.firmaJava.libreria.utilidades.UtilidadSistemaOperativo.SO;

/**
 * Utilidad para el copiado de ficheros con integridad.
 * 
 * Esta librera accede a un fichero de propiedades donde se relaciona una clave con un conjunto de recursos. Bajo peticin puede copiar
 * esos recursos a un lugar fsico. En caso de ya existir comprueba la integridad de esos ficheros y si no la cumple procede a su sustitucin.
 * 
 * Recupera la informacin del fichero de propiedades "rescopfil".
 *
 * @author  Ministerio de Industria, Turismo y Comercio
 * @version 0.9 beta
 */

public class CopiaFicherosManager {

    private static final Log log = LogFactory.getLog(CopiaFicherosManager.class);

    private static CopiaFicherosManager instance;
    static {
        instance = new CopiaFicherosManager();
    }

    private static final int BUFFER_IN_SIZE = 32000;
    private static final int BUFFER_OUT_SIZE = 4096;

    private static final String STR_RESCOPFIL = "rescopfil";
    private static final String STR_FILE_DOT = "file.";
    private static final String STR_DOT_NAME = ".name";
    private static final String STR_DOT_RES = ".res";
    private static final String STR_DOT_ADLER32 = ".Adler32";
    private static final String STR_DOT_SIZE = ".size";

    private static final String[] STR_OS_NAME_WIN = { "windows.", "windows4.", "windows5." };
    private static final String[] STR_OS_NAME_LIN = { "linux.", "linux24.", "linux26." };

    private ResourceBundle props = null;

    /**
     * Constructor
     */
    public CopiaFicherosManager() {
        try {
            props = ResourceBundle.getBundle(STR_RESCOPFIL);
        } catch (MissingResourceException ex) {
            log.error(I18n.getResource(ConstantesXADES.LIBRERIAXADES_FIRMAMOZILLA_ERROR_16), ex);
        }
    }

    /**
     * Devuelve una instancia del manager
     * @return
     */
    public static CopiaFicherosManager getInstance() {
        return instance;
    }

    /**
     * Comprueba si hay ficheros relacionados con el sistema operativo y si los hay, comprueba si es necesario volver a copiarlos
     * (comprobando su integridad).
     * 
     * <br/><br/>
     * Para buscar los ficheros relacionados con el sistema operativo compone un nombre dependiente del sistema operativo y le aade
     * el addendum indicado. Sistemas operativos que busca:
     * <ul>
     *   <li>Windows</li>
     *   <li>Linux</li>
     * </ul>
     * 
     * @param dir Directorio donde se copiarn los ficheros
     * @param addendum Cadena extra que se aadir para buscar los ficheros (no se aade nada si es <code>null</code>). 
     * @throws FilesNotAvalaibleException si no existe la clave indicada o algunos de los ficheros como recurso
     * TODOLARGO: cambiar la comprobacin de adler32 a sha-2 para endurecer las posibilidades de colisin (comprobar el impacto en rendimiento)
     */
    public String copiaFicherosOS(String dir, String addendum) throws FilesNotAvalaibleException {
        String clave;
        SO so = UtilidadSistemaOperativo.getSO();
        if (so.isWindows()) {
            if ("4".equals(so.getVersion()))
                clave = STR_OS_NAME_WIN[1] + addendum;
            else if ("5".equals(so.getVersion()))
                clave = STR_OS_NAME_WIN[2] + addendum;
            else
                clave = STR_OS_NAME_WIN[0] + addendum;
        } else if (so.isLinux()) {
            if ("2.6".equals(so.getVersion()))
                clave = STR_OS_NAME_LIN[2] + addendum;
            else
                clave = STR_OS_NAME_LIN[0] + addendum;
        } else
            throw new FilesNotAvalaibleException("Sistema operativo no reconocido");
        // si no se ha indicado directorio busca uno entre los disponibles del path
        if (dir == null) {
            File fileDir = new File(System.getProperty(ConstantesXADES.USER_HOME) + File.separator
                    + Configuracion.getNombreDirExterno());
            if (!fileDir.exists()) {
                if (!fileDir.mkdir())
                    throw new FilesNotAvalaibleException("No se pudo crear directorio de aplicacin");
            }
            updateLibraryPath(fileDir.getAbsolutePath());
            dir = fileDir.getAbsolutePath();
        } else {
            updateLibraryPath(dir);
        }
        log.debug("Copiando ficheros de: " + clave + " en " + dir);
        copiaFicheros(dir, clave);
        return dir;
    }

    /**
     * Actualiza la variable java.library.path con la nueva ruta indicada.
     * 
     * <br/><br/>Esta variable permite indicar dnde se encuentran las libreras JNI de usuario que se van a utilizar.
     *  
     * @param path Nueva ruta a incluir
     */
    public void updateLibraryPath(String path) {
        String libPath = System.getProperty("java.library.path");
        File fileDir = new File(path);
        if (!libPath.contains(fileDir.getAbsolutePath())) {
            libPath = fileDir.getAbsolutePath() + File.pathSeparator + libPath;
            System.setProperty("java.library.path", libPath);
            try {
                Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
                fieldSysPath.setAccessible(true);
                if (fieldSysPath != null)
                    fieldSysPath.set(System.class.getClassLoader(), null);
            } catch (NoSuchFieldException ex) {
                log.error("Error estableciendo path", ex);
            } catch (IllegalAccessException ex) {
                log.error("Error estableciendo path", ex);
            }
        }
    }

    /**
     * Comprueba si hay ficheros relacionados con la clave indicada y si los hay, comprueba si es necesario volver a copiarlos
     * (comprobando su integridad).
     * 
     * @param dir Directorio donde se copiarn los ficheros
     * @param clave Clave donde se agrupan los ficheros que se comprobarn/copiarn
     * @throws FilesNotAvalaibleException si no existe la clave indicada o algunos de los ficheros como recurso
     * TODOLARGO: cambiar la comprobacin de adler32 a sha-2 para endurecer las posibilidades de colisin (comprobar el impacto en rendimiento)
     */
    public void copiaFicheros(String dir, String clave) throws FilesNotAvalaibleException {
        if (props != null) {
            try {
                String conjunto = props.getString(clave);
                StringTokenizer st = new StringTokenizer(conjunto, ConstantesXADES.COMA);
                boolean hasMore = st.hasMoreTokens();
                while (hasMore) {
                    // Recupera los datos relacionados con ese fichero. AppPerfect: falsos positivos, las expresiones no son constantes
                    String fichero = st.nextToken();
                    hasMore = st.hasMoreTokens();
                    String nombreFichero = props.getString(STR_FILE_DOT + fichero + STR_DOT_NAME);
                    String resname = props.getString(STR_FILE_DOT + fichero + STR_DOT_RES);
                    long crcValue = Long.parseLong(props.getString(STR_FILE_DOT + fichero + STR_DOT_ADLER32));
                    long size = Long.parseLong(props.getString(STR_FILE_DOT + fichero + STR_DOT_SIZE));
                    copyLibrary(dir, nombreFichero, resname, crcValue, size);
                }
            } catch (MissingResourceException ex) {
                log.error(I18n.getResource(ConstantesXADES.LIBRERIAXADES_FIRMAMOZILLA_ERROR_17)
                        + ConstantesXADES.ESPACIO + clave);
                throw new FilesNotAvalaibleException(
                        I18n.getResource(ConstantesXADES.LIBRERIAXADES_FIRMAMOZILLA_ERROR_18));
            } catch (NumberFormatException ex) {
                log.error(I18n.getResource(ConstantesXADES.LIBRERIAXADES_FIRMAMOZILLA_ERROR_19)
                        + ConstantesXADES.ESPACIO + clave + ConstantesXADES.ESPACIO + ConstantesXADES.ESPACIO
                        + I18n.getResource(ConstantesXADES.LIBRERIAXADES_FIRMAMOZILLA_ERROR_20), ex);
                throw new FilesNotAvalaibleException(
                        I18n.getResource(ConstantesXADES.LIBRERIAXADES_FIRMAMOZILLA_ERROR_18));
            }
        } else
            throw new FilesNotAvalaibleException(
                    I18n.getResource(ConstantesXADES.LIBRERIAXADES_FIRMAMOZILLA_ERROR_18));
    }

    /**
     * Comprueba si existe el fichero indicado en la ruta y si no existe o no est ntegro procede a volverlo a copiar
     * 
     * @param dir
     * @param clave
     */
    private void copyLibrary(String dir, String fichero, String resname, long crcValue, long size)
            throws FilesNotAvalaibleException {
        InputStream entrada = null;
        OutputStream salida = null;
        try {
            File file = new File(dir, fichero);
            if ((!file.exists()) || (!checkIntegrityFile(file, crcValue, size))) {
                if (log.isTraceEnabled())
                    log.trace(I18n.getResource(ConstantesXADES.LIBRERIAXADES_FIRMAMOZILLA_INFO_5)
                            + file.getAbsolutePath());
                entrada = new BufferedInputStream(this.getClass().getClassLoader().getResourceAsStream(resname),
                        BUFFER_IN_SIZE);
                salida = new BufferedOutputStream(new FileOutputStream(file));
                byte[] buffer = new byte[BUFFER_OUT_SIZE];
                int readed = entrada.read(buffer);
                while (readed > 0) {
                    salida.write(buffer, 0, readed);
                    readed = entrada.read(buffer);
                }
                salida.flush();
            }
        } catch (FileNotFoundException ex) {
            log.error(I18n.getResource(ConstantesXADES.LIBRERIAXADES_FIRMAMOZILLA_ERROR_21), ex);
            throw new FilesNotAvalaibleException(ex);
        } catch (SecurityException ex) {
            log.error(I18n.getResource(ConstantesXADES.LIBRERIAXADES_FIRMAMOZILLA_ERROR_22), ex);
            throw new FilesNotAvalaibleException(ex);
        } catch (IOException ex) {
            log.error(I18n.getResource(ConstantesXADES.LIBRERIAXADES_FIRMAMOZILLA_ERROR_23), ex);
            throw new FilesNotAvalaibleException(ex);
        } finally {
            if (entrada != null) {
                try {
                    entrada.close();
                } catch (IOException e) {
                    log.error(e.getMessage());
                }
            }
            if (salida != null)
                try {
                    salida.close();
                } catch (IOException e) {
                    log.error(e.getMessage());
                }
        }
    }

    /**
     * Comprueba si el fichero indicado es ntegro.
     * 
     * @param file
     * @param crcValue
     * @param size
     * @return
     */
    private boolean checkIntegrityFile(File file, long crcValue, long size)
            throws FileNotFoundException, IOException {
        if (log.isTraceEnabled())
            log.trace(I18n.getResource(ConstantesXADES.LIBRERIAXADES_FIRMAMOZILLA_INFO_6) + ConstantesXADES.ESPACIO
                    + file.getAbsolutePath());
        if (!file.exists())
            return false;
        // Primero comprueba el tamao
        if (file.length() != size)
            return false;
        // despus comprueba el crc
        Adler32 crc = new Adler32();
        InputStream entrada = new BufferedInputStream(new FileInputStream(file), BUFFER_IN_SIZE);
        byte[] buffer = new byte[BUFFER_OUT_SIZE];
        int readed = entrada.read(buffer);
        while (readed > 0) {
            crc.update(buffer, 0, readed);
            readed = entrada.read(buffer);
        }
        if (log.isTraceEnabled())
            log.trace(I18n.getResource(ConstantesXADES.LIBRERIAXADES_FIRMAMOZILLA_INFO_7) + ConstantesXADES.ESPACIO
                    + crc.getValue() + ConstantesXADES.ESPACIO
                    + I18n.getResource(ConstantesXADES.LIBRERIAXADES_FIRMAMOZILLA_INFO_8) + ConstantesXADES.ESPACIO
                    + crcValue);
        if (crc.getValue() != crcValue)
            return false;
        return true;
    }
}