Bukkit-API  1.7.9-R0.2
The inofficial Bukkit-API
StandardMessenger.java
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 
12 /**
13  * Standard implementation to {@link Messenger}
14  */
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 
428  /**
429  * Validates a Plugin Channel name.
430  *
431  * @param channel Channel name to validate.
432  */
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 
442  /**
443  * Validates the input of a Plugin Message, ensuring the arguments are all
444  * valid.
445  *
446  * @param messenger Messenger to use for validation.
447  * @param source Source plugin of the Message.
448  * @param channel Plugin Channel to send the message by.
449  * @param message Raw message payload to send.
450  * @throws IllegalArgumentException Thrown if the source plugin is
451  * disabled.
452  * @throws IllegalArgumentException Thrown if source, channel or message
453  * is null.
454  * @throws MessageTooLargeException Thrown if the message is too big.
455  * @throws ChannelNameTooLongException Thrown if the channel name is too
456  * long.
457  * @throws ChannelNotRegisteredException Thrown if the channel is not
458  * registered for this plugin.
459  */
460  public static void validatePluginMessage(Messenger messenger, Plugin source, String channel, byte[] message) {
461  if (messenger == null) {
462  throw new IllegalArgumentException("Messenger cannot be null");
463  }
464  if (source == null) {
465  throw new IllegalArgumentException("Plugin source cannot be null");
466  }
467  if (!source.isEnabled()) {
468  throw new IllegalArgumentException("Plugin must be enabled to send messages");
469  }
470  if (message == null) {
471  throw new IllegalArgumentException("Message cannot be null");
472  }
473  if (!messenger.isOutgoingChannelRegistered(source, channel)) {
474  throw new ChannelNotRegisteredException(channel);
475  }
476  if (message.length > Messenger.MAX_MESSAGE_SIZE) {
477  throw new MessageTooLargeException(message);
478  }
479  validateChannel(channel);
480  }
481 }
void registerOutgoingPluginChannel(Plugin plugin, String channel)
boolean isOutgoingChannelRegistered(Plugin plugin, String channel)
void onPluginMessageReceived(String channel, Player player, byte[] message)
void unregisterOutgoingPluginChannel(Plugin plugin, String channel)
Set< PluginMessageListenerRegistration > getIncomingChannelRegistrations(Plugin plugin, String channel)
void unregisterIncomingPluginChannel(Plugin plugin, String channel)
void unregisterIncomingPluginChannel(Plugin plugin, String channel, PluginMessageListener listener)
static void validatePluginMessage(Messenger messenger, Plugin source, String channel, byte[] message)
boolean isRegistrationValid(PluginMessageListenerRegistration registration)
boolean isOutgoingChannelRegistered(Plugin plugin, String channel)
boolean isIncomingChannelRegistered(Plugin plugin, String channel)
Set< PluginMessageListenerRegistration > getIncomingChannelRegistrations(Plugin plugin)
Set< PluginMessageListenerRegistration > getIncomingChannelRegistrations(String channel)
void dispatchIncomingMessage(Player source, String channel, byte[] message)
PluginMessageListenerRegistration registerIncomingPluginChannel(Plugin plugin, String channel, PluginMessageListener listener)