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  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 }