org.viafirma.nucleo.custodia.Custodia.java Source code

Java tutorial

Introduction

Here is the source code for org.viafirma.nucleo.custodia.Custodia.java

Source

/* Copyright (C) 2007 Flix Garca Borrego (borrego at gmail.com)
      
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.
      
   This library 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
   Library General Public License for more details.
      
   You should have received a copy of the GNU Library General Public
   License along with this library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
   MA 02111-1307, USA 
 */

package org.viafirma.nucleo.custodia;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xml.security.utils.XMLUtils;
import org.viafirma.cliente.firma.TypeFormatSign;
import org.viafirma.cliente.vo.FirmaInfoViafirma;
import org.viafirma.excepciones.CodigoError;
import org.viafirma.excepciones.ExcepcionErrorInterno;
import org.viafirma.util.CheckDigit;
import org.viafirma.util.XmlSignUtil;
import org.w3c.dom.Document;

import com.viavansi.framework.core.persistencia.servicios.excepciones.ExcepcionDatosNoEncontrados;
import com.viavansi.framework.core.persistencia.servicios.excepciones.ExcepcionServicio;
import com.viavansi.framework.tools.repositorio.ManagerFileRepository;
import com.viavansi.framework.tools.repositorio.ManagerFileRepositoryFactory;
import com.viavansi.framework.tools.repositorio.vo.DocumentVO;

/**
 * Gestiona la custodia de documentos. Se comporta como un repositorio de
 * documentos.
 * 
 * @author Felix Garcia Borrego (borrego at gmail.com)
 * @author Alexis Castilla Armero <Pencerval at Gmail.com>
 */
public class Custodia {
    private static Custodia singleton;

    ManagerFileRepository manager;

    public static final String SEPARADOR = "-";

    /**
     * Nombre del parametro que indica el path absoluto en el que se encuentra
     * el directorio de custodia de documentos.
     */
    private static final String PARAM_PATH_CUSTODIA = "PATH_CUSTODIA";

    /**
     * @param manager2
     */
    private Custodia(ManagerFileRepository manager) {
        this.manager = manager;
    }

    public static Custodia getInstance() {
        if (singleton == null) {
            throw new ExceptionInInitializerError("El sistema de custodia no esta inicializado.");
        }
        return singleton;
    }

    /**
     * Inicializa el sistema de custoria.
     * 
     * @param properties
     */
    public static void init(Properties properties) {
        // inicializa el sistema de custodia de documentos.
        // comprobamos que el parametro que espera encontrar custodia existe
        String pathCustodia = properties.getProperty(PARAM_PATH_CUSTODIA);
        if (pathCustodia == null) {
            // System.out.println(
            // "El sistema de custodia no esta utilizando ningun sistema de ficheros"
            // )
            // throw new ExceptionInInitializerError("Parametro '" +
            // PARAM_PATH_CUSTODIA +
            // "' requerido para inicializar el sistema de custodia de documentacin."
            // );
        } else {
            // aadimos este parametro a las propiedades para que el manejadore
            // de repositorio en el que se basa la custodia
            // encuentre el parametros
            properties.put("fileSystem.default.PATH_BASE", pathCustodia);
        }
        ManagerFileRepositoryFactory.init(properties);
        ManagerFileRepository manager = ManagerFileRepositoryFactory.getDefaultManager();
        singleton = new Custodia(manager);
    }

    /**
     * Almacena un xml signature.
     * 
     * @param id
     * @param signature
     * @throws ExcepcionErrorInterno
     */
    public String custodiar(String id, Document xmlDocument, TypeFormatSign typeSign) throws ExcepcionErrorInterno {
        try {

            // validamos el XMLSignature antes de guardarlo para prevenir
            // posibles problemas

            if (!XmlSignUtil.getInstance().checkSignatureFrom(xmlDocument, false)) {
                log.error("El XML a custodiar no es valido:");
                XMLUtils.outputDOM(xmlDocument, System.out);
                throw new ExcepcionErrorInterno(CodigoError.ERROR_XMLSIGN_FORMAT);
            }

            // Le asignamos un identificador definitivo.

            // En funcin del tipo de documento le asginamos un tipo
            // identificador de tipo de custoria (resevado para el futuro)
            int tipo = typeSign.getCode();
            // A1HH-EZH9T5E1-1889-3802-8854
            String newId = tipo + id;
            // Generamos dgito de control
            newId = CheckDigit.generateCheckDigit(newId) + newId;
            // generamos los -
            StringBuilder b = new StringBuilder();
            for (int i = 0; i < newId.length(); i++) {
                char caracter = newId.charAt(i);
                b.append(caracter);
                if ((i + 1) % 4 == 0 && i < (newId.length() - 1)) {
                    b.append("-");
                }
            }

            // Transformamos el identificador en el path del documento.
            newId = b.toString();
            String newUri = decode(newId);
            OutputStream out;
            try {
                out = manager.openOutputStreamToUri(newUri);
            } catch (ExcepcionServicio e) {
                throw new org.viafirma.excepciones.ExcepcionErrorInterno(CodigoError.ERROR_CUSTODIA, e);
            }
            XMLUtils.outputDOM(xmlDocument, out);
            out.close();

            // retornamos el identificador asignado al custoridar
            return newId;

        } catch (IOException e) {
            // problemas al custodiar el documento
            throw new ExcepcionErrorInterno(CodigoError.ERROR_CUSTODIA, e);
        } catch (ExcepcionErrorInterno e) {
            throw e;
        } catch (Exception e) {
            // problemas al custodiar el documento
            throw new ExcepcionErrorInterno(CodigoError.ERROR_CUSTODIA, e);

        }
    }

    /**
     * Recupera y valida un xml signature asociado al cdigo de firma indicado.
     * 
     * @param id
     * @param signature
     * @throws ExcepcionErrorInterno
     * 
     * 
     */
    public Document recuperar(String id) throws ExcepcionErrorInterno {
        InputStream input = null;
        try {
            // Le asignamos un identificador definitivo.
            String newUri = decode(id);

            try {
                input = manager.readDocument(newUri);
            } catch (ExcepcionServicio e) {
                throw new org.viafirma.excepciones.ExcepcionErrorInterno(CodigoError.ERROR_CUSTODIA, e);
            }
            return streamToDoc(input);
        } catch (ExcepcionErrorInterno e) {
            log.warn("Problemas al recuperar el XMLSignature asociado al id: '" + id + "'");
            throw e;
        } catch (Exception e) {
            // problemas al custodiar el documento
            throw new ExcepcionErrorInterno(CodigoError.ERROR_CUSTODIA, e);
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    log.warn("No se puede cerrar el InputStream para el XmlSignature: " + id);
                }
            }
        }

    }

    /**
     * Recupera el documento asociado y el documento xml.
     * @throws ExcepcionDatosNoEncontrados
     * @throws ExcepcionServicio
     */
    public Object[] recuperarMoreInfo(String id) throws ExcepcionErrorInterno {
        try {
            DocumentVO documentVO = manager.loadDocument(decode(id), null);
            return new Object[] { documentVO, streamToDoc(documentVO.dataStream) };
        } catch (ExcepcionServicio e) {
            throw new org.viafirma.excepciones.ExcepcionErrorInterno(CodigoError.ERROR_CUSTODIA, e);
        } catch (ExcepcionDatosNoEncontrados e) {
            throw new org.viafirma.excepciones.ExcepcionErrorInterno(CodigoError.ERROR_CUSTODIA, e);
        }
    }

    /**
     * Transforma identificadores de documentos a uris dentro del sistema de
     * ficheros Todas las uris en el sistema de ficheros(abstracto) son del tipo
     * /directorio/nombreFichero
     * 
     * //A1HH-EZH9T5E1-1889-3802-8854
     * 
     * @param newUri
     * @return
     * @throws ExcepcionErrorInterno
     */
    private String decode(String newId) throws ExcepcionErrorInterno {
        try {
            String id = newId.replaceAll("-", "");

            // Comprobamos el cdigo de chequeo
            if (!CheckDigit.validateCheckDigit(id)) {
                throw new ExcepcionErrorInterno(CodigoError.ERROR_CUSTODIA_CHECK_DIGIT,
                        "El digito de control no es correcto para el identificador: " + newId);
            }
            // obtengo el tipo de documento
            TypeFormatSign typeFormatSign = XmlSignUtil.getTypeFormatSign(newId);

            // obtengo el timestamp
            long timeStamp = new Long(id.substring(11, id.length()));
            Calendar g = new GregorianCalendar();
            g.setTimeInMillis(timeStamp);
            int anyo = g.get(Calendar.YEAR);
            int mes = g.get(Calendar.MONTH) + 1;
            return "/" + typeFormatSign.getCode() + "/" + anyo + "/" + mes + "/" + newId + ".xml";
        } catch (java.lang.StringIndexOutOfBoundsException e) {
            throw new ExcepcionErrorInterno(CodigoError.ERROR_PARAM,
                    "El identificador indicado no es vlido. newId= " + newId);
        }
    }

    private Log log = LogFactory.getLog(Custodia.class);

    /**
     * 
     * Parsea un stream pasandolo a xml
     * 
     */
    private Document streamToDoc(InputStream stream) throws ExcepcionErrorInterno {
        XmlSignUtil xmlSignParser = XmlSignUtil.getInstance();
        try {
            // obtengo el xml signature asociado al cdigo de firma indicado
            Document documento = xmlSignParser.parseDocument(new InputStreamReader(stream));
            // validamos el XMLSignature
            if (!XmlSignUtil.getInstance().checkSignatureFrom(documento, false)) {
                throw new ExcepcionErrorInterno(CodigoError.ERROR_CUSTODIA_NO_VALID);
            }
            // retornamos el identificador asignado al custoridar
            return documento;
        } catch (ExcepcionErrorInterno e) {
            log.warn("Problemas al recuperar el XMLSignature");
            throw e;
        } catch (Exception e) {
            // problemas al custodiar el documento
            throw new ExcepcionErrorInterno(CodigoError.ERROR_CUSTODIA, e);
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                    log.warn("No se puede cerrar el InputStream para el XmlSignature");
                }
            }
        }
    }
}