Bukkit-API  1.7.9-R0.2
The inofficial Bukkit-API
HandlerList.java
1 package org.bukkit.event;
2 
3 import org.bukkit.plugin.Plugin;
5 
6 import java.util.*;
7 import java.util.Map.Entry;
8 
9 /**
10  * A list of event handlers, stored per-event. Based on lahwran's fevents.
11  */
12 public class HandlerList {
13 
14  /**
15  * Handler array. This field being an array is the key to this system's
16  * speed.
17  */
18  private volatile RegisteredListener[] handlers = null;
19 
20  /**
21  * Dynamic handler lists. These are changed using register() and
22  * unregister() and are automatically baked to the handlers array any time
23  * they have changed.
24  */
25  private final EnumMap<EventPriority, ArrayList<RegisteredListener>> handlerslots;
26 
27  /**
28  * List of all HandlerLists which have been created, for use in bakeAll()
29  */
30  private static ArrayList<HandlerList> allLists = new ArrayList<HandlerList>();
31 
32  /**
33  * Bake all handler lists. Best used just after all normal event
34  * registration is complete, ie just after all plugins are loaded if
35  * you're using fevents in a plugin system.
36  */
37  public static void bakeAll() {
38  synchronized (allLists) {
39  for (HandlerList h : allLists) {
40  h.bake();
41  }
42  }
43  }
44 
45  /**
46  * Unregister all listeners from all handler lists.
47  */
48  public static void unregisterAll() {
49  synchronized (allLists) {
50  for (HandlerList h : allLists) {
51  synchronized (h) {
52  for (List<RegisteredListener> list : h.handlerslots.values()) {
53  list.clear();
54  }
55  h.handlers = null;
56  }
57  }
58  }
59  }
60 
61  /**
62  * Unregister a specific plugin's listeners from all handler lists.
63  *
64  * @param plugin plugin to unregister
65  */
66  public static void unregisterAll(Plugin plugin) {
67  synchronized (allLists) {
68  for (HandlerList h : allLists) {
69  h.unregister(plugin);
70  }
71  }
72  }
73 
74  /**
75  * Unregister a specific listener from all handler lists.
76  *
77  * @param listener listener to unregister
78  */
79  public static void unregisterAll(Listener listener) {
80  synchronized (allLists) {
81  for (HandlerList h : allLists) {
82  h.unregister(listener);
83  }
84  }
85  }
86 
87  /**
88  * Create a new handler list and initialize using EventPriority.
89  * <p>
90  * The HandlerList is then added to meta-list for use in bakeAll()
91  */
92  public HandlerList() {
93  handlerslots = new EnumMap<EventPriority, ArrayList<RegisteredListener>>(EventPriority.class);
94  for (EventPriority o : EventPriority.values()) {
95  handlerslots.put(o, new ArrayList<RegisteredListener>());
96  }
97  synchronized (allLists) {
98  allLists.add(this);
99  }
100  }
101 
102  /**
103  * Register a new listener in this handler list
104  *
105  * @param listener listener to register
106  */
107  public synchronized void register(RegisteredListener listener) {
108  if (handlerslots.get(listener.getPriority()).contains(listener))
109  throw new IllegalStateException("This listener is already registered to priority " + listener.getPriority().toString());
110  handlers = null;
111  handlerslots.get(listener.getPriority()).add(listener);
112  }
113 
114  /**
115  * Register a collection of new listeners in this handler list
116  *
117  * @param listeners listeners to register
118  */
119  public void registerAll(Collection<RegisteredListener> listeners) {
120  for (RegisteredListener listener : listeners) {
121  register(listener);
122  }
123  }
124 
125  /**
126  * Remove a listener from a specific order slot
127  *
128  * @param listener listener to remove
129  */
130  public synchronized void unregister(RegisteredListener listener) {
131  if (handlerslots.get(listener.getPriority()).remove(listener)) {
132  handlers = null;
133  }
134  }
135 
136  /**
137  * Remove a specific plugin's listeners from this handler
138  *
139  * @param plugin plugin to remove
140  */
141  public synchronized void unregister(Plugin plugin) {
142  boolean changed = false;
143  for (List<RegisteredListener> list : handlerslots.values()) {
144  for (ListIterator<RegisteredListener> i = list.listIterator(); i.hasNext();) {
145  if (i.next().getPlugin().equals(plugin)) {
146  i.remove();
147  changed = true;
148  }
149  }
150  }
151  if (changed) handlers = null;
152  }
153 
154  /**
155  * Remove a specific listener from this handler
156  *
157  * @param listener listener to remove
158  */
159  public synchronized void unregister(Listener listener) {
160  boolean changed = false;
161  for (List<RegisteredListener> list : handlerslots.values()) {
162  for (ListIterator<RegisteredListener> i = list.listIterator(); i.hasNext();) {
163  if (i.next().getListener().equals(listener)) {
164  i.remove();
165  changed = true;
166  }
167  }
168  }
169  if (changed) handlers = null;
170  }
171 
172  /**
173  * Bake HashMap and ArrayLists to 2d array - does nothing if not necessary
174  */
175  public synchronized void bake() {
176  if (handlers != null) return; // don't re-bake when still valid
177  List<RegisteredListener> entries = new ArrayList<RegisteredListener>();
178  for (Entry<EventPriority, ArrayList<RegisteredListener>> entry : handlerslots.entrySet()) {
179  entries.addAll(entry.getValue());
180  }
181  handlers = entries.toArray(new RegisteredListener[entries.size()]);
182  }
183 
184  /**
185  * Get the baked registered listeners associated with this handler list
186  *
187  * @return the array of registered listeners
188  */
190  RegisteredListener[] handlers;
191  while ((handlers = this.handlers) == null) bake(); // This prevents fringe cases of returning null
192  return handlers;
193  }
194 
195  /**
196  * Get a specific plugin's registered listeners associated with this
197  * handler list
198  *
199  * @param plugin the plugin to get the listeners of
200  * @return the list of registered listeners
201  */
202  public static ArrayList<RegisteredListener> getRegisteredListeners(Plugin plugin) {
203  ArrayList<RegisteredListener> listeners = new ArrayList<RegisteredListener>();
204  synchronized (allLists) {
205  for (HandlerList h : allLists) {
206  synchronized (h) {
207  for (List<RegisteredListener> list : h.handlerslots.values()) {
208  for (RegisteredListener listener : list) {
209  if (listener.getPlugin().equals(plugin)) {
210  listeners.add(listener);
211  }
212  }
213  }
214  }
215  }
216  }
217  return listeners;
218  }
219 
220  /**
221  * Get a list of all handler lists for every event type
222  *
223  * @return the list of all handler lists
224  */
225  @SuppressWarnings("unchecked")
226  public static ArrayList<HandlerList> getHandlerLists() {
227  synchronized (allLists) {
228  return (ArrayList<HandlerList>) allLists.clone();
229  }
230  }
231 }
RegisteredListener[] getRegisteredListeners()
synchronized void unregister(Listener listener)
static void unregisterAll(Listener listener)
static void unregisterAll(Plugin plugin)
synchronized void bake()
static ArrayList< RegisteredListener > getRegisteredListeners(Plugin plugin)
static ArrayList< HandlerList > getHandlerLists()
void registerAll(Collection< RegisteredListener > listeners)
synchronized void unregister(Plugin plugin)
synchronized void unregister(RegisteredListener listener)