001/* 002 * acme4j - Java ACME client 003 * 004 * Copyright (C) 2022 Richard "Shred" Körber 005 * http://acme4j.shredzone.org 006 * 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 013 */ 014package org.shredzone.acme4j.smime.exception; 015 016import static java.util.Collections.unmodifiableList; 017 018import java.util.ArrayList; 019import java.util.Collections; 020import java.util.List; 021import java.util.Optional; 022 023import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 024import org.bouncycastle.i18n.ErrorBundle; 025import org.bouncycastle.i18n.LocalizedException; 026import org.shredzone.acme4j.exception.AcmeException; 027 028/** 029 * This exception is thrown when the challenge email message is invalid. 030 * <p> 031 * If this exception is thrown, the challenge message does not match the actual challenge 032 * or has other issues. It <em>must</em> be rejected. 033 * <p> 034 * Reasons may be (for example): 035 * <ul> 036 * <li>Unexpected sender address</li> 037 * <li>Bad S/MIME signature</li> 038 * </ul> 039 * 040 * @since 2.15 041 */ 042public class AcmeInvalidMessageException extends AcmeException { 043 private static final long serialVersionUID = 5607857024718309330L; 044 045 private final List<ErrorBundle> errors; 046 047 /** 048 * Creates a new {@link AcmeInvalidMessageException}. 049 * 050 * @param msg 051 * Reason of the exception 052 */ 053 public AcmeInvalidMessageException(String msg) { 054 super(msg); 055 this.errors = Collections.emptyList(); 056 } 057 058 /** 059 * Creates a new {@link AcmeInvalidMessageException}. 060 * 061 * @param msg 062 * Reason of the exception 063 * @param errors 064 * List of {@link ErrorBundle} with further details 065 * @since 2.16 066 */ 067 public AcmeInvalidMessageException(String msg, List<ErrorBundle> errors) { 068 super(msg); 069 this.errors = unmodifiableList(errors); 070 } 071 072 /** 073 * Creates a new {@link AcmeInvalidMessageException}. 074 * 075 * @param msg 076 * Reason of the exception 077 * @param cause 078 * Cause 079 */ 080 public AcmeInvalidMessageException(String msg, Throwable cause) { 081 super(msg, cause); 082 var errors = new ArrayList<ErrorBundle>(1); 083 Optional.ofNullable(cause) 084 .filter(LocalizedException.class::isInstance) 085 .map(LocalizedException.class::cast) 086 .map(LocalizedException::getErrorMessage) 087 .ifPresent(errors::add); 088 this.errors = unmodifiableList(errors); 089 } 090 091 /** 092 * Returns a list with further error details, if available. The list may be empty, but 093 * is never {@code null}. 094 * 095 * @since 2.16 096 */ 097 @SuppressFBWarnings("EI_EXPOSE_REP") // errors is always an unmodifiable list 098 public List<ErrorBundle> getErrors() { 099 return errors; 100 } 101 102}