001    /*
002     * Sonar, open source software quality management tool.
003     * Copyright (C) 2008-2011 SonarSource
004     * mailto:contact AT sonarsource DOT com
005     *
006     * Sonar is free software; you can redistribute it and/or
007     * modify it under the terms of the GNU Lesser General Public
008     * License as published by the Free Software Foundation; either
009     * version 3 of the License, or (at your option) any later version.
010     *
011     * Sonar is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014     * Lesser General Public License for more details.
015     *
016     * You should have received a copy of the GNU Lesser General Public
017     * License along with Sonar; if not, write to the Free Software
018     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
019     */
020    package org.sonar.server.plugins;
021    
022    import com.google.common.collect.ArrayListMultimap;
023    import com.google.common.collect.ListMultimap;
024    import org.slf4j.LoggerFactory;
025    import org.sonar.api.Extension;
026    import org.sonar.api.ExtensionProvider;
027    import org.sonar.api.Plugin;
028    import org.sonar.api.ServerExtension;
029    import org.sonar.api.platform.ComponentContainer;
030    import org.sonar.api.platform.PluginMetadata;
031    import org.sonar.api.platform.PluginRepository;
032    
033    import java.util.Map;
034    
035    public class ServerExtensionInstaller {
036      private PluginRepository pluginRepository;
037    
038      public ServerExtensionInstaller(PluginRepository pluginRepository) {
039        this.pluginRepository = pluginRepository;
040      }
041    
042      public void registerExtensions(ComponentContainer container) {
043        ListMultimap<PluginMetadata, Object> installedExtensionsByPlugin = ArrayListMultimap.create();
044    
045        for (PluginMetadata pluginMetadata : pluginRepository.getMetadata()) {
046          Plugin plugin = pluginRepository.getPlugin(pluginMetadata.getKey());
047          container.addExtension(pluginMetadata, plugin);
048    
049          for (Object extension : plugin.getExtensions()) {
050            if (installExtension(container, pluginMetadata, extension, true) != null) {
051              installedExtensionsByPlugin.put(pluginMetadata, extension);
052            } else {
053              container.declareExtension(pluginMetadata, extension);
054            }
055          }
056        }
057        for (Map.Entry<PluginMetadata, Object> entry : installedExtensionsByPlugin.entries()) {
058          PluginMetadata plugin = entry.getKey();
059          Object extension = entry.getValue();
060          if (isExtensionProvider(extension)) {
061            ExtensionProvider provider = (ExtensionProvider) container.getComponentByKey(extension);
062            installProvider(container, plugin, provider);
063          }
064        }
065      }
066    
067      private void installProvider(ComponentContainer container, PluginMetadata plugin, ExtensionProvider provider) {
068        Object obj = provider.provide();
069        if (obj != null) {
070          if (obj instanceof Iterable) {
071            for (Object ext : (Iterable) obj) {
072              installExtension(container, plugin, ext, false);
073            }
074          } else {
075            installExtension(container, plugin, obj, false);
076          }
077        }
078      }
079    
080      Object installExtension(ComponentContainer container, PluginMetadata pluginMetadata, Object extension, boolean acceptProvider) {
081        if (isType(extension, ServerExtension.class)) {
082          if (!acceptProvider && isExtensionProvider(extension)) {
083            LoggerFactory.getLogger(getClass()).error("ExtensionProvider can not include providers itself: " + extension);
084          } else {
085            container.addExtension(pluginMetadata, extension);
086            return extension;
087          }
088        }
089        return null;
090      }
091    
092      static boolean isExtensionProvider(Object extension) {
093        return isType(extension, ExtensionProvider.class) || extension instanceof ExtensionProvider;
094      }
095    
096      static boolean isType(Object extension, Class<? extends Extension> extensionClass) {
097        Class clazz = (extension instanceof Class ? (Class) extension : extension.getClass());
098        return extensionClass.isAssignableFrom(clazz);
099      }
100    }