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