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      public PluginManager(PluginContext context, PluginDiscovery discovery) {
047        this.context = context;
048        this.plugins = null;
049        this.discovery = discovery;
050      }
051    
052      public synchronized <T> Iterable<T> getPlugins(Class<T> wantedType) {
053    
054        //
055        if (plugins == null) {
056          List<CRaSHPlugin<?>> plugins = Utils.list(discovery.getPlugins());
057          for (CRaSHPlugin<?> plugin : plugins) {
058            plugin.context = context;
059            plugin.status = CRaSHPlugin.CONSTRUCTED;
060          }
061          this.plugins = plugins;
062        }
063    
064        //
065        List<T> tmp = Collections.emptyList();
066    
067        //
068        for (CRaSHPlugin<?> plugin : plugins) {
069          Class<?> pluginType = plugin.getType();
070          if (wantedType.isAssignableFrom(pluginType)) {
071    
072            switch (plugin.status) {
073              default:
074              case CRaSHPlugin.FAILED:
075              case CRaSHPlugin.INITIALIZED:
076                // Do nothing
077                break;
078              case CRaSHPlugin.CONSTRUCTED:
079                int status = CRaSHPlugin.FAILED;
080                try {
081                  plugin.status = CRaSHPlugin.INITIALIZING;
082                  plugin.init();
083                  log.info("Initialized plugin " + plugin);
084                  status = CRaSHPlugin.INITIALIZED;
085                }
086                catch (Exception e) {
087                  log.error("Could not initialize plugin " + plugin, e);
088                } finally {
089                  plugin.status = status;
090                }
091                break;
092              case CRaSHPlugin.INITIALIZING:
093                throw new RuntimeException("Circular dependency");
094            }
095    
096            //
097            if (plugin.status == CRaSHPlugin.INITIALIZED) {
098              if (tmp.isEmpty()) {
099                tmp = new ArrayList<T>();
100              }
101              T t = wantedType.cast(plugin);
102              tmp.add(t);
103            }
104          }
105        }
106    
107        //
108        return tmp;
109      }
110    
111      public void shutdown() {
112        if (plugins != null) {
113          for (CRaSHPlugin<?> plugin : plugins) {
114            plugin.destroy();
115          }
116        }
117      }
118    }