//# 0 errors, 400 messages
//#
/*
    //#pluginlocator.java:1:1: class: net.sourceforge.pebble.plugins.PluginLocator$2
    //#pluginlocator.java:1:1: method: net.sourceforge.pebble.plugins.PluginLocator$2.net.sourceforge.pebble.plugins.PluginLocator$2__static_init
    //#pluginlocator.java:1:1: class: net.sourceforge.pebble.plugins.PluginLocator$1
    //#pluginlocator.java:1:1: method: net.sourceforge.pebble.plugins.PluginLocator$1.net.sourceforge.pebble.plugins.PluginLocator$1__static_init
    //#pluginlocator.java:1:1: class: net.sourceforge.pebble.plugins.PluginLocator
    //#pluginlocator.java:1: method: void net.sourceforge.pebble.plugins.PluginLocator$2.net.sourceforge.pebble.plugins.PluginLocator$2(List)
    //#input(void net.sourceforge.pebble.plugins.PluginLocator$2(List)): Param_1
    //#input(void net.sourceforge.pebble.plugins.PluginLocator$2(List)): this
    //#output(void net.sourceforge.pebble.plugins.PluginLocator$2(List)): this.val$installedPlugins
    //#post(void net.sourceforge.pebble.plugins.PluginLocator$2(List)): this.val$installedPlugins == Param_1
    //#post(void net.sourceforge.pebble.plugins.PluginLocator$2(List)): init'ed(this.val$installedPlugins)
    //#pluginlocator.java:1: method: int net.sourceforge.pebble.plugins.PluginLocator$2.compare(Object, Object)
    //#input(int compare(Object, Object)): Param_0
    //#input(int compare(Object, Object)): Param_0.__Tag
    //#input(int compare(Object, Object)): Param_0.val$installedPlugins
    //#input(int compare(Object, Object)): Param_1
    //#input(int compare(Object, Object)): Param_1.__Tag
    //#input(int compare(Object, Object)): Param_1.pluginClass
    //#input(int compare(Object, Object)): Param_1.weight
    //#input(int compare(Object, Object)): Param_2
    //#input(int compare(Object, Object)): Param_2.__Tag
    //#input(int compare(Object, Object)): Param_2.pluginClass
    //#input(int compare(Object, Object)): Param_2.weight
    //#input(int compare(Object, Object)): __Descendant_Table[net/sourceforge/pebble/plugins/PluginLocator$2]
    //#input(int compare(Object, Object)): __Descendant_Table[others]
    //#input(int compare(Object, Object)): __Dispatch_Table.compare(Lnet/sourceforge/pebble/plugins/Plugin;Lnet/sourceforge/pebble/plugins/Plugin;)I
    //#input(int compare(Object, Object)): net/sourceforge/pebble/plugins/Plugin.__Descendant_Table[net/sourceforge/pebble/plugins/Plugin]
    //#input(int compare(Object, Object)): net/sourceforge/pebble/plugins/Plugin.__Descendant_Table[others]
    //#input(int compare(Object, Object)): net/sourceforge/pebble/plugins/Plugin.__Dispatch_Table.getPluginClass()Ljava/lang/String;
    //#input(int compare(Object, Object)): net/sourceforge/pebble/plugins/Plugin.__Dispatch_Table.getWeight()I
    //#output(int compare(Object, Object)): return_value
    //#pre[2] (int compare(Object, Object)): Param_0.__Tag == net/sourceforge/pebble/plugins/PluginLocator$2
    //#pre[3] (int compare(Object, Object)): Param_0.val$installedPlugins != null
    //#pre[4] (int compare(Object, Object)): Param_1 != null
    //#pre[8] (int compare(Object, Object)): Param_2 != null
    //#pre[5] (int compare(Object, Object)): (soft) Param_1.__Tag == net/sourceforge/pebble/plugins/Plugin
    //#pre[9] (int compare(Object, Object)): (soft) Param_2.__Tag == net/sourceforge/pebble/plugins/Plugin
    //#pre[12] (int compare(Object, Object)): (soft) Param_2.weight - Param_1.weight in -4_294_967_295..2_147_483_648
    //#post(int compare(Object, Object)): init'ed(return_value)
    //#unanalyzed(int compare(Object, Object)): Effects-of-calling:java.util.List:indexOf
    //#pluginlocator.java:1: end of method: int net.sourceforge.pebble.plugins.PluginLocator$2.compare(Object, Object)
    //#pluginlocator.java:1: method: int net.sourceforge.pebble.plugins.PluginLocator$1.compare(Object, Object)
    //#input(int compare(Object, Object)): Param_0
    //#input(int compare(Object, Object)): Param_0.__Tag
    //#input(int compare(Object, Object)): Param_1
    //#input(int compare(Object, Object)): Param_1.__Tag
    //#input(int compare(Object, Object)): Param_1.weight
    //#input(int compare(Object, Object)): Param_2
    //#input(int compare(Object, Object)): Param_2.__Tag
    //#input(int compare(Object, Object)): Param_2.weight
    //#input(int compare(Object, Object)): __Descendant_Table[net/sourceforge/pebble/plugins/PluginLocator$1]
    //#input(int compare(Object, Object)): __Descendant_Table[others]
    //#input(int compare(Object, Object)): __Dispatch_Table.compare(Lnet/sourceforge/pebble/plugins/Plugin;Lnet/sourceforge/pebble/plugins/Plugin;)I
    //#input(int compare(Object, Object)): net/sourceforge/pebble/plugins/Plugin.__Descendant_Table[net/sourceforge/pebble/plugins/Plugin]
    //#input(int compare(Object, Object)): net/sourceforge/pebble/plugins/Plugin.__Descendant_Table[others]
    //#input(int compare(Object, Object)): net/sourceforge/pebble/plugins/Plugin.__Dispatch_Table.getWeight()I
    //#output(int compare(Object, Object)): return_value
    //#pre[2] (int compare(Object, Object)): Param_0.__Tag == net/sourceforge/pebble/plugins/PluginLocator$1
    //#pre[3] (int compare(Object, Object)): Param_1 != null
    //#pre[6] (int compare(Object, Object)): Param_2 != null
    //#pre[9] (int compare(Object, Object)): Param_2.weight - Param_1.weight in -4_294_967_295..2_147_483_648
    //#pre[4] (int compare(Object, Object)): (soft) Param_1.__Tag == net/sourceforge/pebble/plugins/Plugin
    //#pre[7] (int compare(Object, Object)): (soft) Param_2.__Tag == net/sourceforge/pebble/plugins/Plugin
    //#post(int compare(Object, Object)): return_value == -(Param_2.weight - Param_1.weight)
    //#post(int compare(Object, Object)): init'ed(return_value)
    //#pluginlocator.java:1: end of method: int net.sourceforge.pebble.plugins.PluginLocator$1.compare(Object, Object)
 * Copyright (c) 2003-2005, Simon Brown
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *
 *   - Neither the name of Pebble nor the names of its contributors may
 *     be used to endorse or promote products derived from this software
 *     without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package net.sourceforge.pebble.plugins;

import net.sourceforge.pebble.domain.Blog;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import java.io.IOException;
import java.net.URL;
import java.util.*;

/**
 * Locates plugins
 *
 * @author James Roper
 */
public class PluginLocator {
    //#pluginlocator.java:51: method: void net.sourceforge.pebble.plugins.PluginLocator.net.sourceforge.pebble.plugins.PluginLocator()
    //#pluginlocator.java:51: end of method: void net.sourceforge.pebble.plugins.PluginLocator.net.sourceforge.pebble.plugins.PluginLocator()
  private static final Log log = LogFactory.getLog(PluginLocator.class);
    //#pluginlocator.java:52: method: net.sourceforge.pebble.plugins.PluginLocator.net.sourceforge.pebble.plugins.PluginLocator__static_init
    //#pluginlocator.java:52: Warning: method not available
    //#    -- call on Log org.apache.commons.logging.LogFactory:getLog(Class)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: net.sourceforge.pebble.plugins.PluginLocator__static_init
    //#    unanalyzed callee: Log org.apache.commons.logging.LogFactory:getLog(Class)
    //#input(net.sourceforge.pebble.plugins.PluginLocator__static_init): net/sourceforge/pebble/plugins/CheckboxPluginConfigType.INSTANCE
    //#input(net.sourceforge.pebble.plugins.PluginLocator__static_init): net/sourceforge/pebble/plugins/PasswordPluginConfigType.INSTANCE
    //#input(net.sourceforge.pebble.plugins.PluginLocator__static_init): net/sourceforge/pebble/plugins/PlainTextPluginConfigType.INSTANCE
    //#input(net.sourceforge.pebble.plugins.PluginLocator__static_init): net/sourceforge/pebble/plugins/TextAreaPluginConfigType.INSTANCE
    //#output(net.sourceforge.pebble.plugins.PluginLocator__static_init): PLUGIN_CONFIG_TYPES
    //#output(net.sourceforge.pebble.plugins.PluginLocator__static_init): __Descendant_Table[net/sourceforge/pebble/plugins/PluginLocator]
    //#output(net.sourceforge.pebble.plugins.PluginLocator__static_init): log
    //#output(net.sourceforge.pebble.plugins.PluginLocator__static_init): new HashMap(PluginLocator__static_init#1) num objects
    //#new obj(net.sourceforge.pebble.plugins.PluginLocator__static_init): new HashMap(PluginLocator__static_init#1)
    //#post(net.sourceforge.pebble.plugins.PluginLocator__static_init): PLUGIN_CONFIG_TYPES == &new HashMap(PluginLocator__static_init#1)
    //#post(net.sourceforge.pebble.plugins.PluginLocator__static_init): __Descendant_Table[net/sourceforge/pebble/plugins/PluginLocator] == &__Dispatch_Table
    //#post(net.sourceforge.pebble.plugins.PluginLocator__static_init): init'ed(log)
    //#post(net.sourceforge.pebble.plugins.PluginLocator__static_init): new HashMap(PluginLocator__static_init#1) num objects == 1
  private static final Map<String, PluginConfigType> PLUGIN_CONFIG_TYPES;
  static {
    PLUGIN_CONFIG_TYPES = new HashMap<String, PluginConfigType>();
    PLUGIN_CONFIG_TYPES.put("string", PlainTextPluginConfigType.INSTANCE);
    PLUGIN_CONFIG_TYPES.put("textarea", TextAreaPluginConfigType.INSTANCE);
    PLUGIN_CONFIG_TYPES.put("checkbox", CheckboxPluginConfigType.INSTANCE);
    PLUGIN_CONFIG_TYPES.put("password", PasswordPluginConfigType.INSTANCE);
    //#pluginlocator.java:59: end of method: net.sourceforge.pebble.plugins.PluginLocator.net.sourceforge.pebble.plugins.PluginLocator__static_init
  }

  private static AvailablePlugins availablePlugins;

  /**
   * Locates all the plugins installed in Pebble
   *
   * @return A map of plugin types to lists of plugin class names
   */
  public static synchronized AvailablePlugins locateAvailablePlugins() {
    if (availablePlugins == null) {
    //#pluginlocator.java:70: method: AvailablePlugins net.sourceforge.pebble.plugins.PluginLocator.locateAvailablePlugins()
    //#input(AvailablePlugins locateAvailablePlugins()): PLUGIN_CONFIG_TYPES
    //#input(AvailablePlugins locateAvailablePlugins()): availablePlugins
    //#input(AvailablePlugins locateAvailablePlugins()): log
    //#input(AvailablePlugins locateAvailablePlugins()): net/sourceforge/pebble/plugins/PlainTextPluginConfigType.INSTANCE
    //#input(AvailablePlugins locateAvailablePlugins()): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[net/sourceforge/pebble/plugins/CheckboxPluginConfigType]
    //#input(AvailablePlugins locateAvailablePlugins()): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[net/sourceforge/pebble/plugins/PasswordPluginConfigType]
    //#input(AvailablePlugins locateAvailablePlugins()): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[net/sourceforge/pebble/plugins/PlainTextPluginConfigType]
    //#input(AvailablePlugins locateAvailablePlugins()): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[net/sourceforge/pebble/plugins/PluginConfigType]
    //#input(AvailablePlugins locateAvailablePlugins()): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[net/sourceforge/pebble/plugins/TextAreaPluginConfigType]
    //#input(AvailablePlugins locateAvailablePlugins()): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[others]
    //#output(AvailablePlugins locateAvailablePlugins()): availablePlugins
    //#output(AvailablePlugins locateAvailablePlugins()): new AvailablePlugins(locateAvailablePlugins#3) num objects
    //#output(AvailablePlugins locateAvailablePlugins()): new AvailablePlugins(locateAvailablePlugins#3).__Tag
    //#output(AvailablePlugins locateAvailablePlugins()): new AvailablePlugins(locateAvailablePlugins#3).plugins
    //#output(AvailablePlugins locateAvailablePlugins()): new HashMap(locateAvailablePlugins#1) num objects
    //#output(AvailablePlugins locateAvailablePlugins()): return_value
    //#new obj(AvailablePlugins locateAvailablePlugins()): new AvailablePlugins(locateAvailablePlugins#3)
    //#new obj(AvailablePlugins locateAvailablePlugins()): new HashMap(locateAvailablePlugins#1)
    //#pre[1] (AvailablePlugins locateAvailablePlugins()): init'ed(availablePlugins)
    //#presumption(AvailablePlugins locateAvailablePlugins()): java.lang.Class:getClassLoader(...)@73 != null
    //#presumption(AvailablePlugins locateAvailablePlugins()): java.lang.ClassLoader:getResources(...)@73 != null
    //#presumption(AvailablePlugins locateAvailablePlugins()): java.util.Enumeration:nextElement(...)@75 != null
    //#presumption(AvailablePlugins locateAvailablePlugins()): java.util.Map:values(...)@82 != null
    //#presumption(AvailablePlugins locateAvailablePlugins()): org.apache.commons.logging.LogFactory:getLog(...)@52 != null
    //#post(AvailablePlugins locateAvailablePlugins()): availablePlugins == One-of{old availablePlugins, &new AvailablePlugins(locateAvailablePlugins#3)}
    //#post(AvailablePlugins locateAvailablePlugins()): availablePlugins != null
    //#post(AvailablePlugins locateAvailablePlugins()): return_value == availablePlugins
    //#post(AvailablePlugins locateAvailablePlugins()): new AvailablePlugins(locateAvailablePlugins#3) num objects <= 1
    //#post(AvailablePlugins locateAvailablePlugins()): new AvailablePlugins(locateAvailablePlugins#3).__Tag == net/sourceforge/pebble/plugins/AvailablePlugins
    //#post(AvailablePlugins locateAvailablePlugins()): new AvailablePlugins(locateAvailablePlugins#3).plugins == &new HashMap(locateAvailablePlugins#1)
    //#post(AvailablePlugins locateAvailablePlugins()): new HashMap(locateAvailablePlugins#1) num objects <= 1
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:java.util.Map:put
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:org.jdom.Element:getChildren
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:java.lang.Iterable:iterator
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:org.jdom.Element:getAttributeValue
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:java.lang.Boolean:parseBoolean
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:java.util.Map:get
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:java.util.Properties
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:org.jdom.Element:getName
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:org.jdom.Element:getText
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:java.util.Properties:setProperty
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:java.util.Collection:add
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:org.jdom.input.SAXBuilder
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:java.net.URL:openStream
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:org.jdom.input.SAXBuilder:build
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:org.jdom.Document:getRootElement
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:org.jdom.Element:getChild
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:java.lang.Integer:parseInt
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:org.apache.commons.logging.Log:error
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:java.lang.Thread:currentThread
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:java.lang.Thread:getContextClassLoader
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:java.lang.ClassLoader:loadClass
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:org.apache.commons.logging.Log:debug
    //#unanalyzed(AvailablePlugins locateAvailablePlugins()): Effects-of-calling:java.util.List:add
    //#test_vector(AvailablePlugins locateAvailablePlugins()): availablePlugins: Inverse{null}, Addr_Set{null}
    //#test_vector(AvailablePlugins locateAvailablePlugins()): java.util.Iterator:hasNext(...)@82: {1}, {0}
      Map<String, List<Plugin>> plugins = new HashMap<String, List<Plugin>>();
      try {
        Enumeration<URL> resources = PluginLocator.class.getClassLoader().getResources("pebble-plugins.xml");
        while (resources.hasMoreElements()) {
          installPlugins(plugins, resources.nextElement());
        }
      }
      catch (IOException ioe) {
        log.error("Error occured while scanning context classloader for plugins", ioe);
    //#pluginlocator.java:79: Warning: method not available
    //#    -- call on void org.apache.commons.logging.Log:error(Object, Throwable)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: AvailablePlugins locateAvailablePlugins()
    //#    unanalyzed callee: void org.apache.commons.logging.Log:error(Object, Throwable)
      }
      // Sort the plugins
      for (List<Plugin> pluginsList : plugins.values())
      {
        Collections.sort(pluginsList, new Comparator<Plugin>() {
    //#pluginlocator.java:84: method: void net.sourceforge.pebble.plugins.PluginLocator$1.net.sourceforge.pebble.plugins.PluginLocator$1()
    //#pluginlocator.java:84: end of method: void net.sourceforge.pebble.plugins.PluginLocator$1.net.sourceforge.pebble.plugins.PluginLocator$1()
          public int compare(Plugin o1, Plugin o2) {
            return o1.getWeight() - o2.getWeight();
    //#pluginlocator.java:86: method: int net.sourceforge.pebble.plugins.PluginLocator$1.compare(Plugin, Plugin)
    //#input(int compare(Plugin, Plugin)): net/sourceforge/pebble/plugins/Plugin.__Descendant_Table[net/sourceforge/pebble/plugins/Plugin]
    //#input(int compare(Plugin, Plugin)): net/sourceforge/pebble/plugins/Plugin.__Descendant_Table[others]
    //#input(int compare(Plugin, Plugin)): net/sourceforge/pebble/plugins/Plugin.__Dispatch_Table.getWeight()I
    //#input(int compare(Plugin, Plugin)): o1
    //#input(int compare(Plugin, Plugin)): o1.__Tag
    //#input(int compare(Plugin, Plugin)): o1.weight
    //#input(int compare(Plugin, Plugin)): o2
    //#input(int compare(Plugin, Plugin)): o2.__Tag
    //#input(int compare(Plugin, Plugin)): o2.weight
    //#output(int compare(Plugin, Plugin)): return_value
    //#pre[1] (int compare(Plugin, Plugin)): o1 != null
    //#pre[2] (int compare(Plugin, Plugin)): o1.__Tag == net/sourceforge/pebble/plugins/Plugin
    //#pre[4] (int compare(Plugin, Plugin)): o2 != null
    //#pre[5] (int compare(Plugin, Plugin)): o2.__Tag == net/sourceforge/pebble/plugins/Plugin
    //#pre[7] (int compare(Plugin, Plugin)): o2.weight - o1.weight in -4_294_967_295..2_147_483_648
    //#post(int compare(Plugin, Plugin)): return_value == -(o2.weight - o1.weight)
    //#post(int compare(Plugin, Plugin)): init'ed(return_value)
    //#pluginlocator.java:86: end of method: int net.sourceforge.pebble.plugins.PluginLocator$1.compare(Plugin, Plugin)
          }
        });
      }
      availablePlugins = new AvailablePlugins(plugins);
    }
    return availablePlugins;
    //#pluginlocator.java:92: end of method: AvailablePlugins net.sourceforge.pebble.plugins.PluginLocator.locateAvailablePlugins()
  }

  public static AvailablePlugins getAvailablePluginsSortedForBlog(Blog blog) {
    Map<String, List<Plugin>> plugins = locateAvailablePlugins().copyMap();
    //#pluginlocator.java:96: method: AvailablePlugins net.sourceforge.pebble.plugins.PluginLocator.getAvailablePluginsSortedForBlog(Blog)
    //#input(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): PLUGIN_CONFIG_TYPES
    //#input(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): availablePlugins
    //#input(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): blog
    //#input(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): log
    //#input(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): net/sourceforge/pebble/plugins/AvailablePlugins.__Descendant_Table[net/sourceforge/pebble/plugins/AvailablePlugins]
    //#input(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): net/sourceforge/pebble/plugins/AvailablePlugins.__Descendant_Table[others]
    //#input(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): net/sourceforge/pebble/plugins/AvailablePlugins.__Dispatch_Table.copyMap()Ljava/util/Map;
    //#input(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): net/sourceforge/pebble/plugins/PlainTextPluginConfigType.INSTANCE
    //#input(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[net/sourceforge/pebble/plugins/CheckboxPluginConfigType]
    //#input(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[net/sourceforge/pebble/plugins/PasswordPluginConfigType]
    //#input(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[net/sourceforge/pebble/plugins/PlainTextPluginConfigType]
    //#input(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[net/sourceforge/pebble/plugins/PluginConfigType]
    //#input(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[net/sourceforge/pebble/plugins/TextAreaPluginConfigType]
    //#input(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[others]
    //#output(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): availablePlugins
    //#output(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): new AvailablePlugins(getAvailablePluginsSortedForBlog#1) num objects
    //#output(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): return_value.__Tag
    //#output(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): return_value.plugins
    //#output(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): new AvailablePlugins(locateAvailablePlugins#3) num objects
    //#output(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): new AvailablePlugins(locateAvailablePlugins#3).__Tag
    //#output(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): new AvailablePlugins(locateAvailablePlugins#3).plugins
    //#output(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): new HashMap(copyMap#1) num objects
    //#output(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): new HashMap(locateAvailablePlugins#1) num objects
    //#output(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): return_value
    //#new obj(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): new AvailablePlugins(getAvailablePluginsSortedForBlog#1)
    //#new obj(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): new AvailablePlugins(locateAvailablePlugins#3)
    //#new obj(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): new HashMap(copyMap#1)
    //#new obj(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): new HashMap(locateAvailablePlugins#1)
    //#pre[1] (AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): blog != null
    //#pre[2] (AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): init'ed(availablePlugins)
    //#presumption(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): locateAvailablePlugins(...).__Tag == net/sourceforge/pebble/plugins/AvailablePlugins
    //#presumption(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): locateAvailablePlugins(...).plugins != null
    //#post(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): availablePlugins == One-of{old availablePlugins, &new AvailablePlugins(locateAvailablePlugins#3)}
    //#post(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): availablePlugins != null
    //#post(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): return_value == &new AvailablePlugins(getAvailablePluginsSortedForBlog#1)
    //#post(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): new AvailablePlugins(getAvailablePluginsSortedForBlog#1) num objects == 1
    //#post(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): new HashMap(copyMap#1) num objects == 1
    //#post(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): return_value.__Tag == net/sourceforge/pebble/plugins/AvailablePlugins
    //#post(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): new AvailablePlugins(locateAvailablePlugins#3).__Tag == net/sourceforge/pebble/plugins/AvailablePlugins
    //#post(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): return_value.plugins == &new HashMap(copyMap#1)
    //#post(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): new AvailablePlugins(locateAvailablePlugins#3) num objects <= 1
    //#post(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): new HashMap(locateAvailablePlugins#1) num objects == new AvailablePlugins(locateAvailablePlugins#3) num objects
    //#post(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): new AvailablePlugins(locateAvailablePlugins#3).plugins == &new HashMap(locateAvailablePlugins#1)
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.util.HashMap
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.util.Map:put
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:org.jdom.Element:getChildren
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.lang.Iterable:iterator
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:org.jdom.Element:getAttributeValue
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.lang.Boolean:parseBoolean
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.util.Map:get
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.util.Properties
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:org.jdom.Element:getName
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:org.jdom.Element:getText
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.util.Properties:setProperty
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.util.Collection:add
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:org.jdom.input.SAXBuilder
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.net.URL:openStream
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:org.jdom.input.SAXBuilder:build
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:org.jdom.Document:getRootElement
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:org.jdom.Element:getChild
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.lang.Integer:parseInt
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:org.apache.commons.logging.Log:error
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.lang.Thread:currentThread
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.lang.Thread:getContextClassLoader
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.lang.ClassLoader:loadClass
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:org.apache.commons.logging.Log:debug
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.util.List:add
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.lang.Class:getClassLoader
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.lang.ClassLoader:getResources
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.util.Enumeration:hasMoreElements
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.util.Enumeration:nextElement
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.util.Map:values
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.util.Collection:iterator
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.util.Collections:sort
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.util.Map:entrySet
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.util.Set:iterator
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.util.Map$Entry:getKey
    //#unanalyzed(AvailablePlugins getAvailablePluginsSortedForBlog(Blog)): Effects-of-calling:java.util.Map$Entry:getValue
    // Sort the decorators
    plugins.put(AvailablePlugins.CONTENT_DECORATOR, sortPlugins(plugins.get(AvailablePlugins.CONTENT_DECORATOR),
            blog.getContentDecorators()));
    //#pluginlocator.java:99: Warning: method not available
    //#    -- call on List net.sourceforge.pebble.domain.Blog:getContentDecorators()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: AvailablePlugins getAvailablePluginsSortedForBlog(Blog)
    //#    unanalyzed callee: List net.sourceforge.pebble.domain.Blog:getContentDecorators()
    return new AvailablePlugins(plugins);
    //#pluginlocator.java:100: end of method: AvailablePlugins net.sourceforge.pebble.plugins.PluginLocator.getAvailablePluginsSortedForBlog(Blog)
  }

  private static List<Plugin> sortPlugins(List<Plugin> plugins, final List<String> installedPlugins) {
    if (plugins == null)
    //#pluginlocator.java:104: method: List net.sourceforge.pebble.plugins.PluginLocator.sortPlugins(List, List)
    //#input(List sortPlugins(List, List)): installedPlugins
    //#input(List sortPlugins(List, List)): plugins
    //#output(List sortPlugins(List, List)): return_value
    //#post(List sortPlugins(List, List)): return_value == One-of{null, plugins}
    //#post(List sortPlugins(List, List)): init'ed(return_value)
    //#test_vector(List sortPlugins(List, List)): plugins: Inverse{null}, Addr_Set{null}
    {
      return null;
    }
    Collections.sort(plugins, new Comparator<Plugin>() {
    //#pluginlocator.java:108: end of method: void net.sourceforge.pebble.plugins.PluginLocator$2.net.sourceforge.pebble.plugins.PluginLocator$2(List)
      public int compare(Plugin plugin1, Plugin plugin2) {
        // This comparator ensures installed plugins are at the top, in the order specified by the user,
        // and that not installed plugins are sorted by their weight.
        int index1 = installedPlugins.indexOf(plugin1.getPluginClass());
    //#pluginlocator.java:112: method: int net.sourceforge.pebble.plugins.PluginLocator$2.compare(Plugin, Plugin)
    //#input(int compare(Plugin, Plugin)): net/sourceforge/pebble/plugins/Plugin.__Descendant_Table[net/sourceforge/pebble/plugins/Plugin]
    //#input(int compare(Plugin, Plugin)): net/sourceforge/pebble/plugins/Plugin.__Descendant_Table[others]
    //#input(int compare(Plugin, Plugin)): net/sourceforge/pebble/plugins/Plugin.__Dispatch_Table.getPluginClass()Ljava/lang/String;
    //#input(int compare(Plugin, Plugin)): net/sourceforge/pebble/plugins/Plugin.__Dispatch_Table.getWeight()I
    //#input(int compare(Plugin, Plugin)): plugin1
    //#input(int compare(Plugin, Plugin)): plugin1.__Tag
    //#input(int compare(Plugin, Plugin)): plugin1.pluginClass
    //#input(int compare(Plugin, Plugin)): plugin1.weight
    //#input(int compare(Plugin, Plugin)): plugin2
    //#input(int compare(Plugin, Plugin)): plugin2.__Tag
    //#input(int compare(Plugin, Plugin)): plugin2.pluginClass
    //#input(int compare(Plugin, Plugin)): plugin2.weight
    //#input(int compare(Plugin, Plugin)): this
    //#input(int compare(Plugin, Plugin)): this.val$installedPlugins
    //#output(int compare(Plugin, Plugin)): return_value
    //#pre[1] (int compare(Plugin, Plugin)): plugin1 != null
    //#pre[2] (int compare(Plugin, Plugin)): plugin1.__Tag == net/sourceforge/pebble/plugins/Plugin
    //#pre[5] (int compare(Plugin, Plugin)): plugin2 != null
    //#pre[6] (int compare(Plugin, Plugin)): plugin2.__Tag == net/sourceforge/pebble/plugins/Plugin
    //#pre[11] (int compare(Plugin, Plugin)): this.val$installedPlugins != null
    //#pre[9] (int compare(Plugin, Plugin)): (soft) plugin2.weight - plugin1.weight in -4_294_967_295..2_147_483_648
    //#presumption(int compare(Plugin, Plugin)): java.util.List:indexOf(...)@113 - java.util.List:indexOf(...)@112 in {-6_442_450_943..2_147_483_648, 4_294_967_296..6_442_450_943}
    //#post(int compare(Plugin, Plugin)): init'ed(return_value)
    //#test_vector(int compare(Plugin, Plugin)): java.util.List:indexOf(...)@112: {-2_147_483_648..-1}, {0..4_294_967_295}
    //#test_vector(int compare(Plugin, Plugin)): java.util.List:indexOf(...)@113: {-2_147_483_648..-1}, {0..4_294_967_295}
    //#test_vector(int compare(Plugin, Plugin)): java.util.List:indexOf(...)@113 - java.util.List:indexOf(...)@112: {1..2_147_483_647}, {-6_442_450_943..-1}
        int index2 = installedPlugins.indexOf(plugin2.getPluginClass());
        if (index1 >= 0 && index2 >= 0)
        {
          return index1 - index2;
        }
        if (index1 < 0 && index2 < 0)
        {
          return plugin1.getWeight() - plugin2.getWeight();
        }
        if (index1 >= 0)
        {
          return -1;
        }
        return 1;
    //#pluginlocator.java:126: end of method: int net.sourceforge.pebble.plugins.PluginLocator$2.compare(Plugin, Plugin)
      }
    });
    return plugins;
    //#pluginlocator.java:129: end of method: List net.sourceforge.pebble.plugins.PluginLocator.sortPlugins(List, List)
  }

  /**
   * Install the plugins from the given resource
   * @param plugins The plugins to install
   * @param resource The resource to install them from
   */
  static void installPlugins(Map<String, List<Plugin>> plugins, URL resource) {
    SAXBuilder saxBuilder = new SAXBuilder();
    //#pluginlocator.java:138: method: void net.sourceforge.pebble.plugins.PluginLocator.installPlugins(Map, URL)
    //#pluginlocator.java:138: Warning: method not available
    //#    -- call on void org.jdom.input.SAXBuilder()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: void installPlugins(Map, URL)
    //#    unanalyzed callee: void org.jdom.input.SAXBuilder()
    //#input(void installPlugins(Map, URL)): PLUGIN_CONFIG_TYPES
    //#input(void installPlugins(Map, URL)): log
    //#input(void installPlugins(Map, URL)): net/sourceforge/pebble/plugins/PlainTextPluginConfigType.INSTANCE
    //#input(void installPlugins(Map, URL)): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[net/sourceforge/pebble/plugins/CheckboxPluginConfigType]
    //#input(void installPlugins(Map, URL)): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[net/sourceforge/pebble/plugins/PasswordPluginConfigType]
    //#input(void installPlugins(Map, URL)): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[net/sourceforge/pebble/plugins/PlainTextPluginConfigType]
    //#input(void installPlugins(Map, URL)): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[net/sourceforge/pebble/plugins/PluginConfigType]
    //#input(void installPlugins(Map, URL)): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[net/sourceforge/pebble/plugins/TextAreaPluginConfigType]
    //#input(void installPlugins(Map, URL)): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[others]
    //#input(void installPlugins(Map, URL)): plugins
    //#input(void installPlugins(Map, URL)): resource
    //#pre[1] (void installPlugins(Map, URL)): (soft) plugins != null
    //#pre[2] (void installPlugins(Map, URL)): (soft) resource != null
    //#presumption(void installPlugins(Map, URL)): java.lang.Iterable:iterator(...)@142 != null
    //#presumption(void installPlugins(Map, URL)): java.lang.Thread:currentThread(...)@165 != null
    //#presumption(void installPlugins(Map, URL)): java.lang.Thread:getContextClassLoader(...)@165 != null
    //#presumption(void installPlugins(Map, URL)): java.util.Iterator:next(...)@142 != null
    //#presumption(void installPlugins(Map, URL)): org.apache.commons.logging.LogFactory:getLog(...)@52 != null
    //#presumption(void installPlugins(Map, URL)): org.jdom.Document:getRootElement(...)@141 != null
    //#presumption(void installPlugins(Map, URL)): org.jdom.Element:getChildren(...)@142 != null
    //#presumption(void installPlugins(Map, URL)): org.jdom.input.SAXBuilder:build(...)@140 != null
    //#unanalyzed(void installPlugins(Map, URL)): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(void installPlugins(Map, URL)): Effects-of-calling:org.jdom.Element:getChildren
    //#unanalyzed(void installPlugins(Map, URL)): Effects-of-calling:java.lang.Iterable:iterator
    //#unanalyzed(void installPlugins(Map, URL)): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(void installPlugins(Map, URL)): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(void installPlugins(Map, URL)): Effects-of-calling:org.jdom.Element:getAttributeValue
    //#unanalyzed(void installPlugins(Map, URL)): Effects-of-calling:java.lang.Boolean:parseBoolean
    //#unanalyzed(void installPlugins(Map, URL)): Effects-of-calling:java.util.Map:get
    //#unanalyzed(void installPlugins(Map, URL)): Effects-of-calling:java.util.Properties
    //#unanalyzed(void installPlugins(Map, URL)): Effects-of-calling:org.jdom.Element:getName
    //#unanalyzed(void installPlugins(Map, URL)): Effects-of-calling:org.jdom.Element:getText
    //#unanalyzed(void installPlugins(Map, URL)): Effects-of-calling:java.util.Properties:setProperty
    //#unanalyzed(void installPlugins(Map, URL)): Effects-of-calling:java.util.Collection:add
    //#test_vector(void installPlugins(Map, URL)): java.util.Map:get(...)@168: Inverse{null}, Addr_Set{null}
    //#test_vector(void installPlugins(Map, URL)): org.jdom.Element:getAttributeValue(...)@153: Addr_Set{null}, Inverse{null}
    //#test_vector(void installPlugins(Map, URL)): org.jdom.Element:getChild(...)@146: Addr_Set{null}, Inverse{null}
    try {
      Document document = saxBuilder.build(resource.openStream());
    //#pluginlocator.java:140: Warning: method not available
    //#    -- call on Document org.jdom.input.SAXBuilder:build(InputStream)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: void installPlugins(Map, URL)
    //#    unanalyzed callee: Document org.jdom.input.SAXBuilder:build(InputStream)
      Element root = document.getRootElement();
    //#pluginlocator.java:141: Warning: method not available
    //#    -- call on Element org.jdom.Document:getRootElement()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: void installPlugins(Map, URL)
    //#    unanalyzed callee: Element org.jdom.Document:getRootElement()
      for (Element element : (Iterable<Element>) root.getChildren())
    //#pluginlocator.java:142: Warning: method not available
    //#    -- call on List org.jdom.Element:getChildren()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: void installPlugins(Map, URL)
    //#    unanalyzed callee: List org.jdom.Element:getChildren()
      {
        String type = element.getName();
    //#pluginlocator.java:144: Warning: method not available
    //#    -- call on String org.jdom.Element:getName()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: void installPlugins(Map, URL)
    //#    unanalyzed callee: String org.jdom.Element:getName()
        String name = element.getAttributeValue("name");
    //#pluginlocator.java:145: Warning: method not available
    //#    -- call on String org.jdom.Element:getAttributeValue(String)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: void installPlugins(Map, URL)
    //#    unanalyzed callee: String org.jdom.Element:getAttributeValue(String)
        Element descriptionElement = element.getChild("description");
    //#pluginlocator.java:146: Warning: method not available
    //#    -- call on Element org.jdom.Element:getChild(String)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: void installPlugins(Map, URL)
    //#    unanalyzed callee: Element org.jdom.Element:getChild(String)
        String description = null;
        if (descriptionElement != null)
        {
          description = descriptionElement.getText();
    //#pluginlocator.java:150: Warning: method not available
    //#    -- call on String org.jdom.Element:getText()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: void installPlugins(Map, URL)
    //#    unanalyzed callee: String org.jdom.Element:getText()
        }
        String className = element.getAttributeValue("class");
    //#pluginlocator.java:152: Warning: method not available
    //#    -- call on String org.jdom.Element:getAttributeValue(String)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: void installPlugins(Map, URL)
    //#    unanalyzed callee: String org.jdom.Element:getAttributeValue(String)
        String weightStr = element.getAttributeValue("weight");
    //#pluginlocator.java:153: Warning: method not available
    //#    -- call on String org.jdom.Element:getAttributeValue(String)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: void installPlugins(Map, URL)
    //#    unanalyzed callee: String org.jdom.Element:getAttributeValue(String)
        int weight = 100;
        if (weightStr != null)
        {
          try {
            weight = Integer.parseInt(weightStr);
          } catch (NumberFormatException e) {
            log.error("Invalid weight for plugin " + name + ": " + weightStr);
    //#pluginlocator.java:160: Warning: method not available
    //#    -- call on void org.apache.commons.logging.Log:error(Object)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: void installPlugins(Map, URL)
    //#    unanalyzed callee: void org.apache.commons.logging.Log:error(Object)
          }
        }
        // Try and load the class - for validation
        try {
          Thread.currentThread().getContextClassLoader().loadClass(className);
          // Successful, add it
          log.debug("Installing plugin '" + name + "' of type " + type + " with class " + className);
    //#pluginlocator.java:167: Warning: method not available
    //#    -- call on void org.apache.commons.logging.Log:debug(Object)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: void installPlugins(Map, URL)
    //#    unanalyzed callee: void org.apache.commons.logging.Log:debug(Object)
          List<Plugin> list = plugins.get(type);
          if (list == null)
          {
            list = new ArrayList<Plugin>();
            plugins.put(type, list);
          }
          Collection<PluginConfig> pluginConfig = parsePluginConfig(element);
          list.add(new Plugin(name, description, className, weight, pluginConfig));
        } catch (ClassNotFoundException e) {
          log.error("Plugin class " + className + " of type " + type + " from descriptor " + resource +
    //#pluginlocator.java:177: Warning: method not available
    //#    -- call on void org.apache.commons.logging.Log:error(Object)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: void installPlugins(Map, URL)
    //#    unanalyzed callee: void org.apache.commons.logging.Log:error(Object)
                  " could not be found.");
        }
      }
    } catch (JDOMException e) {
      log.error("Error parsing plugin descriptor at " + resource, e);
    //#pluginlocator.java:182: Warning: method not available
    //#    -- call on void org.apache.commons.logging.Log:error(Object, Throwable)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: void installPlugins(Map, URL)
    //#    unanalyzed callee: void org.apache.commons.logging.Log:error(Object, Throwable)
    } catch (IOException e) {
      log.error("Error reading plugin descriptor at " + resource, e);
    //#pluginlocator.java:184: Warning: method not available
    //#    -- call on void org.apache.commons.logging.Log:error(Object, Throwable)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: void installPlugins(Map, URL)
    //#    unanalyzed callee: void org.apache.commons.logging.Log:error(Object, Throwable)
    }
  }
    //#pluginlocator.java:186: end of method: void net.sourceforge.pebble.plugins.PluginLocator.installPlugins(Map, URL)

  private static Collection<PluginConfig> parsePluginConfig(Element element)
  {
    Collection<PluginConfig> results = new ArrayList<PluginConfig>();
    //#pluginlocator.java:190: method: Collection net.sourceforge.pebble.plugins.PluginLocator.parsePluginConfig(Element)
    //#input(Collection parsePluginConfig(Element)): PLUGIN_CONFIG_TYPES
    //#input(Collection parsePluginConfig(Element)): element
    //#input(Collection parsePluginConfig(Element)): net/sourceforge/pebble/plugins/PlainTextPluginConfigType.INSTANCE
    //#input(Collection parsePluginConfig(Element)): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[net/sourceforge/pebble/plugins/CheckboxPluginConfigType]
    //#input(Collection parsePluginConfig(Element)): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[net/sourceforge/pebble/plugins/PasswordPluginConfigType]
    //#input(Collection parsePluginConfig(Element)): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[net/sourceforge/pebble/plugins/PlainTextPluginConfigType]
    //#input(Collection parsePluginConfig(Element)): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[net/sourceforge/pebble/plugins/PluginConfigType]
    //#input(Collection parsePluginConfig(Element)): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[net/sourceforge/pebble/plugins/TextAreaPluginConfigType]
    //#input(Collection parsePluginConfig(Element)): net/sourceforge/pebble/plugins/PluginConfigType.__Descendant_Table[others]
    //#output(Collection parsePluginConfig(Element)): new ArrayList(parsePluginConfig#1) num objects
    //#output(Collection parsePluginConfig(Element)): return_value
    //#new obj(Collection parsePluginConfig(Element)): new ArrayList(parsePluginConfig#1)
    //#pre[1] (Collection parsePluginConfig(Element)): element != null
    //#presumption(Collection parsePluginConfig(Element)): java.lang.Iterable:iterator(...)@191 != null
    //#presumption(Collection parsePluginConfig(Element)): java.lang.Iterable:iterator(...)@208 != null
    //#presumption(Collection parsePluginConfig(Element)): java.util.Iterator:next(...)@191 != null
    //#presumption(Collection parsePluginConfig(Element)): java.util.Iterator:next(...)@208 != null
    //#presumption(Collection parsePluginConfig(Element)): java.util.Map:get(...).__Tag@204 in {net/sourceforge/pebble/plugins/CheckboxPluginConfigType, net/sourceforge/pebble/plugins/PasswordPluginConfigType, net/sourceforge/pebble/plugins/PlainTextPluginConfigType, net/sourceforge/pebble/plugins/PluginConfigType, net/sourceforge/pebble/plugins/TextAreaPluginConfigType}
    //#presumption(Collection parsePluginConfig(Element)): org.jdom.Element:getChildren(...)@191 != null
    //#presumption(Collection parsePluginConfig(Element)): org.jdom.Element:getChildren(...)@208 != null
    //#post(Collection parsePluginConfig(Element)): return_value == &new ArrayList(parsePluginConfig#1)
    //#post(Collection parsePluginConfig(Element)): new ArrayList(parsePluginConfig#1) num objects == 1
    //#test_vector(Collection parsePluginConfig(Element)): java.util.Iterator:hasNext(...)@191: {1}, {0}
    //#test_vector(Collection parsePluginConfig(Element)): java.util.Iterator:hasNext(...)@208: {1}, {0}
    //#test_vector(Collection parsePluginConfig(Element)): org.jdom.Element:getAttributeValue(...)@196: Inverse{null}, Addr_Set{null}
    for (Element configElement : (Iterable<Element>) element.getChildren("config"))
    //#pluginlocator.java:191: Warning: method not available
    //#    -- call on List org.jdom.Element:getChildren(String)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: Collection parsePluginConfig(Element)
    //#    unanalyzed callee: List org.jdom.Element:getChildren(String)
    {
      String key = configElement.getAttributeValue("key");
    //#pluginlocator.java:193: Warning: method not available
    //#    -- call on String org.jdom.Element:getAttributeValue(String)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: Collection parsePluginConfig(Element)
    //#    unanalyzed callee: String org.jdom.Element:getAttributeValue(String)
      String name = configElement.getAttributeValue("name");
    //#pluginlocator.java:194: Warning: method not available
    //#    -- call on String org.jdom.Element:getAttributeValue(String)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: Collection parsePluginConfig(Element)
    //#    unanalyzed callee: String org.jdom.Element:getAttributeValue(String)
      boolean required = Boolean.parseBoolean(configElement.getAttributeValue("required"));
    //#pluginlocator.java:195: Warning: method not available
    //#    -- call on String org.jdom.Element:getAttributeValue(String)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: Collection parsePluginConfig(Element)
    //#    unanalyzed callee: String org.jdom.Element:getAttributeValue(String)
      String type = configElement.getAttributeValue("type");
    //#pluginlocator.java:196: Warning: method not available
    //#    -- call on String org.jdom.Element:getAttributeValue(String)
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: Collection parsePluginConfig(Element)
    //#    unanalyzed callee: String org.jdom.Element:getAttributeValue(String)
      PluginConfigType pluginConfigType;
      if (type == null)
      {
        pluginConfigType = PlainTextPluginConfigType.INSTANCE;
      }
      else
      {
        pluginConfigType = PLUGIN_CONFIG_TYPES.get(type);
      }
      // todo custom class instantiation
      Properties properties = new Properties();
      for (Element property : (Iterable<Element>) configElement.getChildren())
    //#pluginlocator.java:208: Warning: method not available
    //#    -- call on List org.jdom.Element:getChildren()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: Collection parsePluginConfig(Element)
    //#    unanalyzed callee: List org.jdom.Element:getChildren()
      {
        properties.setProperty(property.getName(), property.getText());
    //#pluginlocator.java:210: Warning: method not available
    //#    -- call on String org.jdom.Element:getName()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: Collection parsePluginConfig(Element)
    //#    unanalyzed callee: String org.jdom.Element:getName()
    //#pluginlocator.java:210: Warning: method not available
    //#    -- call on String org.jdom.Element:getText()
    //#    severity: INFORMATIONAL
    //#    class: net.sourceforge.pebble.plugins.PluginLocator
    //#    method: Collection parsePluginConfig(Element)
    //#    unanalyzed callee: String org.jdom.Element:getText()
      }
      results.add(new PluginConfig(key, name, pluginConfigType, required, properties));
    }
    return results;
    //#pluginlocator.java:214: end of method: Collection net.sourceforge.pebble.plugins.PluginLocator.parsePluginConfig(Element)
  }
}
    //#output(net.sourceforge.pebble.plugins.PluginLocator$2__static_init): __Descendant_Table[net/sourceforge/pebble/plugins/PluginLocator$2]
    //#output(net.sourceforge.pebble.plugins.PluginLocator$2__static_init): __Dispatch_Table.compare(Ljava/lang/Object;Ljava/lang/Object;)I
    //#output(net.sourceforge.pebble.plugins.PluginLocator$2__static_init): __Dispatch_Table.compare(Lnet/sourceforge/pebble/plugins/Plugin;Lnet/sourceforge/pebble/plugins/Plugin;)I
    //#post(net.sourceforge.pebble.plugins.PluginLocator$2__static_init): __Descendant_Table[net/sourceforge/pebble/plugins/PluginLocator$2] == &__Dispatch_Table
    //#post(net.sourceforge.pebble.plugins.PluginLocator$2__static_init): __Dispatch_Table.compare(Ljava/lang/Object;Ljava/lang/Object;)I == &compare
    //#post(net.sourceforge.pebble.plugins.PluginLocator$2__static_init): __Dispatch_Table.compare(Lnet/sourceforge/pebble/plugins/Plugin;Lnet/sourceforge/pebble/plugins/Plugin;)I == &compare
    //#pluginlocator.java:: end of method: net.sourceforge.pebble.plugins.PluginLocator$2.net.sourceforge.pebble.plugins.PluginLocator$2__static_init
    //#pluginlocator.java:: end of class: net.sourceforge.pebble.plugins.PluginLocator$2
    //#output(net.sourceforge.pebble.plugins.PluginLocator$1__static_init): __Descendant_Table[net/sourceforge/pebble/plugins/PluginLocator$1]
    //#output(net.sourceforge.pebble.plugins.PluginLocator$1__static_init): __Dispatch_Table.compare(Ljava/lang/Object;Ljava/lang/Object;)I
    //#output(net.sourceforge.pebble.plugins.PluginLocator$1__static_init): __Dispatch_Table.compare(Lnet/sourceforge/pebble/plugins/Plugin;Lnet/sourceforge/pebble/plugins/Plugin;)I
    //#post(net.sourceforge.pebble.plugins.PluginLocator$1__static_init): __Descendant_Table[net/sourceforge/pebble/plugins/PluginLocator$1] == &__Dispatch_Table
    //#post(net.sourceforge.pebble.plugins.PluginLocator$1__static_init): __Dispatch_Table.compare(Ljava/lang/Object;Ljava/lang/Object;)I == &compare
    //#post(net.sourceforge.pebble.plugins.PluginLocator$1__static_init): __Dispatch_Table.compare(Lnet/sourceforge/pebble/plugins/Plugin;Lnet/sourceforge/pebble/plugins/Plugin;)I == &compare
    //#pluginlocator.java:: end of method: net.sourceforge.pebble.plugins.PluginLocator$1.net.sourceforge.pebble.plugins.PluginLocator$1__static_init
    //#pluginlocator.java:: end of class: net.sourceforge.pebble.plugins.PluginLocator$1
    //#pluginlocator.java:: end of class: net.sourceforge.pebble.plugins.PluginLocator
