001/* 002 * acme4j - Java ACME client 003 * 004 * Copyright (C) 2016 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.exception; 015 016import java.io.Serial; 017import java.net.MalformedURLException; 018import java.net.URI; 019import java.net.URL; 020import java.util.Optional; 021 022import edu.umd.cs.findbugs.annotations.Nullable; 023import org.shredzone.acme4j.Problem; 024 025/** 026 * The user is required to take manual action as indicated. 027 * <p> 028 * Usually this exception is thrown when the terms of service have changed, and the CA 029 * requires an agreement to the new terms before proceeding. 030 */ 031public class AcmeUserActionRequiredException extends AcmeServerException { 032 @Serial 033 private static final long serialVersionUID = 7719055447283858352L; 034 035 private final @Nullable URI tosUri; 036 037 /** 038 * Creates a new {@link AcmeUserActionRequiredException}. 039 * 040 * @param problem 041 * {@link Problem} that caused the exception 042 * @param tosUri 043 * {@link URI} of the terms-of-service document to accept, may be 044 * {@code null} 045 */ 046 public AcmeUserActionRequiredException(Problem problem, @Nullable URI tosUri) { 047 super(problem); 048 this.tosUri = tosUri; 049 } 050 051 /** 052 * Returns the {@link URI} of the terms-of-service document to accept. Empty 053 * if the server did not provide a link to such a document. 054 */ 055 public Optional<URI> getTermsOfServiceUri() { 056 return Optional.ofNullable(tosUri); 057 } 058 059 /** 060 * Returns the {@link URL} of a document that gives instructions on the actions to be 061 * taken by a human. 062 */ 063 public URL getInstance() { 064 var instance = getProblem().getInstance() 065 .orElseThrow(() -> new AcmeProtocolException("Instance URL required, but missing.")); 066 067 try { 068 return instance.toURL(); 069 } catch (MalformedURLException ex) { 070 throw new AcmeProtocolException("Bad instance URL: " + instance, ex); 071 } 072 } 073 074 @Override 075 public String toString() { 076 return getProblem().getInstance() 077 .map(uri -> "Please visit " + uri + " - details: " + getProblem()) 078 .orElseGet(super::toString); 079 } 080 081}