package org.bukkit.plugin; import org.bukkit.Bukkit; import org.bukkit.event.server.ServiceRegisterEvent; import org.bukkit.event.server.ServiceUnregisterEvent; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.List; import java.util.NoSuchElementException; import java.util.Set; /** * A simple services manager. */ public class SimpleServicesManager implements ServicesManager { /** * Map of providers. */ private final Map, List>> providers = new HashMap, List>>(); /** * Register a provider of a service. * * @param Provider * @param service service class * @param provider provider to register * @param plugin plugin with the provider * @param priority priority of the provider */ public void register(Class service, T provider, Plugin plugin, ServicePriority priority) { RegisteredServiceProvider registeredProvider = null; synchronized (providers) { List> registered = providers.get(service); if (registered == null) { registered = new ArrayList>(); providers.put(service, registered); } registeredProvider = new RegisteredServiceProvider(service, provider, priority, plugin); // Insert the provider into the collection, much more efficient big O than sort int position = Collections.binarySearch(registered, registeredProvider); if (position < 0) { registered.add(-(position + 1), registeredProvider); } else { registered.add(position, registeredProvider); } } Bukkit.getServer().getPluginManager().callEvent(new ServiceRegisterEvent(registeredProvider)); } /** * Unregister all the providers registered by a particular plugin. * * @param plugin The plugin */ public void unregisterAll(Plugin plugin) { ArrayList unregisteredEvents = new ArrayList(); synchronized (providers) { Iterator, List>>> it = providers.entrySet().iterator(); try { while (it.hasNext()) { Map.Entry, List>> entry = it.next(); Iterator> it2 = entry.getValue().iterator(); try { // Removed entries that are from this plugin while (it2.hasNext()) { RegisteredServiceProvider registered = it2.next(); if (registered.getPlugin().equals(plugin)) { it2.remove(); unregisteredEvents.add(new ServiceUnregisterEvent(registered)); } } } catch (NoSuchElementException e) { // Why does Java suck } // Get rid of the empty list if (entry.getValue().size() == 0) { it.remove(); } } } catch (NoSuchElementException e) {} } for (ServiceUnregisterEvent event : unregisteredEvents) { Bukkit.getServer().getPluginManager().callEvent(event); } } /** * Unregister a particular provider for a particular service. * * @param service The service interface * @param provider The service provider implementation */ public void unregister(Class service, Object provider) { ArrayList unregisteredEvents = new ArrayList(); synchronized (providers) { Iterator, List>>> it = providers.entrySet().iterator(); try { while (it.hasNext()) { Map.Entry, List>> entry = it.next(); // We want a particular service if (entry.getKey() != service) { continue; } Iterator> it2 = entry.getValue().iterator(); try { // Removed entries that are from this plugin while (it2.hasNext()) { RegisteredServiceProvider registered = it2.next(); if (registered.getProvider() == provider) { it2.remove(); unregisteredEvents.add(new ServiceUnregisterEvent(registered)); } } } catch (NoSuchElementException e) { // Why does Java suck } // Get rid of the empty list if (entry.getValue().size() == 0) { it.remove(); } } } catch (NoSuchElementException e) {} } for (ServiceUnregisterEvent event : unregisteredEvents) { Bukkit.getServer().getPluginManager().callEvent(event); } } /** * Unregister a particular provider. * * @param provider The service provider implementation */ public void unregister(Object provider) { ArrayList unregisteredEvents = new ArrayList(); synchronized (providers) { Iterator, List>>> it = providers.entrySet().iterator(); try { while (it.hasNext()) { Map.Entry, List>> entry = it.next(); Iterator> it2 = entry.getValue().iterator(); try { // Removed entries that are from this plugin while (it2.hasNext()) { RegisteredServiceProvider registered = it2.next(); if (registered.getProvider().equals(provider)) { it2.remove(); unregisteredEvents.add(new ServiceUnregisterEvent(registered)); } } } catch (NoSuchElementException e) { // Why does Java suck } // Get rid of the empty list if (entry.getValue().size() == 0) { it.remove(); } } } catch (NoSuchElementException e) {} } for (ServiceUnregisterEvent event : unregisteredEvents) { Bukkit.getServer().getPluginManager().callEvent(event); } } /** * Queries for a provider. This may return if no provider has been * registered for a service. The highest priority provider is returned. * * @param The service interface * @param service The service interface * @return provider or null */ public T load(Class service) { synchronized (providers) { List> registered = providers.get(service); if (registered == null) { return null; } // This should not be null! return service.cast(registered.get(0).getProvider()); } } /** * Queries for a provider registration. This may return if no provider * has been registered for a service. * * @param The service interface * @param service The service interface * @return provider registration or null */ @SuppressWarnings("unchecked") public RegisteredServiceProvider getRegistration(Class service) { synchronized (providers) { List> registered = providers.get(service); if (registered == null) { return null; } // This should not be null! return (RegisteredServiceProvider) registered.get(0); } } /** * Get registrations of providers for a plugin. * * @param plugin The plugin * @return provider registration or null */ public List> getRegistrations(Plugin plugin) { ImmutableList.Builder> ret = ImmutableList.>builder(); synchronized (providers) { for (List> registered : providers.values()) { for (RegisteredServiceProvider provider : registered) { if (provider.getPlugin().equals(plugin)) { ret.add(provider); } } } } return ret.build(); } /** * Get registrations of providers for a service. The returned list is * an unmodifiable copy. * * @param The service interface * @param service The service interface * @return a copy of the list of registrations */ @SuppressWarnings("unchecked") public List> getRegistrations(Class service) { ImmutableList.Builder> ret; synchronized (providers) { List> registered = providers.get(service); if (registered == null) { return ImmutableList.>of(); } ret = ImmutableList.>builder(); for (RegisteredServiceProvider provider : registered) { ret.add((RegisteredServiceProvider) provider); } } return ret.build(); } /** * Get a list of known services. A service is known if it has registered * providers for it. * * @return a copy of the set of known services */ public Set> getKnownServices() { synchronized (providers) { return ImmutableSet.>copyOf(providers.keySet()); } } /** * Returns whether a provider has been registered for a service. * * @param service * @param service service to check * @return true if and only if there are registered providers */ public boolean isProvidedFor(Class service) { synchronized (providers) { return providers.containsKey(service); } } }