1/*
2 * Copyright (c) 1999, 2000, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package javax.naming.event;
27
28import javax.naming.Binding;
29
30/**
31  * This class represents an event fired by a naming/directory service.
32  *<p>
33  * The {@code NamingEvent}'s state consists of
34  * <ul>
35  * <li>The event source: the {@code EventContext} which fired this event.
36  * <li>The event type.
37  * <li>The new binding: information about the object after the change.
38  * <li>The old binding: information about the object before the change.
39  * <li>Change information: information about the change
40  * that triggered this event; usually service provider-specific or server-specific
41  * information.
42  * </ul>
43  * <p>
44  * Note that the event source is always the same {@code EventContext}
45  * <em>instance</em>  that the listener has registered with.
46  * Furthermore, the names of the bindings in
47  * the {@code NamingEvent} are always relative to that instance.
48  * For example, suppose a listener makes the following registration:
49  *<blockquote><pre>
50  *     NamespaceChangeListener listener = ...;
51  *     src.addNamingListener("x", SUBTREE_SCOPE, listener);
52  *</pre></blockquote>
53  * When an object named "x/y" is subsequently deleted, the corresponding
54  * {@code NamingEvent} ({@code evt}) must contain:
55  *<blockquote><pre>
56  *     evt.getEventContext() == src
57  *     evt.getOldBinding().getName().equals("x/y")
58  *</pre></blockquote>
59  *
60  * Care must be taken when multiple threads are accessing the same
61  * {@code EventContext} concurrently.
62  * See the
63  * <a href=package-summary.html#THREADING>package description</a>
64  * for more information on threading issues.
65  *
66  * @author Rosanna Lee
67  * @author Scott Seligman
68  *
69  * @see NamingListener
70  * @see EventContext
71  * @since 1.3
72  */
73public class NamingEvent extends java.util.EventObject {
74    /**
75     * Naming event type for indicating that a new object has been added.
76     * The value of this constant is {@code 0}.
77     */
78    public static final int OBJECT_ADDED = 0;
79
80    /**
81     * Naming event type for indicating that an object has been removed.
82     * The value of this constant is {@code 1}.
83     */
84    public static final int OBJECT_REMOVED = 1;
85
86    /**
87     * Naming event type for indicating that an object has been renamed.
88     * Note that some services might fire multiple events for a single
89     * logical rename operation. For example, the rename operation might
90     * be implemented by adding a binding with the new name and removing
91     * the old binding.
92     *<p>
93     * The old/new binding in {@code NamingEvent} may be null if the old
94     * name or new name is outside of the scope for which the listener
95     * has registered.
96     *<p>
97     * When an interior node in the namespace tree has been renamed, the
98     * topmost node which is part of the listener's scope should used to generate
99     * a rename event. The extent to which this can be supported is
100     * provider-specific. For example, a service might generate rename
101     * notifications for all descendants of the changed interior node and the
102     * corresponding provider might not be able to prevent those
103     * notifications from being propagated to the listeners.
104     *<p>
105     * The value of this constant is {@code 2}.
106     */
107    public static final int OBJECT_RENAMED = 2;
108
109    /**
110     * Naming event type for indicating that an object has been changed.
111     * The changes might include the object's attributes, or the object itself.
112     * Note that some services might fire multiple events for a single
113     * modification. For example, the modification might
114     * be implemented by first removing the old binding and adding
115     * a new binding containing the same name but a different object.
116     *<p>
117     * The value of this constant is {@code 3}.
118     */
119    public static final int OBJECT_CHANGED = 3;
120
121    /**
122     * Contains information about the change that generated this event.
123     * @serial
124     */
125    protected Object changeInfo;
126
127    /**
128     * Contains the type of this event.
129     * @see #OBJECT_ADDED
130     * @see #OBJECT_REMOVED
131     * @see #OBJECT_RENAMED
132     * @see #OBJECT_CHANGED
133     * @serial
134     */
135    protected int type;
136
137    /**
138     * Contains information about the object before the change.
139     * @serial
140     */
141    protected Binding oldBinding;
142
143    /**
144     * Contains information about the object after the change.
145     * @serial
146     */
147    protected Binding newBinding;
148
149    /**
150     * Constructs an instance of {@code NamingEvent}.
151     *<p>
152     * The names in {@code newBd} and {@code oldBd} are to be resolved relative
153     * to the event source {@code source}.
154     *
155     * For an {@code OBJECT_ADDED} event type, {@code newBd} must not be null.
156     * For an {@code OBJECT_REMOVED} event type, {@code oldBd} must not be null.
157     * For an {@code OBJECT_CHANGED} event type,  {@code newBd} and
158     * {@code oldBd} must not be null. For  an {@code OBJECT_RENAMED} event type,
159     * one of {@code newBd} or {@code oldBd} may be null if the new or old
160     * binding is outside of the scope for which the listener has registered.
161     *
162     * @param source The non-null context that fired this event.
163     * @param type The type of the event.
164     * @param newBd A possibly null binding before the change. See method description.
165     * @param oldBd A possibly null binding after the change. See method description.
166     * @param changeInfo A possibly null object containing information about the change.
167     * @see #OBJECT_ADDED
168     * @see #OBJECT_REMOVED
169     * @see #OBJECT_RENAMED
170     * @see #OBJECT_CHANGED
171     */
172    public NamingEvent(EventContext source, int type,
173        Binding newBd, Binding oldBd, Object changeInfo) {
174        super(source);
175        this.type = type;
176        oldBinding = oldBd;
177        newBinding = newBd;
178        this.changeInfo = changeInfo;
179    }
180
181    /**
182     * Returns the type of this event.
183     * @return The type of this event.
184     * @see #OBJECT_ADDED
185     * @see #OBJECT_REMOVED
186     * @see #OBJECT_RENAMED
187     * @see #OBJECT_CHANGED
188     */
189    public int getType() {
190        return type;
191    }
192
193    /**
194     * Retrieves the event source that fired this event.
195     * This returns the same object as {@code EventObject.getSource()}.
196     *<p>
197     * If the result of this method is used to access the
198     * event source, for example, to look up the object or get its attributes,
199     * then it needs to be locked  because implementations of {@code Context}
200     * are not guaranteed to be thread-safe
201     * (and {@code EventContext} is a subinterface of {@code Context}).
202     * See the
203     * <a href=package-summary.html#THREADING>package description</a>
204     * for more information on threading issues.
205     *
206     * @return The non-null context that fired this event.
207     */
208    public EventContext getEventContext() {
209        return (EventContext)getSource();
210    }
211
212    /**
213     * Retrieves the binding of the object before the change.
214     *<p>
215     * The binding must be nonnull if the object existed before the change
216     * relative to the source context ({@code getEventContext()}).
217     * That is, it must be nonnull for {@code OBJECT_REMOVED} and
218     * {@code OBJECT_CHANGED}.
219     * For {@code OBJECT_RENAMED}, it is null if the object before the rename
220     * is outside of the scope for which the listener has registered interest;
221     * it is nonnull if the object is inside the scope before the rename.
222     *<p>
223     * The name in the binding is to be resolved relative
224     * to the event source {@code getEventContext()}.
225     * The object returned by {@code Binding.getObject()} may be null if
226     * such information is unavailable.
227     *
228     * @return The possibly null binding of the object before the change.
229     */
230    public Binding getOldBinding() {
231        return oldBinding;
232    }
233
234    /**
235     * Retrieves the binding of the object after the change.
236     *<p>
237     * The binding must be nonnull if the object existed after the change
238     * relative to the source context ({@code getEventContext()}).
239     * That is, it must be nonnull for {@code OBJECT_ADDED} and
240     * {@code OBJECT_CHANGED}. For {@code OBJECT_RENAMED},
241     * it is null if the object after the rename is outside the scope for
242     * which the listener registered interest; it is nonnull if the object
243     * is inside the scope after the rename.
244     *<p>
245     * The name in the binding is to be resolved relative
246     * to the event source {@code getEventContext()}.
247     * The object returned by {@code Binding.getObject()} may be null if
248     * such information is unavailable.
249     *
250     * @return The possibly null binding of the object after the change.
251     */
252    public Binding getNewBinding() {
253        return newBinding;
254    }
255
256    /**
257     * Retrieves the change information for this event.
258     * The value of the change information is service-specific. For example,
259     * it could be an ID that identifies the change in a change log on the server.
260     *
261     * @return The possibly null change information of this event.
262     */
263    public Object getChangeInfo() {
264        return changeInfo;
265    }
266
267    /**
268     * Invokes the appropriate listener method on this event.
269     * The default implementation of
270     * this method handles the following event types:
271     * {@code OBJECT_ADDED, OBJECT_REMOVED,
272     * OBJECT_RENAMED, OBJECT_CHANGED}.
273     *<p>
274     * The listener method is executed in the same thread
275     * as this method.  See the
276     * <a href=package-summary.html#THREADING>package description</a>
277     * for more information on threading issues.
278     * @param listener The nonnull listener.
279     */
280    public void dispatch(NamingListener listener) {
281        switch (type) {
282        case OBJECT_ADDED:
283            ((NamespaceChangeListener)listener).objectAdded(this);
284            break;
285
286        case OBJECT_REMOVED:
287            ((NamespaceChangeListener)listener).objectRemoved(this);
288            break;
289
290        case OBJECT_RENAMED:
291            ((NamespaceChangeListener)listener).objectRenamed(this);
292            break;
293
294        case OBJECT_CHANGED:
295            ((ObjectChangeListener)listener).objectChanged(this);
296            break;
297        }
298    }
299    private static final long serialVersionUID = -7126752885365133499L;
300}
301