mitm.djigzo.web.pages.crl.CRLImport.java Source code

Java tutorial

Introduction

Here is the source code for mitm.djigzo.web.pages.crl.CRLImport.java

Source

/*
 * Copyright (c) 2008-2011, Martijn Brinkers, Djigzo.
 * 
 * This file is part of Djigzo email encryption.
 *
 * Djigzo is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License 
 * version 3, 19 November 2007 as published by the Free Software 
 * Foundation.
 *
 * Djigzo 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public 
 * License along with Djigzo. If not, see <http://www.gnu.org/licenses/>
 *
 * Additional permission under GNU AGPL version 3 section 7
 * 
 * If you modify this Program, or any covered work, by linking or 
 * combining it with saaj-api-1.3.jar, saaj-impl-1.3.jar, 
 * wsdl4j-1.6.1.jar (or modified versions of these libraries), 
 * containing parts covered by the terms of Common Development and 
 * Distribution License (CDDL), Common Public License (CPL) the 
 * licensors of this Program grant you additional permission to 
 * convey the resulting work.
 */
package mitm.djigzo.web.pages.crl;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.NoSuchProviderException;
import java.security.cert.CRLException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509CRL;
import java.util.Collection;
import java.util.LinkedList;

import mitm.application.djigzo.admin.FactoryRoles;
import mitm.application.djigzo.ws.X509CRLStoreWS;
import mitm.common.security.SecurityFactoryFactoryException;
import mitm.common.security.asn1.ObjectEncoding;
import mitm.common.security.crl.CRLUtils;
import mitm.common.security.crl.X509CRLInspector;
import mitm.common.ws.WebServiceCheckedException;
import mitm.djigzo.web.pages.CRLs;

import org.apache.commons.fileupload.FileUploadException;
import org.apache.tapestry5.Block;
import org.apache.tapestry5.PersistenceConstants;
import org.apache.tapestry5.annotations.Component;
import org.apache.tapestry5.annotations.IncludeStylesheet;
import org.apache.tapestry5.annotations.OnEvent;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.annotations.SetupRender;
import org.apache.tapestry5.corelib.components.Checkbox;
import org.apache.tapestry5.corelib.components.Form;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.upload.components.Upload;
import org.apache.tapestry5.upload.services.UploadEvents;
import org.apache.tapestry5.upload.services.UploadedFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.annotation.Secured;

@IncludeStylesheet("context:styles/pages/crl/crlImport.css")
@Secured({ FactoryRoles.ROLE_ADMIN, FactoryRoles.ROLE_PKI_MANAGER })
public class CRLImport {
    private final static Logger logger = LoggerFactory.getLogger(CRLImport.class);

    /*
     * Maximum number of CRLs that are uploaded in one call.
     */
    @Parameter(value = "5")
    private int maxBatchSize;

    /*
     * 'Handle' to the file that's uploaded
     */
    private UploadedFile file;

    @Inject
    @Property
    private X509CRLStoreWS crlStore;

    /*
     * If true expired certificates are ignored
     */
    @Property
    @Persist
    private Boolean ignoreExpired;

    /*
     * The number of CRLs actually imported
     */
    @Property
    @Persist(PersistenceConstants.FLASH)
    private Integer importCount;

    /*
     * The total number of CRLs found in the uploaded file
     */
    @SuppressWarnings("unused")
    @Property
    @Persist(PersistenceConstants.FLASH)
    private int totalCount;

    /*
     * True when uploading a file resulted in an error (mostly when file size exceeds maximum)
     */
    @Persist(PersistenceConstants.FLASH)
    private boolean importError;

    /*
     * The error message accompanying the uploadError property.
     */
    @Persist(PersistenceConstants.FLASH)
    private String importErrorMessage;

    @SuppressWarnings("unused")
    @Component(id = "upload", parameters = { "value=file", "validate=required" })
    private Upload upload;

    /*
     * I disabled clientValidation because it kept on popping up a warning when I opened the file
     * browser
     */
    @Component(id = "importForm", parameters = { "clientValidation=false" })
    private Form form;

    @SuppressWarnings("unused")
    @Component(id = "ignoreExpired", parameters = { "value=ignoreExpired" })
    private Checkbox ignoreExpiredCheckbox;

    @Inject
    private Block infoBlockPlural;

    @Inject
    private Block infoBlockSingular;

    @SetupRender
    @Secured({ FactoryRoles.ROLE_ADMIN, FactoryRoles.ROLE_PKI_MANAGER })
    protected void setupRender() {
        if (ignoreExpired == null) {
            ignoreExpired = true;
        }
    }

    public UploadedFile getFile() {
        return file;
    }

    public void setFile(UploadedFile file) {
        this.file = file;
    }

    public Block getInfoBlock() {
        if (importCount == null) {
            return null;
        }

        return importCount == 1 ? infoBlockSingular : infoBlockPlural;
    }

    public void onValidateFromUpload(UploadedFile file) throws NoSuchProviderException {
        /*
         * We need to check if the uploaded file is really a certificate file.
         */
        try {
            Collection<X509CRL> crls;
            try {
                crls = CRLUtils.readX509CRLs(file.getStream());
            } catch (CertificateException e) {
                throw new CRLException(e);
            } catch (SecurityFactoryFactoryException e) {
                throw new CRLException(e);
            }

            if (crls.size() == 0) {
                form.recordError("The uploaded file does not contain valid CRLs.");
            }
        } catch (CRLException e) {
            logger.error("Error validating uploaded file.", e);

            form.recordError("The uploaded file is not a valid CRL file.");
        }
    }

    /*
     * Event handler that gets called when the uploaded file exceeds the maximum size
     */
    @OnEvent(UploadEvents.UPLOAD_EXCEPTION)
    protected Object onUploadException(FileUploadException uploadException) {
        logger.error("Error uploading file", uploadException);

        importError = true;
        importErrorMessage = uploadException.getMessage();

        return CRLImport.class;
    }

    private void addCRLs(Collection<X509CRL> crls)
            throws CRLException, CertificateEncodingException, IOException, WebServiceCheckedException {
        /*
         * Create some initial buffer space. Assume certificate is 4K on average.
         */
        ByteArrayOutputStream bos = new ByteArrayOutputStream(maxBatchSize * 4096);

        CRLUtils.writeX509CRLs(crls, bos, ObjectEncoding.DER);

        int added = crlStore.addCRLs(bos.toByteArray());

        importCount = importCount + added;
    }

    /*
     * Returns true if the CRL is to be accepted for import.
     */
    private boolean accept(X509CRL crl) {
        return !(ignoreExpired && X509CRLInspector.isExpired(crl));
    }

    /*
     * Called when the form is submitted.
     */
    public void onSuccess() throws CertificateException, NoSuchProviderException, SecurityFactoryFactoryException,
            CRLException, IOException, WebServiceCheckedException {
        importCount = new Integer(0);

        /*
         * It should already be checked that the file contains certificates.
         */
        Collection<X509CRL> crls = CRLUtils.readX509CRLs(file.getStream());

        totalCount = crls.size();

        Collection<X509CRL> batch = new LinkedList<X509CRL>();

        for (X509CRL crl : crls) {
            if (accept(crl)) {
                batch.add(crl);

                if (batch.size() == maxBatchSize) {
                    addCRLs(batch);

                    batch.clear();
                }
            }
        }

        /*
         * Check if there are still some certificates left to add (happens when the number
         * of certificates is not a multiple of maxBatchSize)
         */
        if (batch.size() > 0) {
            addCRLs(batch);
        }
    }

    public boolean isImportError() {
        return importError;
    }

    public String getImportErrorMessage() {
        return importErrorMessage;
    }

    /*
     * Event handler called when the cancel button is pressed.
     */
    protected Object onCancel() {
        return CRLs.class;
    }
}