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