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 }