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.plugins;
021    
022    import org.apache.commons.io.IOUtils;
023    import org.sonar.api.*;
024    import org.sonar.api.utils.SonarException;
025    
026    import java.io.IOException;
027    import java.io.InputStream;
028    import java.net.URL;
029    import java.util.Collection;
030    import java.util.Enumeration;
031    import java.util.HashMap;
032    import java.util.Map;
033    import java.util.jar.Manifest;
034    
035    /**
036     * @since 2.1
037     */
038    public class PluginProvider implements BatchExtension, ServerExtension {
039    
040      private Map<String, Plugin> pluginsByKey = new HashMap<String, Plugin>();
041    
042      public PluginProvider() {
043        try {
044          loadPlugins();
045        } catch (Exception e) {
046          throw new SonarException("can not load plugins", e);
047        }
048      }
049    
050      private void loadPlugins() throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
051        Enumeration<URL> pluginsEnum = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");
052        while (pluginsEnum.hasMoreElements()) {
053          URL pluginUrl = pluginsEnum.nextElement();
054          InputStream in = pluginUrl.openStream();
055          try {
056            Manifest manifest = new Manifest(in);
057            String pluginClassProp = manifest.getMainAttributes().getValue("Plugin-Class");
058            if (pluginClassProp != null) {
059              Class<?> pluginClass = Class.forName(pluginClassProp, true, getClass().getClassLoader());
060              Plugin pluginInstance = (Plugin) pluginClass.newInstance();
061              pluginsByKey.put(pluginInstance.getKey(), pluginInstance);
062            }
063          } finally {
064            IOUtils.closeQuietly(in);
065          }
066        }
067      }
068    
069      public Collection<Plugin> getPlugins() {
070        return pluginsByKey.values();
071      }
072    
073      public Plugin getPlugin(String key) {
074        return pluginsByKey.get(key);
075      }
076    
077      /**
078       * Returns the list of properties of a plugin
079       */
080      public Property[] getPluginProperties(Plugin plugin) {
081        if (plugin != null) {
082          Class<? extends Plugin> classInstance = plugin.getClass();
083          if (classInstance.isAnnotationPresent(Properties.class)) {
084            return classInstance.getAnnotation(Properties.class).value();
085          }
086        }
087        return new Property[0];
088      }
089    
090      public Property[] getPluginProperties(String pluginKey) {
091        return getPluginProperties(pluginsByKey.get(pluginKey));
092      }
093    }