001    /*
002     * Sonar, open source software quality management tool.
003     * Copyright (C) 2008-2012 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.sonar.api.Extension;
025    import org.sonar.api.ExtensionProvider;
026    import org.sonar.api.Plugin;
027    import org.sonar.api.ServerExtension;
028    import org.sonar.api.platform.ComponentContainer;
029    import org.sonar.api.platform.PluginMetadata;
030    import org.sonar.api.platform.PluginRepository;
031    
032    import java.util.Map;
033    
034    public class ServerExtensionInstaller {
035      private PluginRepository pluginRepository;
036    
037      public ServerExtensionInstaller(PluginRepository pluginRepository) {
038        this.pluginRepository = pluginRepository;
039      }
040    
041      public void registerExtensions(ComponentContainer container) {
042        ListMultimap<PluginMetadata, Object> installedExtensionsByPlugin = ArrayListMultimap.create();
043    
044        for (PluginMetadata pluginMetadata : pluginRepository.getMetadata()) {
045          Plugin plugin = pluginRepository.getPlugin(pluginMetadata.getKey());
046          container.addExtension(pluginMetadata, plugin);
047    
048          for (Object extension : plugin.getExtensions()) {
049            if (installExtension(container, pluginMetadata, extension, true) != null) {
050              installedExtensionsByPlugin.put(pluginMetadata, extension);
051            } else {
052              container.declareExtension(pluginMetadata, extension);
053            }
054          }
055        }
056        for (Map.Entry<PluginMetadata, Object> entry : installedExtensionsByPlugin.entries()) {
057          PluginMetadata plugin = entry.getKey();
058          Object extension = entry.getValue();
059          if (isExtensionProvider(extension)) {
060            ExtensionProvider provider = (ExtensionProvider) container.getComponentByKey(extension);
061            installProvider(container, plugin, provider);
062          }
063        }
064      }
065    
066      private void installProvider(ComponentContainer container, PluginMetadata plugin, ExtensionProvider provider) {
067        Object obj = provider.provide();
068        if (obj != null) {
069          if (obj instanceof Iterable) {
070            for (Object ext : (Iterable) obj) {
071              installExtension(container, plugin, ext, false);
072            }
073          } else {
074            installExtension(container, plugin, obj, false);
075          }
076        }
077      }
078    
079      Object installExtension(ComponentContainer container, PluginMetadata pluginMetadata, Object extension, boolean acceptProvider) {
080        if (isType(extension, ServerExtension.class)) {
081          if (!acceptProvider && isExtensionProvider(extension)) {
082            throw new IllegalStateException("ExtensionProvider can not include providers itself: " + extension);
083          }
084          container.addExtension(pluginMetadata, extension);
085          return extension;
086        }
087        return null;
088      }
089    
090      static boolean isExtensionProvider(Object extension) {
091        return isType(extension, ExtensionProvider.class) || extension instanceof ExtensionProvider;
092      }
093    
094      static boolean isType(Object extension, Class<? extends Extension> extensionClass) {
095        Class clazz = (extension instanceof Class ? (Class) extension : extension.getClass());
096        return extensionClass.isAssignableFrom(clazz);
097      }
098    }