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
020package org.crsh.plugin;
021
022import org.crsh.util.Utils;
023
024import java.util.*;
025import java.util.logging.Level;
026import java.util.logging.Logger;
027
028class 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}