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.core.plugin; 021 022 import com.google.common.collect.BiMap; 023 import com.google.common.collect.HashBiMap; 024 import com.google.common.collect.Maps; 025 import org.picocontainer.Characteristics; 026 import org.picocontainer.MutablePicoContainer; 027 import org.picocontainer.PicoContainer; 028 import org.slf4j.Logger; 029 import org.slf4j.LoggerFactory; 030 import org.sonar.api.*; 031 import org.sonar.api.platform.PluginRepository; 032 033 import java.util.Collection; 034 import java.util.List; 035 import java.util.Map; 036 037 /** 038 * @since 2.2 039 */ 040 public abstract class AbstractPluginRepository implements PluginRepository { 041 042 private static final Logger LOG = LoggerFactory.getLogger(AbstractPluginRepository.class); 043 044 private BiMap<String, Plugin> pluginByKey = HashBiMap.create(); 045 private Map<Object, Plugin> pluginByExtension = Maps.newIdentityHashMap(); 046 047 protected void registerPlugin(MutablePicoContainer container, Plugin plugin, String pluginKey) { 048 LOG.debug("Register the plugin {}", pluginKey); 049 pluginByKey.put(pluginKey, plugin); 050 for (Object extension : plugin.getExtensions()) { 051 registerExtension(container, plugin, pluginKey, extension); 052 } 053 } 054 055 /** 056 * Must be executed by implementations when all plugins are registered. 057 */ 058 protected void invokeExtensionProviders(MutablePicoContainer container) { 059 List<ExtensionProvider> providers = container.getComponents(ExtensionProvider.class); 060 for (ExtensionProvider provider : providers) { 061 Plugin plugin = getPluginForExtension(provider); 062 Object obj = provider.provide(); 063 if (obj instanceof Iterable) { 064 for (Object elt : (Iterable) obj) { 065 registerExtension(container, plugin, getPluginKey(plugin), elt); 066 } 067 } else { 068 registerExtension(container, plugin, getPluginKey(plugin), obj); 069 } 070 } 071 } 072 073 private void registerExtension(MutablePicoContainer container, Plugin plugin, String pluginKey, Object extension) { 074 if (shouldRegisterExtension(container, pluginKey, extension)) { 075 LOG.debug("Register the extension: {}", extension); 076 container.as(Characteristics.CACHE).addComponent(getExtensionKey(extension), extension); 077 pluginByExtension.put(extension, plugin); 078 079 } 080 } 081 082 protected abstract boolean shouldRegisterExtension(PicoContainer container, String pluginKey, Object extension); 083 084 public Collection<Plugin> getPlugins() { 085 return pluginByKey.values(); 086 } 087 088 public Plugin getPlugin(String key) { 089 return pluginByKey.get(key); 090 } 091 092 public String getPluginKey(Plugin plugin) { 093 return pluginByKey.inverse().get(plugin); 094 } 095 096 /** 097 * Returns the list of properties of a plugin 098 */ 099 public Property[] getProperties(Plugin plugin) { 100 if (plugin != null) { 101 Class<? extends Plugin> classInstance = plugin.getClass(); 102 if (classInstance.isAnnotationPresent(Properties.class)) { 103 return classInstance.getAnnotation(Properties.class).value(); 104 } 105 } 106 return new Property[0]; 107 } 108 109 public Property[] getProperties(String pluginKey) { 110 return getProperties(pluginByKey.get(pluginKey)); 111 } 112 113 public Plugin getPluginForExtension(Object extension) { 114 Plugin plugin = pluginByExtension.get(extension); 115 if (plugin == null && !(extension instanceof Class)) { 116 plugin = pluginByExtension.get(extension.getClass()); 117 } 118 return plugin; 119 } 120 121 protected static boolean isType(Object extension, Class<? extends Extension> extensionClass) { 122 Class clazz = (extension instanceof Class ? (Class) extension : extension.getClass()); 123 return extensionClass.isAssignableFrom(clazz); 124 } 125 126 protected static boolean isExtensionProvider(Object extension) { 127 return isType(extension, ExtensionProvider.class); 128 } 129 130 protected static Object getExtensionKey(Object component) { 131 if (component instanceof Class) { 132 return component; 133 } 134 return component.getClass().getCanonicalName() + "-" + component.toString(); 135 } 136 }