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.io.Serial; 019import java.util.ArrayList; 020import java.util.Collections; 021import java.util.List; 022import java.util.Optional; 023 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 @Serial 044 private static final long serialVersionUID = 5607857024718309330L; 045 046 private final List<ErrorBundle> errors; 047 048 /** 049 * Creates a new {@link AcmeInvalidMessageException}. 050 * 051 * @param msg 052 * Reason of the exception 053 */ 054 public AcmeInvalidMessageException(String msg) { 055 super(msg); 056 this.errors = Collections.emptyList(); 057 } 058 059 /** 060 * Creates a new {@link AcmeInvalidMessageException}. 061 * 062 * @param msg 063 * Reason of the exception 064 * @param errors 065 * List of {@link ErrorBundle} with further details 066 * @since 2.16 067 */ 068 public AcmeInvalidMessageException(String msg, List<ErrorBundle> errors) { 069 super(msg); 070 this.errors = unmodifiableList(errors); 071 } 072 073 /** 074 * Creates a new {@link AcmeInvalidMessageException}. 075 * 076 * @param msg 077 * Reason of the exception 078 * @param cause 079 * Cause 080 */ 081 public AcmeInvalidMessageException(String msg, Throwable cause) { 082 super(msg, cause); 083 var errors = new ArrayList<ErrorBundle>(1); 084 Optional.ofNullable(cause) 085 .filter(LocalizedException.class::isInstance) 086 .map(LocalizedException.class::cast) 087 .map(LocalizedException::getErrorMessage) 088 .ifPresent(errors::add); 089 this.errors = unmodifiableList(errors); 090 } 091 092 /** 093 * Returns a list with further error details, if available. The list may be empty, but 094 * is never {@code null}. 095 * 096 * @since 2.16 097 */ 098 public List<ErrorBundle> getErrors() { 099 return errors; 100 } 101 102}