001    /*
002     * Copyright (C) 2012 eXo Platform SAS.
003     *
004     * This is free software; you can redistribute it and/or modify it
005     * under the terms of the GNU Lesser General Public License as
006     * published by the Free Software Foundation; either version 2.1 of
007     * the License, or (at your option) any later version.
008     *
009     * This software is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012     * Lesser General Public License for more details.
013     *
014     * You should have received a copy of the GNU Lesser General Public
015     * License along with this software; if not, write to the Free
016     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018     */
019    
020    package org.crsh.plugin;
021    
022    import org.crsh.util.Utils;
023    
024    import java.util.*;
025    import java.util.logging.Level;
026    import java.util.logging.Logger;
027    
028    class PluginManager {
029    
030      /** . */
031      private final Logger log = Logger.getLogger(PluginManager.class.getName());
032    
033      /** . */
034      private final PluginContext context;
035    
036      /** . */
037      private List<CRaSHPlugin<?>> plugins;
038    
039      /** . */
040      private PluginDiscovery discovery;
041    
042      PluginManager(PluginContext context, PluginDiscovery discovery) {
043        this.context = context;
044        this.plugins = null;
045        this.discovery = discovery;
046      }
047    
048      synchronized Iterable<CRaSHPlugin<?>> getPlugins() {
049        if (plugins == null) {
050          List<CRaSHPlugin<?>> plugins = Utils.list(discovery.getPlugins());
051          for (CRaSHPlugin<?> plugin : plugins) {
052            plugin.context = context;
053            plugin.status = CRaSHPlugin.CONSTRUCTED;
054          }
055          this.plugins = plugins;
056        }
057        return plugins;
058      }
059    
060      synchronized <T> Iterable<T> getPlugins(Class<T> wantedType) {
061    
062        //
063        Iterable<CRaSHPlugin<?>> plugins = getPlugins();
064    
065        //
066        List<T> tmp = Collections.emptyList();
067    
068        //
069        for (CRaSHPlugin<?> plugin : plugins) {
070          Class<?> pluginType = plugin.getType();
071          if (wantedType.isAssignableFrom(pluginType)) {
072    
073            switch (plugin.status) {
074              default:
075              case CRaSHPlugin.FAILED:
076              case CRaSHPlugin.INITIALIZED:
077                // Do nothing
078                break;
079              case CRaSHPlugin.CONSTRUCTED:
080                int status = CRaSHPlugin.FAILED;
081                try {
082                  plugin.status = CRaSHPlugin.INITIALIZING;
083                  plugin.init();
084                  log.log(Level.INFO, "Initialized plugin " + plugin);
085                  status = CRaSHPlugin.INITIALIZED;
086                }
087                catch (Exception e) {
088                  log.log(Level.SEVERE, "Could not initialize plugin " + plugin, e);
089                } finally {
090                  plugin.status = status;
091                }
092                break;
093              case CRaSHPlugin.INITIALIZING:
094                throw new RuntimeException("Circular dependency");
095            }
096    
097            //
098            if (plugin.status == CRaSHPlugin.INITIALIZED) {
099              if (tmp.isEmpty()) {
100                tmp = new ArrayList<T>();
101              }
102              T t = wantedType.cast(plugin.getImplementation());
103              tmp.add(t);
104            }
105          }
106        }
107    
108        //
109        return tmp;
110      }
111    
112      void shutdown() {
113        if (plugins != null) {
114          for (CRaSHPlugin<?> plugin : plugins) {
115            plugin.destroy();
116          }
117        }
118      }
119    }