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 import java.io.IOException;
22 import net.jini.core.lookup.ServiceItem;
23 import org.apache.river.api.io.AtomicSerial;
24 import org.apache.river.api.io.AtomicSerial.GetArg;
25
26 /**
27 * The <code>ServiceDiscoveryEvent</code> class encapsulates the
28 * service discovery information made available by the event mechanism
29 * of the {@link net.jini.lookup.LookupCache LookupCache}. All listeners
30 * that an entity has registered with the cache's event mechanism will
31 * receive an event of type <code>ServiceDiscoveryEvent</code> upon
32 * the discovery, removal, or modification of one of the cache's services.
33 * This class is used by
34 * {@link net.jini.lookup.ServiceDiscoveryManager ServiceDiscoveryManager}.
35 *
36 * @author Sun Microsystems, Inc.
37 *
38 * @see ServiceDiscoveryManager
39 */
40 @AtomicSerial
41 public class ServiceDiscoveryEvent extends java.util.EventObject {
42 private static final long serialVersionUID = -4654412297235019084L;
43
44 /** Represents the state of the service prior to the event.
45 *
46 * @serial
47 */
48 private final ServiceItem preEventItem;
49
50 /** Represents the state of the service after the event.
51 *
52 * @serial
53 */
54 private final ServiceItem postEventItem;
55
56 /**
57 * <p>
58 * The constructor of <code>ServiceDiscoveryEvent</code> takes
59 * three arguments:</p>
60 * <ul>
61 * <li>An instance of <code>Object</code> corresponding to the
62 * instance of <code>LookupCache</code> from which the given event
63 * originated</li>
64 *
65 * <li>A <code>ServiceItem</code> reference representing the state
66 * of the service (associated with the given event) prior to the
67 * occurrence of the event</li>
68 *
69 * <li>A <code>ServiceItem</code> reference representing the state
70 * of the service after the occurrence of the event</li>
71 * </ul>
72 * <p>
73 * If <code>null</code> is passed as the source parameter for the
74 * constructor, a <code>NullPointerException</code> will be thrown.
75 * </p><p>
76 * Depending on the nature of the discovery event, a null reference
77 * may be passed as one or the other of the remaining parameters, but
78 * never both. If <code>null</code> is passed as both the
79 * <code>preEventItem </code>and the <code>postEventItem</code>
80 * parameters, a <code>NullPointerException</code> will be thrown.
81 * </p><p>
82 * Note that the constructor will not modify the contents of either
83 * <code>ServiceItem</code> argument. Doing so can result in
84 * unpredictable and undesirable effects on future processing by the
85 * <code>ServiceDiscoveryManager</code>. That is why the effects of any
86 * such modification to the contents of either input parameter are
87 * undefined.</p>
88 *
89 * @param source an instance of <code>Object</code> corresponding
90 * to the instance of <code>LookupCache</code> from
91 which the given event originated.
92 *
93 * @param preEventItem a <code>ServiceItem</code> reference
94 * representing the state of the service (associated
95 * with the given event) prior to the occurrence of
96 * the event.
97 *
98 * @param postEventItem a <code>ServiceItem</code> reference
99 * representing the state of the service after the
100 * occurrence of the event.
101 *
102 * @throws NullPointerException if <code>null</code> is
103 * passed as the source parameter for the constructor,
104 * or if <code>null</code> is passed as both the
105 * <code>preEventItem </code>and the
106 * <code>postEventItem</code> parameters.
107 */
108 public ServiceDiscoveryEvent(
109 Object source,
110 ServiceItem preEventItem,
111 ServiceItem postEventItem)
112 {
113 this(source, preEventItem, postEventItem,
114 nullCheck(source, preEventItem, postEventItem));
115 }
116
117 private static boolean nullCheck( //Prevent finalizer attack.
118 Object source,
119 ServiceItem preEventItem,
120 ServiceItem postEventItem) throws NullPointerException
121 {
122 if((preEventItem == null && postEventItem == null)|| source == null)
123 throw new NullPointerException();
124 return true;
125 }
126
127 private ServiceDiscoveryEvent(
128 Object source,
129 ServiceItem preEventItem,
130 ServiceItem postEventItem,
131 boolean check)
132 {
133 super(source);
134 if(preEventItem != null)
135 this.preEventItem = preEventItem.clone();
136 else this.preEventItem = null;
137 if(postEventItem != null)
138 this.postEventItem = postEventItem.clone();
139 else this.postEventItem = null;
140 }
141
142 /**
143 * AtomicSerial constructor
144 * @param arg
145 * @throws IOException
146 */
147 public ServiceDiscoveryEvent(GetArg arg) throws IOException{
148 // source cannot be null in the constructor, but it is after
149 // deserialization because it is transient.
150 this(Boolean.TRUE, arg.get("preEventItem", null, ServiceItem.class),
151 arg.get("postEventItem", null, ServiceItem.class), false);
152 source = null;
153 }
154
155 /**
156 * Returns an instance of a <code>ServiceItem</code> containing the
157 * service reference corresponding to the given event. The service
158 * state reflected in the returned service item is the state of the
159 * service prior to the occurrence of the event.
160 * <p>
161 * If the event is a discovery event (as opposed to a removal or
162 * modification event), then this method will return <code>null</code>
163 * because the discovered service had no state in the cache prior to
164 * its discovery.
165 * <p>
166 * Because making a copy can be a very expensive process, this
167 * method does not return a copy of the service reference associated
168 * with the given event. Rather, it returns the appropriate service
169 * reference from the cache itself. Due to this cost, listeners that
170 * receive a <code>ServiceDiscoveryEvent</code> must not modify the
171 * contents of the object returned by this method; doing so could
172 * cause the state of the cache to become corrupted or inconsistent
173 * because the objects returned by this method are also members of
174 * the cache. This potential for corruption or inconsistency is why
175 * the effects of modifying the object returned by this accessor
176 * method are undefined.
177 *
178 * @return ServiceItem containing the service reference corresponding
179 * to the given event.
180 */
181 public ServiceItem getPreEventServiceItem()
182 {
183 return preEventItem.clone();
184 }
185
186 /**
187 * Returns an instance of a <code>ServiceItem</code> containing the
188 * service reference corresponding to the given event. The service
189 * state reflected in the returned service item is the state of the
190 * service after the occurrence of the event.
191 * <p>
192 * If the event is a removal event, then this method will return
193 * <code>null</code> because the discovered service has no state in
194 * the cache after it is removed from the cache.
195 * <p>
196 * Because making a copy can be a very expensive process, this
197 * method does not return a copy of the service reference associated
198 * with the given event. Rather, it returns the appropriate service
199 * reference from the cache itself. Due to this cost, listeners that
200 * receive a <code>ServiceDiscoveryEvent</code> must not modify the
201 * contents of the object returned by this method; doing so could
202 * cause the state of the cache to become corrupted or inconsistent
203 * because the objects returned by this method are also members of
204 * the cache. This potential for corruption or inconsistency is why
205 * the effects of modifying the object returned by this accessor
206 * method are undefined.
207 *
208 * @return ServiceItem containing the service reference corresponding
209 * to the given event.
210 */
211 public ServiceItem getPostEventServiceItem()
212 {
213 return postEventItem.clone();
214 }
215
216 }