#3771: Make PluginManager methods thread safe
This commit is contained in:
		| @@ -23,6 +23,10 @@ import java.util.Locale; | |||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
| import java.util.Stack; | import java.util.Stack; | ||||||
|  | import java.util.concurrent.locks.Lock; | ||||||
|  | import java.util.concurrent.locks.ReadWriteLock; | ||||||
|  | import java.util.concurrent.locks.ReentrantLock; | ||||||
|  | import java.util.concurrent.locks.ReentrantReadWriteLock; | ||||||
| import java.util.jar.JarEntry; | import java.util.jar.JarEntry; | ||||||
| import java.util.jar.JarFile; | import java.util.jar.JarFile; | ||||||
| import java.util.logging.Level; | import java.util.logging.Level; | ||||||
| @@ -59,6 +63,9 @@ public final class PluginManager | |||||||
|     private final Multimap<Plugin, Command> commandsByPlugin = ArrayListMultimap.create(); |     private final Multimap<Plugin, Command> commandsByPlugin = ArrayListMultimap.create(); | ||||||
|     private final Multimap<Plugin, Listener> listenersByPlugin = ArrayListMultimap.create(); |     private final Multimap<Plugin, Listener> listenersByPlugin = ArrayListMultimap.create(); | ||||||
|  |  | ||||||
|  |     private final ReadWriteLock commandsLock = new ReentrantReadWriteLock(); | ||||||
|  |     private final Lock listenersLock = new ReentrantLock(); | ||||||
|  |  | ||||||
|     @SuppressWarnings("unchecked") |     @SuppressWarnings("unchecked") | ||||||
|     public PluginManager(ProxyServer proxy) |     public PluginManager(ProxyServer proxy) | ||||||
|     { |     { | ||||||
| @@ -92,6 +99,9 @@ public final class PluginManager | |||||||
|      * @param command the command to register |      * @param command the command to register | ||||||
|      */ |      */ | ||||||
|     public void registerCommand(Plugin plugin, Command command) |     public void registerCommand(Plugin plugin, Command command) | ||||||
|  |     { | ||||||
|  |         commandsLock.writeLock().lock(); | ||||||
|  |         try | ||||||
|         { |         { | ||||||
|             commandMap.put( command.getName().toLowerCase( Locale.ROOT ), command ); |             commandMap.put( command.getName().toLowerCase( Locale.ROOT ), command ); | ||||||
|             for ( String alias : command.getAliases() ) |             for ( String alias : command.getAliases() ) | ||||||
| @@ -99,6 +109,10 @@ public final class PluginManager | |||||||
|                 commandMap.put( alias.toLowerCase( Locale.ROOT ), command ); |                 commandMap.put( alias.toLowerCase( Locale.ROOT ), command ); | ||||||
|             } |             } | ||||||
|             commandsByPlugin.put( plugin, command ); |             commandsByPlugin.put( plugin, command ); | ||||||
|  |         } finally | ||||||
|  |         { | ||||||
|  |             commandsLock.writeLock().unlock(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -107,9 +121,16 @@ public final class PluginManager | |||||||
|      * @param command the command to unregister |      * @param command the command to unregister | ||||||
|      */ |      */ | ||||||
|     public void unregisterCommand(Command command) |     public void unregisterCommand(Command command) | ||||||
|  |     { | ||||||
|  |         commandsLock.writeLock().lock(); | ||||||
|  |         try | ||||||
|         { |         { | ||||||
|             while ( commandMap.values().remove( command ) ); |             while ( commandMap.values().remove( command ) ); | ||||||
|             commandsByPlugin.values().remove( command ); |             commandsByPlugin.values().remove( command ); | ||||||
|  |         } finally | ||||||
|  |         { | ||||||
|  |             commandsLock.writeLock().unlock(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -118,6 +139,9 @@ public final class PluginManager | |||||||
|      * @param plugin the plugin to register the commands of |      * @param plugin the plugin to register the commands of | ||||||
|      */ |      */ | ||||||
|     public void unregisterCommands(Plugin plugin) |     public void unregisterCommands(Plugin plugin) | ||||||
|  |     { | ||||||
|  |         commandsLock.writeLock().lock(); | ||||||
|  |         try | ||||||
|         { |         { | ||||||
|             for ( Iterator<Command> it = commandsByPlugin.get( plugin ).iterator(); it.hasNext(); ) |             for ( Iterator<Command> it = commandsByPlugin.get( plugin ).iterator(); it.hasNext(); ) | ||||||
|             { |             { | ||||||
| @@ -125,6 +149,10 @@ public final class PluginManager | |||||||
|                 while ( commandMap.values().remove( command ) ); |                 while ( commandMap.values().remove( command ) ); | ||||||
|                 it.remove(); |                 it.remove(); | ||||||
|             } |             } | ||||||
|  |         } finally | ||||||
|  |         { | ||||||
|  |             commandsLock.writeLock().unlock(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private Command getCommandIfEnabled(String commandName, CommandSender sender) |     private Command getCommandIfEnabled(String commandName, CommandSender sender) | ||||||
| @@ -137,7 +165,14 @@ public final class PluginManager | |||||||
|             return null; |             return null; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         commandsLock.readLock().lock(); | ||||||
|  |         try | ||||||
|  |         { | ||||||
|             return commandMap.get( commandLower ); |             return commandMap.get( commandLower ); | ||||||
|  |         } finally | ||||||
|  |         { | ||||||
|  |             commandsLock.readLock().unlock(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -433,6 +468,9 @@ public final class PluginManager | |||||||
|      * @param listener the listener to register events for |      * @param listener the listener to register events for | ||||||
|      */ |      */ | ||||||
|     public void registerListener(Plugin plugin, Listener listener) |     public void registerListener(Plugin plugin, Listener listener) | ||||||
|  |     { | ||||||
|  |         listenersLock.lock(); | ||||||
|  |         try | ||||||
|         { |         { | ||||||
|             for ( Method method : listener.getClass().getDeclaredMethods() ) |             for ( Method method : listener.getClass().getDeclaredMethods() ) | ||||||
|             { |             { | ||||||
| @@ -441,6 +479,10 @@ public final class PluginManager | |||||||
|             } |             } | ||||||
|             eventBus.register( listener ); |             eventBus.register( listener ); | ||||||
|             listenersByPlugin.put( plugin, listener ); |             listenersByPlugin.put( plugin, listener ); | ||||||
|  |         } finally | ||||||
|  |         { | ||||||
|  |             listenersLock.unlock(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -449,9 +491,16 @@ public final class PluginManager | |||||||
|      * @param listener the listener to unregister |      * @param listener the listener to unregister | ||||||
|      */ |      */ | ||||||
|     public void unregisterListener(Listener listener) |     public void unregisterListener(Listener listener) | ||||||
|  |     { | ||||||
|  |         listenersLock.lock(); | ||||||
|  |         try | ||||||
|         { |         { | ||||||
|             eventBus.unregister( listener ); |             eventBus.unregister( listener ); | ||||||
|             listenersByPlugin.values().remove( listener ); |             listenersByPlugin.values().remove( listener ); | ||||||
|  |         } finally | ||||||
|  |         { | ||||||
|  |             listenersLock.unlock(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -460,12 +509,19 @@ public final class PluginManager | |||||||
|      * @param plugin target plugin |      * @param plugin target plugin | ||||||
|      */ |      */ | ||||||
|     public void unregisterListeners(Plugin plugin) |     public void unregisterListeners(Plugin plugin) | ||||||
|  |     { | ||||||
|  |         listenersLock.lock(); | ||||||
|  |         try | ||||||
|         { |         { | ||||||
|             for ( Iterator<Listener> it = listenersByPlugin.get( plugin ).iterator(); it.hasNext(); ) |             for ( Iterator<Listener> it = listenersByPlugin.get( plugin ).iterator(); it.hasNext(); ) | ||||||
|             { |             { | ||||||
|                 eventBus.unregister( it.next() ); |                 eventBus.unregister( it.next() ); | ||||||
|                 it.remove(); |                 it.remove(); | ||||||
|             } |             } | ||||||
|  |         } finally | ||||||
|  |         { | ||||||
|  |             listenersLock.unlock(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -474,8 +530,15 @@ public final class PluginManager | |||||||
|      * @return commands |      * @return commands | ||||||
|      */ |      */ | ||||||
|     public Collection<Map.Entry<String, Command>> getCommands() |     public Collection<Map.Entry<String, Command>> getCommands() | ||||||
|  |     { | ||||||
|  |         commandsLock.readLock().lock(); | ||||||
|  |         try | ||||||
|         { |         { | ||||||
|             return Collections.unmodifiableCollection( commandMap.entrySet() ); |             return Collections.unmodifiableCollection( commandMap.entrySet() ); | ||||||
|  |         } finally | ||||||
|  |         { | ||||||
|  |             commandsLock.readLock().unlock(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     boolean isTransitiveDepend(PluginDescription plugin, PluginDescription depend) |     boolean isTransitiveDepend(PluginDescription plugin, PluginDescription depend) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 BoomEaro
					BoomEaro