All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bukkit.plugin.messaging.StandardMessenger Maven / Gradle / Ivy

package org.bukkit.plugin.messaging;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Standard implementation to {@link Messenger}
 */
public class StandardMessenger implements Messenger {
  private final Map> incomingByChannel = new HashMap>();
  private final Map> incomingByPlugin = new HashMap>();
  private final Map> outgoingByChannel = new HashMap>();
  private final Map> outgoingByPlugin = new HashMap>();
  private final Object incomingLock = new Object();
  private final Object outgoingLock = new Object();

  /**
   * Validates a Plugin Channel name.
   *
   * @param channel Channel name to validate.
   */
  public static void validateChannel(String channel) {
    if (channel == null) {
      throw new IllegalArgumentException("Channel cannot be null");
    }
    if (channel.length() > Messenger.MAX_CHANNEL_SIZE) {
      throw new ChannelNameTooLongException(channel);
    }
  }

  /**
   * Validates the input of a Plugin Message, ensuring the arguments are all
   * valid.
   *
   * @param messenger Messenger to use for validation.
   * @param source    Source plugin of the Message.
   * @param channel   Plugin Channel to send the message by.
   * @param message   Raw message payload to send.
   * @throws IllegalArgumentException      Thrown if the source plugin is
   *                                       disabled.
   * @throws IllegalArgumentException      Thrown if source, channel or message
   *                                       is null.
   * @throws MessageTooLargeException      Thrown if the message is too big.
   * @throws ChannelNameTooLongException   Thrown if the channel name is too
   *                                       long.
   * @throws ChannelNotRegisteredException Thrown if the channel is not
   *                                       registered for this plugin.
   */
  public static void validatePluginMessage(Messenger messenger, Plugin source, String channel, byte[] message) {
    if (messenger == null) {
      throw new IllegalArgumentException("Messenger cannot be null");
    }
    if (source == null) {
      throw new IllegalArgumentException("Plugin source cannot be null");
    }
    if (!source.isEnabled()) {
      throw new IllegalArgumentException("Plugin must be enabled to send messages");
    }
    if (message == null) {
      throw new IllegalArgumentException("Message cannot be null");
    }
    if (!messenger.isOutgoingChannelRegistered(source, channel)) {
      throw new ChannelNotRegisteredException(channel);
    }
    if (message.length > Messenger.MAX_MESSAGE_SIZE) {
      throw new MessageTooLargeException(message);
    }
    validateChannel(channel);
  }

  private void addToOutgoing(Plugin plugin, String channel) {
    synchronized (outgoingLock) {
      Set plugins = outgoingByChannel.get(channel);
      Set channels = outgoingByPlugin.get(plugin);

      if (plugins == null) {
        plugins = new HashSet();
        outgoingByChannel.put(channel, plugins);
      }

      if (channels == null) {
        channels = new HashSet();
        outgoingByPlugin.put(plugin, channels);
      }

      plugins.add(plugin);
      channels.add(channel);
    }
  }

  private void removeFromOutgoing(Plugin plugin, String channel) {
    synchronized (outgoingLock) {
      Set plugins = outgoingByChannel.get(channel);
      Set channels = outgoingByPlugin.get(plugin);

      if (plugins != null) {
        plugins.remove(plugin);

        if (plugins.isEmpty()) {
          outgoingByChannel.remove(channel);
        }
      }

      if (channels != null) {
        channels.remove(channel);

        if (channels.isEmpty()) {
          outgoingByChannel.remove(channel);
        }
      }
    }
  }

  private void removeFromOutgoing(Plugin plugin) {
    synchronized (outgoingLock) {
      Set channels = outgoingByPlugin.get(plugin);

      if (channels != null) {
        String[] toRemove = channels.toArray(new String[0]);

        outgoingByPlugin.remove(plugin);

        for (String channel : toRemove) {
          removeFromOutgoing(plugin, channel);
        }
      }
    }
  }

  private void addToIncoming(PluginMessageListenerRegistration registration) {
    synchronized (incomingLock) {
      Set registrations = incomingByChannel.get(registration.getChannel());

      if (registrations == null) {
        registrations = new HashSet();
        incomingByChannel.put(registration.getChannel(), registrations);
      } else {
        if (registrations.contains(registration)) {
          throw new IllegalArgumentException("This registration already exists");
        }
      }

      registrations.add(registration);

      registrations = incomingByPlugin.get(registration.getPlugin());

      if (registrations == null) {
        registrations = new HashSet();
        incomingByPlugin.put(registration.getPlugin(), registrations);
      } else {
        if (registrations.contains(registration)) {
          throw new IllegalArgumentException("This registration already exists");
        }
      }

      registrations.add(registration);
    }
  }

  private void removeFromIncoming(PluginMessageListenerRegistration registration) {
    synchronized (incomingLock) {
      Set registrations = incomingByChannel.get(registration.getChannel());

      if (registrations != null) {
        registrations.remove(registration);

        if (registrations.isEmpty()) {
          incomingByChannel.remove(registration.getChannel());
        }
      }

      registrations = incomingByPlugin.get(registration.getPlugin());

      if (registrations != null) {
        registrations.remove(registration);

        if (registrations.isEmpty()) {
          incomingByPlugin.remove(registration.getPlugin());
        }
      }
    }
  }

  private void removeFromIncoming(Plugin plugin, String channel) {
    synchronized (incomingLock) {
      Set registrations = incomingByPlugin.get(plugin);

      if (registrations != null) {
        PluginMessageListenerRegistration[] toRemove = registrations.toArray(new PluginMessageListenerRegistration[0]);

        for (PluginMessageListenerRegistration registration : toRemove) {
          if (registration.getChannel().equals(channel)) {
            removeFromIncoming(registration);
          }
        }
      }
    }
  }

  private void removeFromIncoming(Plugin plugin) {
    synchronized (incomingLock) {
      Set registrations = incomingByPlugin.get(plugin);

      if (registrations != null) {
        PluginMessageListenerRegistration[] toRemove = registrations.toArray(new PluginMessageListenerRegistration[0]);

        incomingByPlugin.remove(plugin);

        for (PluginMessageListenerRegistration registration : toRemove) {
          removeFromIncoming(registration);
        }
      }
    }
  }

  public boolean isReservedChannel(String channel) {
    validateChannel(channel);

    return channel.equals("REGISTER") || channel.equals("UNREGISTER");
  }

  public void registerOutgoingPluginChannel(Plugin plugin, String channel) {
    if (plugin == null) {
      throw new IllegalArgumentException("Plugin cannot be null");
    }
    validateChannel(channel);
    if (isReservedChannel(channel)) {
      throw new ReservedChannelException(channel);
    }

    addToOutgoing(plugin, channel);
  }

  public void unregisterOutgoingPluginChannel(Plugin plugin, String channel) {
    if (plugin == null) {
      throw new IllegalArgumentException("Plugin cannot be null");
    }
    validateChannel(channel);

    removeFromOutgoing(plugin, channel);
  }

  public void unregisterOutgoingPluginChannel(Plugin plugin) {
    if (plugin == null) {
      throw new IllegalArgumentException("Plugin cannot be null");
    }

    removeFromOutgoing(plugin);
  }

  public PluginMessageListenerRegistration registerIncomingPluginChannel(Plugin plugin, String channel, PluginMessageListener listener) {
    if (plugin == null) {
      throw new IllegalArgumentException("Plugin cannot be null");
    }
    validateChannel(channel);
    if (isReservedChannel(channel)) {
      throw new ReservedChannelException(channel);
    }
    if (listener == null) {
      throw new IllegalArgumentException("Listener cannot be null");
    }

    PluginMessageListenerRegistration result = new PluginMessageListenerRegistration(this, plugin, channel, listener);

    addToIncoming(result);

    return result;
  }

  public void unregisterIncomingPluginChannel(Plugin plugin, String channel, PluginMessageListener listener) {
    if (plugin == null) {
      throw new IllegalArgumentException("Plugin cannot be null");
    }
    if (listener == null) {
      throw new IllegalArgumentException("Listener cannot be null");
    }
    validateChannel(channel);

    removeFromIncoming(new PluginMessageListenerRegistration(this, plugin, channel, listener));
  }

  public void unregisterIncomingPluginChannel(Plugin plugin, String channel) {
    if (plugin == null) {
      throw new IllegalArgumentException("Plugin cannot be null");
    }
    validateChannel(channel);

    removeFromIncoming(plugin, channel);
  }

  public void unregisterIncomingPluginChannel(Plugin plugin) {
    if (plugin == null) {
      throw new IllegalArgumentException("Plugin cannot be null");
    }

    removeFromIncoming(plugin);
  }

  public Set getOutgoingChannels() {
    synchronized (outgoingLock) {
      Set keys = outgoingByChannel.keySet();
      return ImmutableSet.copyOf(keys);
    }
  }

  public Set getOutgoingChannels(Plugin plugin) {
    if (plugin == null) {
      throw new IllegalArgumentException("Plugin cannot be null");
    }

    synchronized (outgoingLock) {
      Set channels = outgoingByPlugin.get(plugin);

      if (channels != null) {
        return ImmutableSet.copyOf(channels);
      } else {
        return ImmutableSet.of();
      }
    }
  }

  public Set getIncomingChannels() {
    synchronized (incomingLock) {
      Set keys = incomingByChannel.keySet();
      return ImmutableSet.copyOf(keys);
    }
  }

  public Set getIncomingChannels(Plugin plugin) {
    if (plugin == null) {
      throw new IllegalArgumentException("Plugin cannot be null");
    }

    synchronized (incomingLock) {
      Set registrations = incomingByPlugin.get(plugin);

      if (registrations != null) {
        Builder builder = ImmutableSet.builder();

        for (PluginMessageListenerRegistration registration : registrations) {
          builder.add(registration.getChannel());
        }

        return builder.build();
      } else {
        return ImmutableSet.of();
      }
    }
  }

  public Set getIncomingChannelRegistrations(Plugin plugin) {
    if (plugin == null) {
      throw new IllegalArgumentException("Plugin cannot be null");
    }

    synchronized (incomingLock) {
      Set registrations = incomingByPlugin.get(plugin);

      if (registrations != null) {
        return ImmutableSet.copyOf(registrations);
      } else {
        return ImmutableSet.of();
      }
    }
  }

  public Set getIncomingChannelRegistrations(String channel) {
    validateChannel(channel);

    synchronized (incomingLock) {
      Set registrations = incomingByChannel.get(channel);

      if (registrations != null) {
        return ImmutableSet.copyOf(registrations);
      } else {
        return ImmutableSet.of();
      }
    }
  }

  public Set getIncomingChannelRegistrations(Plugin plugin, String channel) {
    if (plugin == null) {
      throw new IllegalArgumentException("Plugin cannot be null");
    }
    validateChannel(channel);

    synchronized (incomingLock) {
      Set registrations = incomingByPlugin.get(plugin);

      if (registrations != null) {
        Builder builder = ImmutableSet.builder();

        for (PluginMessageListenerRegistration registration : registrations) {
          if (registration.getChannel().equals(channel)) {
            builder.add(registration);
          }
        }

        return builder.build();
      } else {
        return ImmutableSet.of();
      }
    }
  }

  public boolean isRegistrationValid(PluginMessageListenerRegistration registration) {
    if (registration == null) {
      throw new IllegalArgumentException("Registration cannot be null");
    }

    synchronized (incomingLock) {
      Set registrations = incomingByPlugin.get(registration.getPlugin());

      if (registrations != null) {
        return registrations.contains(registration);
      }

      return false;
    }
  }

  public boolean isIncomingChannelRegistered(Plugin plugin, String channel) {
    if (plugin == null) {
      throw new IllegalArgumentException("Plugin cannot be null");
    }
    validateChannel(channel);

    synchronized (incomingLock) {
      Set registrations = incomingByPlugin.get(plugin);

      if (registrations != null) {
        for (PluginMessageListenerRegistration registration : registrations) {
          if (registration.getChannel().equals(channel)) {
            return true;
          }
        }
      }

      return false;
    }
  }

  public boolean isOutgoingChannelRegistered(Plugin plugin, String channel) {
    if (plugin == null) {
      throw new IllegalArgumentException("Plugin cannot be null");
    }
    validateChannel(channel);

    synchronized (outgoingLock) {
      Set channels = outgoingByPlugin.get(plugin);

      if (channels != null) {
        return channels.contains(channel);
      }

      return false;
    }
  }

  public void dispatchIncomingMessage(Player source, String channel, byte[] message) {
    if (source == null) {
      throw new IllegalArgumentException("Player source cannot be null");
    }
    if (message == null) {
      throw new IllegalArgumentException("Message cannot be null");
    }
    validateChannel(channel);

    Set registrations = getIncomingChannelRegistrations(channel);

    for (PluginMessageListenerRegistration registration : registrations) {
      // Spigot Start
      try {
        registration.getListener().onPluginMessageReceived(channel, source, message);
      } catch (Throwable t) {
        org.bukkit.Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Could not pass incoming plugin message to " + registration.getPlugin(), t);
      }
      // Spigot End
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy