Package com.sun.jini.mahalo

Source Code of com.sun.jini.mahalo.JoinStateManager

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

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.rmi.MarshalledObject;
import java.rmi.RemoteException;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import net.jini.config.Configuration;
import net.jini.config.ConfigurationException;
import net.jini.core.discovery.LookupLocator;
import net.jini.core.entry.Entry;
import net.jini.core.lookup.ServiceID;
import net.jini.discovery.DiscoveryManagement;
import net.jini.discovery.DiscoveryLocatorManagement;
import net.jini.discovery.DiscoveryGroupManagement;
import net.jini.discovery.LookupDiscoveryManager;
import net.jini.id.Uuid;
import net.jini.lookup.JoinManager;
import net.jini.lookup.ServiceIDListener;
import net.jini.security.ProxyPreparer;


import com.sun.jini.config.Config;
import com.sun.jini.logging.Levels;
import com.sun.jini.reliableLog.LogHandler;
import com.sun.jini.reliableLog.ReliableLog;

/**
* <code>JoinStateManager</code> provides a utility that manages
* a service's join state (optionally persisting that state) and
* manages the join protocol protocol on behalf of the service.
*
* @author Sun Microsystems, Inc.
*
* @see net.jini.lookup.ServiceIDListener
* @see com.sun.jini.reliableLog.LogHandler
*/
class JoinStateManager extends LogHandler {
    /** Logger for logging initialization related messages */
    private static final Logger initlogger = TxnManagerImpl.initLogger;

    /** Logger for logging operations related messages */
    private static final Logger operationsLogger = TxnManagerImpl.operationsLogger;

     /** Logger for transaction persistence related messages */
    private static final Logger persistenceLogger = TxnManagerImpl.persistenceLogger;

    /** <code>ProxyPreparer</code> for <code>LookupLocators</code> */
    private ProxyPreparer lookupLocatorPreparer;

    /**
     * Object used to find lookups. Has to implement DiscoveryManagement
     * and DiscoveryLocatorManagement as well as DiscoveryGroupManagement.
     */
    private DiscoveryManagement dm;

    /**
     * <code>JoinManager</code> that is handling the details of binding
     * into Jini lookup services.
     */
    private JoinManager  mgr;

    /**
     * The object coordinating our persistent state.
     */
    private ReliableLog log;

    /**
     * The join state, this data needs to be persisted between restarts
     */
    private Entry[]    attributes;
    private LookupLocator[]  locators;
    private String[]    groups;

    /** Service's internal <code>Uuid</code> which needs to be persisted */
    private Uuid    serviceUuid;
   
    /**
     * Conceptually, true if this is the first time this
     * service has come up, implemented as if there was
     * no previous state then this is the first time.
     */
    private boolean initial = true;
   
    /**
     * Simple constructor.
     */
    JoinStateManager(String logPath) throws IOException {
        super();
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.entering(JoinStateManager.class.getName(),
          "JoinStateManager", logPath);
  }
  this.log = (logPath==null) ? null : new ReliableLog(logPath, this);
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.exiting(JoinStateManager.class.getName(),
          "JoinStateManager");
  }
    }
   
    void recover() throws IOException {
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.entering(JoinStateManager.class.getName(),
          "recover");
  }
  if (log != null) log.recover();
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.exiting(JoinStateManager.class.getName(),
          "recover");
  }
    }
    /**
     * Start the manager. Start looking for lookup and registering
     * with them.
     * @param config object to use to obtain
     *               <code>DiscoveryManagement</code> object, and if
     *               this is the initial incarnation of this service,
     *               the object used to get the initial set of groups,
     *               locators, and deployer defined attributes.
     * @param service The proxy object to register with lookups.
     * @param baseAttributes Any attributes the implementation wants
     *                       attached, only used if this is the
     *                       initial incarnation.
     * @throws IOException if the is problem persisting the
     *         initial state or in starting discovery.
     * @throws ConfigurationException if the configuration
     *         is invalid.
     */
    void startManager(Configuration config, Object service,
          ServiceID serviceID, Entry[] baseAttributes)
  throws IOException, ConfigurationException
    {
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.entering(JoinStateManager.class.getName(),
          "startManager",
          new Object[] { config, service, serviceID,
        Arrays.asList(baseAttributes)});
  }
  if (serviceID == null || serviceUuid == null)
            throw new AssertionError(
         "serviceID and serviceUuid must be set");
   
        // Default do nothing preparer
        final ProxyPreparer defaultPreparer =
            new net.jini.security.BasicProxyPreparer();
        lookupLocatorPreparer =
            (ProxyPreparer)Config.getNonNullEntry(config,
                TxnManager.MAHALO, "lookupLocatorPreparer",
                ProxyPreparer.class, defaultPreparer);
        if(initlogger.isLoggable(Level.CONFIG)) {
      initlogger.log(Level.CONFIG, "lookupLocatorPreparer: {0}",
           lookupLocatorPreparer);
  }
//TODO - defer creation of default LDM
  dm = (DiscoveryManagement)
      Config.getNonNullEntry(config, TxnManager.MAHALO,
    "discoveryManager", DiscoveryManagement.class,
    new LookupDiscoveryManager(
                    DiscoveryGroupManagement.NO_GROUPS, null, null, config));
        if(initlogger.isLoggable(Level.CONFIG)) {
      initlogger.log(Level.CONFIG, "discoveryManager: {0}", dm);
  }

  if (dm instanceof DiscoveryGroupManagement) {
      // Verify proper initial state ---> NO_GROUPS
            String[] groups =
                       ((DiscoveryGroupManagement)dm).getGroups();
            if( (groups == DiscoveryGroupManagement.ALL_GROUPS) ||
          (groups.length != 0) )
            {
                throw new ConfigurationException(
        "discoveryManager entry must be configured " +
        "to initially discover/join NO_GROUPS");
            }//endif
   
        } else {
            throw new ConfigurationException("Entry for component " +
    TxnManager.MAHALO + ", name " +
    "discoveryManager must implement " +
          "net.jini.discovery.DiscoveryGroupManagement");
  }
 
  if (dm instanceof DiscoveryLocatorManagement) {
            LookupLocator[] locs =
                    ((DiscoveryLocatorManagement)dm).getLocators();
            if( (locs != null) && (locs.length != 0) ) {
                throw new ConfigurationException
                    ("discoveryManager entry must be initially"
        + "configured with no locators");
            }//endif
  } else {
      throw new ConfigurationException("Entry for component " +
    TxnManager.MAHALO + ", name " +
    "discoveryManager must implement " +
    "net.jini.discovery.DiscoveryLocatorManagement");
  }

  // if this is the first incarnation, consult config for groups,
  // locators and attributes.
  if (initial) {
            if(initlogger.isLoggable(Level.FINEST)) {
          initlogger.log(Level.FINEST, "Obtaining initial values");
      }
      groups = (String[])
    config.getEntry(TxnManager.MAHALO,
        "initialLookupGroups", String[].class,
        new String[] { "" }); //default to public group
            if(initlogger.isLoggable(Level.CONFIG)) {
          initlogger.log(Level.CONFIG, "Obtaining initial groups: {0}",
    (groups==null?
        Arrays.asList(new String[] {"<ALL_GROUPS>"}):
        Arrays.asList(groups)));
      }
      locators = (LookupLocator[])
    Config.getNonNullEntry(config, TxnManager.MAHALO,
         "initialLookupLocators", LookupLocator[].class,
                     new LookupLocator[0]);
            if(initlogger.isLoggable(Level.CONFIG)) {
          initlogger.log(Level.CONFIG, "Obtaining initial locators: {0}",
    Arrays.asList(locators));
      }
      final Entry[] cAttrs = (Entry[])
    Config.getNonNullEntry(config, TxnManager.MAHALO,
        "initialLookupAttributes", Entry[].class, new Entry[0]);
            if(initlogger.isLoggable(Level.CONFIG)) {
          initlogger.log(Level.CONFIG, "Obtaining initial attributes: {0}",
    Arrays.asList(cAttrs));
      }
      if (cAttrs.length == 0) {
    attributes = baseAttributes;
      } else {
    attributes = new Entry[cAttrs.length + baseAttributes.length];
                System.arraycopy(baseAttributes, 0, attributes,
                                 0, baseAttributes.length);
                System.arraycopy(cAttrs, 0, attributes,
                                 baseAttributes.length, cAttrs.length);
      }
            if(initlogger.isLoggable(Level.FINEST)) {
          initlogger.log(Level.FINEST, "Combined attributes: {0}",
    Arrays.asList(attributes));
      }

        } else {
            /* recovery : if there are any locators get and
             * use recoveredLookupLocatorPreparer
             */
            if(initlogger.isLoggable(Level.FINEST)) {
          initlogger.log(Level.FINEST, "Recovered locators: {0}",
    Arrays.asList(locators));
      }
            if (locators.length > 0) {
                final ProxyPreparer recoveredLookupLocatorPreparer =
                    (ProxyPreparer)Config.getNonNullEntry(config,
                        TxnManager.MAHALO,
                        "recoveredLookupLocatorPreparer", ProxyPreparer.class,
                         defaultPreparer);
                if(initlogger.isLoggable(Level.CONFIG)) {
              initlogger.log(Level.CONFIG, "recoveredLookupLocatorPreparer: {0}",
        recoveredLookupLocatorPreparer);
                }
    final List prepared = new java.util.LinkedList();
                for (int i=0; i<locators.length; i++) {
                    try {
                        prepared.add(recoveredLookupLocatorPreparer.
                                     prepareProxy(locators[i]));
                    } catch (Throwable t) {
                        if(initlogger.isLoggable(Levels.HANDLED)) {
                      initlogger.log(Levels.HANDLED,
          "Exception re-preparing LookupLocator: {0}. "
              + "Dropping locator.",
          locators[i]);
      }
                        if(initlogger.isLoggable(Levels.HANDLED)) {
                      initlogger.log(Levels.HANDLED,
          "Preparer exception: ", t);
      }
                    }
                }
                locators =
                    (LookupLocator[])prepared.toArray(new LookupLocator[0]);
      }
  }

  // Now that we have groups & locators (either from
  // a previous incarnation or from the config) start discovery.
        if(initlogger.isLoggable(Level.FINEST)) {
      initlogger.log(Level.FINEST, "Setting groups and locators");
  }
  ((DiscoveryGroupManagement)dm).setGroups(groups);
  ((DiscoveryLocatorManagement)dm).setLocators(locators);

        if(initlogger.isLoggable(Level.FINEST)) {
      initlogger.log(Level.FINEST, "Creating JoinManager");
        }
  mgr = new JoinManager(service, attributes, serviceID,
            dm, null, config);
        // Once we are running we don't need the attributes,
        // locators, and groups fields, null them out (the
        // state is in the mgr and dm.
        attributes = null;
        groups = null;
        locators = null;

  // Now that we have state, make sure it is written to disk.
        if(initlogger.isLoggable(Level.FINEST)) {
      initlogger.log(Level.FINEST, "Taking snapshot");
  }
  update();
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.exiting(JoinStateManager.class.getName(),
          "startManager");
  }
    }

    public void setServiceUuid(Uuid serviceUuid) {
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.entering(JoinStateManager.class.getName(),
          "setServiceUuid", serviceUuid);
  }
  if (serviceUuid == null)
            throw new NullPointerException("serviceUuid can't be null");
        this.serviceUuid = serviceUuid;
  // Can't update until mgr & dm are started.
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.exiting(JoinStateManager.class.getName(),
          "setServiceUuid");
  }
    }
   
    public Uuid getServiceUuid() {
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.entering(JoinStateManager.class.getName(),
          "getServiceUuid");
  }
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.exiting(JoinStateManager.class.getName(),
          "getServiceUuid", serviceUuid);
  }
        return serviceUuid;
    }

    /**
     * Make a good faith attempt to terminate
     * discovery, and cancel any lookup registrations.  */
    public void stop() {
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.entering(JoinStateManager.class.getName(),
          "stop");
  }
  // Unregister with lookup

  // Terminate the JoinManager first so it will not call
  // into the dm after it has been terminated.
  if (mgr != null)
      mgr.terminate();

  if (dm != null)
      dm.terminate();
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.exiting(JoinStateManager.class.getName(),
          "stop");
  }
    }

    public void destroy() {
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.entering(JoinStateManager.class.getName(),
          "destroy");
  }
  stop();
  if (log != null)
      log.deletePersistentStore();
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.exiting(JoinStateManager.class.getName(),
          "destroy");
  }
    }

    /* Basically we are implementing JoinAdmin, for get methods we just
     * delegate to JoinManager, for the set methods we call
     * JoinManager to and then persist the change by calling the
     * appropriate method on our JoinAdminState.  If the call on our
     * JoinAdminState throws an IOException we throw a runtime
     * exception since JoinAdmin methods don't let us throw a
     * IOException
     */

    /**
     * Get the current attribute sets for the service.
     *
     * @return the current attribute sets for the service
     */
    public Entry[] getLookupAttributes() {
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.entering(JoinStateManager.class.getName(),
          "getLookupAttributes");
  }
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.exiting(JoinStateManager.class.getName(),
          "getLookupAttributes");
  }
  return mgr.getAttributes();
    }

    /**
     * Add attribute sets for the service.  The resulting set will be used
     * for all future joins.  The attribute sets are also added to all
     * currently-joined lookup services.
     *
     * @param attrSets the attribute sets to add
     * @throws java.rmi.RuntimeException if the change can not be persisted.
     */
    public void addLookupAttributes(Entry[] attrSets) {
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.entering(JoinStateManager.class.getName(),
          "addLookupAttributes");
  }
  mgr.addAttributes(attrSets, true);
  update();
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.exiting(JoinStateManager.class.getName(),
          "addLookupAttributes");
  }
    }

    /** 
     * Modify the current attribute sets, using the same semantics as
     * ServiceRegistration.modifyAttributes.  The resulting set will be used
     * for all future joins.  The same modifications are also made to all
     * currently-joined lookup services.
     *
     * @param attrSetTemplates the templates for matching attribute sets
     * @param attrSets the modifications to make to matching sets
     *    
     * @throws java.rmi.RuntimeException if the change can not be persisted.
     * @see net.jini.core.lookup.ServiceRegistration#modifyAttributes
     */
    public void modifyLookupAttributes(Entry[] attrSetTemplates,
               Entry[] attrSets) {
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.entering(JoinStateManager.class.getName(),
          "modifyLookupAttributes");
  }
  mgr.modifyAttributes(attrSetTemplates, attrSets, true);
  update();
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.exiting(JoinStateManager.class.getName(),
          "modifyLookupAttributes");
  }
    }

   /**
     * Get the list of groups to join.  An empty array means the service
     * joins no groups (as opposed to "all" groups).
     *
     * @return an array of groups to join. An empty array means the service
     *         joins no groups (as opposed to "all" groups).
     * @see #setLookupGroups
     */
    public String[] getLookupGroups() {
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.entering(JoinStateManager.class.getName(),
          "getLookupGroups");
  }
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.exiting(JoinStateManager.class.getName(),
          "getLookupGroups");
  }
  return ((DiscoveryGroupManagement)dm).getGroups();
    }

    /**
     * Add new groups to the set to join.  Lookup services in the new
     * groups will be discovered and joined.
     *
     * @param groups groups to join
     * @throws java.rmi.RuntimeException if the change can not be persisted.
     * @see #removeLookupGroups
     */
    public void addLookupGroups(String[] groups) {
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.entering(JoinStateManager.class.getName(),
          "addLookupGroups");
  }
   try {
      ((DiscoveryGroupManagement)dm).addGroups(groups);
  } catch (IOException e) {
      throw new RuntimeException("Could not change groups");
  }
  update();
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.exiting(JoinStateManager.class.getName(),
          "addLookupGroups");
  }
    }

    /**
     * Remove groups from the set to join.  Leases are cancelled at lookup
     * services that are not members of any of the remaining groups.
     *
     * @param groups groups to leave
     * @throws java.rmi.RuntimeException if the change can not be persisted.
     * @see #addLookupGroups
     */
    public void removeLookupGroups(String[] groups) {
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.entering(JoinStateManager.class.getName(),
          "removeLookupGroups");
  }
        ((DiscoveryGroupManagement)dm).removeGroups(groups);
  update();
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.exiting(JoinStateManager.class.getName(),
          "removeLookupGroups");   
  }
    }

    /**
     * Replace the list of groups to join with a new list.  Leases are
     * cancelled at lookup services that are not members of any of the
     * new groups.  Lookup services in the new groups will be discovered
     * and joined.
     *
     * @param groups groups to join
     * @throws java.rmi.RuntimeException if the change can not be persisted.
     * @see #getLookupGroups
     */
    public void setLookupGroups(String[] groups) {
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.entering(JoinStateManager.class.getName(),
          "setLookupGroups");
  }
  try {
      ((DiscoveryGroupManagement)dm).setGroups(groups);
  } catch (IOException e) {
      throw new RuntimeException("Could not change groups");
  }
  update();
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.exiting(JoinStateManager.class.getName(),
          "setLookupGroups");
  }
    }
   
    /**
     * Get the list of locators of specific lookup services to join.
     *
     * @return the list of locators of specific lookup services to join
     * @see #setLookupLocators
     */
    public LookupLocator[] getLookupLocators() {
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.entering(JoinStateManager.class.getName(),
          "getLookupLocators");
  }
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.exiting(JoinStateManager.class.getName(),
          "getLookupLocators");
  }
      return ((DiscoveryLocatorManagement)dm).getLocators();
    }

    /**
     * Add locators for specific new lookup services to join.  The new
     * lookup services will be discovered and joined.
     *
     * @param locators locators of specific lookup services to join
     * @throws java.rmi.RuntimeException if the change can not be persisted.
     * @see #removeLookupLocators
     */
    public void addLookupLocators(LookupLocator[] locators)
        throws RemoteException
    {
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.entering(JoinStateManager.class.getName(),
          "addLookupLocators");
  }
        prepareLocators(locators);
  ((DiscoveryLocatorManagement)dm).addLocators(locators);
  update();
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.exiting(JoinStateManager.class.getName(),
          "addLookupLocators");
  }
    }

    /**
     * Remove locators for specific lookup services from the set to join.
     * Any leases held at the lookup services are cancelled.
     *
     * @param locators locators of specific lookup services to leave
     * @throws java.rmi.RuntimeException if the change can not be persisted.
     * @see #addLookupLocators
     */
    public void removeLookupLocators(LookupLocator[] locators)        
        throws RemoteException
    {
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.entering(JoinStateManager.class.getName(),
          "removeLookupLocators");
  }
        prepareLocators(locators);
  ((DiscoveryLocatorManagement)dm).removeLocators(locators);
  update();
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.exiting(JoinStateManager.class.getName(),
          "removeLookupLocators");
  }
    }

    /**
     * Replace the list of locators of specific lookup services to join
     * with a new list.  Leases are cancelled at lookup services that were
     * in the old list but are not in the new list.  Any new lookup services
     * will be discovered and joined.
     *
     * @param locators locators of specific lookup services to join
     * @throws java.rmi.RuntimeException if the change can not be persisted.
     * @see #getLookupLocators
     */
    public void setLookupLocators(LookupLocator[] locators)
        throws RemoteException
    {
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.entering(JoinStateManager.class.getName(),
          "setLookupLocators");
  }
        prepareLocators(locators);
  ((DiscoveryLocatorManagement)dm).setLocators(locators);
  update();
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.exiting(JoinStateManager.class.getName(),
          "setLookupLocators");
  }
    }

    /**
     * Apply <code>lookupLocatorPreparer</code> to each locator in the
     * array, replacing the original locator with the result of the
     * <code>prepareProxy</code> call. If call fails with an exception
     * throw that exception.
     * @param locators the <code>LookupLocator</code>s to be prepared.
     * @throws RemoteException if preparation of any of the locators
     *         does.
     * @throws SecurityException if preparation of any of the locators
     *         does.
     */
    private void prepareLocators(LookupLocator[] locators)
        throws RemoteException
    {
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.entering(JoinStateManager.class.getName(),
          "prepareLocators");
  }
        for (int i = 0; i<locators.length; i++) {
            locators[i] = (LookupLocator)lookupLocatorPreparer.prepareProxy(
                locators[i]);
  }
  if (operationsLogger.isLoggable(Level.FINER)) {
            operationsLogger.exiting(JoinStateManager.class.getName(),
          "prepareLocators");
  }
    }

    private void update() {
  if (log != null) {
      synchronized (log) {
    try {
              log.snapshot();
          } catch (IOException e) {
              if (persistenceLogger.isLoggable(Level.WARNING)) {
                        persistenceLogger.log(Level.WARNING,
                      "Failed to persist join state", e);
              }
//TODO - need a better strategy here
              throw new RuntimeException("Problem persisting state.", e);
          }
      }
  }
    }

    /**
     * Utility method to write out an array of entities to an
     * <code>ObjectOutputStream</code>.  Can be recovered by a call
     * to <code>readAttributes()</code>
     * <p>
     * Packages each attribute in its own <code>MarshalledObject</code> so
     * a bad codebase on an attribute class will not corrupt the whole array.
     */
    // @see JoinAdminActivationState#readAttributes
    static private void writeAttributes(Entry[] attributes,
                                        ObjectOutput out)
        throws IOException
    {
        // Need to package each attribute in its own marshaled object,
        // this makes sure that the attribute's code base is preserved
        // and when we unpack to discard attributes who's codebase
        // has been lost without throwing away those we can still deal with.
        
        out.writeInt(attributes.length);
        for (int i=0; i<attributes.length; i++) {
            out.writeObject(new MarshalledObject(attributes[i]));
  }
    }
    /**
     * Utility method to read in an array of entities from a
     * <code>ObjectInputStream</code>.  Array should have been written
     * by a call to <code>writeAttributes()</code>
     * <p>
     *  
     * Will try and recover as many attributes as possible.
     * Attributes which can't be recovered won't be returned but they
     * will remain in the log.
     *
     */
    // @see JoinAdminActivationState#writeAttributes
    static private Entry[] readAttributes(ObjectInput in)
        throws IOException, ClassNotFoundException
    {
        final List entries = new java.util.LinkedList();
        final int objectCount = in.readInt();
        for (int i=0; i<objectCount; i++) {
            try {
                MarshalledObject mo = (MarshalledObject)in.readObject();
                entries.add(mo.get());
            } catch (IOException e) {
                if(initlogger.isLoggable(Levels.HANDLED)) {
              initlogger.log(Levels.HANDLED,
        "Exception getting service attribute ... skipping", e);
    }
            } catch (ClassNotFoundException e) {
                if(initlogger.isLoggable(Levels.HANDLED)) {
              initlogger.log(Levels.HANDLED,
        "Exception getting service attribute ... skipping", e);
    }
            }
        }
        return (Entry[])entries.toArray(new Entry[0]);
    }

    // -----------------------------------
    //  Methods required by LogHandler
    // -----------------------------------
    // inherit doc comment
    public void snapshot(OutputStream out) throws IOException {
  ObjectOutputStream oostream = new ObjectOutputStream(out);
        oostream.writeObject(serviceUuid);
        writeAttributes(mgr.getAttributes(), oostream);
        oostream.writeObject(((DiscoveryLocatorManagement)dm).getLocators());
        oostream.writeObject(((DiscoveryGroupManagement)dm).getGroups());
  oostream.flush();
    }

    // inherit doc comment
    public void recover(InputStream in)
  throws Exception
    {
  initial = false;
  ObjectInputStream oistream = new ObjectInputStream(in);
  serviceUuid = (Uuid)oistream.readObject();
        attributes  = readAttributes(oistream);
        locators    = (LookupLocator [])oistream.readObject();
        groups      = (String [])oistream.readObject();
    }
    /**
     * This method always throws
     * <code>UnsupportedOperationException</code> since
     * <code>FileJoinAdminState</code> should never update a
     * log.
     */
    public void applyUpdate(Object update) throws Exception {
        throw new UnsupportedOperationException(
                "JoinStateManager:Updating log" +
                ", this should not happen");
    }

}
TOP

Related Classes of com.sun.jini.mahalo.JoinStateManager

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.