You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@river.apache.org by pe...@apache.org on 2014/05/09 09:03:19 UTC

svn commit: r1593493 [8/24] - in /river/jtsk/skunk/qa_refactor/trunk: qa/ qa/src/com/sun/jini/test/impl/end2end/jssewrapper/ qa/src/com/sun/jini/test/impl/joinmanager/ qa/src/com/sun/jini/test/impl/mahalo/ qa/src/com/sun/jini/test/impl/outrigger/matchi...

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerImpl.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerImpl.java?rev=1593493&r1=1593492&r2=1593493&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerImpl.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerImpl.java Fri May  9 07:03:18 2014
@@ -1,8146 +1,8146 @@
-/*
- * 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.fiddler;
-
-import com.sun.jini.config.Config;
-
-import com.sun.jini.constants.ThrowableConstants;
-import com.sun.jini.constants.TimeConstants;
-import com.sun.jini.constants.VersionConstants;
-
-import com.sun.jini.logging.Levels;
-
-import com.sun.jini.lookup.entry.BasicServiceType;
-import com.sun.jini.lookup.entry.LookupAttributes;
-
-import com.sun.jini.proxy.ThrowThis;
-
-import com.sun.jini.reliableLog.ReliableLog;
-import com.sun.jini.reliableLog.LogHandler;
-
-import com.sun.jini.start.LifeCycle;
-import org.apache.river.api.util.Startable;
-
-import com.sun.jini.thread.InterruptedStatusThread;
-import com.sun.jini.thread.ReadersWriter;
-import com.sun.jini.thread.ReadersWriter.ConcurrentLockException;
-import com.sun.jini.thread.ReadyState;
-
-import net.jini.activation.ActivationExporter;
-import net.jini.activation.ActivationGroup;
-import net.jini.config.Configuration;
-import net.jini.config.ConfigurationProvider;
-import net.jini.config.ConfigurationException;
-import net.jini.config.NoSuchEntryException;
-
-import net.jini.discovery.DiscoveryEvent;
-import net.jini.discovery.DiscoveryChangeListener;
-import net.jini.discovery.DiscoveryGroupManagement;
-import net.jini.discovery.DiscoveryLocatorManagement;
-import net.jini.discovery.DiscoveryManagement;
-import net.jini.discovery.LookupDiscoveryManager;
-import net.jini.discovery.LookupDiscoveryRegistration;
-import net.jini.discovery.RemoteDiscoveryEvent;
-
-import net.jini.export.Exporter;
-import net.jini.export.ProxyAccessor;
-
-import net.jini.id.Uuid;
-import net.jini.id.UuidFactory;
-
-import net.jini.jeri.BasicILFactory;
-import net.jini.jeri.BasicJeriExporter;
-import net.jini.jeri.InvocationLayerFactory;
-import net.jini.jeri.ServerEndpoint;
-import net.jini.jeri.tcp.TcpServerEndpoint;
-
-import net.jini.lookup.JoinManager;
-import net.jini.lookup.entry.Comment;
-import net.jini.lookup.entry.ServiceInfo;
-import net.jini.lookup.entry.Status;
-import net.jini.lookup.entry.StatusType;
-
-import net.jini.security.BasicProxyPreparer;
-import net.jini.security.ProxyPreparer;
-import net.jini.security.TrustVerifier;
-import net.jini.security.proxytrust.ServerProxyTrust;
-import net.jini.security.proxytrust.TrustEquivalence;
-
-import net.jini.core.discovery.LookupLocator;
-import net.jini.core.entry.Entry;
-import net.jini.core.event.EventRegistration;
-import net.jini.core.event.RemoteEventListener;
-import net.jini.core.lease.Lease;
-import net.jini.core.lease.UnknownLeaseException;
-import net.jini.core.lookup.ServiceID;
-import net.jini.core.lookup.ServiceRegistrar;
-
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-
-import java.lang.reflect.Array;
-
-import java.net.InetAddress;
-
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.OutputStream;
-import java.io.Serializable;
-
-import java.rmi.activation.ActivationException;
-import java.rmi.activation.ActivationID;
-import java.rmi.activation.ActivationSystem;
-import java.rmi.MarshalledObject;
-import java.rmi.NoSuchObjectException;
-import java.rmi.RemoteException;
-import java.rmi.server.ExportException;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-
-import java.security.PrivilegedExceptionAction;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Condition;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import net.jini.io.MarshalledInstance;
-
-/**
- * This class is the server side of an implementation of the lookup
- * discovery service. Multiple client-side proxy classes are used to
- * interact and communicate with this backend server. Those proxy
- * classes are: <code>FiddlerProxy</code> (the proxy for the 
- * <code>LookupDiscoveryService</code> interface which defines how clients
- * register with the lookup discovery service), <code>FiddlerAdminProxy</code>
- * (the proxy for the <code>FiddlerAdmin</code> interface which specifies 
- * the methods through which administration duties such as joining, persistent
- * state logging policy, and shutting down the lookup discovery service can
- * be performed), and <code>FiddlerRegistration</code> (the proxy for the 
- * <code>LookupDiscoveryRegistration</code> interface which defines the
- * methods through which clients can perform duties such as group and
- * locator management, state retrieval, and discarding discovered but
- * unavailable lookup services so they are eligible for re-discovery).
- * <p>
- * It is through the proxies that communicate with this class that clients
- * interact with the lookup discovery service. When a client makes a method
- * invocation on one of the proxies, the proxy makes a corresponding call
- * on the methods specified in the <code>Fiddler</code> interface which
- * are implemented in this class, ultimately executing on the backend server.
- * <p>
- *
- * @com.sun.jini.impl
- *
- * This implementation of the lookup discovery service employs a number of
- * {@link java.util.logging.Logger}s. The details of each such
- * {@link java.util.logging.Logger} are described
- * <a href="./package-summary.html#fiddlerLoggers">here</a>.
- * <p>
- * The configuration entries supported by this implementation are described
- * <a href="./package-summary.html#fiddlerConfigEntries">here</a>.
- *
- * @author Sun Microsystems, Inc.
- */
-class FiddlerImpl implements ServerProxyTrust, ProxyAccessor, Fiddler, Startable {
-
-    /* Name of this component; used in config entry retrieval and the logger.*/
-    static final String COMPONENT_NAME = "com.sun.jini.fiddler";
-    /* Loggers used by this implementation of the service. */
-    static final Logger problemLogger      = Logger.getLogger(COMPONENT_NAME+
-                                                              ".problem");
-    static final Logger startupLogger      = Logger.getLogger(COMPONENT_NAME+
-                                                              ".startup");
-    static final Logger tasksLogger        = Logger.getLogger(COMPONENT_NAME+
-                                                              ".tasks");
-    static final Logger eventsLogger       = Logger.getLogger(COMPONENT_NAME+
-                                                              ".events");
-    static final Logger groupsLogger       = Logger.getLogger(COMPONENT_NAME+
-                                                              ".groups");
-    static final Logger locatorsLogger     = Logger.getLogger(COMPONENT_NAME+
-                                                              ".locators");
-    static final Logger discardLogger      = Logger.getLogger(COMPONENT_NAME+
-                                                              ".discard");
-    static final Logger leaseLogger        = Logger.getLogger(COMPONENT_NAME+
-                                                              ".lease");
-    static final Logger registrationLogger = Logger.getLogger(COMPONENT_NAME+
-                                                              ".registration");
-    static final Logger persistLogger      = Logger.getLogger(COMPONENT_NAME+
-                                                              ".persist");
-    /** Data structure - associated with a <code>ServiceRegistrar</code> -
-     *  containing the <code>LookupLocator</code> and the member groups of
-     *  the registrar
-     */
-    static final class LocatorGroupsStruct {
-        final LookupLocator locator;
-        final String[]      groups;
-        LocatorGroupsStruct(LookupLocator locator, String[] groups) {
-            this.locator = locator;
-            this.groups  = groups;
-        }
-    }//end class LocatorGroupsStruct
-
-    /* ServiceInfo values */
-    private static final String PRODUCT      = "Lookup Discovery Service";
-    private static final String MANUFACTURER = "Sun Microsystems, Inc.";
-    private static final String VENDOR       = MANUFACTURER;
-    private static final String VERSION      = VersionConstants.SERVER_VERSION;
-
-    /** When re-setting the bound on lease durations, that bound cannot be
-     *  set to a value larger than this value */
-    static final long MAX_LEASE = 1000L * 60 * 60 * 24 * 365 * 1000;
-    /** Log format version */
-    private static final int LOG_VERSION = 2;
-
-    /** The outer (smart) proxy to this server */
-    private FiddlerProxy outerProxy;
-    /** The inner proxy (stub or dynamic proxy) to this server */
-    private Fiddler innerProxy;
-    /** The admin proxy to this server */
-    private FiddlerAdminProxy adminProxy;
-    /** The service ID associated with this service when it is registered
-     *  with any lookup service.
-     */
-    private ServiceID serviceID = null;
-    /** The activation id of the current instance of the lookup discovery
-     *  service, if it happens to be and activatable instance
-     */
-    private final ActivationID activationID;
-    /* Holds the prepared proxy to the ActivationSystem */
-    private final ActivationSystem activationSystem;
-    /** The unique identifier generated (or recovered) when an instance of
-     *  this service is constructed. This ID is typically used to determine
-     *  equality between the proxies of any two instances of this service.
-     */
-    private Uuid proxyID = null;
-    /** Map from the set of all currently discovered registrars to their 
-     *  corresponding [locator,member groups] pairs (locatorGroupsStuct).
-     */
-    private final HashMap allDiscoveredRegs = new HashMap(11);
-    /** Map from registrationID to registrationInfo.  Every registration is in
-     *  this map under its registrationID.
-     */
-    private final HashMap registrationByID = new HashMap(11);
-    /** Map from registrationInfo to registrationInfo (that is, to itself),
-     *  where the elements of the map are ordered by lease expiration time.
-     */
-    private final TreeMap registrationByTime = new TreeMap();
-    /** Performs all group and locator discovery on behalf of clients */
-    private final LookupDiscoveryManager discoveryMgr; 
-    /** The listener registered for both group discovery events and locator
-     *  discovery events.
-     */
-    private final LookupDiscoveryListener discoveryListener 
-                                               = new LookupDiscoveryListener();
-    /** For each registration created by the lookup discovery service, an
-     *  event identifier that uniquely maps the registration to the
-     *  registration's listener and managed sets will be generated and
-     *  associated with the registration through the EventRegistration
-     *  field of the registrationInfo. This event ID is unique across
-     *  all registrations with the current instance of the lookup discovery
-     *  service.
-     */
-    private long curEventID = 0;
-    /** Earliest expiration time over all active registrations */
-    private long minExpiration = Long.MAX_VALUE;
-    /** The lookup discovery manager this service's join manager will use */
-    private final DiscoveryManagement joinMgrLDM;
-    /** Manager for discovering and registering with lookup services */
-    private JoinManager joinMgr;
-    /** Executor for sending remote discovery events */
-    private final ExecutorService executorService;
-    /** Registration lease expiration thread */
-    private final LeaseExpireThread leaseExpireThread;
-    /** Snapshot-taking thread */
-    private final SnapshotThread snapshotThread;
-
-    /** Concurrent object to control read and write access */
-    private final ReadersWriter concurrentObj = new ReadersWriter();
-    /** Object for synchronizing with the registration expire thread */
-    private final Condition leaseExpireThreadSyncObj;
-    /** Object on which the snapshot-taking thread will synchronize */
-    private final Condition snapshotThreadSyncObj;
-
-    /** Reliable log object to hold persistent state of the service.
-     *  This object is also used as a flag: non-null ==> persistent service
-     *                                      null ==> non-persistent service
-     */
-    private final ReliableLog log;
-    /** Flag indicating whether system is in a state of recovery */
-    private boolean inRecovery;
-    /** Current number of records in the Log File since the last snapshot */
-    private int logFileSize = 0;
-    /** The name of the directory to which the persistent modes of this service
-     *  will log the service's state (using ReliableLog).
-     */
-    private final String persistDir;
-    /** least upper bound applied to all granted lease durations */
-    private long leaseBound = 1000 * 60 * 30;
-    /** Weight factor applied to snapshotSize when deciding to take snapshot */
-    private float snapshotWt = 10;
-    /** Log File must contain this many records before snapshot allowed */
-    private int snapshotThresh = 200;
-    /** Groups whose members are lookup services this service should join.
-     *  Unless configured otherwise, this service will initially join the
-     *  un-named public group. The desired join groups for this service can
-     *  be set administratively after start up.
-     */
-    private String[] thisServicesGroups = new String[] {""};
-    /** Locators of specific lookup services this service should join.
-     *  This service will initially join no lookups found through locator
-     *  discovery. The locators of the specific lookup services that are
-     *  desired for this service to join should be set administratively
-     *  after start up.
-     */
-    private LookupLocator[] thisServicesLocators = {};
-    /** The attributes to use when joining lookup service(s) */
-    private Entry[] thisServicesAttrs
-            = new Entry[]
-                 { new ServiceInfo(PRODUCT,MANUFACTURER,VENDOR,VERSION,"",""),
-                   new BasicServiceType("Lookup Discovery Service")
-                 };
-    /* Object used to obtain the configuration items for this service. */
-    private Configuration config;
-    /* The JAAS login context to use when performing a JAAS login. */
-    private final LoginContext loginContext;
-    /* The exporter used to export this service. */
-    private final Exporter serverExporter;
-    /* Maximum value of upper bound on lease durations.*/
-    private final long leaseMax;
-    /* Flag indicating this service is being started for the very 1st time */
-    private boolean initialStartup = true;
-    /** Object that, if non-<code>null</code>, will cause the object's
-     *  <code>unregister</code> method to be invoked during service shutdown
-     *  to notify the service starter framework that the reference to this
-     *  service's implementation can be 'released' for garbage collection;
-     *  the framework is notified that it does not have to hold on to the
-     *  service reference any longer.  Note hat this object is used only 
-     *  in the non-activatable case.
-     */
-    private final LifeCycle lifeCycle;
-    
-    /* ProxyPreparer fields were originally static and set every time a 
-     * constructor was called, this was done to enable the static class
-     * RegistrationInfo to prepare recovered proxy's after deserialization.
-     * 
-     * These fields are now final instance fields.  This would for instance
-     * enable multiple FiddlerImpl to co exist in one jvm if necessary using
-     * different configurations.
-     */
-    /* Preparer for proxies to remote listeners newly registered with this
-     * service.
-     */
-    private final ProxyPreparer listenerPreparer;
-    /* Preparer for proxies to remote listeners, previously prepared, and
-     * recovered from this service's persisted state.
-     */
-    private final ProxyPreparer recoveredListenerPreparer;
-    /* Preparer for initial and new lookup locators this service should
-     * discover and join.
-     */
-    private final ProxyPreparer locatorToJoinPreparer;
-    /* Preparer for lookup locators this service should discover and join
-     * that were previously prepared and which were recovered from this
-     * service's persisted state.
-     */
-    private final ProxyPreparer recoveredLocatorToJoinPreparer;
-    /* Preparer for initial and new lookup locators this service should
-     * discover on behalf of the clients that register with it.
-     */
-    private final ProxyPreparer locatorToDiscoverPreparer;
-    /* Preparer for lookup locators this service should discover on behalf
-     * of its registered clients that were previously prepared and which
-     * were recovered from this service's persisted state.
-     */
-    private final ProxyPreparer recoveredLocatorToDiscoverPreparer;
-    /** Object used to prevent access to this service during the service's
-     *  initialization or shutdown processing.
-     */
-    private final ReadyState readyState = new ReadyState();
-    
-    private boolean persistent;
-    private LocalLogHandler logHandler;
-    private AccessControlContext context;
-    
-    private boolean started;
-
-    /* ************************* BEGIN Constructors ************************ */
-    /**
-     * Constructs a new instance of FiddlerImpl. This version of the
-     * constructor is used to create an activatable instance of the lookup
-     * discovery service that logs its state information to persistent storage.
-     * <p>
-     * A constructor having this signature is required for the class to be
-     * activatable. This constructor is automatically called by the 
-     * activation group when the lookup discovery service is activated.
-     * 
-     * @param activationID the activation ID generated by the activation
-     *                     system and assigned to the instance of the server
-     *                     being activated
-     * @param data         state data (represented as a 
-     *                     <code>MarshalledObject</code>) which is needed to
-     *                     re-activate this server
-     *
-     * @throws IOException            this exception can occur when there is
-     *                                a problem recovering data from disk,
-     *                                exporting the server that's being
-     *                                activated, or when unmarshalling the
-     *                                given <code>data</code> parameter.
-     * @throws ConfigurationException this exception can occur when a
-     *                                problem occurs while retrieving an item
-     *                                from the <code>Configuration</code>
-     *                                generated from the contents of the
-     *                                given <code>data</code> parameter
-     * @throws ActivationException    this exception can occur when a problem
-     *                                occurs while activating the service
-     * @throws LoginException         this exception occurs when authentication
-     *                                fails while performing a JAAS login for
-     *                                this service
-     * @throws ClassNotFoundException this exception can occur while 
-     *                                unmarshalling the given <code>data</code>
-     *                                parameter; when a class needed in the
-     *                                unmarshalling process cannot be found.
-     * @throws ClassCastException     this exception can occur while
-     *                                unmarshalling the given <code>data</code>
-     *                                parameter; when the contents of that
-     *                                parameter is not a <code>String</code>
-     *                                array.
-     */
-    FiddlerImpl(ActivationID activationID,
-                MarshalledObject data) throws IOException,
-                                              ActivationException,
-                                              ConfigurationException,
-                                              LoginException,
-                                              ClassNotFoundException
-    {
-            this(init( (String[]) new MarshalledInstance(data).get(false), true /* persistent */, activationID ), null);
-    }//end activatable constructor
-
-    /**
-     * Constructs a new instance of FiddlerImpl. This version of the
-     * constructor is used to create a NON-activatable instance of the
-     * lookup discovery service.
-     *
-     * @param configArgs <code>String</code> array whose elements are
-     *                   the arguments to use when creating this version of
-     *                   the server
-     * @param lifeCycle  instance of <code>LifeCycle</code> that, if 
-     *                   non-<code>null</code>, will cause this object's
-     *                   <code>unregister</code> method to be invoked during
-     *                   shutdown to notify the service starter framework that
-     *                   the reference to this service's implementation can be
-     *                   'released' for garbage collection. A value of 
-     *                   <code>null</code> for this argument is allowed.
-     * @param persistent if <code>true</code>, then the service should persist
-     *                   its state.
-     *
-     * @throws IOException            this exception can occur when there is
-     *                                a problem recovering data from disk, or
-     *                                while exporting the server that's being
-     *                                created.
-     * @throws ConfigurationException this exception can occur when an
-     *                                problem occurs while retrieving an item
-     *                                from the <code>Configuration</code>
-     *                                generated from the contents of the
-     *                                given <code>configArgs</code> parameter
-     * @throws LoginException         this exception occurs when authentication
-     *                                fails while performing a JAAS login for
-     *                                this service
-     */
-    FiddlerImpl(String[] configArgs, LifeCycle lifeCycle, boolean persistent)
-                                             throws IOException,
-                                                    ConfigurationException,
-                                                    LoginException
-    {
-        this(init(configArgs, persistent), lifeCycle);
-    }//end non-activatable constructor
-    
-    FiddlerImpl(FiddlerInit i, LifeCycle lifeCycle){
-        this.snapshotThreadSyncObj = concurrentObj.newCondition();
-        this.leaseExpireThreadSyncObj = concurrentObj.newCondition();
-        this.lifeCycle = lifeCycle;
-        discoveryMgr = i.discoveryMgr;
-        listenerPreparer = i.listenerPreparer;
-        locatorToJoinPreparer = i.locatorToJoinPreparer;
-        locatorToDiscoverPreparer = i.locatorToDiscoverPreparer;
-        recoveredListenerPreparer = i.recoveredListenerPreparer;
-        recoveredLocatorToJoinPreparer = i.recoveredLocatorToJoinPreparer;
-        recoveredLocatorToDiscoverPreparer = i.recoveredLocatorToDiscoverPreparer;
-        persistDir = i.persistDir;
-        log = i.log;
-        joinMgrLDM = i.joinMgrLDM;
-        leaseMax = i.leaseMax;
-        executorService = i.executorService;
-        activationSystem = i.activationSystem;
-        serverExporter = i.serverExporter;
-        logHandler = i.logHandler;
-        activationID = i.activationID;
-        // These three fields are used by the Starter.start() implementation.
-        persistent = i.persistent;
-        config = i.config;
-        context = i.context;
-        loginContext = i.loginContext;
-        leaseExpireThread = AccessController.doPrivileged(
-            new PrivilegedAction<LeaseExpireThread>(){
-                @Override
-                public LeaseExpireThread run() {
-                    return new LeaseExpireThread(FiddlerImpl.this);
-                }
-                    
-            }, context);
-        if (log != null){
-            snapshotThread = AccessController.doPrivileged(
-                new PrivilegedAction<SnapshotThread>(){
-                    @Override
-                    public SnapshotThread run() {
-                        return new SnapshotThread(FiddlerImpl.this);
-                    }
-
-                }, context);
-        } else {
-            snapshotThread = null;
-        }
-    }
-    /* ************************** END Constructors ************************* */
-
-    /* ******************* BEGIN Inner Class Definitions ******************* */
-    /** Class which is used to communicate the status of this service to
-     *  interested entities. In particular, when certain errors occur during
-     *  operation, an instance of this class will be registered as an 
-     *  attribute in all of the lookup services with which this service
-     *  is registered. By registering for notification (from the lookup
-     *  services) of the existence of this attribute, interested entities
-     *  such as administrative clients and clients wishing to use this
-     *  service will be informed when this service can not proceed with its
-     *  processing, and can take appropriate action.
-     */
-    private static class FiddlerStatus extends Status {
-        private static final long serialVersionUID = -8511826097053446749L;
-        public FiddlerStatus(StatusType severity) {
-            super(severity);
-        }
-    }//end class FiddlerStatus
-
-    /** Class whose discovered() method is invoked by threads in the 
-     *  LookupDiscovery class whenever a new lookup service is discovered
-     *  on behalf of a client registration
-     */
-    private class LookupDiscoveryListener implements DiscoveryChangeListener {
-        public LookupDiscoveryListener() {
-            super();
-        }
-        public void discovered(DiscoveryEvent event) {
-            executorService.execute(new DiscoveredEventTask(event));
-        }
-        public void discarded(DiscoveryEvent event) {
-            executorService.execute(new DiscardedEventTask(event));
-        }
-        public void changed(DiscoveryEvent event) {
-            executorService.execute(new ChangedEventTask(event));
-        }
-    }//end class LookupDiscoveryListener
-
-    /** This class acts as a record of one registration with the lookup
-     *  discovery service; containing all of the information about that
-     *  registration.
-     */
-    private final static class RegistrationInfo
-                                          implements Comparable, Serializable
-    {
-        private static final long serialVersionUID = 2L;
-
-        /** The unique identifier assigned to the registration to which the
-         *  data in the current implementation of this class corresponds.
-         *  This identifier is unique across all other active registrations
-         *  generated with the current instance of the lookup discovery
-         *  service.
-         *  @serial
-         */
-        public final Uuid registrationID;
-        /** Map from the set of instances of the <code>ServiceRegistrar</code>
-         *  interface, to the set of marshalled instances of the
-         *  <code>ServiceRegistrar</code> interface, where each key and
-         *  each value (which is the marshalled form of its corresponding
-         *  key) is a proxy to one of the lookup service(s) that have been
-         *  discovered for the current registration. The contents of
-         *  this set represents the 'remote state' of the registration's
-         *  currently discovered lookup service(s).
-         *  @serial
-         */
-        public final HashMap discoveredRegsMap;
-        /** The managed set containing the names of the groups whose
-         *  members are the lookup services the lookup discovery service
-         *  should attempt to discover for the current registration.
-         *  (HashSet is used to prevent duplicates.)
-         *  @serial
-         */
-        public HashSet<String> groups;
-        /** The managed set containing the locators of the specific lookup
-         *  services the lookup discovery service should attempt to discover
-         *  for the current registration. (HashSet is used to prevent
-         *  duplicates.)
-         *  @serial
-         */
-        public HashSet locators;
-        /** The ID of the lease placed on the current registration.
-         *  @serial
-         */
-        public final Uuid leaseID;
-        /** The absolute expiration time of the current lease.
-         *  @serial
-         */
-        public long leaseExpiration;
-        /** The identifier that maps the current registration to the remote
-         *  event listener and the managed set of groups and locators.
-         */
-        public long eventID;
-        /** The current sequence number of the set of remote discovery events
-         *  sent to the current registration's listener. When a registration
-         *  is granted, this class is instantiated to contain the information
-         *  related to that particular registration. The event sequence
-         *  number is initialized to 0 upon instantiation because the
-         *  remote discovery events are sent to the listeners of each 
-         *  separate registration. Thus, each registration has its own
-         *  sequence of events.
-         *  @serial
-         */
-        public long seqNum;
-        /** The handback object returned with every remote discovery event
-         *  sent to the current registration's listener.
-         *  @serial
-         */
-        public final MarshalledObject handback;
-        /** When the lookup discovery service discards a registrar as a 
-         *  result of some internal condition (such as multicast announcements
-         *  ceasing) and not as a result of a request from a registration,
-         *  every registration configured for group discovery of that discarded
-         *  registrar will be sent a remote discarded event. On the other
-         *  hand, for the case where a registrar is discarded as a result
-         *  of a request from a registration, only those registrations that
-         *  actually request that the registrar be discarded will be sent
-         *  a remote discarded event. This flag is used to determine whether
-         *  to send a remote discarded event to one or multiple listeners.
-         */
-        public boolean discardFlag;
-        /** The remote event listener registered by the client. This field
-         *  is transient because it is marshalled separately from the rest
-         *  of this class when being serialized. (See the description for
-         *  <code>writeObject</code> below.)
-         */
-         public transient RemoteEventListener listener;
-         
-        /** Constructs an instance of this class and stores the information
-         *  related to the current registration: IDs, managed sets, lease
-         *  information, and event registration information.
-         */
-        public RegistrationInfo(Uuid registrationID,
-                String[] groups, 
-                LookupLocator[] locators, 
-                Uuid leaseID, 
-                long leaseExpiration, 
-                long eventID, 
-                MarshalledObject handback, 
-                                RemoteEventListener listener)
-        {
-            this.registrationID = registrationID;
-            /* Initialize the groups field, removing nulls and duplicates */
-            if(groups != null) {
-                this.groups = new HashSet<String>();
-                for(int i=0;i<groups.length;i++) {
-                    if(groups[i] == null) continue;
-                    this.groups.add(groups[i]);
-                }
-            }
-            /* Initialize the locators field, removing nulls and duplicates */
-            this.locators = new HashSet();
-            if( (locators != null) && (locators.length > 0) ) {
-                for(int i=0;i<locators.length;i++) {
-                    if(locators[i] == null) continue;
-                    this.locators.add(locators[i]);
-                }
-            }
-            this.discoveredRegsMap = new HashMap(11);
-            this.leaseID = leaseID;
-            this.leaseExpiration = leaseExpiration;
-
-            this.eventID = eventID;
-            this.seqNum = 0; // initialize to 0
-            this.handback = handback;
-            this.discardFlag = false;//set true only on first discard request
-            this.listener = listener;
-        }//end constructor
-
-        /** Attempts to marshal each element of the input set of instances of
-         *  the <code>ServiceRegistrar</code> interface and then map the
-         *  registrar to its marshalled form, and store the mapping in this
-         *  registration's <code>discoveredRegsMap</code> field.
-         *  <p>
-         *  This method is typically invoked to handle discovered (as opposed
-         *  to discarded) registrars. Note that if a particular registrar
-         *  cannot be serialized (marshalled), it is not included in the
-         *  mapping; nor is it included in the return set.
-         * 
-         * @param regMapIn mapping in which the key values are the registrars
-         *                 to serialize and store, and the map values are data
-         *                 structures of type <code>LocatorGroupsStruct</code>
-         *                 that contain the locator and member groups of the
-         *                 corresponding registrar key
-         * 
-         *  @return a <code>HashMap</code> whose keys are the registrars
-         *          whose marshalled form and un-marshalled form were inserted
-         *          as key/value pairs into the <code>discoveredRegsMap</code>
-         *          field of this regInfo; and whose values are the member
-         *          groups of each corresponding registrar key.
-         */
-        public HashMap addToDiscoveredRegs(HashMap regMapIn) {
-            HashMap regMapOut = new HashMap(regMapIn.size());
-            Iterator itr = (regMapIn.entrySet()).iterator();
-            nextReg:
-            for(int i=0;itr.hasNext();i++) {
-                Map.Entry pair = (Map.Entry)itr.next();
-                ServiceRegistrar reg = (ServiceRegistrar)pair.getKey();
-                /* If reg is already in map, go to next registrar */
-                if( discoveredRegsMap.containsKey(reg) ) continue nextReg;
-                /* It doesn't contain it, try to marshal it */
-                MarshalledObject mReg = null;
-                try {
-                    mReg = new MarshalledInstance(reg).convertToMarshalledObject();
-                } catch(IOException e) { continue nextReg; } //failed, next reg
-                /* Succeeded, map registrar to its marshalled form */
-                discoveredRegsMap.put(reg,mReg);
-                /* Map the registrar to its member groups for the return map */
-                regMapOut.put(reg,
-                              ((LocatorGroupsStruct)pair.getValue()).groups);
-            }//end loop
-            return regMapOut;
-        }//end addToDiscoveredRegs
-
-        /** Performs a primary sort by leaseExpiration, and a secondary sort
-         *  by registrationID. The secondary sort is immaterial, except to
-         *  ensure a total order (required by <code>TreeMap</code>).
-         */
-        public int compareTo(Object obj) {
-            RegistrationInfo regInfo = (RegistrationInfo)obj;
-            if (this == regInfo)  return 0;
-            if (    (leaseExpiration < regInfo.leaseExpiration)
-                 || (    (leaseExpiration == regInfo.leaseExpiration)
-		      && (eventID < regInfo.eventID) )  )
-            {
-                return -1;
-            }//endif
-            return 1;
-        }//end compareTo
-        
-        /** When a registration is granted to a client, the client registers
-         *  a remote listener with the lookup discovery service so that the
-         *  lookup discovery service may send remote discovery events to the
-         *  client. The client typically annotates the listener with an RMI
-         *  codebase from which the backend server can download the remote
-         *  listener's proxy (stub). When the current registration is logged
-         *  to persistent storage (for example, a snapshot is taken), the
-         *  listener is written to the output snapshot or log file through
-         *  an <code>ObjectOutputStream</code> which only serializes the
-         *  listener; it does not marshal the listener. Thus, when the
-         *  listener field of this class is logged, unless special action
-         *  is taken, the codebase from which to retrieve the listener will
-         *  not be included in the output. 
-         *
-         *  In order to include the codebase with the listener when saving
-         *  state, the following custom <code>writeObject</code> method
-         *  is provided which first serializes the current instance of
-         *  this class (excluding the transient <code>listener</code> field),
-         *  and then explicitly marshals the listener to preserve the
-         *  codebase upon writing to the file. In this way, the listener --
-         *  along with its codebase -- is persisted through a mechanism that
-         *  is separate from the normal mechanism applied to the remaining
-         *  fields of this class.
-         */
-        private void writeObject(ObjectOutputStream stream) throws IOException{
-            stream.defaultWriteObject();
-            stream.writeObject(new MarshalledInstance(listener).convertToMarshalledObject());
-        }//end writeObject
-
-        /** When this class is deserialized, this method is invoked. This
-         *  method first deserializes the non-transient elements of this
-         *  class, and then unmarshals the remote event listener. (See the
-         *  description for <code>writeObject</code> above.)
-         */
-        private void readObject(ObjectInputStream stream)
-                                    throws IOException, ClassNotFoundException
-        {
-            stream.defaultReadObject();
-            MarshalledObject mo = (MarshalledObject)stream.readObject();
-            try {
-                listener = (RemoteEventListener) new MarshalledInstance(mo).get(false);
-            } catch (Throwable e) {
-                problemLogger.log(Level.INFO, "problem recovering listener "
-                                  +"for recovered registration", e);
-                if((e instanceof Error) && (ThrowableConstants.retryable(e)
-                                             == ThrowableConstants.BAD_OBJECT))
-                {
-                   throw (Error)e;
-                }//endif
-            }
-        }//end readObject
-        
-        /**
-         * Must be called immediately after de-serialization to prepare
-         * proxies.
-         * 
-         * @param recoveredListenerPreparer
-         * @param recoveredLocatorToDiscoverPreparer 
-         */
-        public void prepare(ProxyPreparer recoveredListenerPreparer,
-                     ProxyPreparer recoveredLocatorToDiscoverPreparer )
-        {
-            try {
-                /* Re-prepare the recovered listener */
-                listener = (RemoteEventListener)
-                        recoveredListenerPreparer.prepareProxy(listener);
-            } catch (Throwable e) {
-                problemLogger.log(Level.INFO, "problem recovering listener "
-                                  +"for recovered registration", e);
-                if((e instanceof Error) && (ThrowableConstants.retryable(e)
-                                             == ThrowableConstants.BAD_OBJECT))
-                {
-                   throw (Error)e;
-                }//endif
-            }
-            
-            /* Prepare the locators recovered from the stream */
-            int nUnprepared = (locators).size();
-            locators = (HashSet)prepareOldLocators
-                                         ( recoveredLocatorToDiscoverPreparer,
-                                           locators );
-            if( nUnprepared != (locators).size() ) {
-                /* Failure occurred when preparing one of the locs. Because
-                 * this breaks the contract with the client, this registration
-                 * will not be recovered so that the client will eventually
-                 * be notified. To facilitate this, the listener is set to
-                 * null so that the registration will not be added to the
-                 * managed set, and so that when the client eventually attempts
-                 * to renew the lease on that registration, an exception will
-                 * occur; causing the client to be "notified" that there was
-                 * a problem with that registration. The client can then
-                 * retry the registration; and if problems still exist, the
-                 * exception the client receives may give the client more
-                 * useful information from which the client can determine
-                 * how to proceed.
-                 */
-                listener = null;
-                if( problemLogger.isLoggable(Level.WARNING) ) {
-                    problemLogger.log(Level.WARNING, "failure preparing "
-                                      +"locator while recovering registration"
-                                      +"... discarding recovered"
-                                      +"registration");
-                }//endif
-            }
-        }
-        
-    }//end class RegistrationInfo
-
-    /** This class represents a <code>Task</code> object that is placed
-     *  in the <code>TaskManager</code> queue for processing in the thread
-     *  pool. Instances of this class are placed on the task queue when
-     *  registrations are granted. 
-     *  <p>
-     *  The <code>run</code> method of this class will determine if any of
-     *  the new registration's desired lookup service(s) have already been
-     *  discovered, and will send the appropriate remote discovery event to
-     *  the registration's listener.
-     */
-    private final class NewRegistrationTask implements Runnable {
-        /** The data structure record corresponding to the new registration */
-        public final RegistrationInfo regInfo;
-        /** Constructs an instance of this class and stores the registration
-         *  information.
-         */
-        public NewRegistrationTask(RegistrationInfo regInfo) {
-            this.regInfo = regInfo;
-        }//end constructor
-        /** This method processes the information associated with the new
-         *  registration and determines, based on the current state of the
-         *  set of 'already-discovered' lookup service(s), whether to send
-         *  a <code>RemoteDiscoveryEvent</code> to the new registration's
-         *  listener.
-         */
-        public void run() {
-            concurrentObj.writeLock();
-            try {
-                logInfoTasks("NewRegistrationTask.run(): "
-                             +"new Registration added");
-                maybeSendDiscoveredEvent(regInfo,allDiscoveredRegs);
-            } finally {
-                concurrentObj.writeUnlock();
-            }
-        }//end run
-
-    }//end class NewRegistrationTask
-
-    /** This class represents a <code>Task</code> object that is placed
-     *  in the <code>TaskManager</code> queue for processing in the thread
-     *  pool. An instance of this class is placed on the task queue when a
-     *  <code>DiscoveryEvent</code> instance indicating a discovered event
-     *  is received from the local discovery process. 
-     *  <p>
-     *  The <code>run</code> method of this class will process discovery
-     *  event information and determine to which active registrations the
-     *  appropriate <code>RemoteDiscoveryEvent</code> should be sent; and
-     *  then sends that event.
-     */
-    private final class DiscoveredEventTask implements Runnable {
-        /** The local event sent by the discovery manager. */
-        public final DiscoveryEvent event;
-        /** Constructs an instance of this class and stores the event*/
-        public DiscoveredEventTask(DiscoveryEvent event) {
-            this.event = event;
-        }//end constructor
-        /** This method processes the local discovery event information and
-         *  determines, based on the current state of each active 
-         *  registration, to which such registration the appropriate
-         *  <code>RemoteDiscoveryEvent</code> should be sent. After making
-         *  the determination, the remote event appropriate for each 
-         *  registration is constructed and sent.
-         */
-        public void run() {
-            /* Get locators before sync block (no remote calls in sync block)*/
-            Map groupsMap = event.getGroups();
-            ServiceRegistrar[] regs = event.getRegistrars();
-            HashMap regMap = new HashMap(regs.length);
-            for(int i=0;i<regs.length;i++) {
-                try {
-                    LookupLocator regLoc = regs[i].getLocator();
-                    String[] regGroups = (String[])groupsMap.get(regs[i]);
-                    LocatorGroupsStruct regLocGroups
-                                  = new LocatorGroupsStruct(regLoc,regGroups);
-                    regMap.put(regs[i],regLocGroups);
-                } catch(Exception e) {
-                    problemLogger.log(Levels.FAILED,
-                                       "problem retrieving locator "
-                                      +"from discovered lookup service ... "
-                                      +"discarded the lookup service", e);
-                    discoveryMgr.discard(regs[i]);
-                }
-            }//end loop
-            /* Synchronization block -- no remote calls here */
-            concurrentObj.writeLock();
-            logInfoTasks("DiscoveredEventTask.run(): processing DISCOVERED "
-                         +"event from discovery manager");
-            try {
-                /* Update the global allDiscoveredRegs map with new pairs */
-                Set eSet = regMap.entrySet();
-                for(Iterator itr = eSet.iterator(); itr.hasNext(); ) {
-                    Map.Entry pair = (Map.Entry)itr.next();
-                    allDiscoveredRegs.put(pair.getKey(),pair.getValue());
-                }//end loop
-                /* Loop thru regInfo's, adding only those not already known */
-                for( Iterator itr=registrationByID.values().iterator();
-                                                              itr.hasNext(); )
-                {
-                    RegistrationInfo regInfo = (RegistrationInfo)itr.next();
-                    /* Build and send the "discovered event" if appropriate */
-                    maybeSendDiscoveredEvent(regInfo,regMap);
-                }//end loop
-            } finally {
-                concurrentObj.writeUnlock();
-            }
-        }//end run
-
-    }//end class DiscoveredEventTask
-
-    /** This class represents a <code>Task</code> object that is placed
-     *  in the <code>TaskManager</code> queue for processing in the thread
-     *  pool.  An instance of this class is placed on the task queue when a
-     *  <code>DiscoveryEvent</code> instance indicating a discarded event
-     *  is received from the local discovery process. 
-     *  <p>
-     *  The <code>run</code> method of this class will process event
-     *  information resulting from the "discarding" of one or more
-     *  lookup services (registrars), and will determine to which active 
-     *  registrations the appropriate <code>RemoteDiscoveryEvent</code>
-     *  should be sent; and then sends that event.
-     */
-    private final class DiscardedEventTask implements Runnable {
-        /** The local event sent by the discovery manager. */
-        public final DiscoveryEvent event;
-        /** Constructs an instance of this class and stores the event*/
-        public DiscardedEventTask(DiscoveryEvent event) {
-            this.event = event;
-        }//end constructor
-        /** This method processes the local discovery event information and
-         *  determines, based on the current state of each active 
-         *  registration, to which such registration the appropriate
-         *  <code>RemoteDiscoveryEvent</code> should be sent. After making
-         *  the determination, the remote event appropriate for each 
-         *  registration is constructed and sent.
-         */
-        public void run() {
-            concurrentObj.writeLock();
-            logInfoTasks("DiscardedEventTask.run(): processing DISCARDED "
-                         +"event from discovery manager");
-            try {
-                /* Get the registrars that were just discarded */
-                Map groupsMap = event.getGroups();
-                HashSet allDiscardedRegs = new HashSet(groupsMap.size());
-                /* Determine if we're here because of an external request for
-                 * discard from one of the regInfo's (an active communication
-                 * discard), or because the discovery manager has determined
-                 * one or more of the discovered registrars has become 
-                 * unreachable (a passive communication discard)
-                 */
-                RegistrationInfo regInfo = externalDiscardRequest();
-                /* If an external request, send the discarded event to only
-                 * the regInfo that requested the discard; otherwise, send
-                 * it to all regInfo's that might be interested.
-                 */
-                if(regInfo != null) {
-                    /* Send discard event to only this one registration */
-                    HashSet discardedRegs = maybeSendDiscardedEvent
-                                                    (regInfo,groupsMap,true);
-                    /* Transfer the just-discarded regs to the summary set */
-                    for(Iterator jtr=discardedRegs.iterator();jtr.hasNext(); ){
-                        allDiscardedRegs.add(jtr.next());
-                    }
-                } else {
-                    /* Send discard event to each "eligible" registration */
-                    for( Iterator itr=registrationByID.values().iterator();
-                                                              itr.hasNext(); )
-                    {
-                        regInfo = (RegistrationInfo)itr.next();
-                        HashSet discardedRegs = maybeSendDiscardedEvent
-                                                     (regInfo,groupsMap,false);
-                        /* Transfer the just-discarded regs to summary set */
-                        for(Iterator jtr=discardedRegs.iterator();
-                                                             jtr.hasNext(); ) {
-                            allDiscardedRegs.add(jtr.next());
-                        }
-                    }//end loop
-                }//endif
-                maybeRemoveDiscardedRegsFromGlobalSet(allDiscardedRegs);
-            } finally {
-                concurrentObj.writeUnlock();
-            }
-        }//end run
-
-        /** This method determines, based on the current state of the 
-         * <code>regInfo</code> parameter, whether or not to send a
-         * remote discarded event to the regInfo's listener, and then builds
-         * and sends the event if appropriate. This method is called in
-         * response to one of the following situations:
-         * <p>
-         * 1 after invocation of the public <code>discard</code> method
-         * 2 after receipt of a "passive" discarded event from the discovery
-         *   manager.
-         * <p>
-         * For case 1, such an event typically indicates what is referred to
-         * as an "active, communication" discarded event. This term is used
-         * in this situation because the regInfo takes the specific action
-         * of requesting that a registrar the client has determined is
-         * unreachable be discarded.
-         * <p>
-         * For case 2, such an event typically indicates what is referred to
-         * as a "passive, communication" discarded event. This term is used
-         * here because the discovery manager - not the client - has determined
-         * that one or more of the previously discovered registrars are now
-         * unreachable. In this case, the client remains "passive", and it
-         * is the discovery manager that discards the unreachable registrars
-         * and notifies the client(s).
-         * 
-         * @param regInfo    the data structure record corresponding to the 
-         *                   registration whose listener will receive the event
-         * @param groupsMap  mapping from the registrars referenced in the 
-         *                   just-received event to their corresponding set of
-         *                   member groups
-         * @param active     flag indicating whether the event is an "active"
-         *                   or a "passive" discarded event
-         *
-         * @return set of registrars that were discarded for the given regInfo
-         */
-        private HashSet maybeSendDiscardedEvent(RegistrationInfo regInfo,
-                                                Map groupsMap,
-                                                boolean active)
-        {
-            HashSet discardedRegs = new HashSet(groupsMap.size()); //return val
-            /* If no interest in groups or locators, go to next regInfo*/
-            if(     (regInfo.groups != null) && ((regInfo.groups).size() == 0)
-                 && ((regInfo.locators).size() == 0) )
-            {
-                return discardedRegs;
-            }
-            HashMap discardMap = new HashMap(groupsMap.size());
-            /* loop thru the (registrar,groups) pairs, find regs to discard */
-            Set eSet = groupsMap.entrySet();
-            for(Iterator itr = eSet.iterator(); itr.hasNext(); ) {
-                Map.Entry pair = (Map.Entry)itr.next();
-                ServiceRegistrar reg = (ServiceRegistrar)pair.getKey();
-                /* Include the current reg in the discard map only if that
-                 * reg is in the regInfo's discovered set.
-                 */
-                if( (regInfo.discoveredRegsMap).containsKey(reg) ) {
-                    /* The groups corresponding to the discarded registrar that
-                     * arrived in the event may be more up-to-date than the
-                     * groups associated with the registrar in the global map.
-                     * Thus, if the event is a passive communication discarded
-                     * event, when determining whether the regInfo is still
-                     * interested in the discarded registrar, use the old group
-                     * info rather than the group info sent in the event.
-                     */
-                    String[] regGroups = (active ? (String[])pair.getValue() :
-                    ((LocatorGroupsStruct)allDiscoveredRegs.get(reg)).groups );
-
-                    if( active || interested(regGroups,regInfo.groups) ) {
-                        discardMap.put(reg,regGroups);
-                        discardedRegs.add(reg);
-                        (regInfo.discoveredRegsMap).remove(reg);
-                    }//end if
-                }//end if
-            }//end loop
-            /* Build and send the "discarded event" */
-            RemoteDiscoveryEvent event = buildEvent(regInfo,discardMap,true);
-            if(event != null) {
-                queueEvent(regInfo,event);
-                logInfoEvents("DiscardedEventTask.run(): "
-                              +"DISCARDED Event SENT to regInfo\n");
-            }
-            return discardedRegs;
-        }//end maybeSendDiscardedEvent
-
-    }//end class DiscardedEventTask
-
-    /** This class represents a <code>Task</code> object that is placed
-     *  in the <code>TaskManager</code> queue for processing in the thread
-     *  pool. Instances of this class are placed on the task queue when
-     *  registrations request that a given registrar be discarded. 
-     *  <p>
-     *  The <code>run</code> method of this class will remove the indicated
-     *  registrar from the registration's set of discovered registrars and
-     *  if successfully removed, will build and send a remote discarded event
-     *  to the registration's listener.
-     */
-    private final class DiscardRegistrarTask implements Runnable {
-        /** Data structure record corresponding to the registration that has
-         *  requested to have one of its discovered registrars discarded
-         */
-        public final RegistrationInfo regInfo;
-        /** The registrar to discard */
-        public final ServiceRegistrar registrar;
-        /** Constructs an instance of this class and stores the registration
-         *  information.
-         */
-        public DiscardRegistrarTask(RegistrationInfo regInfo,
-                                    ServiceRegistrar registrar)
-        {
-            this.regInfo   = regInfo;
-            this.registrar = registrar;
-        }//end constructor
-        /** This method attempts to remove the indicated registrar from
-         *  the registration's set of discovered registrars. If successful,
-         *  this method builds and sends a remote discarded event to the
-         *  registration's listener.
-         */
-        public void run() {
-            concurrentObj.writeLock();
-            try {
-                logInfoTasks("DiscardRegistrarTask.run(): "
-                             +"registrar requested to be discarded");
-                /* Remove registrar from regInfo's set and send event */
-                if( (regInfo.discoveredRegsMap).remove(registrar) != null) {
-                    HashMap groupsMap = mapRegToGroups(registrar,
-               ((LocatorGroupsStruct)allDiscoveredRegs.get(registrar)).groups);
-
-                    RemoteDiscoveryEvent event = buildEvent
-                                                      (regInfo,groupsMap,true);
-                    if(event != null) {
-                        queueEvent(regInfo,event);
-                        logInfoEvents("DiscardRegistrarTask.run(): "
-                                      +"DISCARDED Event was SENT\n");
-                    }//endif
-                    maybeRemoveDiscardedRegFromGlobalSet(registrar);
-                }
-            } finally {
-                concurrentObj.writeUnlock();
-            }
-        }//end run
-    }//end class DiscardRegistrarTask
-
-    /** This class represents a <code>Task</code> object that is placed
-     *  in the <code>TaskManager</code> queue for processing in the thread
-     *  pool.  An instance of this class is placed on the task queue when a
-     *  <code>DiscoveryEvent</code> instance indicating a changed event
-     *  is received from the local discovery process. 
-     *  <p>
-     *  The <code>run</code> method of this class will process event
-     *  information resulting from a change in the state of the member
-     *  groups of one or more lookup services (registrars). This task
-     *  analyzes the group information in the event and, based on that
-     *  information, determines which active registrations are no longer
-     *  interested in the registrars referenced in the event. A
-     *  <code>RemoteDiscoveryEvent</code> indicating a discarded event
-     *  will be sent to each active registration that has lost interest
-     *  in any of the registrars of the event.
-     */
-    private final class ChangedEventTask implements Runnable {
-        /** The local event sent by the discovery manager. */
-        public final DiscoveryEvent event;
-        /** Constructs an instance of this class and stores the event*/
-        public ChangedEventTask(DiscoveryEvent event) {
-            this.event = event;
-        }//end constructor
-        /** This method processes the local discovery event information and
-         *  determines, based on the current state of each active 
-         *  registration, to which such registration the appropriate
-         *  <code>RemoteDiscoveryEvent</code> should be sent. After making
-         *  the determination, the remote event appropriate for each 
-         *  registration is constructed and sent.
-         */
-        public void run() {
-            concurrentObj.writeLock();
-            logInfoTasks("ChangedEventTask.run(): processing CHANGED "
-                         +"event from discovery manager");
-            try {
-                Map groupsMap = event.getGroups();
-                HashSet allDiscardedRegs = new HashSet(groupsMap.size());
-                HashMap locatorMap = new HashMap(groupsMap.size());
-                /* Retrieve the locators of each registrar in the event */
-                for(Iterator itr = (groupsMap.keySet()).iterator();
-                                                            itr.hasNext(); )
-                {
-                    ServiceRegistrar reg = (ServiceRegistrar)itr.next();
-                    locatorMap.put(reg,
-                    ((LocatorGroupsStruct)allDiscoveredRegs.get(reg)).locator);
-                }//end loop
-
-                for( Iterator itr=registrationByID.values().iterator();
-                                                              itr.hasNext(); )
-                {
-                    RegistrationInfo regInfo = (RegistrationInfo)itr.next();
-                    HashSet discardedRegs = maybeSendDiscardedEvent
-                                                (regInfo,groupsMap,locatorMap);
-                    /* Transfer the just-discarded regs to the summary set */
-                    for(Iterator jtr=discardedRegs.iterator();jtr.hasNext(); ){
-                        allDiscardedRegs.add(jtr.next());
-                    }//end loop
-                }//end loop
-                maybeRemoveDiscardedRegsFromGlobalSet(allDiscardedRegs);
-                updateGroupsInGlobalSet(groupsMap); //replace with new groups
-            } finally {
-                concurrentObj.writeUnlock();
-            }
-        }//end run
-
-        /** This method determines, based on the current state of the 
-         * <code>regInfo</code> parameter, whether or not to send a
-         * remote discarded event to the regInfo's listener, and then builds
-         * and sends the event if appropriate. This method is called in
-         * response to the receipt of a changed event from the discovery
-         * manager. 
-         * <p>
-         * Such an event may indicate what is referred to as a
-         * "passive, no interest" discard; passive because the event 
-         * resulted from action taken by the discovery manager rather than
-         * the client, and no interest because the discovery manager sends
-         * such an event when it determines that one or more of the 
-         * previously discovered registrars - although still reachable -
-         * have changed their member groups in such a way that they may
-         * now be of no interest to one or more of the client registrations.
-         * <p>
-         * Note that changed events can be sent for registrars having a
-         * locator and member groups that the current regInfo never asked
-         * to be discovered. This can happen because some other regInfo
-         * asked that the registrar's locator or groups be discovered. 
-         * <p>
-         * If a particular registrar is contained in the discovered set 
-         * of the given regInfo, then we know that that regInfo must
-         * have requested discovery of the registrar (through either
-         * locator or group discovery). If the registrar is not contained
-         * in that set, then there's no need to proceed with the processing
-         * of the registrar since we don't want to send a discarded event
-         * to a regInfo that was never interested in that registrar in the
-         * first place.
-         * <p>
-         * If the locator of the registrar is contained in the regInfo's
-         * set of locators to discover, then that regInfo is considered
-         * "still interested" in the registrar; and so no discarded event
-         * is sent to the regInfo.
-         * <p>
-         * Thus, a discarded event is sent to the given regInfo only
-         * if the regInfo is not interested in discovering the registrar
-         * through locator discovery, and the registrar's member groups have
-         * changed in such a way that it now belongs to groups that
-         * the regInfo is not interested in discovering and joining.
-         *
-         * @param regInfo    the data structure record corresponding to the 
-         *                   registration whose listener will receive the event
-         * @param groupsMap  mapping from the registrars referenced in the 
-         *                   just-received event to their corresponding set of
-         *                   member groups
-         * @param locatorMap mapping from the registrars referenced in the 
-         *                   just-received event to their corresponding locator
-         *
-         * @return the registrars that were discarded for the given regInfo
-         */
-        private HashSet maybeSendDiscardedEvent(RegistrationInfo regInfo,
-                                                Map groupsMap,
-                                                Map locatorMap)
-        {
-            /* For each registrar discard candidate, send a discarded event if:
-             *   The candidate is in the discovered set and
-             *    a. regInfo is configured for at least group discovery
-             *    b. candidate is NOT to be discovered by locator discovery
-             *    c. regInfo is no longer interested in the candidate's groups
-             */
-            HashSet discardedRegs = new HashSet(groupsMap.size()); //return val
-            /* If this regInfo isn't interested in groups, go to next regInfo*/
-            if( (regInfo.groups != null) && ((regInfo.groups).size() == 0) )
-            {
-                return discardedRegs;
-            }
-            HashMap discardMap = new HashMap(groupsMap.size());
-            /* loop thru the (registrar,groups) pairs, find regs to discard */
-            Set eSet = groupsMap.entrySet();
-            for(Iterator itr = eSet.iterator(); itr.hasNext(); ) {
-                Map.Entry pair = (Map.Entry)itr.next();
-                ServiceRegistrar reg = (ServiceRegistrar)pair.getKey();
-                String[] regGroups = (String[])pair.getValue();
-                LookupLocator regLoc = (LookupLocator)locatorMap.get(reg);
-                /* Include the current reg in the discard map only if that
-                 * reg is in the regInfo's discovered set, the regInfo
-                 * is not interested in discovering the reg through locator
-                 * discovery, and the reg's member groups have changed in
-                 * such a way that it now belongs to groups that the regInfo
-                 * is not interested in discovering and joining.
-                 */
-                if(    ( (regInfo.discoveredRegsMap).containsKey(reg) )
-                    && (!interested(regLoc,regGroups,
-                                         regInfo.locators,regInfo.groups)) )
-                {
-                    discardMap.put(reg,regGroups);
-                    discardedRegs.add(reg);
-                    (regInfo.discoveredRegsMap).remove(reg);
-                }
-            }//end loop
-            /* Build and send the "discarded event" */
-            RemoteDiscoveryEvent event = buildEvent(regInfo,discardMap,true);
-            if(event != null) {
-                queueEvent(regInfo,event);
-                logInfoEvents("ChangedEventTask.run(): "
-                              +"DISCARDED Event was SENT\n");
-            }//endif
-            return discardedRegs;
-        }//end maybeSendDiscardedEvent
-    }//end class ChangedEventTask
-
-    /** This class represents a <code>Task</code> object that is placed
-     *  in the <code>TaskManager</code> queue for processing in the thread
-     *  pool. Instances of this class are placed on the task queue when
-     *  a registration has requested the augmentation of the set of groups
-     *  that currently will be discovered for it.
-     */
-    private final class AddGroupsTask implements Runnable {
-        /** Data structure record of the registration that made the request */
-        public final RegistrationInfo regInfo;
-        /** The group set with which to replace the registration's old set */
-        public final String[] groups;
-        /** Constructs an instance of this class and stores the input */
-        public AddGroupsTask(RegistrationInfo regInfo, String[] groups) {
-            this.regInfo = regInfo;
-            this.groups  = groups;
-        }//end constructor
-        public void run() {
-            /* For the regInfo associated with the current instance of this
-             * task, do the following:
-             * a. in the given regInfo data structure, add the new groups,
-             *    with duplicates removed, to that regInfo's current set of
-             *    desired groups
-             * b. from the global mapping of all currently discovered 
-             *    registrars to (locator,groups) pairs, retrieve the elements
-             *    that contain registrars belonging to groups that regInfo
-             *    should now be interested in as a result of the call to
-             *    addGroups
-             * c. for each registrar-to-(locator,groups) mapping retrieved in
-             *    b. above, add that mapping to the given regInfo data
-             *    structure's discovered state (these are the registrars that
-             *    were previously discovered for OTHER regInfo's, not the
-             *    current regInfo)
-             * d. for each of the registrars previously discovered for other
-             *    registrations that belong to any of the new groups regInfo
-             *    is now interested in as a result of the call to addGroups,
-             *    queue a remote discovery event to be sent to that regInfo's
-             *    listener
-             * e. if any of the new groups regInfo is now interested in as
-             *    as a result of the call to addGroups were not previously
-             *    in the local discovery manager's managed set of groups,
-             *    (and the local discovery manager is currently not configured
-             *    to discover ALL_GROUPS), add the new groups to the local
-             *    discovery manager so that when that manager does discover
-             *    one of those groups in the future, a remote discovered
-             *    event will be sent to the given regInfo's listener
-             */
-            concurrentObj.writeLock();
-            try {
-                HashSet newGroupSet = addRegInfoGroups(regInfo,groups);  // a.
-                if(newGroupSet.size() > 0) {
-                    logInfoTasks("AddGroupsTask.run(): adding to the "
-                                 +"registration's groups");
-                    HashMap discoveredRegs = getDesiredRegsByGroup
-                                                              (regInfo); // b.
-                    HashMap regsAdded = regInfo.addToDiscoveredRegs
-                                                       (discoveredRegs); // c.
-                    RemoteDiscoveryEvent event = buildEvent
-                                              (regInfo,regsAdded,false); // d.
-                    if(event != null) {
-                        queueEvent(regInfo,event);                       // d.
-                        logInfoEvents("AddGroupsTask.run(): DISCOVERED "
-                                      +"Event was SENT\n");
-                    }//endif
-                    updateDiscoveryMgrGroups();                          // e.
-                }//endif(newGroupSet.size() > 0)
-            } finally {
-                concurrentObj.writeUnlock();
-            }
-        }//end run
-
-        /** Augments the registration's managed set of groups with the new
-         *  groups.
-         *
-         * @return the set of new groups added to regInfo's desired groups
-         */
-        private HashSet addRegInfoGroups(RegistrationInfo regInfo,
-                                         String[] groups)
-        {
-            /* Build a HashSet (removes duplicates) from the input groups */
-            HashSet newGroupSet = new HashSet(1);
-            for(int i=0;i<groups.length;i++) {
-                newGroupSet.add(groups[i]);
-            }//end loop
-            /* If the input set was not empty, add the new groups to the 
-             * registration's managed set of groups.
-             */
-            if( newGroupSet.size() > 0 ) {
-                (regInfo.groups).addAll(newGroupSet);
-            }//endif
-            return newGroupSet;
-        }//end addRegInfoGroups
-
-    }//end class AddGroupsTask
-
-    /** This class represents a <code>Task</code> object that is placed
-     *  in the <code>TaskManager</code> queue for processing in the thread
-     *  pool. Instances of this class are placed on the task queue when
-     *  a registration has requested the replacement of the set of groups
-     *  that currently will be discovered for it.
-     */
-    private final class SetGroupsTask implements Runnable {
-        /** Data structure record of the registration that made the request */
-        public final RegistrationInfo regInfo;
-        /** The group set with which to replace the registration's old set */
-        public final String[] groups;
-        /** Constructs an instance of this class and stores the input */
-        public SetGroupsTask(RegistrationInfo regInfo, String[] groups) {
-            this.regInfo = regInfo;
-            this.groups  = groups;
-        }//end constructor
-        public void run() {
-            /* For the regInfo associated with the current instance of this
-             * task, do the following:
-             * a. from the global mapping of all currently discovered 
-             *    registrars to their (locator,groups) pair, retrieve the
-             *    elements that contain registrars belonging to groups that
-             *    regInfo was interested in PRIOR to the call to setGroups
-             * b. in the given regInfo data structure, replace that regInfo's
-             *    current set of desired groups with the new set of desired
-             *    groups that resulted from the call to setGroups
-             * c. again from the global mapping of all currently discovered 
-             *    registrars to (locator,groups) pairs, retrieve the elements
-             *    that contain registrars belonging to groups that regInfo
-             *    should now be interested in as a result of the call to
-             *    setGroups
-             * d. for each registrar-to-(locator,groups) mapping retrieved in
-             *    c. above, add that mapping to the given regInfo data
-             *    structure's state (these are the registrars that were
-             *    previously discovered for OTHER regInfo's, not the current
-             *    regInfo)
-             * e. for each of the registrars previously discovered for other
-             *    registrations that belong to any of the new groups regInfo
-             *    is now interested in as a result of the call to setGroups,
-             *    queue a remote discovery event to be sent to that regInfo's
-             *    listener
-             * f. from the mapping of already-discovered registrars that 
-             *    regInfo was interested in prior to the call to setGroups
-             *    (the mapping retrieved in a. above), retrieve the elements
-             *    that contain registrars belonging to groups that regInfo is
-             *    no longer interested in due to the call to setGroups
-             * g. for each registrar-to-(locator,groups) mapping retrieved in
-             *    f. above, remove that mapping from the given regInfo data
-             *    structure's state, and queue a remote discarded event to be
-             *    sent to that regInfo's listener
-             * h. if any of the new groups regInfo is now interested in as
-             *    as a result of the call to setGroups were not previously
-             *    in the local discovery manager's managed set of groups,
-             *    add those groups to that discovery manager so that when
-             *    that manager does discover one of those groups in the  
-             *    future, a remote discovered event will be sent to the given
-             *    regInfo's listener
-             */
-            concurrentObj.writeLock();
-            try {
-                logInfoTasks("SetGroupsTask.run(): setting the "
-                             +"registration's groups");
-                Map oldDesiredRegs = getDesiredRegsByGroup(regInfo);     // a.
-                setRegInfoGroups(regInfo,groups);                        // b.
-                HashMap newDesiredRegs = getDesiredRegsByGroup(regInfo); // c.
-                HashMap regsAdded = regInfo.addToDiscoveredRegs
-                                                       (newDesiredRegs); // d.
-                RemoteDiscoveryEvent event = buildEvent
-                                              (regInfo,regsAdded,false); // e.
-                if(event != null) {
-                    queueEvent(regInfo,event);                           // e.
-                    logInfoEvents("SetGroupsTask.run(): DISCOVERED "
-                                  +"Event was SENT\n");
-                }//endif
-                Map discardRegs = getUndesiredRegsByGroup
-                                               (oldDesiredRegs,regInfo); // f.
-                for(Iterator itr = (discardRegs.keySet()).iterator();
-                                                             itr.hasNext(); )
-                {
-                    (regInfo.discoveredRegsMap).remove(itr.next());     // g.
-                }//end loop
-                event = buildEvent(regInfo,discardRegs,true);           // g.
-                if(event != null) {
-                    queueEvent(regInfo,event);                          // g.
-                    logInfoEvents("SetGroupsTask.run(): "
-                                  +"DISCARDED Event was SENT\n");
-                }//endif
-                updateDiscoveryMgrGroups();                             // h.
-            } finally {
-                concurrentObj.writeUnlock();
-            }
-        }//end run
-
-        /** Replaces the registration's managed set of groups with the new
-         *  groups (even if the new set of groups is empty -- this just means
-         *  group discovery will be "turned off" for this registration).
-         */
-        private void setRegInfoGroups(RegistrationInfo regInfo,
-                                      String[] groups)
-        {
-            if(groups == DiscoveryGroupManagement.ALL_GROUPS) {
-                regInfo.groups = null;
-            } else {
-                /* Build a HashSet from the input set */
-                HashSet newGroups = new HashSet();
-                for(int i=0;i<groups.length;i++) {
-                    newGroups.add(groups[i]);
-                }//end loop
-                /* Prepare the registration's managed set for replacement */
-                if(regInfo.groups == null) {
-                    regInfo.groups = new HashSet();
-                } else {
-                    (regInfo.groups).clear();
-                }//endif
-                /* Replace the registration's managed set with the new set */
-                (regInfo.groups).addAll(newGroups);
-            }//end if (groups == DiscoveryGroupManagement.ALL_GROUPS)
-        }//end setRegInfoGroups
-    }//end class SetGroupsTask
-
-    /** This class represents a <code>Task</code> object that is placed
-     *  in the <code>TaskManager</code> queue for processing in the thread
-     *  pool. Instances of this class are placed on the task queue when
-     *  a registration has requested the removal of a set of groups from
-     *  the current set of groups to discover for it.
-     */
-    private final class RemoveGroupsTask implements Runnable {
-        /** Data structure record of the registration that made the request */
-        public final RegistrationInfo regInfo;
-        /** The groups to remove from the registration's old set */
-        public final String[] groups;
-        /** Constructs an instance of this class and stores the input */
-        public RemoveGroupsTask(RegistrationInfo regInfo, String[] groups) {
-            this.regInfo = regInfo;
-            this.groups  = groups;
-        }//end constructor
-        public void run() {
-            concurrentObj.writeLock();
-            try {
-                if(groups.length == 0) return; // nothing from which to remove
-               logInfoTasks("RemoveGroupsTask.run(): removing groups from "
-                            +"the registration's current group set");
-                /* regInfo's discovered regs (by group) previously desired */
-                Map oldDesiredRegs = getDesiredRegsByGroup(regInfo);
-                /* update regInfo's desired regs */
-                removeRegInfoGroups(regInfo,groups);
-                /* regInfo's discovered regs (by group) no longer desired */
-                Map discardRegs = getUndesiredRegsByGroup(oldDesiredRegs,
-                                                          regInfo);
-                /* remove regInfo's undesired regs from its discovered map */
-                for(Iterator itr = (discardRegs.keySet()).iterator();
-                                                              itr.hasNext(); )
-                {
-                    (regInfo.discoveredRegsMap).remove(itr.next());
-                }//end loop
-                RemoteDiscoveryEvent event = buildEvent
-                                                    (regInfo,discardRegs,true);
-                if(event != null) {
-                    queueEvent(regInfo,event);
-                    logInfoEvents("RemoveGroupsTask.run(): "
-                                  +"DISCARDED Event was SENT\n");
-                }//endif
-                updateDiscoveryMgrGroups(); // may send more discards
-            } finally {
-                concurrentObj.writeUnlock();
-            }
-        }//end run
-
-        /** Removes the elements of the given set from the given registration's
-         *  current set of groups to discover.
-         */
-        private void removeRegInfoGroups(RegistrationInfo regInfo,
-                                         String[] groups)
-        {
-            HashSet<String> removeSet = new HashSet<String>();
-            int l = groups.length;
-            for(int i = 0; i < l; i++) {
-                removeSet.add(groups[i]);
-            }//end loop
-            (regInfo.groups).removeAll(removeSet);
-        }//end setRegInfoGroups
-
-    }//end class RemoveGroupsTask
-
-    /** This class represents a <code>Task</code> object that is placed
-     *  in the <code>TaskManager</code> queue for processing in the thread
-     *  pool. Instances of this class are placed on the task queue when
-     *  a registration has requested the augmentation of the set of locators
-     *  that currently will be discovered for it.
-     */
-    private final class AddLocatorsTask implements Runnable {
-        /** Data structure record of the registration that made the request */
-        public final RegistrationInfo regInfo;
-        /** The locator set with which to replace the registration's old set */
-        public final LookupLocator[] locators;
-        /** Constructs an instance of this class and stores the input */
-        public AddLocatorsTask(RegistrationInfo regInfo,
-                               LookupLocator[]  locators)
-        {
-            this.regInfo = regInfo;
-            this.locators  = locators;
-        }//end constructor
-        public void run() {
-            /* For the regInfo associated with the current instance of this
-             * task, do the following:
-             * a. in the given regInfo data structure, add the new locators,
-             *    with duplicates removed, to that regInfo's current set of
-             *    desired locators
-             * b. from the global mapping of all currently discovered 
-             *    registrars to (locator,groups) pairs, retrieve the elements
-             *    that contain registrars having locators that regInfo
-             *    should now be interested in as a result of the call to
-             *    addLocators
-             * c. for each registrar-to-(locator,groups) mapping retrieved in
-             *    b. above, add that mapping to the given regInfo data
-             *    structure's discovered state (these are the registrars that
-             *    were previously discovered for OTHER regInfo's, not the
-             *    current regInfo)
-             * d. for each of the registrars previously discovered for other
-             *    registrations that have locators equal to any of the new
-             *    locators regInfo is now interested in as a result of the
-             *    call to addLocators, queue a remote discovery event to be
-             *    sent to that regInfo's listener
-             * e. if any of the new locators regInfo is now interested in as
-             *    as a result of the call to addLocators were not previously
-             *    in the local discovery manager's managed set of locators,
-             *    add the new locators to the local discovery manager so that
-             *    when that manager does discover one of those locators in
-             *    the future, a remote discovered event will be sent to the
-             *    given regInfo's listener
-             */
-            concurrentObj.writeLock();
-            try {
-                HashSet newLocSet = addRegInfoLocators(regInfo,locators);// a.
-                if(newLocSet.size() > 0) {
-                    logInfoTasks("AddLocatorsTask.run(): adding to the "
-                                 +"registration's locators");
-                    HashMap discoveredRegs = getDesiredRegsByLocator
-                                                              (regInfo); // b.
-                    HashMap regsAdded = regInfo.addToDiscoveredRegs
-                                                       (discoveredRegs); // c.
-                    RemoteDiscoveryEvent event = buildEvent
-                                              (regInfo,regsAdded,false); // d.
-                    if(event != null) {
-                        queueEvent(regInfo,event);                       // d.
-                        logInfoEvents("AddLocatorsTask.run(): DISCOVERED "

[... 14593 lines stripped ...]