Package com.sun.jini.norm

Source Code of com.sun.jini.norm.ClientLeaseMapWrapper

/*
* 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.norm;

import com.sun.jini.proxy.ConstrainableProxyUtil;

import java.lang.reflect.Method;
import java.rmi.RemoteException;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import net.jini.core.constraint.RemoteMethodControl;
import net.jini.core.lease.Lease;
import net.jini.core.lease.LeaseMap;
import net.jini.core.lease.LeaseMapException;

/**
* Class that wraps LeaseMap created by client Leases.  Provides hooks
* for synchronization and data associated with each client lease while
* allowing us to use <code>LeaseRenewalManager</code>.  Objects of this
* class are returned by <code>createLeaseMap</code> calls made on
* <code>ClientLeaseWrapper</code> objects that are not deformed. <p>
*
* This class only allows as keys ClientLeaseWrappers that are non-deformed.
* Internally the mapping from ClientLeaseWrappers to longs is held in two
* Maps.  The first is a LeaseMap that is created by the client lease
* associated with the first ClientLeaseWrapper added to the set.  The second
* is a Map from client leases to the ClientLeaseWrappers that wrap them.
*
* @author Sun Microsystems, Inc.
* @see ClientLeaseWrapper
*/
class ClientLeaseMapWrapper extends AbstractMap implements LeaseMap {
    private static final long serialVersionUID = 1L;

    /** Methods for converting lease constraints to lease map constraints. */
    private static final Method[] leaseToLeaseMapMethods;
    static {
  try {
      Method cancel =
    Lease.class.getMethod("cancel", new Class[] { });
      Method cancelAll =
    LeaseMap.class.getMethod("cancelAll", new Class[] { });
      Method renew =
    Lease.class.getMethod("renew", new Class[] { long.class });
      Method renewAll =
    LeaseMap.class.getMethod("renewAll", new Class[] { });
      leaseToLeaseMapMethods = new Method[] {
    cancel, cancelAll, renew, renewAll };
  } catch (NoSuchMethodException e) {
      throw new NoSuchMethodError(e.getMessage());
  }
    }

    /**
     * LeaseMap created by client lease, mapping client leases to Long
     * expiration times.
     *
     * @serial
     */
    private final LeaseMap clientLeaseMap;

    /**
     * Map from client leases to ClientLeaseWrapper instances.
     *
     * @serial
     */
    private final Map wrapperMap = new HashMap();

    /**
     * Retain initial wrapper so canContainKey can use it to determine if
     * a specified lease may be added.
     *
     * @serial
     */
    private final ClientLeaseWrapper example;

    /**
     * Create a ClientLeaseMapWrapper object that will hold
     * the specified client Lease.
     * @param wrapper a wrapper for the lease that wants to be renewed
     * @param duration the duration to associate with wrapper
     * @throws IllegalArgumentException if wrapper is deformed
     */
    ClientLeaseMapWrapper(ClientLeaseWrapper wrapper, long duration) {
  final Lease clientLease = wrapper.getClientLease();
  if (clientLease == null) {
      throw new IllegalArgumentException("Wrapper cannot be deformed");
  }
  LeaseMap leaseMap = clientLease.createLeaseMap(duration);
  if (clientLease instanceof RemoteMethodControl &&
      leaseMap instanceof RemoteMethodControl)
  {
      leaseMap = (LeaseMap)
    ((RemoteMethodControl) leaseMap).setConstraints(
        ConstrainableProxyUtil.translateConstraints(
      ((RemoteMethodControl) clientLease).getConstraints(),
      leaseToLeaseMapMethods));
  }
  clientLeaseMap = leaseMap;
  wrapperMap.put(clientLease, wrapper);
  example = wrapper;
    }

    // inherit javadoc
    public void cancelAll() {
  throw new UnsupportedOperationException(
       "ClientLeaseMapWrapper.cancelAll: " +
       "LRS should not being canceling client leases");
    }

    /**
     * For each lease in the map, call failedRenewal
     */
    private void applyException(Throwable t) {
  for (Iterator i=wrapperMap.values().iterator(); i.hasNext(); ) {
      final ClientLeaseWrapper clw = (ClientLeaseWrapper) i.next();
      clw.failedRenewal(t);
 
    }

    // inherit javadoc
    // This method assumes that none of the leases in the map are
    // also being renewed by some other thread.
    public void renewAll() throws LeaseMapException, RemoteException {
  LeaseMapException lme = null;
  Map newExceptionMap = null;

  // Iterate over the wrappers, causing the appropriate exceptions
  // for the ones who's sets have expired.
  final long now = System.currentTimeMillis();
  for (Iterator i=wrapperMap.values().iterator(); i.hasNext(); ) {
      final ClientLeaseWrapper clw = (ClientLeaseWrapper) i.next();
      if (!clw.ensureCurrent(now)) {
    // Map an exception to this lease and drop from the map

    // If necessary create newExceptionMap
    if (newExceptionMap == null)
        newExceptionMap = new HashMap(wrapperMap.size());

    // Add to the newExceptionMap
    newExceptionMap.put(clw,
            LRMEventListener.EXPIRED_SET_EXCEPTION);

    // Drop from both the wrapper and inner map
    i.remove();
    clientLeaseMap.remove(clw.getClientLease());

    // Note, we don't call failedRenewal() because the set is
    // dead so logging changes is pointless.  Besides, there
    // is no change to log.
      }
  }

  // If the map is now empty don't bother calling renewAll()
  if (clientLeaseMap.isEmpty()) {
      if (newExceptionMap == null)
    return;

      throw new LeaseMapException("Expired Sets", newExceptionMap);
  }

  try {
      clientLeaseMap.renewAll();
  } catch (LeaseMapException e) {
      lme = e;
  } catch (RemoteException e) {
      applyException(e);
      throw e;
  } catch (Error e) {
      applyException(e);
      throw e;
  } catch (RuntimeException e) {
      applyException(e);
      throw e;
  }

  // For each Lease still in the map we need to update the wrapper
  for (Iterator i=clientLeaseMap.keySet().iterator(); i.hasNext(); ) {
      final Lease cl = (Lease) i.next();
      final ClientLeaseWrapper clw =
    (ClientLeaseWrapper) wrapperMap.get(cl);

      clw.successfulRenewal();
  }

  // If there were no errors just return
  if (lme == null && newExceptionMap == null)
      return;

  // If the renewAll() threw a LeaseMapException we have to
  // remove the problem leases from the wrapper and place
  // them in newExceptionMap

  if (lme != null) {
      final Map exceptionMap = lme.exceptionMap;

      // Create the newExceptionMap if we don't have one
      if (newExceptionMap == null)
    newExceptionMap = new HashMap(exceptionMap.size());

      // Copy each lease out of the exception's map into newExceptionMap,
      // also remove these leases from the wrapper and get the
      // failure logged
      for (Iterator i = exceptionMap.entrySet().iterator();
     i.hasNext(); )
      {
    final Map.Entry e = (Map.Entry) i.next();
    final Lease cl = (Lease) e.getKey();
    final Throwable t = (Throwable) e.getValue();
    final ClientLeaseWrapper clw =
        (ClientLeaseWrapper) wrapperMap.remove(cl);
    i.remove();

    clw.failedRenewal(t);
    newExceptionMap.put(clw, t);
      }
  }

  // If necessary throw a LeaseMapException
  if (newExceptionMap != null) {
      throw new LeaseMapException(
          (lme == null) ? "Expired Sets" : lme.getMessage(),
    newExceptionMap);
  }

  return;
    }

    // inherit javadoc
    public boolean canContainKey(Object key) {
  return key instanceof Lease &&
      example.canBatch((Lease) key);
    }

    /**
     * Check that the key is valid for this map, if it is return the client
     * lease, if not throw IllegalArgumentException.
     */
    private Lease checkKey(Object key) {
  if (canContainKey(key))
      return ((ClientLeaseWrapper) key).getClientLease();

  throw new IllegalArgumentException(
      "key is not valid for this LeaseMap");
    }

    /** Check that the value is a Long. */
    private static void checkValue(Object value) {
  if (!(value instanceof Long))
      throw new IllegalArgumentException("value is not a Long");
    }

    // inherit javadoc
    public boolean containsKey(Object key) {
  final Lease cl = checkKey(key)
  return clientLeaseMap.containsKey(cl);
    }

    // inherit javadoc
    public boolean containsValue(Object value) {
  checkValue(value);
  return clientLeaseMap.containsValue(value);
    }

    // inherit javadoc
    public Object get(Object key) {
  final Lease cl = checkKey(key)
  return clientLeaseMap.get(cl);
    }

    // inherit javadoc
    public Object put(Object key, Object value) {
  final Lease cl = checkKey(key);
  checkValue(value);
 
  // At this point we know key is a ClientLeaseWrapper

  /*
   * Since there is a 1:1 mapping between wrappers and client
   * leases, and, once we get going, we never have two wrapper
   * objects that != but are .equals(), if key is already in this
   * map, then wrapperMap.put() will replace the existing copy of
   * key with a == copy. This gives us the key non-replacement
   * semantics Map.put() should have.
   */
  wrapperMap.put(cl, key);
  return clientLeaseMap.put(cl, value);
    }

    // inherit javadoc
    public Object remove(Object key) {
  final Lease cl = checkKey(key);

  wrapperMap.remove(cl);
  return clientLeaseMap.remove(cl);
    }

    // inherit javadoc
    public void putAll(Map m) {
  Iterator iter = m.entrySet().iterator();
  while (iter.hasNext()) {
      Map.Entry e = (Map.Entry) iter.next();
      put(e.getKey(), e.getValue());
  }
    }

    // inherit javadoc
    public void clear() {
  clientLeaseMap.clear();
  wrapperMap.clear();
    }

    // inherit javadoc
    public boolean equals(Object o) {
  return clientLeaseMap.equals(o); // XXX should sameDestination matter?
    }

    // inherit javadoc
    public int hashCode() {
  return clientLeaseMap.hashCode();
    }

    // inherit javadoc
    public Set entrySet() {
  return new EntrySet();
    }

    /*
     * Classes that we use to implement entrySet()
     */

    /**
     * An implementation of Set backed by the ClientLeaseMapWrapper's
     * mappings, which are from wrapperMap's values to clientLeaseMap
     */
    private final class EntrySet extends AbstractSet {
  // inherit javadoc
  public Iterator iterator() {
      return new EntryIterator();
  }

  /**
   * If the passed object is a Map.Entry that is in the
   * ClientMapWrapper return the client lease associated with it,
   * otherwise return null
   */
  private Lease getClientLease(Object o) {
      if (!(o instanceof Map.Entry))
    return null;

      final Map.Entry e = (Map.Entry) o;
      final Object eValue = e.getValue();

      if (!(e.getKey() instanceof ClientLeaseWrapper) ||
    !(eValue instanceof Long) ||
    (eValue == null))
      {
    return null;
      }

      final ClientLeaseWrapper clw = (ClientLeaseWrapper) e.getKey();
      // Note if clw is deformed this call will return null, this is
      // the right thing since a deformed lease can't be in this map
      return clw.getClientLease();
  }

  // inherit javadoc
  public boolean contains(Object o) {
      final Lease cl = getClientLease(o);

      if (cl == null)
    return false;

      final Object eValue = ((Map.Entry) o).getValue();
      final Object value = clientLeaseMap.get(cl);
      if (value == null)
    return false;

      return value.equals(eValue);
  }

  // inherit javadoc
  public boolean remove(Object o) {
      final Lease cl = getClientLease(o);

      if (cl == null)
    return false;

      final Object eValue = ((Map.Entry) o).getValue();
      final Object value = clientLeaseMap.get(cl);
      if (value == null || !value.equals(eValue))
    return false;

     
      // Use cl to remove the data from the clientLeaseMap
      clientLeaseMap.remove(cl);
      wrapperMap.remove(cl);

      return true;
  }

  // inherit javadoc
  public int size() {
      return clientLeaseMap.size();
  }

  // inherit javadoc
  public void clear() {
      wrapperMap.clear();
      clientLeaseMap.clear();
  }
    }

    /** Our implementation of Map.Entry */
    private final class Entry implements Map.Entry {
  /** The key */
  private final ClientLeaseWrapper key;

  public Entry(ClientLeaseWrapper key) {
      this.key = key;
  }

  public Object getKey() {
      return key;
  }

  public Object getValue() {
      return clientLeaseMap.get(key.getClientLease());
  }

  public Object setValue(Object value) {
      checkValue(value);
      return clientLeaseMap.put(key.getClientLease(), value);
  }

  public boolean equals(Object o) {
      if (o instanceof Entry) {
    final Entry that = (Entry) o;
    return that.key.equals(key);
      }

      return false;
  }

  public int hashCode() {
      return key.hashCode();
  }
    }

    /**
     * An implementation of Iterator backed by the ClientMapWrapper's mappings,
     * which are from wrapperMap's values to clientLeaseMap
     */
    private final class EntryIterator implements Iterator {
  /** Iterator over the wrapperMap values */
  private final Iterator iter;

  /** Lease associated with the last value returned by next() */
  private Lease last;

  public EntryIterator() {
      iter = wrapperMap.entrySet().iterator();
  }

  public boolean hasNext() {
      return iter.hasNext();
  }

  public Object next() {
      final Map.Entry e = (Map.Entry) iter.next();           
      last = (Lease) e.getKey();       
      return new Entry((ClientLeaseWrapper) e.getValue());
  }

  public void remove() {
      // Use last to remove the data from the clientLeaseMap
      clientLeaseMap.remove(last);
      // use iter.remove() to remove from wrapperMap so we don't
      // get a concurrent access exception
      iter.remove();
  }
    }
}
TOP

Related Classes of com.sun.jini.norm.ClientLeaseMapWrapper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.