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;
015
016import java.io.Serializable;
017import java.net.URL;
018import java.util.Objects;
019
020import edu.umd.cs.findbugs.annotations.Nullable;
021
022/**
023 * This is the root class of all ACME resources (like accounts, orders, certificates).
024 * Every resource is identified by its location URL.
025 * <p>
026 * This class also takes care for proper serialization and de-serialization of the
027 * resource. After de-serialization, the resource must be bound to a {@link Login} again,
028 * using {@link #rebind(Login)}.
029 */
030public abstract class AcmeResource implements Serializable {
031    private static final long serialVersionUID = -7930580802257379731L;
032
033    private transient @Nullable Login login;
034    private final URL location;
035
036    /**
037     * Create a new {@link AcmeResource}.
038     *
039     * @param login
040     *            {@link Login} the resource is bound with
041     * @param location
042     *            Location {@link URL} of this resource
043     */
044    protected AcmeResource(Login login, URL location) {
045        this.location = Objects.requireNonNull(location, "location");
046        rebind(login);
047    }
048
049    /**
050     * Gets the {@link Login} this resource is bound with.
051     */
052    protected Login getLogin() {
053        if (login == null) {
054            throw new IllegalStateException("Use rebind() for binding this object to a login.");
055        }
056        return login;
057    }
058
059    /**
060     * Gets the {@link Session} this resource is bound with.
061     */
062    protected Session getSession() {
063        return getLogin().getSession();
064    }
065
066    /**
067     * Rebinds this resource to a {@link Login}.
068     * <p>
069     * Logins are not serialized, because they contain volatile session data and also a
070     * private key. After de-serialization of an {@link AcmeResource}, use this method to
071     * rebind it to a {@link Login}.
072     *
073     * @param login
074     *            {@link Login} to bind this resource to
075     */
076    public void rebind(Login login) {
077        if (this.login != null) {
078            throw new IllegalStateException("Resource is already bound to a login");
079        }
080        this.login = Objects.requireNonNull(login, "login");
081    }
082
083    /**
084     * Gets the resource's location.
085     */
086    public URL getLocation() {
087        return location;
088    }
089
090    @Override
091    protected final void finalize() {
092        // CT_CONSTRUCTOR_THROW: Prevents finalizer attack
093    }
094
095}