View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    * 
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   * 
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package net.jini.lookup;
20  /**
21   * The <code>ServiceDiscoveryListener</code> interface defines the
22   * methods used by objects such as a {@link net.jini.lookup.LookupCache 
23   * LookupCache} to notify an entity that events of interest related to
24   * the elements of the cache have occurred. It is the responsibility of
25   * the entity wishing to be notified of the occurrence of such events to
26   * construct an object that implements the 
27   * <code>ServiceDiscoveryListener</code> interface and then register
28   * that object with the cache's event mechanism. Any implementation of
29   * this interface must define the actions to take upon receipt of an
30   * event notification. The action taken is dependent on both the
31   * application and the particular event that has occurred.
32   * <p>
33   * When the cache receives from one of the managed lookup services, an event
34   * signaling the <i>registration</i> of a service of interest for the 
35   * <i>first time</i> (or for the first time since the service has been
36   * discarded), the cache applies any requested filtering and, if the service of
37   * interest passes the filter (or if no filtering was requested), the cache
38   * invokes the {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded
39   * serviceAdded} method on all instances of
40   * <code>ServiceDiscoveryListener</code> that are registered with the cache.
41   * Invoking the {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded
42   * serviceAdded} method notifies the entity that a service of interest that
43   * matches any additional selection criteria has been discovered, and is
44   * <i>safe</i> to use (if {@link net.jini.security.ProxyPreparer
45   * proxy preparation} was requested).
46   * <p>
47   * When the cache receives, from a managed lookup service, an event signaling
48   * the <i>removal</i> of a service of interest from the <i>last</i> such lookup
49   * service with which it was registered, the cache invokes the 
50   * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
51   * serviceRemoved} method on all instances of
52   * <code>ServiceDiscoveryListener</code> that are registered with the cache;
53   * doing so notifies the entity that a service of interest has been discarded.
54   * <p>
55   * In addition to the scenarios just described, the cache may also receive,
56   * from a managed lookup service, a notification indicating that one of the
57   * following events has occurred:
58   * <ul><li> The service has changed in some fundamental way (for example,
59   *          the service is replaced with a new version), as determined by
60   *          {@link net.jini.io.MarshalledInstance#fullyEquals
61   *          MarshalledInstance.fullyEquals}
62   *     <li> The attributes of interest (across the attribute sets of all
63   *          references to the service) have been uniquely modified
64   * </ul>
65   * <p>
66   * Note that that when determining whether the proxy referenced in the event
67   * is fundamentally different from the corresponding proxy held by the cache
68   * (the proxy that references the same service as the proxy from the event),
69   * the cache applies {@link net.jini.io.MarshalledInstance#fullyEquals
70   * MarshalledInstance.fullyEquals} to the <b><i>unprepared</i></b> forms
71   * of both proxies.
72   * <p>
73   * When the cache receives, from a managed lookup service, a notification
74   * indicating that one of the above events has occurred, the cache will first
75   * apply any requested filtering to the service referenced by the event;
76   * after which the cache will invoke either the
77   * {@link net.jini.lookup.ServiceDiscoveryListener#serviceChanged
78   * serviceChanged} method or
79   * the {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
80   * serviceRemoved} method, possibly followed by the
81   * {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded serviceAdded}
82   * method. Which of those methods the cache ultimately invokes is dependent
83   * on the nature of the notification from the lookup service as well as the
84   * results of any filtering that is performed.
85   * <p>
86   * If the event from the lookup service indicates that attributes of the
87   * service have been modified, and if either no filtering is requested or
88   * the service referenced by the event passes the filter, then the cache
89   * invokes the {@link net.jini.lookup.ServiceDiscoveryListener#serviceChanged
90   * serviceChanged} method on all instances of 
91   * <code>ServiceDiscoveryListener</code> that are registered with the cache.
92   * Invoking the {@link net.jini.lookup.ServiceDiscoveryListener#serviceChanged
93   * serviceChanged} method notifies the entity that the attributes of the
94   * previously discovered service have been changed in some way that is still
95   * of interest to the entity.
96   * <p>
97   * If the event from the lookup service indicates that the previously
98   * discovered service itself has changed, then if either filtering is not
99   * requested or the service passes the requested filter, the cache invokes
100  * the {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
101  * serviceRemoved} method and then the
102  * {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded serviceAdded}
103  * method on all instances of <code>ServiceDiscoveryListener</code> that are
104  * registered with the cache. Invoking the
105  * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
106  * serviceRemoved} method followed by the
107  * {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded serviceAdded}
108  * method notifies the entity that the previously discovered service has been
109  * replaced with a new reference.
110  * <p>
111  * If, on the other hand, filtering is requested but the service fails the
112  * filter, then the cache invokes only the
113  * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
114  * serviceRemoved} method on all instances of
115  * <code>ServiceDiscoveryListener</code> that are registered with the
116  * cache. In this case, the
117  * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
118  * serviceRemoved} method is invoked because the cache has concluded that
119  * the previously discovered service has been replaced with a new reference
120  * that is either no longer of interest to the entity, or is not safe
121  * to use.
122  * <p>
123  * Finally, if filtering is requested but the filtering process results in
124  * an <i>indefinite</i> state, then the cache first invokes the 
125  * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
126  * serviceRemoved} method (to indicate to the entity that the service
127  * is currently unusable), and then periodically retries the filter for
128  * an implementation-dependent amount of time that is likely to exceed
129  * the typical service lease duration, until either a failure occurs
130  * or a pass occurs. If a pass occurs within the retry time period, the cache
131  * invokes the {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded
132  * serviceAdded} method because the cache has concluded that the previously
133  * discovered service has been replaced with a new reference that is still
134  * of interest to the entity, and is now safe to use.
135  * <p>
136  * The methods just described -- 
137  * {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded serviceAdded},
138  * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
139  * serviceRemoved}, and
140  * {@link net.jini.lookup.ServiceDiscoveryListener#serviceChanged
141  * serviceChanged} -- each take a single parameter of type
142  * {@link net.jini.lookup.ServiceDiscoveryEvent ServiceDiscoveryEvent}, which
143  * contains references to the service item corresponding to the event,
144  * including representations of the service's state both before and after
145  * the event.
146  * <p>
147  * Except for possible modifications that result from filtering, each method
148  * defined by this interface must not modify the contents of the
149  * {@link net.jini.lookup.ServiceDiscoveryEvent ServiceDiscoveryEvent}
150  * parameter; doing so can result in unpredictable and undesirable effects
151  * on future processing by the {@link net.jini.lookup.ServiceDiscoveryManager
152  * ServiceDiscoveryManager}. Therefore, the effects of such modifications
153  * are undefined.
154  * <p>
155  * The <code>ServiceDiscoveryListener</code> interface makes the following
156  * concurrency guarantee: for any given listener object that implements this
157  * interface or any sub-interface, no two methods defined by the interface
158  * or sub-interface will be invoked at the same time by the same cache.
159  * This applies to different invocations of the same or different methods,
160  * on the same or different listeners registered with a single cache. For
161  * example, the {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
162  * serviceRemoved} method of one listener will not be invoked while the
163  * invocation of another listener's
164  * {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded serviceAdded},
165  * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
166  * serviceRemoved}, or
167  * {@link net.jini.lookup.ServiceDiscoveryListener#serviceChanged
168  * serviceChanged} method is in progress. Similarly, the one listener's
169  * {@link net.jini.lookup.ServiceDiscoveryListener#serviceRemoved
170  * serviceRemoved} method will not be invoked while that same listener's
171  * {@link net.jini.lookup.ServiceDiscoveryListener#serviceAdded serviceAdded},
172  * or {@link net.jini.lookup.ServiceDiscoveryListener#serviceChanged
173  * serviceChanged} method is in progress.
174  * <p>
175  * Note that the intent of the methods of this interface is to allow the
176  * recipient of the {@link net.jini.lookup.ServiceDiscoveryEvent
177  * ServiceDiscoveryEvent} to be informed that a service has been added to,
178  * removed from, or modified in the cache. Calls to these methods are
179  * synchronous to allow the entity that makes the call (for example, a
180  * thread that interacts with the various lookup services of interest)
181  * to determine whether or not the call succeeded. However, it is not
182  * part of the semantics of the call that the notification return can be
183  * delayed while the recipient of the call reacts to the occurrence of the
184  * event. Thus, it is highly recommended that implementations of this
185  * interface avoid time consuming operations, and return from the method
186  * as quickly as possible. For example, one strategy might be to simply
187  * note the occurrence of the {@link net.jini.lookup.ServiceDiscoveryEvent
188  * ServiceDiscoveryEvent}, and perform any time consuming event handling
189  * asynchronously. 
190  * 
191  * @author Sun Microsystems, Inc.
192  *
193  * @see LookupCache
194  * @see ServiceDiscoveryEvent
195  */
196 public interface ServiceDiscoveryListener {
197     /** 
198      * When the cache receives from one of the managed lookup services,
199      * an event signaling the <i>registration</i> of a service of
200      * interest for the <i>first time</i> (or for the first time since
201      * the service has been discarded), the cache invokes the
202      * <code>serviceAdded</code> method on all instances of
203      * <code>ServiceDiscoveryListener</code> that are registered with the
204      * cache; doing so notifies the entity that a service of interest has
205      * been discovered.
206      *
207      * @param event an instance of <code>ServiceDiscoveryEvent</code> 
208      * 			containing references to the service item 
209      *			corresponding to the event, including 
210      * 			representations of the service's state both 
211      *			before and after the event.
212      */
213     void serviceAdded(ServiceDiscoveryEvent event);
214 
215     /** 
216      * When the cache receives, from a managed lookup service, an event
217      * signaling the removal of a service of interest from the last such
218      * lookup service with which it was registered, the cache invokes
219      * the <code>serviceRemoved</code> method on all instances of
220      * <code>ServiceDiscoveryListener</code> that are registered with
221      * the cache; doing so notifies the entity that a service of interest 
222      * has been discarded.
223      * 
224      * @param event a <code>ServiceDiscoveryEvent</code> object 
225      * 			containing references to the service item 
226      *			corresponding to the event, including 
227      *			representations of the service's state both 
228      *			before and after the event.
229      */
230     void serviceRemoved(ServiceDiscoveryEvent event);
231 
232     /** 
233      * When the cache receives, from a managed lookup service, an event
234      * signaling the unique modification of the attributes of a service
235      * of interest (across the attribute sets of all references to the
236      * service), the cache invokes the <code>serviceChanged</code>
237      * method on all instances of <code>ServiceDiscoveryListener</code>
238      * that are registered with the cache; doing so notifies the entity
239      * that the state of a service of interest has changed.
240      * 
241      * @param event a <code>ServiceDiscoveryEvent</code> object
242      * 			containing references to the service item 
243      * 			corresponding to the event, including 
244      * 			representations of the service's state both
245      * 			before and after the event.
246      */
247     void serviceChanged(ServiceDiscoveryEvent event);
248 }