Bukkit  1.4.7-R1.0
 All Classes Namespaces Files Functions Variables Enumerator Pages
StandardMessenger.java
Go to the documentation of this file.
1 package org.bukkit.plugin.messaging;
2 
3 import com.google.common.collect.ImmutableSet;
4 import com.google.common.collect.ImmutableSet.Builder;
5 import java.util.HashMap;
6 import java.util.HashSet;
7 import java.util.Map;
8 import java.util.Set;
9 import org.bukkit.entity.Player;
10 import org.bukkit.plugin.Plugin;
11 
15 public class StandardMessenger implements Messenger {
16  private final Map<String, Set<PluginMessageListenerRegistration>> incomingByChannel = new HashMap<String, Set<PluginMessageListenerRegistration>>();
17  private final Map<Plugin, Set<PluginMessageListenerRegistration>> incomingByPlugin = new HashMap<Plugin, Set<PluginMessageListenerRegistration>>();
18  private final Map<String, Set<Plugin>> outgoingByChannel = new HashMap<String, Set<Plugin>>();
19  private final Map<Plugin, Set<String>> outgoingByPlugin = new HashMap<Plugin, Set<String>>();
20  private final Object incomingLock = new Object();
21  private final Object outgoingLock = new Object();
22 
23  private void addToOutgoing(Plugin plugin, String channel) {
24  synchronized (outgoingLock) {
25  Set<Plugin> plugins = outgoingByChannel.get(channel);
26  Set<String> channels = outgoingByPlugin.get(plugin);
27 
28  if (plugins == null) {
29  plugins = new HashSet<Plugin>();
30  outgoingByChannel.put(channel, plugins);
31  }
32 
33  if (channels == null) {
34  channels = new HashSet<String>();
35  outgoingByPlugin.put(plugin, channels);
36  }
37 
38  plugins.add(plugin);
39  channels.add(channel);
40  }
41  }
42 
43  private void removeFromOutgoing(Plugin plugin, String channel) {
44  synchronized (outgoingLock) {
45  Set<Plugin> plugins = outgoingByChannel.get(channel);
46  Set<String> channels = outgoingByPlugin.get(plugin);
47 
48  if (plugins != null) {
49  plugins.remove(plugin);
50 
51  if (plugins.isEmpty()) {
52  outgoingByChannel.remove(channel);
53  }
54  }
55 
56  if (channels != null) {
57  channels.remove(channel);
58 
59  if (channels.isEmpty()) {
60  outgoingByChannel.remove(channel);
61  }
62  }
63  }
64  }
65 
66  private void removeFromOutgoing(Plugin plugin) {
67  synchronized (outgoingLock) {
68  Set<String> channels = outgoingByPlugin.get(plugin);
69 
70  if (channels != null) {
71  String[] toRemove = channels.toArray(new String[0]);
72 
73  outgoingByPlugin.remove(plugin);
74 
75  for (String channel : toRemove) {
76  removeFromOutgoing(plugin, channel);
77  }
78  }
79  }
80  }
81 
82  private void addToIncoming(PluginMessageListenerRegistration registration) {
83  synchronized (incomingLock) {
84  Set<PluginMessageListenerRegistration> registrations = incomingByChannel.get(registration.getChannel());
85 
86  if (registrations == null) {
87  registrations = new HashSet<PluginMessageListenerRegistration>();
88  incomingByChannel.put(registration.getChannel(), registrations);
89  } else {
90  if (registrations.contains(registration)) {
91  throw new IllegalArgumentException("This registration already exists");
92  }
93  }
94 
95  registrations.add(registration);
96 
97  registrations = incomingByPlugin.get(registration.getPlugin());
98 
99  if (registrations == null) {
100  registrations = new HashSet<PluginMessageListenerRegistration>();
101  incomingByPlugin.put(registration.getPlugin(), registrations);
102  } else {
103  if (registrations.contains(registration)) {
104  throw new IllegalArgumentException("This registration already exists");
105  }
106  }
107 
108  registrations.add(registration);
109  }
110  }
111 
112  private void removeFromIncoming(PluginMessageListenerRegistration registration) {
113  synchronized (incomingLock) {
114  Set<PluginMessageListenerRegistration> registrations = incomingByChannel.get(registration.getChannel());
115 
116  if (registrations != null) {
117  registrations.remove(registration);
118 
119  if (registrations.isEmpty()) {
120  incomingByChannel.remove(registration.getChannel());
121  }
122  }
123 
124  registrations = incomingByPlugin.get(registration.getPlugin());
125 
126  if (registrations != null) {
127  registrations.remove(registration);
128 
129  if (registrations.isEmpty()) {
130  incomingByPlugin.remove(registration.getPlugin());
131  }
132  }
133  }
134  }
135 
136  private void removeFromIncoming(Plugin plugin, String channel) {
137  synchronized (incomingLock) {
138  Set<PluginMessageListenerRegistration> registrations = incomingByPlugin.get(plugin);
139 
140  if (registrations != null) {
141  PluginMessageListenerRegistration[] toRemove = registrations.toArray(new PluginMessageListenerRegistration[0]);
142 
143  for (PluginMessageListenerRegistration registration : toRemove) {
144  if (registration.getChannel().equals(channel)) {
145  removeFromIncoming(registration);
146  }
147  }
148  }
149  }
150  }
151 
152  private void removeFromIncoming(Plugin plugin) {
153  synchronized (incomingLock) {
154  Set<PluginMessageListenerRegistration> registrations = incomingByPlugin.get(plugin);
155 
156  if (registrations != null) {
157  PluginMessageListenerRegistration[] toRemove = registrations.toArray(new PluginMessageListenerRegistration[0]);
158 
159  incomingByPlugin.remove(plugin);
160 
161  for (PluginMessageListenerRegistration registration : toRemove) {
162  removeFromIncoming(registration);
163  }
164  }
165  }
166  }
167 
168  public boolean isReservedChannel(String channel) {
169  validateChannel(channel);
170 
171  return channel.equals("REGISTER") || channel.equals("UNREGISTER");
172  }
173 
174  public void registerOutgoingPluginChannel(Plugin plugin, String channel) {
175  if (plugin == null) {
176  throw new IllegalArgumentException("Plugin cannot be null");
177  }
178  validateChannel(channel);
179  if (isReservedChannel(channel)) {
180  throw new ReservedChannelException(channel);
181  }
182 
183  addToOutgoing(plugin, channel);
184  }
185 
186  public void unregisterOutgoingPluginChannel(Plugin plugin, String channel) {
187  if (plugin == null) {
188  throw new IllegalArgumentException("Plugin cannot be null");
189  }
190  validateChannel(channel);
191 
192  removeFromOutgoing(plugin, channel);
193  }
194 
196  if (plugin == null) {
197  throw new IllegalArgumentException("Plugin cannot be null");
198  }
199 
200  removeFromOutgoing(plugin);
201  }
202 
204  if (plugin == null) {
205  throw new IllegalArgumentException("Plugin cannot be null");
206  }
207  validateChannel(channel);
208  if (isReservedChannel(channel)) {
209  throw new ReservedChannelException(channel);
210  }
211  if (listener == null) {
212  throw new IllegalArgumentException("Listener cannot be null");
213  }
214 
215  PluginMessageListenerRegistration result = new PluginMessageListenerRegistration(this, plugin, channel, listener);
216 
217  addToIncoming(result);
218 
219  return result;
220  }
221 
222  public void unregisterIncomingPluginChannel(Plugin plugin, String channel, PluginMessageListener listener) {
223  if (plugin == null) {
224  throw new IllegalArgumentException("Plugin cannot be null");
225  }
226  if (listener == null) {
227  throw new IllegalArgumentException("Listener cannot be null");
228  }
229  validateChannel(channel);
230 
231  removeFromIncoming(new PluginMessageListenerRegistration(this, plugin, channel, listener));
232  }
233 
234  public void unregisterIncomingPluginChannel(Plugin plugin, String channel) {
235  if (plugin == null) {
236  throw new IllegalArgumentException("Plugin cannot be null");
237  }
238  validateChannel(channel);
239 
240  removeFromIncoming(plugin, channel);
241  }
242 
244  if (plugin == null) {
245  throw new IllegalArgumentException("Plugin cannot be null");
246  }
247 
248  removeFromIncoming(plugin);
249  }
250 
251  public Set<String> getOutgoingChannels() {
252  synchronized (outgoingLock) {
253  Set<String> keys = outgoingByChannel.keySet();
254  return ImmutableSet.copyOf(keys);
255  }
256  }
257 
258  public Set<String> getOutgoingChannels(Plugin plugin) {
259  if (plugin == null) {
260  throw new IllegalArgumentException("Plugin cannot be null");
261  }
262 
263  synchronized (outgoingLock) {
264  Set<String> channels = outgoingByPlugin.get(plugin);
265 
266  if (channels != null) {
267  return ImmutableSet.copyOf(channels);
268  } else {
269  return ImmutableSet.of();
270  }
271  }
272  }
273 
274  public Set<String> getIncomingChannels() {
275  synchronized (incomingLock) {
276  Set<String> keys = incomingByChannel.keySet();
277  return ImmutableSet.copyOf(keys);
278  }
279  }
280 
281  public Set<String> getIncomingChannels(Plugin plugin) {
282  if (plugin == null) {
283  throw new IllegalArgumentException("Plugin cannot be null");
284  }
285 
286  synchronized (incomingLock) {
287  Set<PluginMessageListenerRegistration> registrations = incomingByPlugin.get(plugin);
288 
289  if (registrations != null) {
290  Builder<String> builder = ImmutableSet.builder();
291 
292  for (PluginMessageListenerRegistration registration : registrations) {
293  builder.add(registration.getChannel());
294  }
295 
296  return builder.build();
297  } else {
298  return ImmutableSet.of();
299  }
300  }
301  }
302 
303  public Set<PluginMessageListenerRegistration> getIncomingChannelRegistrations(Plugin plugin) {
304  if (plugin == null) {
305  throw new IllegalArgumentException("Plugin cannot be null");
306  }
307 
308  synchronized (incomingLock) {
309  Set<PluginMessageListenerRegistration> registrations = incomingByPlugin.get(plugin);
310 
311  if (registrations != null) {
312  return ImmutableSet.copyOf(registrations);
313  } else {
314  return ImmutableSet.of();
315  }
316  }
317  }
318 
319  public Set<PluginMessageListenerRegistration> getIncomingChannelRegistrations(String channel) {
320  validateChannel(channel);
321 
322  synchronized (incomingLock) {
323  Set<PluginMessageListenerRegistration> registrations = incomingByChannel.get(channel);
324 
325  if (registrations != null) {
326  return ImmutableSet.copyOf(registrations);
327  } else {
328  return ImmutableSet.of();
329  }
330  }
331  }
332 
333  public Set<PluginMessageListenerRegistration> getIncomingChannelRegistrations(Plugin plugin, String channel) {
334  if (plugin == null) {
335  throw new IllegalArgumentException("Plugin cannot be null");
336  }
337  validateChannel(channel);
338 
339  synchronized (incomingLock) {
340  Set<PluginMessageListenerRegistration> registrations = incomingByPlugin.get(plugin);
341 
342  if (registrations != null) {
343  Builder<PluginMessageListenerRegistration> builder = ImmutableSet.builder();
344 
345  for (PluginMessageListenerRegistration registration : registrations) {
346  if (registration.getChannel().equals(channel)) {
347  builder.add(registration);
348  }
349  }
350 
351  return builder.build();
352  } else {
353  return ImmutableSet.of();
354  }
355  }
356  }
357 
359  if (registration == null) {
360  throw new IllegalArgumentException("Registration cannot be null");
361  }
362 
363  synchronized (incomingLock) {
364  Set<PluginMessageListenerRegistration> registrations = incomingByPlugin.get(registration.getPlugin());
365 
366  if (registrations != null) {
367  return registrations.contains(registration);
368  }
369 
370  return false;
371  }
372  }
373 
374  public boolean isIncomingChannelRegistered(Plugin plugin, String channel) {
375  if (plugin == null) {
376  throw new IllegalArgumentException("Plugin cannot be null");
377  }
378  validateChannel(channel);
379 
380  synchronized (incomingLock) {
381  Set<PluginMessageListenerRegistration> registrations = incomingByPlugin.get(plugin);
382 
383  if (registrations != null) {
384  for (PluginMessageListenerRegistration registration : registrations) {
385  if (registration.getChannel().equals(channel)) {
386  return true;
387  }
388  }
389  }
390 
391  return false;
392  }
393  }
394 
395  public boolean isOutgoingChannelRegistered(Plugin plugin, String channel) {
396  if (plugin == null) {
397  throw new IllegalArgumentException("Plugin cannot be null");
398  }
399  validateChannel(channel);
400 
401  synchronized (outgoingLock) {
402  Set<String> channels = outgoingByPlugin.get(plugin);
403 
404  if (channels != null) {
405  return channels.contains(channel);
406  }
407 
408  return false;
409  }
410  }
411 
412  public void dispatchIncomingMessage(Player source, String channel, byte[] message) {
413  if (source == null) {
414  throw new IllegalArgumentException("Player source cannot be null");
415  }
416  if (message == null) {
417  throw new IllegalArgumentException("Message cannot be null");
418  }
419  validateChannel(channel);
420 
421  Set<PluginMessageListenerRegistration> registrations = getIncomingChannelRegistrations(channel);
422 
423  for (PluginMessageListenerRegistration registration : registrations) {
424  registration.getListener().onPluginMessageReceived(channel, source, message);
425  }
426  }
427 
433  public static void validateChannel(String channel) {
434  if (channel == null) {
435  throw new IllegalArgumentException("Channel cannot be null");
436  }
437  if (channel.length() > Messenger.MAX_CHANNEL_SIZE) {
438  throw new ChannelNameTooLongException(channel);
439  }
440  }
441 
455  public static void validatePluginMessage(Messenger messenger, Plugin source, String channel, byte[] message) {
456  if (messenger == null) {
457  throw new IllegalArgumentException("Messenger cannot be null");
458  }
459  if (source == null) {
460  throw new IllegalArgumentException("Plugin source cannot be null");
461  }
462  if (!source.isEnabled()) {
463  throw new IllegalArgumentException("Plugin must be enabled to send messages");
464  }
465  if (message == null) {
466  throw new IllegalArgumentException("Message cannot be null");
467  }
468  if (!messenger.isOutgoingChannelRegistered(source, channel)) {
469  throw new ChannelNotRegisteredException(channel);
470  }
471  if (message.length > Messenger.MAX_MESSAGE_SIZE) {
472  throw new MessageTooLargeException(message);
473  }
474  validateChannel(channel);
475  }
476 }