/*
* 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 com.sun.jini.lease;
import com.sun.jini.proxy.MarshalledWrapper;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.rmi.MarshalledObject;
import net.jini.core.lease.Lease;
import net.jini.io.MarshalledInstance;
import net.jini.lease.LeaseRenewalSet;
import net.jini.lease.RenewalFailureEvent;
/**
* Basic implementation of <code>RenewalFailureEvent</code> that
* defers unmarshalling.
* <p>
* The <code>Lease</code> that could not be renewed and any
* accompanying <code>Throwable</code> will not be deserialized until
* the appropriate accessor is called.
*
* @author Sun Microsystems, Inc.
* @see LeaseRenewalSet
*/
public class BasicRenewalFailureEvent extends RenewalFailureEvent {
private static final long serialVersionUID = 4122133697986606684L;
/**
* Exception, in marshalled form, returned by <code>getThrowable</code>
* method. May be <code>null</code>.
*
* @serial
*/
private MarshalledInstance marshalledThrowable;
/**
* Lease, in marshalled form, returned by <code>getLease</code> method.
*
* @serial
*/
private MarshalledInstance marshalledLease;
/**
* Transient cache of lease returned by <code>getLease</code> method.
*/
private transient Lease lease = null;
/**
* Transient cache of exception returned by <code>getThrowable</code>
* method.
*/
private transient Throwable throwable;
/** Whether to verify codebase integrity. */
private transient boolean verifyCodebaseIntegrity;
/**
* 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
* @param marshalledLease the lease which could not be renewed, in
* marshalled form
* @param marshalledThrowable the first exception that was thrown in the
* last chain of renewal failures, in marshalled form. May be
* <code>null</code> in which case <code>getThrowable</code> will
* return <code>null</code>.
*/
public BasicRenewalFailureEvent(LeaseRenewalSet source,
long seqNum,
MarshalledObject handback,
MarshalledInstance marshalledLease,
MarshalledInstance marshalledThrowable)
{
super(source, seqNum, handback);
this.marshalledThrowable = marshalledThrowable;
this.marshalledLease = marshalledLease;
}
/**
* Returns the lease that could not be renewed. When the event is
* deserialized, the lease is left in marshalled form. It is only
* unmarshalled when this call is made. If a call to this method
* fails, future calls will attempt to re-unmarshal the lease.
* Once the lease is successfully unmarshalled it is cached in a
* transient field so future calls will not result in
* <code>IOException</code> or
* <code>ClassNotFoundException</code>.
*
* @return the unmarshalled lease
* @throws IOException if there are problems unmarshalling the lease,
* usually because of some sort of class mismatch
* @throws ClassNotFoundException if there are problems unmarshalling the
* lease, usually because one of the classes associated with the
* lease's implementation could not be loaded
* @throws SecurityException if this object was unmarshalled from a stream
* that required codebase integrity, and the integrity of the
* lease's codebase could not be verified
*/
public Lease getLease() throws IOException, ClassNotFoundException {
if (lease == null) {
lease = (Lease) marshalledLease.get(verifyCodebaseIntegrity);
}
return lease;
};
/**
* Returns the exception (if any) that was thrown by the last renewal
* attempt.
* <p>
* When the event is deserialized, the exception is
* left in marshalled form. It is only unmarshalled when this call
* is made. If a call to this method fails, future calls will
* attempt to re-unmarshal the exception. Once the
* exception is successfully unmarshalled it is
* cached in a transient field so future calls will not result in
* <code>IOException</code> or
* <code>ClassNotFoundException</code>.
*
* @return the unmarshalled exception
* @throws IOException if there are problems unmarshalling the exception,
* usually because of some sort of class mismatch
* @throws ClassNotFoundException if there are problems unmarshalling the
* exception, usually because one of the classes associated with
* the exception's implementation could not be loaded
* @throws SecurityException if this object was unmarshalled from a stream
* that required codebase integrity, and the integrity of the
* exception's codebase could not be verified
*/
public Throwable getThrowable() throws IOException, ClassNotFoundException {
// Is there a throwable?
if (marshalledThrowable == null)
return null;
if (throwable == null) {
throwable =
(Throwable) marshalledThrowable.get(verifyCodebaseIntegrity);
}
return throwable;
}
/* Set transient fields. */
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException
{
in.defaultReadObject();
verifyCodebaseIntegrity = MarshalledWrapper.integrityEnforced(in);
}
}