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 }