001    /*
002     * Copyright (C) 2010 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    import org.slf4j.Logger;
024    import org.slf4j.LoggerFactory;
025    
026    import java.util.*;
027    
028    /**
029     * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
030     * @version $Revision$
031     */
032    public class PluginManager {
033    
034      /** . */
035      private final Logger log = LoggerFactory.getLogger(PluginManager.class);
036    
037      /** . */
038      private final PluginContext context;
039    
040      /** . */
041      private List<CRaSHPlugin<?>> plugins;
042    
043      /** . */
044      private PluginDiscovery discovery;
045    
046      PluginManager(PluginContext context, PluginDiscovery discovery) {
047        this.context = context;
048        this.plugins = null;
049        this.discovery = discovery;
050      }
051    
052      public synchronized Iterable<CRaSHPlugin<?>> getPlugins() {
053        if (plugins == null) {
054          List<CRaSHPlugin<?>> plugins = Utils.list(discovery.getPlugins());
055          for (CRaSHPlugin<?> plugin : plugins) {
056            plugin.context = context;
057            plugin.status = CRaSHPlugin.CONSTRUCTED;
058          }
059          this.plugins = plugins;
060        }
061        return plugins;
062      }
063    
064      public synchronized <T> Iterable<T> getPlugins(Class<T> wantedType) {
065    
066        //
067        Iterable<CRaSHPlugin<?>> plugins = getPlugins();
068    
069        //
070        List<T> tmp = Collections.emptyList();
071    
072        //
073        for (CRaSHPlugin<?> plugin : plugins) {
074          Class<?> pluginType = plugin.getType();
075          if (wantedType.isAssignableFrom(pluginType)) {
076    
077            switch (plugin.status) {
078              default:
079              case CRaSHPlugin.FAILED:
080              case CRaSHPlugin.INITIALIZED:
081                // Do nothing
082                break;
083              case CRaSHPlugin.CONSTRUCTED:
084                int status = CRaSHPlugin.FAILED;
085                try {
086                  plugin.status = CRaSHPlugin.INITIALIZING;
087                  plugin.init();
088                  log.info("Initialized plugin " + plugin);
089                  status = CRaSHPlugin.INITIALIZED;
090                }
091                catch (Exception e) {
092                  log.error("Could not initialize plugin " + plugin, e);
093                } finally {
094                  plugin.status = status;
095                }
096                break;
097              case CRaSHPlugin.INITIALIZING:
098                throw new RuntimeException("Circular dependency");
099            }
100    
101            //
102            if (plugin.status == CRaSHPlugin.INITIALIZED) {
103              if (tmp.isEmpty()) {
104                tmp = new ArrayList<T>();
105              }
106              T t = wantedType.cast(plugin);
107              tmp.add(t);
108            }
109          }
110        }
111    
112        //
113        return tmp;
114      }
115    
116      void shutdown() {
117        if (plugins != null) {
118          for (CRaSHPlugin<?> plugin : plugins) {
119            plugin.destroy();
120          }
121        }
122      }
123    }