pluginlocator.java

### File Source: pluginlocator.java

             /*
        P/P   *  Method: int compare(Object, Object)
              *
              *  Preconditions:
              *    Param_1 != null
              *    Param_2 != null
              *    Param_2.weight - Param_1.weight in -232+1..231
              *
              *  Postconditions:
              *    return_value == -(Param_2.weight - Param_1.weight)
              *    init'ed(return_value)
              */
         1  /*
         2   * Copyright (c) 2003-2005, Simon Brown
         3   * All rights reserved.
         4   *
         5   * Redistribution and use in source and binary forms, with or without
         6   * modification, are permitted provided that the following conditions are met:
         7   *
         8   *   - Redistributions of source code must retain the above copyright
         9   *     notice, this list of conditions and the following disclaimer.
        10   *
        11   *   - Redistributions in binary form must reproduce the above copyright
        12   *     notice, this list of conditions and the following disclaimer in
        13   *     the documentation and/or other materials provided with the
        14   *     distribution.
        15   *
        16   *   - Neither the name of Pebble nor the names of its contributors may
        17   *     be used to endorse or promote products derived from this software
        18   *     without specific prior written permission.
        19   *
        20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
        21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
        24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        30   * POSSIBILITY OF SUCH DAMAGE.
        31   */
        32  package net.sourceforge.pebble.plugins;
        33
        34  import net.sourceforge.pebble.domain.Blog;
        35  import org.apache.commons.logging.Log;
        36  import org.apache.commons.logging.LogFactory;
             /*
        P/P   *  Method: void net.sourceforge.pebble.plugins.PluginLocator()
              */
        37  import org.jdom.Document;
        38  import org.jdom.Element;
        39  import org.jdom.JDOMException;
        40  import org.jdom.input.SAXBuilder;
        41
        42  import java.io.IOException;
        43  import java.net.URL;
        44  import java.util.*;
        45
        46  /**
        47   * Locates plugins
        48   *
        49   * @author James Roper
        50   */
        51  public class PluginLocator {
        52    private static final Log log = LogFactory.getLog(PluginLocator.class);
        53    private static final Map<String, PluginConfigType> PLUGIN_CONFIG_TYPES;
        54    static {
        55      PLUGIN_CONFIG_TYPES = new HashMap<String, PluginConfigType>();
        56      PLUGIN_CONFIG_TYPES.put("string", PlainTextPluginConfigType.INSTANCE);
        57      PLUGIN_CONFIG_TYPES.put("textarea", TextAreaPluginConfigType.INSTANCE);
        58      PLUGIN_CONFIG_TYPES.put("checkbox", CheckboxPluginConfigType.INSTANCE);
        59      PLUGIN_CONFIG_TYPES.put("password", PasswordPluginConfigType.INSTANCE);
        60    }
        61
        62    private static AvailablePlugins availablePlugins;
        63
        64    /**
        65     * Locates all the plugins installed in Pebble
        66     *
        67     * @return A map of plugin types to lists of plugin class names
        68     */
               /*
        P/P     *  Method: AvailablePlugins locateAvailablePlugins()
                *
                *  Preconditions:
                *    init'ed(availablePlugins)
                *
                *  Presumptions:
                *    java.lang.Class:getClassLoader(...)@73 != null
                *    java.lang.ClassLoader:getResources(...)@73 != null
                *    java.util.Enumeration:nextElement(...)@75 != null
                *    java.util.Map:values(...)@82 != null
                *    org.apache.commons.logging.LogFactory:getLog(...)@52 != null
                *
                *  Postconditions:
                *    availablePlugins == One-of{old availablePlugins, &new AvailablePlugins(locateAvailablePlugins#3)}
                *    availablePlugins != null
                *    return_value == availablePlugins
                *    new AvailablePlugins(locateAvailablePlugins#3) num objects <= 1
                *    new AvailablePlugins(locateAvailablePlugins#3).plugins == &new HashMap(locateAvailablePlugins#1)
                *    new HashMap(locateAvailablePlugins#1) num objects <= 1
                *
                *  Test Vectors:
                *    availablePlugins: Inverse{null}, Addr_Set{null}
                *    java.util.Iterator:hasNext(...)@82: {1}, {0}
                */
        69    public static synchronized AvailablePlugins locateAvailablePlugins() {
        70      if (availablePlugins == null) {
        71        Map<String, List<Plugin>> plugins = new HashMap<String, List<Plugin>>();
        72        try {
        73          Enumeration<URL> resources = PluginLocator.class.getClassLoader().getResources("pebble-plugins.xml");
        74          while (resources.hasMoreElements()) {
        75            installPlugins(plugins, resources.nextElement());
        76          }
        77        }
        78        catch (IOException ioe) {
        79          log.error("Error occured while scanning context classloader for plugins", ioe);
        80        }
        81        // Sort the plugins
        82        for (List<Plugin> pluginsList : plugins.values())
        83        {
                     /*
        P/P           *  Method: void net.sourceforge.pebble.plugins.PluginLocator$1()
                      */
        84          Collections.sort(pluginsList, new Comparator<Plugin>() {
        85            public int compare(Plugin o1, Plugin o2) {
                         /*
        P/P               *  Method: int compare(Plugin, Plugin)
                          *
                          *  Preconditions:
                          *    o1 != null
                          *    o2 != null
                          *    o2.weight - o1.weight in -232+1..231
                          *
                          *  Postconditions:
                          *    return_value == -(o2.weight - o1.weight)
                          *    init'ed(return_value)
                          */
        86              return o1.getWeight() - o2.getWeight();
        87            }
        88          });
        89        }
        90        availablePlugins = new AvailablePlugins(plugins);
        91      }
        92      return availablePlugins;
        93    }
        94
               /*
        P/P     *  Method: AvailablePlugins getAvailablePluginsSortedForBlog(Blog)
                *
                *  Preconditions:
                *    blog != null
                *    init'ed(availablePlugins)
                *
                *  Presumptions:
                *    locateAvailablePlugins(...).plugins != null
                *
                *  Postconditions:
                *    availablePlugins == One-of{old availablePlugins, &new AvailablePlugins(locateAvailablePlugins#3)}
                *    availablePlugins != null
                *    return_value == &new AvailablePlugins(getAvailablePluginsSortedForBlog#1)
                *    new AvailablePlugins(getAvailablePluginsSortedForBlog#1) num objects == 1
                *    new HashMap(copyMap#1) num objects == 1
                *    return_value.plugins == &new HashMap(copyMap#1)
                *    new AvailablePlugins(locateAvailablePlugins#3) num objects <= 1
                *    new HashMap(locateAvailablePlugins#1) num objects == new AvailablePlugins(locateAvailablePlugins#3) num objects
                *    new AvailablePlugins(locateAvailablePlugins#3).plugins == &new HashMap(locateAvailablePlugins#1)
                */
        95    public static AvailablePlugins getAvailablePluginsSortedForBlog(Blog blog) {
        96      Map<String, List<Plugin>> plugins = locateAvailablePlugins().copyMap();
        97      // Sort the decorators
        98      plugins.put(AvailablePlugins.CONTENT_DECORATOR, sortPlugins(plugins.get(AvailablePlugins.CONTENT_DECORATOR),
        99              blog.getContentDecorators()));
       100      return new AvailablePlugins(plugins);
       101    }
       102
               /*
        P/P     *  Method: List sortPlugins(List, List)
                *
                *  Postconditions:
                *    return_value == One-of{null, plugins}
                *    init'ed(return_value)
                *
                *  Test Vectors:
                *    plugins: Inverse{null}, Addr_Set{null}
                */
       103    private static List<Plugin> sortPlugins(List<Plugin> plugins, final List<String> installedPlugins) {
       104      if (plugins == null)
       105      {
       106        return null;
       107      }
       108      Collections.sort(plugins, new Comparator<Plugin>() {
       109        public int compare(Plugin plugin1, Plugin plugin2) {
       110          // This comparator ensures installed plugins are at the top, in the order specified by the user,
       111          // and that not installed plugins are sorted by their weight.
                     /*
        P/P           *  Method: int compare(Plugin, Plugin)
                      *
                      *  Preconditions:
                      *    plugin1 != null
                      *    plugin2 != null
                      *    this.val$installedPlugins != null
                      *    (soft) plugin2.weight - plugin1.weight in -232+1..231
                      *
                      *  Presumptions:
                      *    java.util.List:indexOf(...)@113 - java.util.List:indexOf(...)@112 in {-6_442_450_943..231, 232..6_442_450_943}
                      *
                      *  Postconditions:
                      *    init'ed(return_value)
                      *
                      *  Test Vectors:
                      *    java.util.List:indexOf(...)@112: {-231..-1}, {0..232-1}
                      *    java.util.List:indexOf(...)@113: {-231..-1}, {0..232-1}
                      *    java.util.List:indexOf(...)@113 - java.util.List:indexOf(...)@112: {1..231-1}, {-6_442_450_943..-1}
                      */
       112          int index1 = installedPlugins.indexOf(plugin1.getPluginClass());
       113          int index2 = installedPlugins.indexOf(plugin2.getPluginClass());
       114          if (index1 >= 0 && index2 >= 0)
       115          {
       116            return index1 - index2;
       117          }
       118          if (index1 < 0 && index2 < 0)
       119          {
       120            return plugin1.getWeight() - plugin2.getWeight();
       121          }
       122          if (index1 >= 0)
       123          {
       124            return -1;
       125          }
       126          return 1;
       127        }
       128      });
       129      return plugins;
       130    }
       131
       132    /**
       133     * Install the plugins from the given resource
       134     * @param plugins The plugins to install
       135     * @param resource The resource to install them from
       136     */
       137    static void installPlugins(Map<String, List<Plugin>> plugins, URL resource) {
                 /*
        P/P       *  Method: void installPlugins(Map, URL)
                  *
                  *  Preconditions:
                  *    (soft) plugins != null
                  *    (soft) resource != null
                  *
                  *  Presumptions:
                  *    java.lang.Iterable:iterator(...)@142 != null
                  *    java.lang.Thread:currentThread(...)@165 != null
                  *    java.lang.Thread:getContextClassLoader(...)@165 != null
                  *    java.util.Iterator:next(...)@142 != null
                  *    org.apache.commons.logging.LogFactory:getLog(...)@52 != null
                  *    ...
                  *
                  *  Test Vectors:
                  *    java.util.Map:get(...)@168: Inverse{null}, Addr_Set{null}
                  *    org.jdom.Element:getAttributeValue(...)@153: Addr_Set{null}, Inverse{null}
                  *    org.jdom.Element:getChild(...)@146: Addr_Set{null}, Inverse{null}
                  */
       138      SAXBuilder saxBuilder = new SAXBuilder();
       139      try {
       140        Document document = saxBuilder.build(resource.openStream());
       141        Element root = document.getRootElement();
       142        for (Element element : (Iterable<Element>) root.getChildren())
       143        {
       144          String type = element.getName();
       145          String name = element.getAttributeValue("name");
       146          Element descriptionElement = element.getChild("description");
       147          String description = null;
       148          if (descriptionElement != null)
       149          {
       150            description = descriptionElement.getText();
       151          }
       152          String className = element.getAttributeValue("class");
       153          String weightStr = element.getAttributeValue("weight");
       154          int weight = 100;
       155          if (weightStr != null)
       156          {
       157            try {
       158              weight = Integer.parseInt(weightStr);
       159            } catch (NumberFormatException e) {
       160              log.error("Invalid weight for plugin " + name + ": " + weightStr);
       161            }
       162          }
       163          // Try and load the class - for validation
       164          try {
       165            Thread.currentThread().getContextClassLoader().loadClass(className);
       166            // Successful, add it
       167            log.debug("Installing plugin '" + name + "' of type " + type + " with class " + className);
       168            List<Plugin> list = plugins.get(type);
       169            if (list == null)
       170            {
       171              list = new ArrayList<Plugin>();
       172              plugins.put(type, list);
       173            }
       174            Collection<PluginConfig> pluginConfig = parsePluginConfig(element);
       175            list.add(new Plugin(name, description, className, weight, pluginConfig));
       176          } catch (ClassNotFoundException e) {
       177            log.error("Plugin class " + className + " of type " + type + " from descriptor " + resource +
       178                    " could not be found.");
       179          }
       180        }
       181      } catch (JDOMException e) {
       182        log.error("Error parsing plugin descriptor at " + resource, e);
       183      } catch (IOException e) {
       184        log.error("Error reading plugin descriptor at " + resource, e);
       185      }
       186    }
       187
       188    private static Collection<PluginConfig> parsePluginConfig(Element element)
       189    {
                 /*
        P/P       *  Method: Collection parsePluginConfig(Element)
                  *
                  *  Preconditions:
                  *    element != null
                  *
                  *  Presumptions:
                  *    java.lang.Iterable:iterator(...)@191 != null
                  *    java.lang.Iterable:iterator(...)@208 != null
                  *    java.util.Iterator:next(...)@191 != null
                  *    java.util.Iterator:next(...)@208 != null
                  *    org.jdom.Element:getChildren(...)@191 != null
                  *    ...
                  *
                  *  Postconditions:
                  *    return_value == &new ArrayList(parsePluginConfig#1)
                  *    new ArrayList(parsePluginConfig#1) num objects == 1
                  *
                  *  Test Vectors:
                  *    java.util.Iterator:hasNext(...)@191: {1}, {0}
                  *    java.util.Iterator:hasNext(...)@208: {1}, {0}
                  *    org.jdom.Element:getAttributeValue(...)@196: Inverse{null}, Addr_Set{null}
                  */
       190      Collection<PluginConfig> results = new ArrayList<PluginConfig>();
       191      for (Element configElement : (Iterable<Element>) element.getChildren("config"))
       192      {
       193        String key = configElement.getAttributeValue("key");
       194        String name = configElement.getAttributeValue("name");
       195        boolean required = Boolean.parseBoolean(configElement.getAttributeValue("required"));
       196        String type = configElement.getAttributeValue("type");
       197        PluginConfigType pluginConfigType;
       198        if (type == null)
       199        {
       200          pluginConfigType = PlainTextPluginConfigType.INSTANCE;
       201        }
       202        else
       203        {
       204          pluginConfigType = PLUGIN_CONFIG_TYPES.get(type);
       205        }
       206        // todo custom class instantiation
       207        Properties properties = new Properties();
       208        for (Element property : (Iterable<Element>) configElement.getChildren())
       209        {
       210          properties.setProperty(property.getName(), property.getText());
       211        }
       212        results.add(new PluginConfig(key, name, pluginConfigType, required, properties));
       213      }
       214      return results;
       215    }
       216  }

SofCheck Inspector Build Version : 2.22510

pluginlocator.java | 2010-Jun-25 19:40:32
pluginlocator.class | 2010-Jul-19 20:23:38
pluginlocator$1.class | 2010-Jul-19 20:23:38
pluginlocator$2.class | 2010-Jul-19 20:23:38