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      * @throws java.lang.ClassNotFoundException 
147      */
148     public ServiceDiscoveryEvent(GetArg arg) throws IOException, ClassNotFoundException{
149 	// source cannot be null in the constructor, but it is after 
150 	// deserialization because it is transient.
151 	this(Boolean.TRUE, arg.get("preEventItem", null, ServiceItem.class),
152 		arg.get("postEventItem", null, ServiceItem.class), false);
153 	source = null;
154     }
155 
156     /**
157      * Returns an instance of a <code>ServiceItem</code> containing the
158      * service reference corresponding to the given event. The service
159      * state reflected in the returned service item is the state of the
160      * service prior to the occurrence of the event.
161      * <p>
162      * If the event is a discovery event (as opposed to a removal or
163      * modification event), then this method will return <code>null</code> 
164      * because the discovered service had no state in the cache prior to 
165      * its discovery.
166      * <p>
167      * Because making a copy can be a very expensive process, this
168      * method does not return a copy of the service reference associated
169      * with the given event. Rather, it returns the appropriate service
170      * reference from the cache itself. Due to this cost, listeners that
171      * receive a <code>ServiceDiscoveryEvent</code> must not modify the
172      * contents of the object returned by this method; doing so could
173      * cause the state of the cache to become corrupted or inconsistent
174      * because the objects returned by this method are also members of
175      * the cache. This potential for corruption or inconsistency is why
176      * the effects of modifying the object returned by this accessor
177      * method are undefined.
178      *
179      * @return ServiceItem containing the service reference corresponding 
180      *  		to the given event.
181      */
182     public ServiceItem getPreEventServiceItem() 
183     {
184 	return preEventItem.clone();
185     }
186 
187     /**
188      * Returns an instance of a <code>ServiceItem</code> containing the
189      * service reference corresponding to the given event. The service
190      * state reflected in the returned service item is the state of the
191      * service after the occurrence of the event.  
192      * <p> 
193      * If the event is a removal event, then this method will return 
194      * <code>null</code> because the discovered service has no state in  
195      * the cache after it is removed from the cache.
196      * <p>
197      * Because making a copy can be a very expensive process, this
198      * method does not return a copy of the service reference associated
199      * with the given event. Rather, it returns the appropriate service
200      * reference from the cache itself. Due to this cost, listeners that
201      * receive a <code>ServiceDiscoveryEvent</code> must not modify the
202      * contents of the object returned by this method; doing so could
203      * cause the state of the cache to become corrupted or inconsistent
204      * because the objects returned by this method are also members of
205      * the cache. This potential for corruption or inconsistency is why
206      * the effects of modifying the object returned by this accessor
207      * method are undefined.
208      *
209      * @return ServiceItem containing the service reference corresponding 
210      *  		to the given event.
211      */
212     public ServiceItem getPostEventServiceItem() 
213     {
214 	return postEventItem.clone();
215     }
216 	
217 }