View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  package org.apache.log4j.plugins;
    18
    19  import org.apache.log4j.spi.LoggerRepository;
    20  import org.apache.log4j.spi.LoggerRepositoryEventListener;
    21  import org.apache.log4j.spi.LoggerRepositoryEx;
    22
    23  import java.util.*;
    24
    25
    26  /**
    27   * This is a registry for Plugin instances. It provides methods to
    28   * start and stop plugin objects individually and to stop all
    29   * plugins for a repository.
    30   *
    31   * @author Mark Womack
    32   * @author Paul Smith
    33   */
    34  public final class PluginRegistry {
    35      /**
    36       * The pluginMap is keyed by plugin name and contains plugins as values.
    37       * key=plugin.getName, value=plugin
    38       */
    39      private final Map<String, Plugin> pluginMap;
    40      /**
    41       * Logger repository.
    42       */
    43      private final LoggerRepositoryEx loggerRepository;
    44
    45      /**
    46       * the listener used to listen for repository events.
    47       */
    48      private final RepositoryListener listener = new RepositoryListener();
    49      /**
    50       * List of listeners.
    51       */
    52      private final List listenerList =
    53          Collections.synchronizedList(new ArrayList());
    54
    55      /**
    56       * Creates a new instance.
    57       *
    58       * @param repository logger repository.
    59       */
    60      public PluginRegistry(final LoggerRepositoryEx repository) {
    61          super();
    62          pluginMap = new HashMap<>();
    63          this.loggerRepository = repository;
    64          this.loggerRepository.addLoggerRepositoryEventListener(listener);
    65      }
    66
    67      /**
    68       * Get logger repository.
    69       *
    70       * @return logger repository.
    71       */
    72      public LoggerRepositoryEx getLoggerRepository() {
    73          return loggerRepository;
    74      }
    75
    76
    77      /**
    78       * Returns true if the specified name is already taken by
    79       * an existing Plugin registered within the scope of the specified
    80       * LoggerRepository.
    81       *
    82       * @param name The name to check the repository for
    83       * @return true if the name is already in use, otherwise false
    84       */
    85      public boolean pluginNameExists(final String name) {
    86          synchronized (pluginMap) {
    87              return pluginMap.containsKey(name);
    88          }
    89      }
    90
    91
    92      /**
    93       * Adds a plugin to the plugin registry.
    94       * If a plugin with the same name exists
    95       * already, it is shutdown and removed.
    96       *
    97       * @param plugin the plugin to add.
    98       */
    99      public void addPlugin(final Plugin plugin) {
    100         // put plugin into the repository's reciever map
    101         synchronized (pluginMap) {
    102             String name = plugin.getName();
    103
    104             // make sure the plugin has reference to repository
    105             plugin.setLoggerRepository(getLoggerRepository());
    106
    107             Plugin existingPlugin = pluginMap.get(name);
    108             if (existingPlugin != null) {
    109                 existingPlugin.shutdown();
    110             }
    111
    112             // put the new plugin into the map
    113             pluginMap.put(name, plugin);
    114             firePluginStarted(plugin);
    115         }
    116     }
    117
    118
    119     /**
    120      * Calls the pluginStarted method on every registered PluginListener.
    121      *
    122      * @param plugin The plugin that has been started.
    123      */
    124     private void firePluginStarted(final Plugin plugin) {
    125         PluginEvent e = null;
    126         synchronized (listenerList) {
    127             for (Object aListenerList : listenerList) {
    128                 PluginListener l = (PluginListener) aListenerList;
    129                 if (e == null) {
    130                     e = new PluginEvent(plugin);
    131                 }
    132                 l.pluginStarted(e);
    133             }
    134         }
    135     }
    136
    137
    138     /**
    139      * Calls the pluginStopped method for every registered PluginListner.
    140      *
    141      * @param plugin The plugin that has been stopped.
    142      */
    143     private void firePluginStopped(final Plugin plugin) {
    144         PluginEvent e = null;
    145         synchronized (listenerList) {
    146             for (Object aListenerList : listenerList) {
    147                 PluginListener l = (PluginListener) aListenerList;
    148                 if (e == null) {
    149                     e = new PluginEvent(plugin);
    150                 }
    151                 l.pluginStopped(e);
    152             }
    153         }
    154     }
    155
    156
    157     /**
    158      * Returns all the plugins for a given repository.
    159      *
    160      * @return List list of plugins from the repository.
    161      */
    162     public List<Plugin> getPlugins() {
    163         synchronized (pluginMap) {
    164             List<Plugin> pluginList = new ArrayList<>(pluginMap.size());
    165
    166             pluginList.addAll(pluginMap.values());
    167             return pluginList;
    168         }
    169     }
    170
    171
    172     /**
    173      * Returns all the plugins for a given repository that are instances
    174      * of a certain class.
    175      *
    176      * @param pluginClass the class the plugin must implement to be selected.
    177      * @return List list of plugins from the repository.
    178      */
    179     public List getPlugins(final Class pluginClass) {
    180         synchronized (pluginMap) {
    181             List pluginList = new ArrayList(pluginMap.size());
    182
    183             for (Object plugin : pluginMap.values()) {
    184                 if (pluginClass.isInstance(plugin)) {
    185                     pluginList.add(plugin);
    186                 }
    187             }
    188             return pluginList;
    189         }
    190     }
    191
    192
    193     /**
    194      * Stops a plugin by plugin name and repository.
    195      *
    196      * @param pluginName the name of the plugin to stop.
    197      * @return Plugin the plugin, if stopped, or null if the
    198      * the plugin was not found in the registry.
    199      */
    200     public Plugin stopPlugin(final String pluginName) {
    201         synchronized (pluginMap) {
    202             Plugin plugin = pluginMap.get(pluginName);
    203
    204             if (plugin == null) {
    205                 return null;
    206             }
    207
    208             // shutdown the plugin
    209             plugin.shutdown();
    210
    211             // remove it from the plugin map
    212             pluginMap.remove(pluginName);
    213             firePluginStopped(plugin);
    214
    215             // return it for future use
    216             return plugin;
    217         }
    218     }
    219
    220     /**
    221      * Stops all plugins in the given logger repository.
    222      */
    223     public void stopAllPlugins() {
    224         synchronized (pluginMap) {
    225             // remove the listener for this repository
    226             loggerRepository.removeLoggerRepositoryEventListener(listener);
    227
    228             for (Object o : pluginMap.values()) {
    229                 Plugin plugin = (Plugin) o;
    230                 plugin.shutdown();
    231                 firePluginStopped(plugin);
    232             }
    233         }
    234     }
    235
    236
    237     /**
    238      * Adds a PluginListener to this registry to be notified
    239      * of PluginEvents.
    240      *
    241      * @param l PluginListener to add to this registry
    242      */
    243     public void addPluginListener(final PluginListener l) {
    244         listenerList.add(l);
    245     }
    246
    247
    248     /**
    249      * Removes a particular PluginListener from this registry
    250      * such that it will no longer be notified of PluginEvents.
    251      *
    252      * @param l PluginListener to remove
    253      */
    254     public void removePluginListener(final PluginListener l) {
    255         listenerList.remove(l);
    256     }
    257
    258     /**
    259      * Internal class used to handle listener events from repositories.
    260      */
    261     private class RepositoryListener implements LoggerRepositoryEventListener {
    262         /**
    263          * Stops all plugins associated with the repository being reset.
    264          *
    265          * @param repository the repository that was reset.
    266          */
    267         public void configurationResetEvent(final LoggerRepository repository) {
    268             PluginRegistry.this.stopAllPlugins();
    269         }
    270
    271
    272         /**
    273          * Called when the repository configuration is changed.
    274          *
    275          * @param repository the repository that was changed.
    276          */
    277         public void configurationChangedEvent(
    278             final LoggerRepository repository) {
    279             // do nothing with this event
    280         }
    281
    282
    283         /**
    284          * Stops all plugins associated with the repository being shutdown.
    285          *
    286          * @param repository the repository being shutdown.
    287          */
    288         public void shutdownEvent(final LoggerRepository repository) {
    289             PluginRegistry.this.stopAllPlugins();
    290         }
    291     }
    292 }