Java tutorial
/* * 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; } }