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 }