001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2009 SonarSource SA
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.api;
021
022 import org.sonar.api.utils.SonarException;
023
024 import java.io.IOException;
025 import java.io.InputStream;
026 import java.net.URL;
027 import java.util.*;
028 import java.util.jar.Manifest;
029
030 /**
031 * Plugins dictionnary.
032 *
033 * @since 1.10
034 */
035 public class Plugins {
036
037 private Map<String, Plugin> plugins = null;
038 private List<Class<? extends Extension>> extensionClasses = null;
039 private Map<Class<? extends Extension>, Plugin> pluginsByExtensionClass = null;
040 private Map<Class<? extends Extension>, List<Class<? extends Extension>>> extensionClassesByType = null;
041
042 public Plugins() {
043 try {
044 introspectPlugins();
045 introspectExtensions();
046
047 } catch (Exception e) {
048 throw new SonarException("can not load plugins", e);
049 }
050 }
051
052 public void introspectPlugins() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
053 Enumeration<URL> pluginsEnum = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");
054 plugins = new HashMap<String, Plugin>();
055 while (pluginsEnum.hasMoreElements()) {
056 URL pluginUrl = pluginsEnum.nextElement();
057 InputStream in = pluginUrl.openStream();
058 Manifest manifest = new Manifest(in);
059 in.close();
060 String pluginClassProp = manifest.getMainAttributes().getValue("Plugin-Class");
061 if (pluginClassProp != null) {
062 Class<?> pluginClass = Class.forName(pluginClassProp, true, getClass().getClassLoader());
063 Plugin pluginInstance = (Plugin) pluginClass.newInstance();
064 plugins.put(pluginInstance.getKey(), pluginInstance);
065
066 }
067 }
068 }
069
070 private void introspectExtensions() {
071 extensionClasses = new ArrayList<Class<? extends Extension>>();
072 pluginsByExtensionClass = new HashMap<Class<? extends Extension>, Plugin>();
073 extensionClassesByType = new HashMap<Class<? extends Extension>, List<Class<? extends Extension>>>();
074
075 for (Plugin plugin : getPlugins()) {
076 for (Class<? extends Extension> extensionClass : plugin.getExtensions()) {
077 extensionClasses.add(extensionClass);
078 pluginsByExtensionClass.put(extensionClass, plugin);
079 }
080 }
081 }
082
083 public Collection<Plugin> getPlugins() {
084 return plugins.values();
085 }
086
087 public Plugin getPlugin(String key) {
088 return plugins.get(key);
089 }
090
091
092 public Plugin getPluginByExtension(Class<? extends Extension> clazz) {
093 return pluginsByExtensionClass.get(clazz);
094 }
095
096 public String getPluginKeyByExtension(Class<? extends Extension> clazz) {
097 Plugin plugin = getPluginByExtension(clazz);
098 if (plugin != null) {
099 return plugin.getKey();
100 }
101 return null;
102 }
103
104 public Plugin getPluginByExtension(Extension extension) {
105 return getPluginByExtension(extension.getClass());
106 }
107
108 public List<Class<? extends Extension>> getExtensions() {
109 return extensionClasses;
110 }
111
112 public List<Class<? extends Extension>> getExtensions(Class<? extends Extension> type) {
113 List<Class<? extends Extension>> list = extensionClassesByType.get(type);
114 if (list == null) {
115 list = new ArrayList<Class<? extends Extension>>();
116 for (Class<? extends Extension> extension : getExtensions()) {
117 if (type.isAssignableFrom(extension)) {
118 list.add(extension);
119 }
120 }
121 extensionClassesByType.put(type, list);
122 }
123
124 return list;
125 }
126
127 public Property[] getProperties(Plugin plugin) {
128 Class<? extends Plugin> classInstance = plugin.getClass();
129 if (classInstance.isAnnotationPresent(Properties.class)) {
130 return classInstance.getAnnotation(Properties.class).value();
131 }
132 return new Property[0];
133 }
134 }