Package com.sun.jini.mercury

Source Code of com.sun.jini.mercury.ServiceRegistration

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

import com.sun.jini.landlord.LeasedResource;
import net.jini.id.Uuid;
import net.jini.security.ProxyPreparer;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.rmi.MarshalledObject;
import java.rmi.RemoteException;
import java.util.Date;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.Map;

import net.jini.core.event.RemoteEventListener;

/**
* The <tt>ServiceRegistration</tt> class serves as the server-side abstraction
* that maintains client registration state information. It implements the
* <tt>LeasedResource</tt> interface to allow it to be used with the
* <tt>Landlord</tt> framework. It implements the <tt>Comparable</tt>
* interface so that it can be used in <tt>SortedMap</tt> collections.
*
* @author Sun Microsystems, Inc.
*
* @since 1.1
*/
class ServiceRegistration implements LeasedResource, Comparable, Serializable {

    private static final long serialVersionUID = 2L;

    /** Unique identifier object */
    private final Uuid cookie;

    /** The current expiration for this registration */
    private long expiration = 0;
   
    /** The prepared, client-provided notification target. */
    // This field is transient in order to allow readObject/writeObject
    // to un/wrap the the listener to/from a MarshalledObject.
    // This is done to prevent the corruption of the input stream.
    // For example, if the associated codebase of the listener object
    // is no longer valid, then the stream is corrupted since the object
    // can't be reconstructed.  Wrapping the reference in a
    // MarshalledObject always allows us to read from the stream.
    // We might not be able to reconstruct the listener field, but
    // the rest of the objects in the stream will be fine.
    private transient RemoteEventListener preparedEventTarget = null;

    /** The marshalled form of the client-provided notification target. */
    private MarshalledObject marshalledEventTarget = null;

    /** Event log iterator. */
    // This field is transient because event state info is persisted
    // separately from the registration state info. It is (re)constructed
    // upon service initialization.
    private transient EventLogIterator eventIterator = null;

    /**
     * Map of collected <tt>EventID</tt>'s that resulted in an
     * UnknownEventException for the current <code>
     * eventTarget</code>. This <code>Map</code> is checked
     * upon each mailbox notification for this registration.
     * If the received event has the same <tt>EventID</tt>
     * as the one contained in this <code>Map</code> then an
     * <code>UnknownEventException</code>
     * is propagated back to the sender and the event is not logged.
     * This structure is also consulted before each event delivery request.
     * If the event to be delivered has an <tt>EventID</tt> that is
     * contained in this <tt>Map</tt>, then event delivery is cancelled
     * for that particular event. Note that this structure gets cleared
     * whenever a target listener is (re)set on the assumption that an
     * active (re)set will provide a new/better target listener that might
     * be able to handle these events.
     */
    private Map unknownEvents = new HashMap();

    /**
     * Unique identifier object for the currently enabled
     * (client-side) remote event iterator.
     */
    private Uuid remoteEventIteratorID;
   
    /**
     * Lock object used to coordinate event delivery via the iterator.
     * Has to be a serializable object versus just a plain Object.
     */
    private final String iteratorNotifier = new String();


    /** Convenience constructor */
    public ServiceRegistration(Uuid cookie, EventLogIterator eventIterator) {
        this.cookie = cookie;
        this.eventIterator = eventIterator;
    }

    // inherit javadoc from parent
    public void setExpiration(long newExpiration) {
   expiration = newExpiration;
    }

    // inherit javadoc from parent
    public long getExpiration() {
  return expiration;
    }

    // inherit javadoc from parent
    public Uuid getCookie() {
  return cookie;
    }

    /**
     * Return the identity map of EventIDs that caused an
     * UnknownEventException to be generated for the current
     * notification target. A Map is used instead of a generic
     * Collection since the space/time tradeoff for searches
     * seems worth it.
     */
    public Map getUnknownEvents() {
  return unknownEvents;
    }

    /**
     * Get the reference to the prepared,
     * client-supplied notification target
     */
    public RemoteEventListener getEventTarget() {
  return preparedEventTarget;

    }

    /** Set the reference to the client-supplied notification target */
    public void setEventTarget(RemoteEventListener preparedTarget)
  throws IOException
    {
        if (preparedTarget == null) {
      preparedEventTarget = null;
      marshalledEventTarget = null;
  } else {
      preparedEventTarget = preparedTarget;
      marshalledEventTarget = new MarshalledObject(preparedTarget);
  }
    }
   
    /** Get the remote iterator id */
    public Uuid getRemoteEventIteratorID() {
  return remoteEventIteratorID;
    }
   
    /**
     * Get the remote iterator notifier object. This is used to coordinate
     * notifications between event delivery and event reception via the
     * iterator.
     */
    public Object getIteratorNotifier() {
  return iteratorNotifier;
    }
   
    /** Set the remote iterator id */
    public void setRemoteEventIteratorID(Uuid id) {
  remoteEventIteratorID = id;

    }
   
    /**
     * Returns <code>true</code> if an event target is currently set and
     * false otherwise.
     */
    public boolean hasEventTarget() {
        return (marshalledEventTarget != null);
    }
    
    /*
     * Method that restores internal, transient state.
     * Note:
     * This method attempts to prepare the target listener object, which
     * might involve a remote invocation. Therefore, calling this method
     * while holding a lock should be avoided.
     */
    public void restoreTransientState(ProxyPreparer targetPreparer)
        throws IOException, ClassNotFoundException
    {
        if (targetPreparer == null) {
            throw new NullPointerException(
          "targetPreparer cannot be null");
        }
        if (marshalledEventTarget != null) {
            RemoteEventListener unprepared =
          (RemoteEventListener)marshalledEventTarget.get();
            preparedEventTarget = (RemoteEventListener)
                targetPreparer.prepareProxy(unprepared);
        }
  /*
   * Note: Would like to defer preparation until listener
   * is needed (i.e. in getEventTarget()). Unfortunately,
   * listeners are obtained within "locks" and proxy
   * preparation (i.e. possible remote calls) should
   * not be done while holding those locks.
   */
    }

    /**
     * Get the  reference to the registration's associated
     * <tt>EventLogIterator</tt>
     */
    public EventLogIterator iterator() {
        return eventIterator;
    }

    /**
     * Set the reference for this registration's
     * <tt>EventLogIterator</tt>
     */
    public void setIterator(EventLogIterator iter) {
        eventIterator = iter;
    }

    /**
     * Primary sort by leaseExpiration, secondary by leaseID.  The
     * secondary sort is immaterial, except to ensure a total order
     * (required by TreeMap).
     */
    public int compareTo(Object obj) {
        ServiceRegistration reg = (ServiceRegistration)obj;
        if (this == reg)
            return 0;
        if ( expiration < reg.expiration ||
             (expiration == reg.expiration &&
             (   (cookie.getMostSignificantBits() <
         reg.cookie.getMostSignificantBits())
              && (cookie.getLeastSignificantBits() <
         reg.cookie.getLeastSignificantBits()) ) ))
            return -1;
        return 1;
    }

    // inherit documentation from supertype
    public String toString () {
        return getClass().getName() + ":" + cookie.toString();
    }

//TODO - implement readObject() for structural checks

    /**
     * Utility method to display debugging information to the
     * provided <tt>Logger</tt>
     */
    void dumpInfo(Logger logger) {
            logger.log(Level.FINEST, "{0}", this.toString());
            logger.log(Level.FINEST, "Expires at: {0}", new Date(expiration));
            logger.log(Level.FINEST, "Prepared target is: {0}", preparedEventTarget);
            logger.log(Level.FINEST, "Marshalled target is: {0}", marshalledEventTarget);
            logger.log(Level.FINEST, "Unknowns: {0}",
          new Integer(unknownEvents.size()));
      // eventIterator is null upon recovery phase  which
      // is before the transient state gets rebuilt.
      if (eventIterator != null) {
          try {
                    logger.log(Level.FINEST, "hasNext: {0}",
            Boolean.valueOf(eventIterator.hasNext()));
          } catch (IOException ioe) {
                    logger.log(Level.FINEST, "hasNext exception.", ioe);
          }
      }
    }
}
TOP

Related Classes of com.sun.jini.mercury.ServiceRegistration

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.