/* * 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 net.jini.lookup; import net.jini.core.lookup.ServiceItem; /** * The <code>ServiceDiscoveryListener</code> interface defines the * methods used by objects such as a {@link net.jini.lookup.LookupCache * LookupCache} to notify an entity that events of interest related to * the elements of the cache have occurred. It is the responsibility of * the entity wishing to be notified of the occurrence of such events to * construct an object that implements the * <code>ServiceDiscoveryListener</code> interface and then register * that object with the cache's event mechanism. Any implementation of * this interface must define the actions to take upon receipt of an * event notification. The action taken is dependent on both the * application and the particular event that has occurred. * <p> * When the cache receives from one of the managed lookup services, an event * signaling the <i>registration</i> of a service of interest for the * <i>first time</i> (or for the first time since the service has been * discarded), the cache applies any requested filtering and, if the service of * interest passes the filter (or if no filtering was requested), the cache * invokes the {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded * serviceAdded} method on all instances of * <code>ServiceDiscoveryListener</code> that are registered with the cache. * Invoking the {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded * serviceAdded} method notifies the entity that a service of interest that * matches any additional selection criteria has been discovered, and is * <i>safe</i> to use (if {@link net.jini.security.ProxyPreparer * proxy preparation} was requested). * <p> * When the cache receives, from a managed lookup service, an event signaling * the <i>removal</i> of a service of interest from the <i>last</i> such lookup * service with which it was registered, the cache invokes the * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved * serviceRemoved} method on all instances of * <code>ServiceDiscoveryListener</code> that are registered with the cache; * doing so notifies the entity that a service of interest has been discarded. * <p> * In addition to the scenarios just described, the cache may also receive, * from a managed lookup service, a notification indicating that one of the * following events has occurred: * <ul><li> The service has changed in some fundamental way (for example, * the service is replaced with a new version), as determined by * {@link net.jini.io.MarshalledInstance#fullyEquals * MarshalledInstance.fullyEquals} * <li> The attributes of interest (across the attribute sets of all * references to the service) have been uniquely modified * </ul> * <p> * Note that that when determining whether the proxy referenced in the event * is fundamentally different from the corresponding proxy held by the cache * (the proxy that references the same service as the proxy from the event), * the cache applies {@link net.jini.io.MarshalledInstance#fullyEquals * MarshalledInstance.fullyEquals} to the <b><i>unprepared</i></b> forms * of both proxies. * <p> * When the cache receives, from a managed lookup service, a notification * indicating that one of the above events has occurred, the cache will first * apply any requested filtering to the service referenced by the event; * after which the cache will invoke either the * {@link net.jini.lookup.ServiceDiscoveryListener#serviceChanged * serviceChanged} method or * the {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved * serviceRemoved} method, possibly followed by the * {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded serviceAdded} * method. Which of those methods the cache ultimately invokes is dependent * on the nature of the notification from the lookup service as well as the * results of any filtering that is performed. * <p> * If the event from the lookup service indicates that attributes of the * service have been modified, and if either no filtering is requested or * the service referenced by the event passes the filter, then the cache * invokes the {@link net.jini.lookup.ServiceDiscoveryListener#serviceChanged * serviceChanged} method on all instances of * <code>ServiceDiscoveryListener</code> that are registered with the cache. * Invoking the {@link net.jini.lookup.ServiceDiscoveryListener#serviceChanged * serviceChanged} method notifies the entity that the attributes of the * previously discovered service have been changed in some way that is still * of interest to the entity. * <p> * If the event from the lookup service indicates that the previously * discovered service itself has changed, then if either filtering is not * requested or the service passes the requested filter, the cache invokes * the {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved * serviceRemoved} method and then the * {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded serviceAdded} * method on all instances of <code>ServiceDiscoveryListener</code> that are * registered with the cache. Invoking the * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved * serviceRemoved} method followed by the * {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded serviceAdded} * method notifies the entity that the previously discovered service has been * replaced with a new reference. * <p> * If, on the other hand, filtering is requested but the service fails the * filter, then the cache invokes only the * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved * serviceRemoved} method on all instances of * <code>ServiceDiscoveryListener</code> that are registered with the * cache. In this case, the * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved * serviceRemoved} method is invoked because the cache has concluded that * the previously discovered service has been replaced with a new reference * that is either no longer of interest to the entity, or is not safe * to use. * <p> * Finally, if filtering is requested but the filtering process results in * an <i>indefinite</i> state, then the cache first invokes the * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved * serviceRemoved} method (to indicate to the entity that the service * is currently unusable), and then periodically retries the filter for * an implementation-dependent amount of time that is likely to exceed * the typical service lease duration, until either a failure occurs * or a pass occurs. If a pass occurs within the retry time period, the cache * invokes the {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded * serviceAdded} method because the cache has concluded that the previously * discovered service has been replaced with a new reference that is still * of interest to the entity, and is now safe to use. * <p> * The methods just described -- * {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded serviceAdded}, * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved * serviceRemoved}, and * {@link net.jini.lookup.ServiceDiscoveryListener#serviceChanged * serviceChanged} -- each take a single parameter of type * {@link net.jini.lookup.ServiceDiscoveryEvent ServiceDiscoveryEvent}, which * contains references to the service item corresponding to the event, * including representations of the service's state both before and after * the event. * <p> * Except for possible modifications that result from filtering, each method * defined by this interface must not modify the contents of the * {@link net.jini.lookup.ServiceDiscoveryEvent ServiceDiscoveryEvent} * parameter; doing so can result in unpredictable and undesirable effects * on future processing by the {@link net.jini.lookup.ServiceDiscoveryManager * ServiceDiscoveryManager}. Therefore, the effects of such modifications * are undefined. * <p> * The <code>ServiceDiscoveryListener</code> interface makes the following * concurrency guarantee: for any given listener object that implements this * interface or any sub-interface, no two methods defined by the interface * or sub-interface will be invoked at the same time by the same cache. * This applies to different invocations of the same or different methods, * on the same or different listeners registered with a single cache. For * example, the {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved * serviceRemoved} method of one listener will not be invoked while the * invocation of another listener's * {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded serviceAdded}, * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved * serviceRemoved}, or * {@link net.jini.lookup.ServiceDiscoveryListener#serviceChanged * serviceChanged} method is in progress. Similarly, the one listener's * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved * serviceRemoved} method will not be invoked while that same listener's * {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded serviceAdded}, * or {@link net.jini.lookup.ServiceDiscoveryListener#serviceChanged * serviceChanged} method is in progress. * <p> * Note that the intent of the methods of this interface is to allow the * recipient of the {@link net.jini.lookup.ServiceDiscoveryEvent * ServiceDiscoveryEvent} to be informed that a service has been added to, * removed from, or modified in the cache. Calls to these methods are * synchronous to allow the entity that makes the call (for example, a * thread that interacts with the various lookup services of interest) * to determine whether or not the call succeeded. However, it is not * part of the semantics of the call that the notification return can be * delayed while the recipient of the call reacts to the occurrence of the * event. Thus, it is highly recommended that implementations of this * interface avoid time consuming operations, and return from the method * as quickly as possible. For example, one strategy might be to simply * note the occurrence of the {@link net.jini.lookup.ServiceDiscoveryEvent * ServiceDiscoveryEvent}, and perform any time consuming event handling * asynchronously. * * @author Sun Microsystems, Inc. * * @see LookupCache * @see ServiceDiscoveryEvent */ public interface ServiceDiscoveryListener { /** * When the cache receives from one of the managed lookup services, * an event signaling the <i>registration</i> of a service of * interest for the <i>first time</i> (or for the first time since * the service has been discarded), the cache invokes the * <code>serviceAdded</code> method on all instances of * <code>ServiceDiscoveryListener</code> that are registered with the * cache; doing so notifies the entity that a service of interest has * been discovered. * * @param event an instance of <code>ServiceDiscoveryEvent</code> * containing references to the service item * corresponding to the event, including * representations of the service's state both * before and after the event. */ void serviceAdded(ServiceDiscoveryEvent event); /** * When the cache receives, from a managed lookup service, an event * signaling the removal of a service of interest from the last such * lookup service with which it was registered, the cache invokes * the <code>serviceRemoved</code> method on all instances of * <code>ServiceDiscoveryListener</code> that are registered with * the cache; doing so notifies the entity that a service of interest * has been discarded. * * @param event a <code>ServiceDiscoveryEvent</code> object * containing references to the service item * corresponding to the event, including * representations of the service's state both * before and after the event. */ void serviceRemoved(ServiceDiscoveryEvent event); /** * When the cache receives, from a managed lookup service, an event * signaling the unique modification of the attributes of a service * of interest (across the attribute sets of all references to the * service), the cache invokes the <code>serviceChanged</code> * method on all instances of <code>ServiceDiscoveryListener</code> * that are registered with the cache; doing so notifies the entity * that the state of a service of interest has changed. * * @param event a <code>ServiceDiscoveryEvent</code> object * containing references to the service item * corresponding to the event, including * representations of the service's state both * before and after the event. */ void serviceChanged(ServiceDiscoveryEvent event); }