/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.jini.lease;

import java.io.IOException;
import java.rmi.MarshalledObject;
import net.jini.core.lease.Lease;
import net.jini.core.event.RemoteEvent;

/**
 * Event generated by a lease renewal set when it can't renew a lease it
 * is responsible for.
 * <p>
 * <code>RenewalFailureEvent</code> is a subclass of
 * <code>RemoteEvent</code>, adding two additional items of abstract
 * state: the client lease that could not be renewed before expiration
 * and the <code>Throwable</code> object that was thrown by the last
 * renewal attempt (if any).
 * <p>
 * The methods of this interface are declared to allow implementations
 * to defer the unmarshalling of the lease and <code>Throwable</code>
 * until the client explicitly asks for them.
 * 
 * 
 * @see LeaseRenewalSet 
 */
public abstract class RenewalFailureEvent extends RemoteEvent {
    private static final long serialVersionUID = 8891457049195932943L;

    /**
     * Simple constructor. Note event id is fixed to
     * <code>LeaseRenewalSet.RENEWAL_FAILURE_EVENT_ID</code>.
     *
     * @param source the <code>LeaseRenewalSet</code> that generated the
     *	      event
     * @param seqNum the sequence number of this event
     * @param handback the client handback
     */
    public RenewalFailureEvent(LeaseRenewalSet  source, 
			       long             seqNum,
			       MarshalledObject handback)
    {
	super(source, LeaseRenewalSet.RENEWAL_FAILURE_EVENT_ID, seqNum, 
	      handback);
    }

    /**
     * Returns the lease that could not be renewed. This method may
     * cause the lease to be unmarshalled. If it does and unmarshalling
     * fails, future calls will attempt to re-unmarshal the lease. Once
     * this method succeeds, subsequent calls must return the same
     * object.
     * <p>
     * If the renewal service was able to renew the lease before the
     * event occurred, the expiration time of the <code>Lease</code>
     * object returned by this method will reflect the result of the
     * last successful renewal call. This time may be distorted by clock
     * skew between hosts if it is currently set to use the
     * <code>Lease.ABSOLUTE</code> serial format. If the
     * <code>Lease</code> object is using the
     * <code>Lease.DURATION</code> serial format, and the implementation
     * only unmarshals the lease when <code>getLease</code> is called,
     * the expiration time may be distorted if a long time has passed
     * between the time the event was generated by the renewal service
     * and when the client called <code>getLease</code>. When a renewal
     * failure event is generated for a given lease, that lease is
     * removed from the set.
     *
     * @return the lease that could not be renewed
     * @throws IOException if there are difficulties unmarshalling the
     *	       lease, usually this will be some sort of class mismatch
     * @throws ClassNotFoundException if there are difficulties
     *	       unmarshalling the lease, usually this will indicate one
     *	       of the classes associated with the lease's implementation
     *	       could not be loaded
     */
    public abstract Lease getLease()
	throws IOException, ClassNotFoundException;

    /**
     * Returns the <code>Throwable</code> (if any) that was thrown by
     * the last renewal attempt. If <code>null</code> is returned it can
     * be assumed ether the last renewal attempt succeeded, or that the
     * renewal service was unable to make a renewal attempt before the
     * lease expired.
     * <p>
     * This method may cause the <code>Throwable</code> to be
     * unmarshalled. If it does and unmarshalling fails, future calls
     * will attempt to re-unmarshal the <code>Throwable</code>. Once
     * this method succeeds, subsequent calls must return the same
     * object.
     *
     * @return the <code>Throwable</code> (if any) that was thrown by
     *	       the last renewal attempt
     * @throws IOException if there are difficulties unmarshalling the
     *	       <code>Throwable</code>, usually this will be some sort of
     *	       class mismatch
     * @throws ClassNotFoundException if there are difficulties
     *	       unmarshalling the <code>Throwable</code>, usually this
     *	       will indicate one of the classes associated with the
     *	       implementation of the <code>Throwable</code> could not be
     *	       loaded
     */
    public abstract Throwable getThrowable() 
	throws IOException, ClassNotFoundException;
}
