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. This class is for internal use 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 /** 043 * Creates the dictionnary of plugins 044 */ 045 public Plugins() { 046 try { 047 introspectPlugins(); 048 introspectExtensions(); 049 050 } catch (Exception e) { 051 throw new SonarException("can not load plugins", e); 052 } 053 } 054 055 protected final void introspectPlugins() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException { 056 Enumeration<URL> pluginsEnum = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF"); 057 plugins = new HashMap<String, Plugin>(); 058 while (pluginsEnum.hasMoreElements()) { 059 URL pluginUrl = pluginsEnum.nextElement(); 060 InputStream in = pluginUrl.openStream(); 061 Manifest manifest = new Manifest(in); 062 in.close(); 063 String pluginClassProp = manifest.getMainAttributes().getValue("Plugin-Class"); 064 if (pluginClassProp != null) { 065 Class<?> pluginClass = Class.forName(pluginClassProp, true, getClass().getClassLoader()); 066 Plugin pluginInstance = (Plugin) pluginClass.newInstance(); 067 plugins.put(pluginInstance.getKey(), pluginInstance); 068 069 } 070 } 071 } 072 073 private void introspectExtensions() { 074 extensionClasses = new ArrayList<Class<? extends Extension>>(); 075 pluginsByExtensionClass = new HashMap<Class<? extends Extension>, Plugin>(); 076 extensionClassesByType = new HashMap<Class<? extends Extension>, List<Class<? extends Extension>>>(); 077 078 for (Plugin plugin : getPlugins()) { 079 for (Class<? extends Extension> extensionClass : plugin.getExtensions()) { 080 extensionClasses.add(extensionClass); 081 pluginsByExtensionClass.put(extensionClass, plugin); 082 } 083 } 084 } 085 086 /** 087 * Gives a collection of available plugins in the Sonar instance 088 */ 089 public Collection<Plugin> getPlugins() { 090 return plugins.values(); 091 } 092 093 /** 094 * Returns a plugin based on its key 095 */ 096 public Plugin getPlugin(String key) { 097 return plugins.get(key); 098 } 099 100 101 /** 102 * Returns a plugin based on its extension 103 */ 104 public Plugin getPluginByExtension(Class<? extends Extension> clazz) { 105 return pluginsByExtensionClass.get(clazz); 106 } 107 108 /** 109 * Returns a plugin key based on its extension 110 */ 111 public String getPluginKeyByExtension(Class<? extends Extension> clazz) { 112 Plugin plugin = getPluginByExtension(clazz); 113 if (plugin != null) { 114 return plugin.getKey(); 115 } 116 return null; 117 } 118 119 /** 120 * Returns a plugin based on its extension 121 */ 122 public Plugin getPluginByExtension(Extension extension) { 123 return getPluginByExtension(extension.getClass()); 124 } 125 126 /** 127 * Returns the list of extensions in the server 128 */ 129 public List<Class<? extends Extension>> getExtensions() { 130 return extensionClasses; 131 } 132 133 /** 134 * Returns the list of extensions given an extension type 135 */ 136 public List<Class<? extends Extension>> getExtensions(Class<? extends Extension> type) { 137 List<Class<? extends Extension>> list = extensionClassesByType.get(type); 138 if (list == null) { 139 list = new ArrayList<Class<? extends Extension>>(); 140 for (Class<? extends Extension> extension : getExtensions()) { 141 if (type.isAssignableFrom(extension)) { 142 list.add(extension); 143 } 144 } 145 extensionClassesByType.put(type, list); 146 } 147 148 return list; 149 } 150 151 /** 152 * Returns the list of properties of a plugin 153 */ 154 public Property[] getProperties(Plugin plugin) { 155 Class<? extends Plugin> classInstance = plugin.getClass(); 156 if (classInstance.isAnnotationPresent(Properties.class)) { 157 return classInstance.getAnnotation(Properties.class).value(); 158 } 159 return new Property[0]; 160 } 161 }