package rmi;

import proof.*;
import sdsi.*;

import java.rmi.*;

/**
 * This exception is the message sent from server to client in response
 * to a request for which the server has no proof of the client's authority.
 * It includes<ul>
 * <li> the identity of the required issuer principal,
 * <li> the subject that tried to make the request,
 * <li> a minimum restriction tag,
 * <li> a textual description of the error, and
 * <li> a {@link ProofRecipient} object where the client's proof can be sent
 * before it retries its request. The {@link #sendProof} method is the
 * client's interface to this operation.
 * </ul>
 */
public class SfNeedAuthorizationException
	extends RuntimeException {

	SDSIPrincipal issuer;
	Subject subject;
	Tag tag;
	ProofRecipient proofRecipient;
	String description;

	public SfNeedAuthorizationException(SDSIPrincipal issuer,
		Subject subject, Tag tag, ProofRecipient proofRecipient) {
		this(issuer, subject, tag, proofRecipient, null);
	}

	public SfNeedAuthorizationException(SDSIPrincipal issuer,
		Subject subject, Tag tag, ProofRecipient proofRecipient,
		String description) {
		this.issuer = issuer;
		this.subject = subject;
		this.tag = tag;
		this.proofRecipient = proofRecipient;
		this.description = description;
	}

	/**
	 * The client ({@link InvokeHack#invoke}) calls this method with its
	 * proof of authority to have that proof shipped to the server.
	 * The method sends a proof via RMI to a destination where it will
	 * be noticed when the call that originally caused this exception
	 * is retried.<p>
	 *
	 * The proof must show that {@tex $S \sfrg{T} I$}, where<dl>
	 * <dt><dd>S = getSubject()
	 * <dt><dd>I = getIssuer()
	 * <dt><dd>T = getTag()
	 * </dl>
	 */
	public void sendProof(Proof proof)
		throws RemoteException {
		proofRecipient.hereIsProof(proof);
	}

	/**
	 * Retrieve the identity of principal over which the proof must
	 * show authority (the <em>issuer</em>).
	 */
	public SDSIPrincipal getIssuer() {
		return issuer;
	}

	/**
	 * Retrieve the <em>subject</em> who the principal believes
	 * <b>says</b> the rejected request.
	 */
	public Subject getSubject() {
		return subject;
	}

	/**
	 * Retrieve the minimum restriction set that includes the rejected
	 * request.
	 */
	public Tag getTag() {
		return tag;
	}

	/**
	 * Retrieve a textual description of the exception.
	 */
	public String toString() {
		return getClass().getName()+
			(description==null
				? ""
				: ": "+description);
	}
}
