/* * 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 net.jini.core.lease.*; import java.io.IOException; import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.rmi.RemoteException; /** * A base class for implementing lease objects. This class takes care of * absolute vs relative time issues and implements some of the Lease methods. * The subclass is responsible for implementing: doRenew, cancel, * createLeaseMap, canBatch, hashCode, equals, and serialization of * any subclass state. * * @author Sun Microsystems, Inc. * */ public abstract class AbstractLease implements Lease, java.io.Serializable { private static final long serialVersionUID = -9067179156916102052L; /** * The lease expiration, in local absolute time. */ protected transient long expiration; /** * Serialization format for the expiration. * * @serial */ protected int serialFormat = Lease.DURATION; /** Construct a relative-format lease. */ protected AbstractLease(long expiration) { this.expiration = expiration; } /** Return the lease expiration. */ public synchronized long getExpiration() { return expiration; } /** Return the serialization format for the expiration. */ public synchronized int getSerialFormat() { return serialFormat; } /** Set the serialization format for the expiration. */ public void setSerialFormat(int format) { if (format != Lease.DURATION && format != Lease.ABSOLUTE) throw new IllegalArgumentException("invalid serial format"); synchronized (this) { serialFormat = format; } } /** Renew the lease for a duration relative to now. */ public void renew(long duration) throws UnknownLeaseException, LeaseDeniedException, RemoteException { long exp = doRenew(duration) + System.currentTimeMillis(); // We added two positive numbers, so if the result is negative // we must have overflowed, so use Long.MAX_VALUE if (exp < 0) exp = Long.MAX_VALUE; synchronized (this) { expiration = exp; } } /** * Renew the lease for a duration relative to now, and return * the duration actually granted. */ protected abstract long doRenew(long duration) throws UnknownLeaseException, LeaseDeniedException, RemoteException; /** * @serialData a long, which is the absolute expiration if serialFormat * is ABSOLUTE, or the relative duration if serialFormat is DURATION */ private void writeObject(ObjectOutputStream stream) throws IOException { int format; long val; synchronized (this) { format = serialFormat; val = expiration; } if (format == Lease.DURATION) { long exp = val; val -= System.currentTimeMillis(); // If we subtract positive from negative, and the result is // positive, we must have underflowed, so use Long.MIN_VALUE if (exp < 0 && val > 0) val = Long.MIN_VALUE; } stream.putFields().put("serialFormat", format); stream.writeFields(); stream.writeLong(val); } /** * Throws an <code>InvalidObjectException</code>. * * @throws InvalidObjectException unconditionally */ private void readObjectNoData() throws InvalidObjectException { throw new InvalidObjectException("no data in stream"); } /** * If serialFormat is DURATION, add the current time to the expiration, * to make it absolute (and if the result of the addition is negative, * correct the overflow by resetting the expiration to Long.MAX_VALUE). * * @throws InvalidObjectException if serialFormat is neither ABSOLUTE * nor DURATION */ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); long val = stream.readLong(); if (serialFormat == Lease.DURATION) { long dur = val; val += System.currentTimeMillis(); // If we add two positive numbers, and the result is negative, // we must have overflowed, so use Long.MAX_VALUE if (val < 0 && dur > 0) val = Long.MAX_VALUE; } else if (serialFormat != Lease.ABSOLUTE) { throw new InvalidObjectException("invalid serial format"); } expiration = val; } }