//# 184 errors, 3,923 messages
//#
/*
    //#PluginInfo.java:1:1: class: com.dmdirc.plugins.PluginInfo$1
    //#PluginInfo.java:1:1: method: com.dmdirc.plugins.PluginInfo$1.com.dmdirc.plugins.PluginInfo$1__static_init
    //#PluginInfo.java:1:1: class: com.dmdirc.plugins.PluginInfo
 * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.dmdirc.plugins;

import com.dmdirc.actions.ActionManager;
import com.dmdirc.actions.CoreActionType;
import com.dmdirc.config.Identity;
import com.dmdirc.config.IdentityManager;
import com.dmdirc.config.prefs.validator.ValidationResponse;
import com.dmdirc.util.resourcemanager.ResourceManager;
import com.dmdirc.util.ConfigFile;
import com.dmdirc.util.InvalidConfigFileException;
import com.dmdirc.logger.Logger;
import com.dmdirc.logger.ErrorLevel;

import com.dmdirc.updater.Version;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Properties;
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import java.net.URL;

public class PluginInfo implements Comparable<PluginInfo>, ServiceProvider {
    //#PluginInfo.java:49: method: int com.dmdirc.plugins.PluginInfo.compareTo(Object)
    //#input(int compareTo(Object)): " - "._tainted
    //#input(int compareTo(Object)): ""._tainted
    //#input(int compareTo(Object)): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(int compareTo(Object)): __Descendant_Table[others]
    //#input(int compareTo(Object)): __Dispatch_Table.compareTo(Lcom/dmdirc/plugins/PluginInfo;)I
    //#input(int compareTo(Object)): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(int compareTo(Object)): __Dispatch_Table.getName()Ljava/lang/String;
    //#input(int compareTo(Object)): __Dispatch_Table.getNiceName()Ljava/lang/String;
    //#input(int compareTo(Object)): __Dispatch_Table.toString()Ljava/lang/String;
    //#input(int compareTo(Object)): this
    //#input(int compareTo(Object)): this.__Tag
    //#input(int compareTo(Object)): this.filename
    //#input(int compareTo(Object)): this.filename._tainted
    //#input(int compareTo(Object)): this.metaData
    //#input(int compareTo(Object)): x0
    //#input(int compareTo(Object)): x0.__Tag
    //#input(int compareTo(Object)): x0.filename
    //#input(int compareTo(Object)): x0.filename._tainted
    //#input(int compareTo(Object)): x0.metaData
    //#output(int compareTo(Object)): return_value
    //#pre[2] (int compareTo(Object)): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[5] (int compareTo(Object)): init'ed(this.metaData)
    //#pre[6] (int compareTo(Object)): x0 != null
    //#pre[7] (int compareTo(Object)): x0.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[10] (int compareTo(Object)): init'ed(x0.metaData)
    //#post(int compareTo(Object)): init'ed(return_value)
    //#unanalyzed(int compareTo(Object)): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(int compareTo(Object)): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(int compareTo(Object)): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(int compareTo(Object)): Effects-of-calling:java.util.Map:get
    //#unanalyzed(int compareTo(Object)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(int compareTo(Object)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(int compareTo(Object)): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(int compareTo(Object)): Effects-of-calling:getNiceName
    //#unanalyzed(int compareTo(Object)): Effects-of-calling:toString
    //#unanalyzed(int compareTo(Object)): Effects-of-calling:java.lang.String:compareTo
    //#PluginInfo.java:49: end of method: int com.dmdirc.plugins.PluginInfo.compareTo(Object)
    //#PluginInfo.java:49: method: ResourceManager com.dmdirc.plugins.PluginInfo.access$002(PluginInfo, ResourceManager)
    //#input(ResourceManager access$002(PluginInfo, ResourceManager)): x0
    //#input(ResourceManager access$002(PluginInfo, ResourceManager)): x1
    //#output(ResourceManager access$002(PluginInfo, ResourceManager)): return_value
    //#output(ResourceManager access$002(PluginInfo, ResourceManager)): x0.myResourceManager
    //#pre[1] (ResourceManager access$002(PluginInfo, ResourceManager)): x0 != null
    //#post(ResourceManager access$002(PluginInfo, ResourceManager)): return_value == x1
    //#post(ResourceManager access$002(PluginInfo, ResourceManager)): init'ed(return_value)
    //#post(ResourceManager access$002(PluginInfo, ResourceManager)): x0.myResourceManager == return_value
    //#PluginInfo.java:49: end of method: ResourceManager com.dmdirc.plugins.PluginInfo.access$002(PluginInfo, ResourceManager)

    /** A logger for this class. */
    private static final java.util.logging.Logger LOGGER = java.util.logging
    //#PluginInfo.java:52: method: com.dmdirc.plugins.PluginInfo.com.dmdirc.plugins.PluginInfo__static_init
    //#output(com.dmdirc.plugins.PluginInfo__static_init): LOGGER
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.activateServices()V
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.addChild(Lcom/dmdirc/plugins/PluginInfo;)V
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.checkFiles(Ljava/lang/String;)Z
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.checkMaximumVersion(Ljava/lang/String;I)Z
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.checkMinimumVersion(Ljava/lang/String;I)Z
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.checkOS(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.checkPlugins(Ljava/lang/String;)Z
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.checkRequirements(Z)Z
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.checkServices(Ljava/util/List;)Z
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.checkUI(Ljava/lang/String;Ljava/lang/String;)Z
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.compareTo(Lcom/dmdirc/plugins/PluginInfo;)I
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.compareTo(Ljava/lang/Object;)I
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.delChild(Lcom/dmdirc/plugins/PluginInfo;)V
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getAddonID()I
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getAuthor()Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getClassList()Ljava/util/List;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getConfigFile()Lcom/dmdirc/util/ConfigFile;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getDefaults()V
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getDescription()Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getExportedService(Ljava/lang/String;)Lcom/dmdirc/plugins/ExportedService;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getFilename()Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getFriendlyVersion()Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getFullFilename()Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getLastError()Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getMainClass()Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getMaxVersion()Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getMetaInfo(Ljava/lang/String;)Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getMetaInfo(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getMetaInfo(Ljava/util/Properties;[Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getMetaInfo([Ljava/lang/String;)Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getMetaInfo([Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getMigratedConfigFile()Lcom/dmdirc/util/ConfigFile;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getMinVersion()Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getName()Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getNiceName()Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getPersistentClasses()Ljava/util/List;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getPlugin()Lcom/dmdirc/plugins/Plugin;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getPluginClassLoader()Lcom/dmdirc/plugins/PluginClassLoader;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getPluginObject()Lcom/dmdirc/plugins/Plugin;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getProviderName()Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getRelativeFilename()Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getRequirementsError()Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getResourceManager()Lcom/dmdirc/util/resourcemanager/ResourceManager;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getResourceManager(Z)Lcom/dmdirc/util/resourcemanager/ResourceManager;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getServices()Ljava/util/List;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getVersion()Lcom/dmdirc/updater/Version;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.hasPersistent()Z
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.isActive()Z
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.isLoaded()Z
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.isMigrated()Z
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.isPersistent()Z
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.isPersistent(Ljava/lang/String;)Z
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.isTempLoaded()Z
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.isUnloadable()Z
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.loadAll()Z
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.loadClass(Ljava/lang/String;)V
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.loadEntirePlugin()V
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.loadPlugin()V
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.loadPluginTemp()V
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.loadRequired()V
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.pluginUpdated()V
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.toString()Ljava/lang/String;
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.unloadPlugin()V
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.unloadPlugin(Z)V
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.updateExports()V
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.updateMetaData()Z
    //#output(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.updateProvides()V
    //#output(com.dmdirc.plugins.PluginInfo__static_init): com/dmdirc/plugins/ServiceProvider.__Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#post(com.dmdirc.plugins.PluginInfo__static_init): init'ed(LOGGER)
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Descendant_Table[com/dmdirc/plugins/PluginInfo] == &__Dispatch_Table
    //#post(com.dmdirc.plugins.PluginInfo__static_init): com/dmdirc/plugins/ServiceProvider.__Descendant_Table[com/dmdirc/plugins/PluginInfo] == &__Dispatch_Table
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.activateServices()V == &activateServices
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.addChild(Lcom/dmdirc/plugins/PluginInfo;)V == &addChild
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.checkFiles(Ljava/lang/String;)Z == &checkFiles
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.checkMaximumVersion(Ljava/lang/String;I)Z == &checkMaximumVersion
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.checkMinimumVersion(Ljava/lang/String;I)Z == &checkMinimumVersion
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.checkOS(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z == &checkOS
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.checkPlugins(Ljava/lang/String;)Z == &checkPlugins
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.checkRequirements(Z)Z == &checkRequirements
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.checkServices(Ljava/util/List;)Z == &checkServices
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.checkUI(Ljava/lang/String;Ljava/lang/String;)Z == &checkUI
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.compareTo(Lcom/dmdirc/plugins/PluginInfo;)I == &compareTo
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.compareTo(Ljava/lang/Object;)I == &compareTo
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.delChild(Lcom/dmdirc/plugins/PluginInfo;)V == &delChild
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getAddonID()I == &getAddonID
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getAuthor()Ljava/lang/String; == &getAuthor
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getClassList()Ljava/util/List; == &getClassList
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getConfigFile()Lcom/dmdirc/util/ConfigFile; == &getConfigFile
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getDefaults()V == &getDefaults
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getDescription()Ljava/lang/String; == &getDescription
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getExportedService(Ljava/lang/String;)Lcom/dmdirc/plugins/ExportedService; == &getExportedService
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getFilename()Ljava/lang/String; == &getFilename
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getFriendlyVersion()Ljava/lang/String; == &getFriendlyVersion
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getFullFilename()Ljava/lang/String; == &getFullFilename
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; == &getKeyValue
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getLastError()Ljava/lang/String; == &getLastError
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getMainClass()Ljava/lang/String; == &getMainClass
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getMaxVersion()Ljava/lang/String; == &getMaxVersion
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getMetaInfo(Ljava/lang/String;)Ljava/lang/String; == &getMetaInfo
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getMetaInfo(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; == &getMetaInfo
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getMetaInfo(Ljava/util/Properties;[Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; == &getMetaInfo
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getMetaInfo([Ljava/lang/String;)Ljava/lang/String; == &getMetaInfo
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getMetaInfo([Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; == &getMetaInfo
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getMigratedConfigFile()Lcom/dmdirc/util/ConfigFile; == &getMigratedConfigFile
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getMinVersion()Ljava/lang/String; == &getMinVersion
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getName()Ljava/lang/String; == &getName
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getNiceName()Ljava/lang/String; == &getNiceName
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getPersistentClasses()Ljava/util/List; == &getPersistentClasses
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getPlugin()Lcom/dmdirc/plugins/Plugin; == &getPlugin
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getPluginClassLoader()Lcom/dmdirc/plugins/PluginClassLoader; == &getPluginClassLoader
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getPluginObject()Lcom/dmdirc/plugins/Plugin; == &getPluginObject
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getProviderName()Ljava/lang/String; == &getProviderName
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getRelativeFilename()Ljava/lang/String; == &getRelativeFilename
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getRequirementsError()Ljava/lang/String; == &getRequirementsError
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getResourceManager()Lcom/dmdirc/util/resourcemanager/ResourceManager; == &getResourceManager
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getResourceManager(Z)Lcom/dmdirc/util/resourcemanager/ResourceManager; == &getResourceManager
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getServices()Ljava/util/List; == &getServices
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.getVersion()Lcom/dmdirc/updater/Version; == &getVersion
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.hasPersistent()Z == &hasPersistent
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.isActive()Z == &isActive
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.isLoaded()Z == &isLoaded
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.isMigrated()Z == &isMigrated
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.isPersistent()Z == &isPersistent
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.isPersistent(Ljava/lang/String;)Z == &isPersistent
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.isTempLoaded()Z == &isTempLoaded
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.isUnloadable()Z == &isUnloadable
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.loadAll()Z == &loadAll
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.loadClass(Ljava/lang/String;)V == &loadClass
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.loadEntirePlugin()V == &loadEntirePlugin
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.loadPlugin()V == &loadPlugin
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.loadPluginTemp()V == &loadPluginTemp
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.loadRequired()V == &loadRequired
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.pluginUpdated()V == &pluginUpdated
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.toString()Ljava/lang/String; == &toString
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.unloadPlugin()V == &unloadPlugin
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.unloadPlugin(Z)V == &unloadPlugin
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.updateExports()V == &updateExports
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.updateMetaData()Z == &updateMetaData
    //#post(com.dmdirc.plugins.PluginInfo__static_init): __Dispatch_Table.updateProvides()V == &updateProvides
    //#PluginInfo.java:52: end of method: com.dmdirc.plugins.PluginInfo.com.dmdirc.plugins.PluginInfo__static_init
            .Logger.getLogger(PluginInfo.class.getName());

	/** Plugin Meta Data */
	private ConfigFile metaData = null;
	/** URL that this plugin was loaded from */
	private final URL url;
	/** Filename for this plugin (taken from URL) */
	private final String filename;
	/** The actual Plugin from this jar */
	private Plugin plugin = null;
	/** The classloader used for this Plugin */
	private PluginClassLoader classloader = null;
	/** The resource manager used by this pluginInfo */
	private ResourceManager myResourceManager = null;
	/** Is this plugin only loaded temporarily? */
	private boolean tempLoaded = false;
	/** List of classes this plugin has */
	private List<String> myClasses = new ArrayList<String>();
	/** Requirements error message. */
	private String requirementsError = "";
	
	/** Last Error Message. */
	private String lastError = "No Error";
	
	/** Are we trying to load? */
	private boolean isLoading = false;
	
	/** Is this plugin using a migrated config? */
	private boolean migrated = false;
	
	/** List of services we provide. */
	private final List<Service> provides = new ArrayList<Service>();
	
	/** List of children of this plugin. */
	private final List<PluginInfo> children = new ArrayList<PluginInfo>();
	
	/** Map of exports */
	private final Map<String, ExportInfo> exports = new HashMap<String, ExportInfo>();

	/**
	 * Create a new PluginInfo.
	 *
	 * @param url URL to file that this plugin is stored in.
	 * @throws PluginException if there is an error loading the Plugin
	 * @since 0.6
	 */
	public PluginInfo(final URL url) throws PluginException {
		this(url, true);
    //#PluginInfo.java:100: method: void com.dmdirc.plugins.PluginInfo.com.dmdirc.plugins.PluginInfo(URL)
    //#PluginInfo.java:100: Warning: call too complex - analysis skipped
    //#    call on void com.dmdirc.plugins.PluginInfo(URL, bool)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void com.dmdirc.plugins.PluginInfo(URL)
    //#    unanalyzed callee: void com.dmdirc.plugins.PluginInfo(URL, bool)
    //#input(void com.dmdirc.plugins.PluginInfo(URL)): this
    //#input(void com.dmdirc.plugins.PluginInfo(URL)): url
	}
    //#PluginInfo.java:101: end of method: void com.dmdirc.plugins.PluginInfo.com.dmdirc.plugins.PluginInfo(URL)

	/**
	 * Create a new PluginInfo.
	 *
	 * @param url URL to file that this plugin is stored in.
	 * @param load Should this plugin be loaded, or is this just a placeholder? (true for load, false for placeholder)
	 * @throws PluginException if there is an error loading the Plugin
	 * @since 0.6
	 */
	public PluginInfo(final URL url, final boolean load) throws PluginException {
    //#PluginInfo.java:111: method: void com.dmdirc.plugins.PluginInfo.com.dmdirc.plugins.PluginInfo(URL, bool)
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): " failed to load, plugin.config failed to open - "._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): " failed to load. "._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): " was not loaded. "._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): ""._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "' not found"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "'"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "')"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "', actual: '"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): ") not found in jar."._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): ")"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "-"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "-resourcemanagerTimer"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): ".class"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): ".update"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): ": Using domain '"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "Error with resourcemanager: "._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "Incomplete plugin.config (Missing or invalid 'author')"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "Incomplete plugin.config (Missing or invalid 'mainclass')"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "Incomplete plugin.config (Missing or invalid 'name')"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "Incomplete plugin.config (Missing or invalid 'version')"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "Invalid OS architecture. (Wanted: '"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "Invalid OS version. (Wanted: '"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "Invalid OS. (Wanted: '"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "No Error"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "One or more requirements not met ("._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "Plugin "._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "Required file '"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "jar:.."._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "main class file ("._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "plugin-"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "plugin.config IOException: "._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "plugin.config IllegalArgumentException: "._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): "plugin.config doesn't exist in jar"._tainted
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): LOGGER
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): __Descendant_Table[others]
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): __Dispatch_Table.checkFiles(Ljava/lang/String;)Z
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): __Dispatch_Table.checkOS(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): __Dispatch_Table.checkPlugins(Ljava/lang/String;)Z
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): __Dispatch_Table.checkRequirements(Z)Z
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): __Dispatch_Table.getAuthor()Ljava/lang/String;
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): __Dispatch_Table.getFullFilename()Ljava/lang/String;
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): __Dispatch_Table.getMainClass()Ljava/lang/String;
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): __Dispatch_Table.getName()Ljava/lang/String;
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): __Dispatch_Table.getResourceManager()Lcom/dmdirc/util/resourcemanager/ResourceManager;
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): __Dispatch_Table.getResourceManager(Z)Lcom/dmdirc/util/resourcemanager/ResourceManager;
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): __Dispatch_Table.getVersion()Lcom/dmdirc/updater/Version;
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): __Dispatch_Table.isPersistent()Z
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): __Dispatch_Table.loadAll()Z
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): load
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): this
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.__Tag
    //#input(void com.dmdirc.plugins.PluginInfo(URL, bool)): url
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): java.lang.StringBuilder:toString(...)._tainted
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): new ArrayList(PluginInfo#1) num objects
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): new ArrayList(PluginInfo#2) num objects
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): new ArrayList(PluginInfo#3) num objects
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): new ConfigFile(getConfigFile#1) num objects
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): new ConfigFile(getMigratedConfigFile#1) num objects
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): new HashMap(PluginInfo#4) num objects
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.__Lock
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.children
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.classloader
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.exports
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.filename
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.isLoading
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.lastError
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.metaData
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.migrated
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.myClasses
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.myResourceManager
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.plugin
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.provides
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.requirementsError
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.tempLoaded
    //#output(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.url
    //#new obj(void com.dmdirc.plugins.PluginInfo(URL, bool)): java.lang.StringBuilder:toString(...)
    //#new obj(void com.dmdirc.plugins.PluginInfo(URL, bool)): new ArrayList(PluginInfo#1)
    //#new obj(void com.dmdirc.plugins.PluginInfo(URL, bool)): new ArrayList(PluginInfo#2)
    //#new obj(void com.dmdirc.plugins.PluginInfo(URL, bool)): new ArrayList(PluginInfo#3)
    //#new obj(void com.dmdirc.plugins.PluginInfo(URL, bool)): new ConfigFile(getConfigFile#1)
    //#new obj(void com.dmdirc.plugins.PluginInfo(URL, bool)): new ConfigFile(getMigratedConfigFile#1)
    //#new obj(void com.dmdirc.plugins.PluginInfo(URL, bool)): new HashMap(PluginInfo#4)
    //#pre[3] (void com.dmdirc.plugins.PluginInfo(URL, bool)): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[4] (void com.dmdirc.plugins.PluginInfo(URL, bool)): url != null
    //#presumption(void com.dmdirc.plugins.PluginInfo(URL, bool)): com.dmdirc.updater.Version:isValid(...)@153 == 1
    //#presumption(void com.dmdirc.plugins.PluginInfo(URL, bool)): com.dmdirc.util.resourcemanager.ResourceManager:getResourcesStartingWith(...)@174 != null
    //#presumption(void com.dmdirc.plugins.PluginInfo(URL, bool)): com.dmdirc.util.resourcemanager.ResourceManager:resourceExists(...)@169 == 1
    //#presumption(void com.dmdirc.plugins.PluginInfo(URL, bool)): java.lang.String:isEmpty(...)@156 == 0
    //#presumption(void com.dmdirc.plugins.PluginInfo(URL, bool)): java.lang.String:isEmpty(...)@159 == 0
    //#presumption(void com.dmdirc.plugins.PluginInfo(URL, bool)): java.lang.String:isEmpty(...)@162 == 0
    //#presumption(void com.dmdirc.plugins.PluginInfo(URL, bool)): java.util.Iterator:next(...)@174 != null
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): init'ed(this.__Lock)
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.children == &new ArrayList(PluginInfo#3)
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): init'ed(this.classloader)
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.exports == &new HashMap(PluginInfo#4)
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): init'ed(this.filename)
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): init'ed(this.isLoading)
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.lastError == &"No Error"
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.metaData in Addr_Set{null,&new ConfigFile(getConfigFile#1),&new ConfigFile(getMigratedConfigFile#1),&new ConfigFile(getConfigFile#1),&new ConfigFile(getMigratedConfigFile#1)}
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): init'ed(this.migrated)
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.myClasses == &new ArrayList(PluginInfo#1)
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): init'ed(this.myResourceManager)
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): init'ed(this.plugin)
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.provides == &new ArrayList(PluginInfo#2)
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.requirementsError in Addr_Set{&"",&java.lang.StringBuilder:toString(...),&java.lang.StringBuilder:toString(...)}
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): init'ed(this.tempLoaded)
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.url == url
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): this.url != null
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): new ArrayList(PluginInfo#1) num objects == 1
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): new ArrayList(PluginInfo#2) num objects == 1
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): new ArrayList(PluginInfo#3) num objects == 1
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): new HashMap(PluginInfo#4) num objects == 1
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): new ConfigFile(getConfigFile#1) num objects <= 1
    //#post(void com.dmdirc.plugins.PluginInfo(URL, bool)): new ConfigFile(getMigratedConfigFile#1) num objects <= 1
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.Properties:getProperty
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.lang.String:isEmpty
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.net.URL:getPath
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.Map:get
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:com.dmdirc.util.ConfigFile:isFlatDomain
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:com.dmdirc.util.ConfigFile:getFlatDomain
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.List:add
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.lang.String:split
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.lang.String:toLowerCase
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.lang.String:matches
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.io.File
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.io.File:exists
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.List:contains
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:getPluginManager
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.lang.String:startsWith
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.lang.String:substring
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.lang.System:getProperty
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:checkPlugins
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:checkServices
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:getPluginInfoByName
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:com.dmdirc.updater.Version
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:com.dmdirc.updater.Version:compareTo
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:getResourceManager
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.Timer
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.TimerTask
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.Timer:schedule
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.List:iterator
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.logging.Logger:finer
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.lang.String:equalsIgnoreCase
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.List:size
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:getServicesByType
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.List:get
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:isActive
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:getService
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:activate
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:com.dmdirc.config.IdentityManager:getAddonIdentity
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.Map:entrySet
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.Set:iterator
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.Map$Entry:getKey
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.lang.Object:toString
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.Map$Entry:getValue
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:com.dmdirc.config.Identity:setOption
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.Map:put
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:getResourceInputStream
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:com.dmdirc.util.ConfigFile
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.Properties
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.Properties:load
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.HashMap
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.Properties:containsKey
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.util.Properties:entrySet
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:com.dmdirc.util.ConfigFile:addDomain
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:resourceExists
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:com.dmdirc.util.ConfigFile:read
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.io.IOException
    //#unanalyzed(void com.dmdirc.plugins.PluginInfo(URL, bool)): Effects-of-calling:java.lang.Exception
    //#test_vector(void com.dmdirc.plugins.PluginInfo(URL, bool)): load: {1}, {0}
    //#test_vector(void com.dmdirc.plugins.PluginInfo(URL, bool)): java.io.File:delete(...)@118: {0}, {1}
    //#test_vector(void com.dmdirc.plugins.PluginInfo(URL, bool)): java.io.File:exists(...)@118: {0}, {1}
    //#test_vector(void com.dmdirc.plugins.PluginInfo(URL, bool)): java.lang.String:matches(...)@176: {0}, {1}
    //#test_vector(void com.dmdirc.plugins.PluginInfo(URL, bool)): java.util.Iterator:hasNext(...)@174: {0}, {1}
		this.url = url;
		this.filename = (new File(url.getPath())).getName();

		ResourceManager res;

		// Check for updates.
		if (new File(getFullFilename()+".update").exists() && new File(getFullFilename()).delete()) {
			new File(getFullFilename()+".update").renameTo(new File(getFullFilename()));
		}

		if (!load) {
			// Load the metaData if available.
			try {
				metaData = getConfigFile();
			} catch (IOException ioe) {
				metaData = null;
			}
			return;
		}

		try {
			res = getResourceManager();
		} catch (IOException ioe) {
			lastError = "Error with resourcemanager: "+ioe.getMessage();
			throw new PluginException("Plugin "+filename+" failed to load. "+lastError, ioe);
		}

		try {
			metaData = getConfigFile();
			if (metaData == null) {
				lastError = "plugin.config doesn't exist in jar";
				throw new PluginException("Plugin "+filename+" failed to load. "+lastError);
    //#PluginInfo.java:143: ?conditional throw
    //#    this.metaData != null
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void com.dmdirc.plugins.PluginInfo(URL, bool)
    //#    basic block: bb_13
    //#    assertion: this.metaData != null
    //#    VN: No_Obj_Id == 3
    //#    Expected: {0}
    //#    Bad: {1}
    //#    Attribs:  Int  Exp in +/-1000  Exp singleton  Bad singleton  Bad overlaps +/-1000  Bad > Exp
			}
		} catch (IOException e) {
			lastError = "plugin.config IOException: "+e.getMessage();
			throw new PluginException("Plugin "+filename+" failed to load, plugin.config failed to open - "+e.getMessage(), e);
		} catch (IllegalArgumentException e) {
			lastError = "plugin.config IllegalArgumentException: "+e.getMessage();
			throw new PluginException("Plugin "+filename+" failed to load, plugin.config failed to open - "+e.getMessage(), e);
		}

		if (!getVersion().isValid()) {
    //#PluginInfo.java:153: Warning: method not available - call not analyzed
    //#    call on bool com.dmdirc.updater.Version:isValid()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void com.dmdirc.plugins.PluginInfo(URL, bool)
    //#    unanalyzed callee: bool com.dmdirc.updater.Version:isValid()
			lastError = "Incomplete plugin.config (Missing or invalid 'version')";
			throw new PluginException("Plugin "+filename+" failed to load. "+lastError);
		} else if (getAuthor().isEmpty()) {
    //#PluginInfo.java:156: ?null dereference
    //#    getAuthor(...) != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void com.dmdirc.plugins.PluginInfo(URL, bool)
    //#    basic block: bb_20
    //#    assertion: getAuthor(...) != null
    //#    VN: getAuthor(...)
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
			lastError = "Incomplete plugin.config (Missing or invalid 'author')";
			throw new PluginException("Plugin "+filename+" failed to load. "+lastError);
		} else if (getName().isEmpty()) {
    //#PluginInfo.java:159: ?null dereference
    //#    getName(...) != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void com.dmdirc.plugins.PluginInfo(URL, bool)
    //#    basic block: bb_22
    //#    assertion: getName(...) != null
    //#    VN: getName(...)
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
			lastError = "Incomplete plugin.config (Missing or invalid 'name')";
			throw new PluginException("Plugin "+filename+" failed to load. "+lastError);
		} else if (getMainClass().isEmpty()) {
    //#PluginInfo.java:162: ?null dereference
    //#    getMainClass(...) != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void com.dmdirc.plugins.PluginInfo(URL, bool)
    //#    basic block: bb_24
    //#    assertion: getMainClass(...) != null
    //#    VN: getMainClass(...)
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
			lastError = "Incomplete plugin.config (Missing or invalid 'mainclass')";
			throw new PluginException("Plugin "+filename+" failed to load. "+lastError);
		}

		if (checkRequirements(true)) {
			final String mainClass = getMainClass().replace('.', '/')+".class";
    //#PluginInfo.java:168: ?null dereference
    //#    getMainClass(...) != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void com.dmdirc.plugins.PluginInfo(URL, bool)
    //#    basic block: bb_27
    //#    assertion: getMainClass(...) != null
    //#    VN: getMainClass(...)
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
			if (!res.resourceExists(mainClass)) {
    //#PluginInfo.java:169: ?null dereference
    //#    res != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void com.dmdirc.plugins.PluginInfo(URL, bool)
    //#    basic block: bb_27
    //#    assertion: res != null
    //#    VN: getResourceManager(...)
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:169: Warning: method not available - call not analyzed
    //#    call on bool com.dmdirc.util.resourcemanager.ResourceManager:resourceExists(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void com.dmdirc.plugins.PluginInfo(URL, bool)
    //#    unanalyzed callee: bool com.dmdirc.util.resourcemanager.ResourceManager:resourceExists(String)
				lastError = "main class file ("+mainClass+") not found in jar.";
				throw new PluginException("Plugin "+filename+" failed to load. "+lastError);
			}

			for (final String classfilename : res.getResourcesStartingWith("")) {
    //#PluginInfo.java:174: Warning: method not available - call not analyzed
    //#    call on List com.dmdirc.util.resourcemanager.ResourceManager:getResourcesStartingWith(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void com.dmdirc.plugins.PluginInfo(URL, bool)
    //#    unanalyzed callee: List com.dmdirc.util.resourcemanager.ResourceManager:getResourcesStartingWith(String)
				String classname = classfilename.replace('/', '.');
				if (classname.matches("^.*\\.class$")) {
					classname = classname.replaceAll("\\.class$", "");
					myClasses.add(classname);
				}
			}

			if (isPersistent() && loadAll()) { loadEntirePlugin(); }
    //#PluginInfo.java:182: Warning: call too complex - analysis skipped
    //#    call on void loadEntirePlugin()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void com.dmdirc.plugins.PluginInfo(URL, bool)
    //#    unanalyzed callee: void loadEntirePlugin()
		} else {
			lastError = "One or more requirements not met ("+requirementsError+")";
			throw new PluginException("Plugin "+filename+" was not loaded. "+lastError);
    //#PluginInfo.java:185: ?conditional throw
    //#    checkRequirements(...) != 0
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void com.dmdirc.plugins.PluginInfo(URL, bool)
    //#    basic block: bb_26
    //#    assertion: checkRequirements(...) != 0
    //#    VN: checkRequirements(...)
    //#    Expected: {-Inf..-1, 1..+Inf}
    //#    Bad: {0}
    //#    Attribs:  Int  Bad singleton  Bad overlaps +/-1000  Bad > Exp
		}

		updateProvides();
    //#PluginInfo.java:188: Warning: call too complex - analysis skipped
    //#    call on void updateProvides()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void com.dmdirc.plugins.PluginInfo(URL, bool)
    //#    unanalyzed callee: void updateProvides()
		getDefaults();
	}
    //#PluginInfo.java:190: end of method: void com.dmdirc.plugins.PluginInfo.com.dmdirc.plugins.PluginInfo(URL, bool)
	
	/**
	 * Get misc meta-information.
	 *
	 * @param properties The properties file to look in
	 * @param metainfo The metainfos to look for in order. If the first item in
	 *                 the array is not found, the next will be looked for, and
	 *                 so on until either one is found, or none are found.
	 * @param fallback Fallback value if requested values are not found
	 * @return Misc Meta Info (or "" if none are found);
	 */
	private String getMetaInfo(final Properties properties, final String[] metainfo, final String fallback) {
		for (String meta : metainfo) {
    //#PluginInfo.java:203: method: String com.dmdirc.plugins.PluginInfo.getMetaInfo(Properties, String[], String)
    //#input(String getMetaInfo(Properties, String[], String)): fallback
    //#input(String getMetaInfo(Properties, String[], String)): metainfo
    //#input(String getMetaInfo(Properties, String[], String)): metainfo.length
    //#input(String getMetaInfo(Properties, String[], String)): metainfo[0..4_294_967_295]
    //#input(String getMetaInfo(Properties, String[], String)): properties
    //#output(String getMetaInfo(Properties, String[], String)): return_value
    //#pre[2] (String getMetaInfo(Properties, String[], String)): metainfo != null
    //#pre[3] (String getMetaInfo(Properties, String[], String)): metainfo.length <= 4_294_967_295
    //#pre[4] (String getMetaInfo(Properties, String[], String)): (soft) init'ed(metainfo[0..4_294_967_295])
    //#pre[5] (String getMetaInfo(Properties, String[], String)): (soft) properties != null
    //#post(String getMetaInfo(Properties, String[], String)): init'ed(return_value)
    //#test_vector(String getMetaInfo(Properties, String[], String)): java.util.Properties:getProperty(...)@204: Addr_Set{null}, Inverse{null}
			String result = properties.getProperty(meta);
			if (result != null) { return result; }
		}
		return fallback;
    //#PluginInfo.java:207: end of method: String com.dmdirc.plugins.PluginInfo.getMetaInfo(Properties, String[], String)
	}
	
	/**
	 * Return a ConfigFile that has been migrated from a Properties file.
	 *
	 * @return ConfigFile object with data from plugin.info properties file
	 */
	private ConfigFile getMigratedConfigFile() throws IOException {
		final ResourceManager res = getResourceManager();
    //#PluginInfo.java:216: method: ConfigFile com.dmdirc.plugins.PluginInfo.getMigratedConfigFile()
    //#input(ConfigFile getMigratedConfigFile()): "-"._tainted
    //#input(ConfigFile getMigratedConfigFile()): "-resourcemanagerTimer"._tainted
    //#input(ConfigFile getMigratedConfigFile()): "jar:.."._tainted
    //#input(ConfigFile getMigratedConfigFile()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(ConfigFile getMigratedConfigFile()): __Descendant_Table[others]
    //#input(ConfigFile getMigratedConfigFile()): __Dispatch_Table.getFullFilename()Ljava/lang/String;
    //#input(ConfigFile getMigratedConfigFile()): __Dispatch_Table.getResourceManager()Lcom/dmdirc/util/resourcemanager/ResourceManager;
    //#input(ConfigFile getMigratedConfigFile()): __Dispatch_Table.getResourceManager(Z)Lcom/dmdirc/util/resourcemanager/ResourceManager;
    //#input(ConfigFile getMigratedConfigFile()): this
    //#input(ConfigFile getMigratedConfigFile()): this.__Tag
    //#input(ConfigFile getMigratedConfigFile()): this.filename
    //#input(ConfigFile getMigratedConfigFile()): this.filename._tainted
    //#input(ConfigFile getMigratedConfigFile()): this.myResourceManager
    //#input(ConfigFile getMigratedConfigFile()): this.url
    //#output(ConfigFile getMigratedConfigFile()): new ConfigFile(getMigratedConfigFile#1) num objects
    //#output(ConfigFile getMigratedConfigFile()): return_value
    //#output(ConfigFile getMigratedConfigFile()): this.migrated
    //#output(ConfigFile getMigratedConfigFile()): this.myResourceManager
    //#new obj(ConfigFile getMigratedConfigFile()): new ConfigFile(getMigratedConfigFile#1)
    //#pre[1] (ConfigFile getMigratedConfigFile()): init'ed(this.myResourceManager)
    //#pre[4] (ConfigFile getMigratedConfigFile()): (soft) this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[7] (ConfigFile getMigratedConfigFile()): (soft) this.url != null
    //#presumption(ConfigFile getMigratedConfigFile()): java.util.Iterator:next(...)@266 != null
    //#presumption(ConfigFile getMigratedConfigFile()): java.util.Map_Entry:getKey(...)@267 != null
    //#presumption(ConfigFile getMigratedConfigFile()): java.util.Map_Entry:getValue(...)@268 != null
    //#presumption(ConfigFile getMigratedConfigFile()): java.util.Properties:entrySet(...)@266 != null
    //#post(ConfigFile getMigratedConfigFile()): return_value == &new ConfigFile(getMigratedConfigFile#1)
    //#post(ConfigFile getMigratedConfigFile()): this.migrated == 1
    //#post(ConfigFile getMigratedConfigFile()): new ConfigFile(getMigratedConfigFile#1) num objects == 1
    //#post(ConfigFile getMigratedConfigFile()): this.myResourceManager != null
    //#unanalyzed(ConfigFile getMigratedConfigFile()): Effects-of-calling:java.util.Properties:getProperty
    //#unanalyzed(ConfigFile getMigratedConfigFile()): Effects-of-calling:java.net.URL:getPath
    //#unanalyzed(ConfigFile getMigratedConfigFile()): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(ConfigFile getMigratedConfigFile()): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(ConfigFile getMigratedConfigFile()): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(ConfigFile getMigratedConfigFile()): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:getResourceManager
    //#unanalyzed(ConfigFile getMigratedConfigFile()): Effects-of-calling:java.util.Timer
    //#unanalyzed(ConfigFile getMigratedConfigFile()): Effects-of-calling:java.util.TimerTask
    //#unanalyzed(ConfigFile getMigratedConfigFile()): Effects-of-calling:java.util.Timer:schedule
    //#test_vector(ConfigFile getMigratedConfigFile()): java.lang.String:startsWith(...)@275: {0}, {1}
    //#test_vector(ConfigFile getMigratedConfigFile()): java.util.Iterator:hasNext(...)@266: {0}, {1}
    //#test_vector(ConfigFile getMigratedConfigFile()): java.util.Properties:containsKey(...)@238: {0}, {1}
    //#test_vector(ConfigFile getMigratedConfigFile()): java.util.Properties:containsKey(...)@241: {0}, {1}
    //#test_vector(ConfigFile getMigratedConfigFile()): java.util.Properties:containsKey(...)@252: {0}, {1}
    //#test_vector(ConfigFile getMigratedConfigFile()): java.util.Properties:containsKey(...)@257: {0}, {1}
    //#test_vector(ConfigFile getMigratedConfigFile()): java.util.Properties:containsKey(...)@261: {0}, {1}
		final ConfigFile file = new ConfigFile(res.getResourceInputStream("META-INF/plugin.config"));
    //#PluginInfo.java:217: ?null dereference
    //#    res != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getMigratedConfigFile()
    //#    basic block: Entry_BB_1
    //#    assertion: res != null
    //#    VN: getResourceManager(...)
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:217: Warning: method not available - call not analyzed
    //#    call on InputStream com.dmdirc.util.resourcemanager.ResourceManager:getResourceInputStream(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getMigratedConfigFile()
    //#    unanalyzed callee: InputStream com.dmdirc.util.resourcemanager.ResourceManager:getResourceInputStream(String)
    //#PluginInfo.java:217: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.util.ConfigFile(InputStream)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getMigratedConfigFile()
    //#    unanalyzed callee: void com.dmdirc.util.ConfigFile(InputStream)
		migrated = true;
		
		// Logger.userError(ErrorLevel.LOW, "Plugin '"+getFilename()+"' is using an older plugin.info file, check for updates.");
		final Properties old = new Properties();
		old.load(res.getResourceInputStream("META-INF/plugin.info"));
    //#PluginInfo.java:222: Warning: method not available - call not analyzed
    //#    call on InputStream com.dmdirc.util.resourcemanager.ResourceManager:getResourceInputStream(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getMigratedConfigFile()
    //#    unanalyzed callee: InputStream com.dmdirc.util.resourcemanager.ResourceManager:getResourceInputStream(String)
		
		final Map<String, String> meta = new HashMap<String, String>();
		final Map<String, String> requires = new HashMap<String, String>();
		final Map<String, String> updates = new HashMap<String, String>();
		final Map<String, String> version = new HashMap<String, String>();
		final Map<String, String> misc = new HashMap<String, String>();
		final List<String> persistent = new ArrayList<String>();
		final List<String> provides = new ArrayList<String>();
		final List<String> required_services = new ArrayList<String>();
		
		meta.put("name", old.getProperty("name", ""));
		meta.put("author", old.getProperty("author", ""));
		meta.put("description", old.getProperty("description", ""));
		meta.put("mainclass", old.getProperty("mainclass", ""));
		
		if (old.containsKey("nicename")) {
			meta.put("nicename", old.getProperty("nicename", ""));
		}
		if (old.containsKey("loadall")) {
			meta.put("loadall", old.getProperty("loadall", "no"));
		}
		
		requires.put("os", getMetaInfo(old, new String[]{"required-os", "require-os"}, ""));
    //#PluginInfo.java:245: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.getMetaInfo: (soft) init'ed(metainfo[0..4_294_967_295])
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getMigratedConfigFile()
    //#    basic block: bb_5
    //#    assertion: (soft) init'ed(getMetaInfo.Param_2[0..4_294_967_295])
    //#    callee: String com/dmdirc/plugins/PluginInfo.getMetaInfo(Properties, String[], String)
    //#    callee assertion: (soft) init'ed(metainfo[0..4_294_967_295])
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [4]
    //#    callee srcpos: 203
    //#    VN: getMetaInfo.Param_2[0..4_294_967_295]
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
		requires.put("files", getMetaInfo(old, new String[]{"required-files", "require-files", "required-files", "require-files"}, ""));
    //#PluginInfo.java:246: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.getMetaInfo: (soft) init'ed(metainfo[0..4_294_967_295])
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getMigratedConfigFile()
    //#    basic block: bb_5
    //#    assertion: (soft) init'ed(getMetaInfo.Param_2[0..4_294_967_295])
    //#    callee: String com/dmdirc/plugins/PluginInfo.getMetaInfo(Properties, String[], String)
    //#    callee assertion: (soft) init'ed(metainfo[0..4_294_967_295])
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [4]
    //#    callee srcpos: 203
    //#    VN: getMetaInfo.Param_2[0..4_294_967_295]
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
		requires.put("plugins", getMetaInfo(old, new String[]{"required-plugins", "require-plugins", "required-plugin", "require-plugin"}, ""));
    //#PluginInfo.java:247: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.getMetaInfo: (soft) init'ed(metainfo[0..4_294_967_295])
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getMigratedConfigFile()
    //#    basic block: bb_5
    //#    assertion: (soft) init'ed(getMetaInfo.Param_2[0..4_294_967_295])
    //#    callee: String com/dmdirc/plugins/PluginInfo.getMetaInfo(Properties, String[], String)
    //#    callee assertion: (soft) init'ed(metainfo[0..4_294_967_295])
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [4]
    //#    callee srcpos: 203
    //#    VN: getMetaInfo.Param_2[0..4_294_967_295]
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
		requires.put("ui", getMetaInfo(old, new String[]{"required-ui", "require-ui"}, ""));
    //#PluginInfo.java:248: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.getMetaInfo: (soft) init'ed(metainfo[0..4_294_967_295])
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getMigratedConfigFile()
    //#    basic block: bb_5
    //#    assertion: (soft) init'ed(getMetaInfo.Param_2[0..4_294_967_295])
    //#    callee: String com/dmdirc/plugins/PluginInfo.getMetaInfo(Properties, String[], String)
    //#    callee assertion: (soft) init'ed(metainfo[0..4_294_967_295])
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [4]
    //#    callee srcpos: 203
    //#    VN: getMetaInfo.Param_2[0..4_294_967_295]
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
		
		requires.put("dmdirc", old.getProperty("minversion", "0") + "-" + old.getProperty("maxversion", ""));
		
		if (old.containsKey("addonid")) {
			updates.put("id", old.getProperty("addonid", ""));
		}
		
		version.put("number", old.getProperty("version", "0"));
		if (old.containsKey("friendlyversion")) {
			version.put("friendly", old.getProperty("friendlyversion", ""));
		}
		
		final boolean hasPersistent = old.containsKey("persistent");
		if (hasPersistent) {
			persistent.add("*");
		}
		
		for (Map.Entry entry : old.entrySet()) {
			final String key = entry.getKey().toString();
			final String value = entry.getValue().toString();
		
			// For compatability reasons, add the contents of the file to the "misc"
			// key section, to allow getMetaInfo() compatability for old files.
			misc.put(key, value);
			
			// Also handle persistent items here
			if (!hasPersistent && key.toLowerCase().startsWith("persistent-")) {
				persistent.add(key.substring(11));
			}
		}
		
		file.addDomain("metadata", meta);
    //#PluginInfo.java:280: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.util.ConfigFile:addDomain(String, Map)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getMigratedConfigFile()
    //#    unanalyzed callee: void com.dmdirc.util.ConfigFile:addDomain(String, Map)
		file.addDomain("requires", requires);
    //#PluginInfo.java:281: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.util.ConfigFile:addDomain(String, Map)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getMigratedConfigFile()
    //#    unanalyzed callee: void com.dmdirc.util.ConfigFile:addDomain(String, Map)
		file.addDomain("updates", updates);
    //#PluginInfo.java:282: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.util.ConfigFile:addDomain(String, Map)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getMigratedConfigFile()
    //#    unanalyzed callee: void com.dmdirc.util.ConfigFile:addDomain(String, Map)
		file.addDomain("version", version);
    //#PluginInfo.java:283: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.util.ConfigFile:addDomain(String, Map)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getMigratedConfigFile()
    //#    unanalyzed callee: void com.dmdirc.util.ConfigFile:addDomain(String, Map)
		file.addDomain("misc", misc);
    //#PluginInfo.java:284: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.util.ConfigFile:addDomain(String, Map)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getMigratedConfigFile()
    //#    unanalyzed callee: void com.dmdirc.util.ConfigFile:addDomain(String, Map)
		file.addDomain("persistent", persistent);
    //#PluginInfo.java:285: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.util.ConfigFile:addDomain(String, List)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getMigratedConfigFile()
    //#    unanalyzed callee: void com.dmdirc.util.ConfigFile:addDomain(String, List)
		file.addDomain("provides", provides);
    //#PluginInfo.java:286: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.util.ConfigFile:addDomain(String, List)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getMigratedConfigFile()
    //#    unanalyzed callee: void com.dmdirc.util.ConfigFile:addDomain(String, List)
		file.addDomain("required-services", required_services);
    //#PluginInfo.java:287: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.util.ConfigFile:addDomain(String, List)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getMigratedConfigFile()
    //#    unanalyzed callee: void com.dmdirc.util.ConfigFile:addDomain(String, List)
		
		return file;
    //#PluginInfo.java:289: end of method: ConfigFile com.dmdirc.plugins.PluginInfo.getMigratedConfigFile()
	}
	
	/**
	 * Get a ConfigFile object for this plugin.
	 * This will load a ConfigFile
	 *
	 * @return the ConfigFile object for this plugin, or null if the plugin has no config
	 */
	private ConfigFile getConfigFile() throws IOException {
		ConfigFile file = null;
    //#PluginInfo.java:299: method: ConfigFile com.dmdirc.plugins.PluginInfo.getConfigFile()
    //#input(ConfigFile getConfigFile()): "-"._tainted
    //#input(ConfigFile getConfigFile()): "-resourcemanagerTimer"._tainted
    //#input(ConfigFile getConfigFile()): "jar:.."._tainted
    //#input(ConfigFile getConfigFile()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(ConfigFile getConfigFile()): __Descendant_Table[others]
    //#input(ConfigFile getConfigFile()): __Dispatch_Table.getFullFilename()Ljava/lang/String;
    //#input(ConfigFile getConfigFile()): __Dispatch_Table.getResourceManager()Lcom/dmdirc/util/resourcemanager/ResourceManager;
    //#input(ConfigFile getConfigFile()): __Dispatch_Table.getResourceManager(Z)Lcom/dmdirc/util/resourcemanager/ResourceManager;
    //#input(ConfigFile getConfigFile()): this
    //#input(ConfigFile getConfigFile()): this.__Tag
    //#input(ConfigFile getConfigFile()): this.filename
    //#input(ConfigFile getConfigFile()): this.filename._tainted
    //#input(ConfigFile getConfigFile()): this.myResourceManager
    //#input(ConfigFile getConfigFile()): this.url
    //#output(ConfigFile getConfigFile()): new ConfigFile(getConfigFile#1) num objects
    //#output(ConfigFile getConfigFile()): new ConfigFile(getMigratedConfigFile#1) num objects
    //#output(ConfigFile getConfigFile()): return_value
    //#output(ConfigFile getConfigFile()): this.migrated
    //#output(ConfigFile getConfigFile()): this.myResourceManager
    //#new obj(ConfigFile getConfigFile()): new ConfigFile(getConfigFile#1)
    //#new obj(ConfigFile getConfigFile()): new ConfigFile(getMigratedConfigFile#1)
    //#pre[2] (ConfigFile getConfigFile()): init'ed(this.myResourceManager)
    //#pre[5] (ConfigFile getConfigFile()): (soft) this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[8] (ConfigFile getConfigFile()): (soft) this.url != null
    //#presumption(ConfigFile getConfigFile()): com.dmdirc.util.resourcemanager.ResourceManager:resourceExists(...)@306 == 1
    //#post(ConfigFile getConfigFile()): return_value in Addr_Set{null,&new ConfigFile(getMigratedConfigFile#1),&new ConfigFile(getConfigFile#1),&new ConfigFile(getMigratedConfigFile#1)}
    //#post(ConfigFile getConfigFile()): possibly_updated(this.migrated)
    //#post(ConfigFile getConfigFile()): this.myResourceManager != null
    //#post(ConfigFile getConfigFile()): new ConfigFile(getConfigFile#1) num objects <= 1
    //#post(ConfigFile getConfigFile()): new ConfigFile(getMigratedConfigFile#1) num objects <= 1
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.util.Properties:getProperty
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.net.URL:getPath
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.util.List:add
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.lang.String:toLowerCase
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.lang.String:startsWith
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.lang.String:substring
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:getResourceManager
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.util.Timer
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.util.TimerTask
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.util.Timer:schedule
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.util.Set:iterator
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.util.Map$Entry:getKey
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.lang.Object:toString
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.util.Map$Entry:getValue
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.util.Map:put
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:getResourceInputStream
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:com.dmdirc.util.ConfigFile
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.util.Properties
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.util.Properties:load
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.util.HashMap
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.util.Properties:containsKey
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:java.util.Properties:entrySet
    //#unanalyzed(ConfigFile getConfigFile()): Effects-of-calling:com.dmdirc.util.ConfigFile:addDomain
    //#test_vector(ConfigFile getConfigFile()): com.dmdirc.util.resourcemanager.ResourceManager:resourceExists(...)@301: {0}, {1}
    //#test_vector(ConfigFile getConfigFile()): com.dmdirc.util.resourcemanager.ResourceManager:resourceExists(...)@312: {0}, {1}
		final ResourceManager res = getResourceManager();
		if (res.resourceExists("META-INF/plugin.config")) {
    //#PluginInfo.java:301: ?null dereference
    //#    res != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getConfigFile()
    //#    basic block: Entry_BB_1
    //#    assertion: res != null
    //#    VN: getResourceManager(...)
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:301: Warning: method not available - call not analyzed
    //#    call on bool com.dmdirc.util.resourcemanager.ResourceManager:resourceExists(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getConfigFile()
    //#    unanalyzed callee: bool com.dmdirc.util.resourcemanager.ResourceManager:resourceExists(String)
			try {
				file = new ConfigFile(res.getResourceInputStream("META-INF/plugin.config"));
    //#PluginInfo.java:303: Warning: method not available - call not analyzed
    //#    call on InputStream com.dmdirc.util.resourcemanager.ResourceManager:getResourceInputStream(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getConfigFile()
    //#    unanalyzed callee: InputStream com.dmdirc.util.resourcemanager.ResourceManager:getResourceInputStream(String)
    //#PluginInfo.java:303: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.util.ConfigFile(InputStream)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getConfigFile()
    //#    unanalyzed callee: void com.dmdirc.util.ConfigFile(InputStream)
				file.read();
    //#PluginInfo.java:304: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.util.ConfigFile:read()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getConfigFile()
    //#    unanalyzed callee: void com.dmdirc.util.ConfigFile:read()
			} catch (InvalidConfigFileException icfe) {
				if (res.resourceExists("META-INF/plugin.info")) {
    //#PluginInfo.java:306: Warning: method not available - call not analyzed
    //#    call on bool com.dmdirc.util.resourcemanager.ResourceManager:resourceExists(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getConfigFile()
    //#    unanalyzed callee: bool com.dmdirc.util.resourcemanager.ResourceManager:resourceExists(String)
					file = getMigratedConfigFile();
				} else {
					throw new IOException("Unable to read plugin.config", icfe);
				}
			}
		} else if (res.resourceExists("META-INF/plugin.info")) {
    //#PluginInfo.java:312: Warning: method not available - call not analyzed
    //#    call on bool com.dmdirc.util.resourcemanager.ResourceManager:resourceExists(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ConfigFile getConfigFile()
    //#    unanalyzed callee: bool com.dmdirc.util.resourcemanager.ResourceManager:resourceExists(String)
			file = getMigratedConfigFile();
		}

		return file;
    //#PluginInfo.java:316: end of method: ConfigFile com.dmdirc.plugins.PluginInfo.getConfigFile()
	}
	
	/**
	 * Get the defaults, formatters and icons for this plugin.
	 */
	private void getDefaults() {
		if (metaData == null) { return; }
    //#PluginInfo.java:323: method: void com.dmdirc.plugins.PluginInfo.getDefaults()
    //#input(void getDefaults()): ""._tainted
    //#input(void getDefaults()): "'"._tainted
    //#input(void getDefaults()): ": Using domain '"._tainted
    //#input(void getDefaults()): "plugin-"._tainted
    //#input(void getDefaults()): LOGGER
    //#input(void getDefaults()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(void getDefaults()): __Descendant_Table[others]
    //#input(void getDefaults()): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(void getDefaults()): __Dispatch_Table.getName()Ljava/lang/String;
    //#input(void getDefaults()): this
    //#input(void getDefaults()): this.__Tag
    //#input(void getDefaults()): this.metaData
    //#pre[3] (void getDefaults()): init'ed(this.metaData)
    //#pre[2] (void getDefaults()): (soft) this.__Tag == com/dmdirc/plugins/PluginInfo
    //#presumption(void getDefaults()): com.dmdirc.config.IdentityManager:getAddonIdentity(...)@325 != null
    //#presumption(void getDefaults()): com.dmdirc.util.ConfigFile:getKeyDomain(...)@331 != null
    //#presumption(void getDefaults()): com.dmdirc.util.ConfigFile:getKeyDomain(...)@342 != null
    //#presumption(void getDefaults()): com.dmdirc.util.ConfigFile:getKeyDomain(...)@353 != null
    //#presumption(void getDefaults()): java.util.Iterator:next(...)@333 != null
    //#presumption(void getDefaults()): java.util.Iterator:next(...)@344 != null
    //#presumption(void getDefaults()): java.util.Iterator:next(...)@355 != null
    //#presumption(void getDefaults()): java.util.Map:entrySet(...)@333 != null
    //#presumption(void getDefaults()): java.util.Map:entrySet(...)@344 != null
    //#presumption(void getDefaults()): java.util.Map:entrySet(...)@355 != null
    //#presumption(void getDefaults()): java.util.Map_Entry:getKey(...)@334 != null
    //#presumption(void getDefaults()): java.util.Map_Entry:getKey(...)@345 != null
    //#presumption(void getDefaults()): java.util.Map_Entry:getKey(...)@356 != null
    //#presumption(void getDefaults()): java.util.Map_Entry:getValue(...)@335 != null
    //#presumption(void getDefaults()): java.util.Map_Entry:getValue(...)@346 != null
    //#presumption(void getDefaults()): java.util.Map_Entry:getValue(...)@357 != null
    //#presumption(void getDefaults()): java.util.logging.Logger:getLogger(...)@52 != null
    //#unanalyzed(void getDefaults()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(void getDefaults()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(void getDefaults()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(void getDefaults()): Effects-of-calling:java.util.Map:get
    //#test_vector(void getDefaults()): this.metaData: Inverse{null}, Addr_Set{null}
    //#test_vector(void getDefaults()): com.dmdirc.util.ConfigFile:isKeyDomain(...)@330: {0}, {1}
    //#test_vector(void getDefaults()): com.dmdirc.util.ConfigFile:isKeyDomain(...)@341: {0}, {1}
    //#test_vector(void getDefaults()): com.dmdirc.util.ConfigFile:isKeyDomain(...)@352: {0}, {1}
    //#test_vector(void getDefaults()): java.util.Iterator:hasNext(...)@333: {0}, {1}
    //#test_vector(void getDefaults()): java.util.Iterator:hasNext(...)@344: {0}, {1}
    //#test_vector(void getDefaults()): java.util.Iterator:hasNext(...)@355: {0}, {1}
	
		final Identity defaults = IdentityManager.getAddonIdentity();
    //#PluginInfo.java:325: Warning: method not available - call not analyzed
    //#    call on Identity com.dmdirc.config.IdentityManager:getAddonIdentity()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void getDefaults()
    //#    unanalyzed callee: Identity com.dmdirc.config.IdentityManager:getAddonIdentity()
		final String domain = "plugin-"+getName();

        LOGGER.finer(getName() + ": Using domain '" + domain + "'");
		
		if (metaData.isKeyDomain("defaults")) {
    //#PluginInfo.java:330: Warning: method not available - call not analyzed
    //#    call on bool com.dmdirc.util.ConfigFile:isKeyDomain(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void getDefaults()
    //#    unanalyzed callee: bool com.dmdirc.util.ConfigFile:isKeyDomain(String)
			final Map<String, String> keysection = metaData.getKeyDomain("defaults");
    //#PluginInfo.java:331: Warning: method not available - call not analyzed
    //#    call on Map com.dmdirc.util.ConfigFile:getKeyDomain(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void getDefaults()
    //#    unanalyzed callee: Map com.dmdirc.util.ConfigFile:getKeyDomain(String)
			
			for (Map.Entry entry : keysection.entrySet()) {
				final String key = entry.getKey().toString();
				final String value = entry.getValue().toString();
				
				defaults.setOption(domain, key, value);
    //#PluginInfo.java:337: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.config.Identity:setOption(String, String, String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void getDefaults()
    //#    unanalyzed callee: void com.dmdirc.config.Identity:setOption(String, String, String)
			}
		}
		
		if (metaData.isKeyDomain("formatters")) {
    //#PluginInfo.java:341: Warning: method not available - call not analyzed
    //#    call on bool com.dmdirc.util.ConfigFile:isKeyDomain(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void getDefaults()
    //#    unanalyzed callee: bool com.dmdirc.util.ConfigFile:isKeyDomain(String)
			final Map<String, String> keysection = metaData.getKeyDomain("formatters");
    //#PluginInfo.java:342: Warning: method not available - call not analyzed
    //#    call on Map com.dmdirc.util.ConfigFile:getKeyDomain(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void getDefaults()
    //#    unanalyzed callee: Map com.dmdirc.util.ConfigFile:getKeyDomain(String)
			
			for (Map.Entry entry : keysection.entrySet()) {
				final String key = entry.getKey().toString();
				final String value = entry.getValue().toString();
				
				defaults.setOption("formatter", key, value);
    //#PluginInfo.java:348: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.config.Identity:setOption(String, String, String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void getDefaults()
    //#    unanalyzed callee: void com.dmdirc.config.Identity:setOption(String, String, String)
			}
		}
		
		if (metaData.isKeyDomain("icons")) {
    //#PluginInfo.java:352: Warning: method not available - call not analyzed
    //#    call on bool com.dmdirc.util.ConfigFile:isKeyDomain(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void getDefaults()
    //#    unanalyzed callee: bool com.dmdirc.util.ConfigFile:isKeyDomain(String)
			final Map<String, String> keysection = metaData.getKeyDomain("icons");
    //#PluginInfo.java:353: Warning: method not available - call not analyzed
    //#    call on Map com.dmdirc.util.ConfigFile:getKeyDomain(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void getDefaults()
    //#    unanalyzed callee: Map com.dmdirc.util.ConfigFile:getKeyDomain(String)
			
			for (Map.Entry entry : keysection.entrySet()) {
				final String key = entry.getKey().toString();
				final String value = entry.getValue().toString();
				
				defaults.setOption("icon", key, value);
    //#PluginInfo.java:359: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.config.Identity:setOption(String, String, String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void getDefaults()
    //#    unanalyzed callee: void com.dmdirc.config.Identity:setOption(String, String, String)
			}
		}
	}
    //#PluginInfo.java:362: end of method: void com.dmdirc.plugins.PluginInfo.getDefaults()
	

	
	/**
	 * Update provides list.
	 */
	private void updateProvides() {
		// Remove us from any existing provides lists.
		for (Service service : provides) {
    //#PluginInfo.java:371: method: void com.dmdirc.plugins.PluginInfo.updateProvides()
    //#input(void updateProvides()): "plugins"._tainted
    //#input(void updateProvides()): com/dmdirc/plugins/PluginManager.__Class_Obj.__Lock
    //#input(void updateProvides()): com/dmdirc/plugins/PluginManager.__Descendant_Table[com/dmdirc/plugins/PluginManager]
    //#input(void updateProvides()): com/dmdirc/plugins/PluginManager.__Descendant_Table[others]
    //#input(void updateProvides()): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getPossiblePluginInfos(Z)Ljava/util/List;
    //#input(void updateProvides()): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getService(Ljava/lang/String;Ljava/lang/String;Z)Lcom/dmdirc/plugins/Service;
    //#input(void updateProvides()): com/dmdirc/plugins/PluginManager.com.dmdirc.actions.CoreActionType.CLIENT_PREFS_CLOSED
    //#input(void updateProvides()): com/dmdirc/plugins/PluginManager.com.dmdirc.actions.CoreActionType.CLIENT_PREFS_OPENED
    //#input(void updateProvides()): com/dmdirc/plugins/PluginManager.me
    //#input(void updateProvides()): com/dmdirc/plugins/PluginManager.me.__Tag
    //#input(void updateProvides()): com/dmdirc/plugins/PluginManager.me.services
    //#input(void updateProvides()): com/dmdirc/plugins/Service.__Descendant_Table[com/dmdirc/plugins/Service]
    //#input(void updateProvides()): com/dmdirc/plugins/Service.__Descendant_Table[others]
    //#input(void updateProvides()): com/dmdirc/plugins/Service.__Dispatch_Table.addProvider(Lcom/dmdirc/plugins/ServiceProvider;)V
    //#input(void updateProvides()): com/dmdirc/plugins/Service.__Dispatch_Table.delProvider(Lcom/dmdirc/plugins/ServiceProvider;)V
    //#input(void updateProvides()): this
    //#input(void updateProvides()): this.metaData
    //#input(void updateProvides()): this.provides
    //#output(void updateProvides()): com/dmdirc/plugins/PluginManager.me
    //#output(void updateProvides()): java.lang.StringBuilder:toString(...)._tainted
    //#output(void updateProvides()): new HashMap(PluginManager#2) num objects
    //#output(void updateProvides()): new Hashtable(PluginManager#1) num objects
    //#output(void updateProvides()): new PluginClassLoader(getSubClassLoader#1) num objects
    //#output(void updateProvides()): new PluginClassLoader(getSubClassLoader#1).__Tag
    //#output(void updateProvides()): new PluginClassLoader(getSubClassLoader#1).pluginInfo
    //#output(void updateProvides()): new PluginManager(getPluginManager#1) num objects
    //#output(void updateProvides()): new PluginManager(getPluginManager#1).__Tag
    //#output(void updateProvides()): new PluginManager(getPluginManager#1).knownPlugins
    //#output(void updateProvides()): new PluginManager(getPluginManager#1).myDir
    //#output(void updateProvides()): new PluginManager(getPluginManager#1).services
    //#new obj(void updateProvides()): java.lang.StringBuilder:toString(...)
    //#new obj(void updateProvides()): new HashMap(PluginManager#2)
    //#new obj(void updateProvides()): new Hashtable(PluginManager#1)
    //#new obj(void updateProvides()): new PluginClassLoader(getSubClassLoader#1)
    //#new obj(void updateProvides()): new PluginManager(getPluginManager#1)
    //#pre[8] (void updateProvides()): this.metaData != null
    //#pre[9] (void updateProvides()): this.provides != null
    //#pre[5] (void updateProvides()): (soft) init'ed(com/dmdirc/plugins/PluginManager.me)
    //#presumption(void updateProvides()): getPluginManager(...).__Tag == com/dmdirc/plugins/PluginManager
    //#presumption(void updateProvides()): getPluginManager(...).services != null
    //#presumption(void updateProvides()): java.util.Iterator:next(...).__Tag@371 == com/dmdirc/plugins/Service
    //#presumption(void updateProvides()): java.util.Iterator:next(...)@371 != null
    //#presumption(void updateProvides()): java.util.Iterator:next(...)@379 != null
    //#presumption(void updateProvides()): service.__Tag@385 == com/dmdirc/plugins/Service
    //#presumption(void updateProvides()): service.serviceproviders@371 != null
    //#presumption(void updateProvides()): service.serviceproviders@385 != null
    //#post(void updateProvides()): init'ed(com/dmdirc/plugins/PluginManager.me)
    //#post(void updateProvides()): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(void updateProvides()): init'ed(new HashMap(PluginManager#2) num objects)
    //#post(void updateProvides()): init'ed(new Hashtable(PluginManager#1) num objects)
    //#post(void updateProvides()): init'ed(new PluginClassLoader(getSubClassLoader#1) num objects)
    //#post(void updateProvides()): init'ed(new PluginClassLoader(getSubClassLoader#1).__Tag)
    //#post(void updateProvides()): init'ed(new PluginClassLoader(getSubClassLoader#1).pluginInfo)
    //#post(void updateProvides()): init'ed(new PluginManager(getPluginManager#1) num objects)
    //#post(void updateProvides()): init'ed(new PluginManager(getPluginManager#1).__Tag)
    //#post(void updateProvides()): init'ed(new PluginManager(getPluginManager#1).knownPlugins)
    //#post(void updateProvides()): init'ed(new PluginManager(getPluginManager#1).myDir)
    //#post(void updateProvides()): init'ed(new PluginManager(getPluginManager#1).services)
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.lang.String:isEmpty
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.net.URL:getPath
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.util.List:remove
    //#unanalyzed(void updateProvides()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(void updateProvides()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.util.Map:get
    //#unanalyzed(void updateProvides()): Effects-of-calling:com.dmdirc.util.ConfigFile:isFlatDomain
    //#unanalyzed(void updateProvides()): Effects-of-calling:com.dmdirc.util.ConfigFile:getFlatDomain
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.util.List:contains
    //#unanalyzed(void updateProvides()): Effects-of-calling:getPluginManager
    //#unanalyzed(void updateProvides()): Effects-of-calling:addError
    //#unanalyzed(void updateProvides()): Effects-of-calling:com.dmdirc.actions.ActionManager:processEvent
    //#unanalyzed(void updateProvides()): Effects-of-calling:getPluginInfoByName
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.util.List:iterator
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.lang.ClassLoader
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.lang.String:equalsIgnoreCase
    //#unanalyzed(void updateProvides()): Effects-of-calling:unloadPlugin
    //#unanalyzed(void updateProvides()): Effects-of-calling:delProvider
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.util.List:clear
    //#unanalyzed(void updateProvides()): Effects-of-calling:isUnloadable
    //#unanalyzed(void updateProvides()): Effects-of-calling:onUnload
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.lang.Exception:getMessage
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.lang.Exception:printStackTrace
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.lang.Exception
    //#unanalyzed(void updateProvides()): Effects-of-calling:com.dmdirc.plugins.PluginInfo
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.util.Hashtable
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.util.HashMap
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.lang.System:getProperty
    //#unanalyzed(void updateProvides()): Effects-of-calling:com.dmdirc.Main:getConfigDir
    //#unanalyzed(void updateProvides()): Effects-of-calling:com.dmdirc.actions.ActionManager:addListener
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.util.Map:values
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.util.Collection:iterator
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.lang.String:toLowerCase
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.util.Map:put
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.util.LinkedList
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.io.File
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.util.LinkedList:add
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.util.LinkedList:isEmpty
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.util.LinkedList:pop
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.io.File:isDirectory
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.io.File:listFiles
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.io.File:isFile
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.io.File:getName
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.lang.String:endsWith
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.io.File:getPath
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.lang.String:length
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.lang.String:substring
    //#unanalyzed(void updateProvides()): Effects-of-calling:addPlugin
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.net.URL
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.net.MalformedURLException:getMessage
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.io.File:exists
    //#unanalyzed(void updateProvides()): Effects-of-calling:delPlugin
    //#unanalyzed(void updateProvides()): Effects-of-calling:com.dmdirc.updater.components.PluginComponent
    //#unanalyzed(void updateProvides()): Effects-of-calling:com.dmdirc.plugins.PluginException:getMessage
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.util.Map:remove
    //#unanalyzed(void updateProvides()): Effects-of-calling:getPossiblePluginInfos
    //#unanalyzed(void updateProvides()): Effects-of-calling:java.util.List:add
    //#test_vector(void updateProvides()): com.dmdirc.util.ConfigFile:getFlatDomain(...)@377: Addr_Set{null}, Inverse{null}
    //#test_vector(void updateProvides()): java.lang.String:equalsIgnoreCase(...)@384: {1}, {0}
    //#test_vector(void updateProvides()): java.util.Iterator:hasNext(...)@371: {0}, {1}
    //#test_vector(void updateProvides()): java.util.Iterator:hasNext(...)@379: {0}, {1}
			service.delProvider(this);
		}
		provides.clear();
		
		// Get services provided by this plugin
		final List<String> providesList = metaData.getFlatDomain("provides");
    //#PluginInfo.java:377: Warning: method not available - call not analyzed
    //#    call on List com.dmdirc.util.ConfigFile:getFlatDomain(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void updateProvides()
    //#    unanalyzed callee: List com.dmdirc.util.ConfigFile:getFlatDomain(String)
		if (providesList != null) {
			for (String item : providesList) {
				final String[] bits = item.split(" ");
				final String name = bits[0];
    //#PluginInfo.java:381: ?use of default init
    //#    init'ed(bits.length)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void updateProvides()
    //#    basic block: bb_7
    //#    assertion: init'ed(bits.length)
    //#    VN: undefined
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#PluginInfo.java:381: ?use of default init
    //#    init'ed(bits[0])
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void updateProvides()
    //#    basic block: bb_7
    //#    assertion: init'ed(bits[0])
    //#    VN: undefined
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
				final String type = (bits.length > 1) ? bits[1] : "misc";
    //#PluginInfo.java:382: ?use of default init
    //#    init'ed(bits.length)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void updateProvides()
    //#    basic block: bb_7
    //#    assertion: init'ed(bits.length)
    //#    VN: undefined
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
				
				if (!name.equalsIgnoreCase("any") && !type.equalsIgnoreCase("export")) {
    //#PluginInfo.java:384: ?use of default init
    //#    init'ed(name)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void updateProvides()
    //#    basic block: bb_10
    //#    assertion: init'ed(name)
    //#    VN: undefined
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
    //#PluginInfo.java:384: ?null dereference
    //#    not_init'ed(name)
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void updateProvides()
    //#    basic block: bb_10
    //#    assertion: not_init'ed(name)
    //#    VN: undefined
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
					final Service service = PluginManager.getPluginManager().getService(type, name, true);
    //#PluginInfo.java:385: ?use of default init
    //#    init'ed(name)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void updateProvides()
    //#    basic block: bb_12
    //#    assertion: init'ed(name)
    //#    VN: undefined
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
					service.addProvider(this);
    //#PluginInfo.java:386: ?null dereference
    //#    service != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void updateProvides()
    //#    basic block: bb_12
    //#    assertion: service != null
    //#    VN: getService(...)
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:386: ?use of default init
    //#    init'ed(service.__Tag)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void updateProvides()
    //#    basic block: bb_12
    //#    assertion: init'ed(service.__Tag)
    //#    VN: service.__Tag
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#PluginInfo.java:386: ?null dereference
    //#    com/dmdirc/plugins/Service.__Descendant_Table[service.__Tag] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void updateProvides()
    //#    basic block: bb_12
    //#    assertion: com/dmdirc/plugins/Service.__Descendant_Table[service.__Tag] != null
    //#    VN: com/dmdirc/plugins/Service.__Descendant_Table[service.__Tag]
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
					provides.add(service);
				}
			}
		}
		
		updateExports();
    //#PluginInfo.java:392: Warning: call too complex - analysis skipped
    //#    call on void updateExports()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void updateProvides()
    //#    unanalyzed callee: void updateExports()
	}
    //#PluginInfo.java:393: end of method: void com.dmdirc.plugins.PluginInfo.updateProvides()
	
	/**
	 * Called when the plugin is updated using the updater.
	 * Reloads metaData and updates the list of files.
	 */
	public void pluginUpdated() {
		try {
			// Force a new resourcemanager just incase.
			final ResourceManager res = getResourceManager(true);
    //#PluginInfo.java:402: method: void com.dmdirc.plugins.PluginInfo.pluginUpdated()
    //#PluginInfo.java:402: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.getResourceManager: init'ed(this.myResourceManager)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void pluginUpdated()
    //#    basic block: bb_2
    //#    assertion: init'ed(this.myResourceManager)
    //#    callee: ResourceManager com/dmdirc/plugins/PluginInfo.getResourceManager(bool)
    //#    callee assertion: init'ed(this.myResourceManager)
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [6]
    //#    callee srcpos: 476
    //#    VN: this.myResourceManager
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
    //#input(void pluginUpdated()): ""._tainted
    //#input(void pluginUpdated()): "'"._tainted
    //#input(void pluginUpdated()): "-"._tainted
    //#input(void pluginUpdated()): "-resourcemanagerTimer"._tainted
    //#input(void pluginUpdated()): ": Using domain '"._tainted
    //#input(void pluginUpdated()): "jar:.."._tainted
    //#input(void pluginUpdated()): "plugin-"._tainted
    //#input(void pluginUpdated()): LOGGER
    //#input(void pluginUpdated()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(void pluginUpdated()): __Descendant_Table[others]
    //#input(void pluginUpdated()): __Dispatch_Table.getFullFilename()Ljava/lang/String;
    //#input(void pluginUpdated()): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(void pluginUpdated()): __Dispatch_Table.getName()Ljava/lang/String;
    //#input(void pluginUpdated()): __Dispatch_Table.getResourceManager()Lcom/dmdirc/util/resourcemanager/ResourceManager;
    //#input(void pluginUpdated()): __Dispatch_Table.getResourceManager(Z)Lcom/dmdirc/util/resourcemanager/ResourceManager;
    //#input(void pluginUpdated()): this
    //#input(void pluginUpdated()): this.__Tag
    //#input(void pluginUpdated()): this.filename
    //#input(void pluginUpdated()): this.filename._tainted
    //#input(void pluginUpdated()): this.metaData
    //#input(void pluginUpdated()): this.myClasses
    //#input(void pluginUpdated()): this.url
    //#output(void pluginUpdated()): new ConfigFile(getConfigFile#1) num objects
    //#output(void pluginUpdated()): new ConfigFile(getMigratedConfigFile#1) num objects
    //#output(void pluginUpdated()): this.metaData
    //#output(void pluginUpdated()): this.migrated
    //#output(void pluginUpdated()): this.myResourceManager
    //#new obj(void pluginUpdated()): new ConfigFile(getConfigFile#1)
    //#new obj(void pluginUpdated()): new ConfigFile(getMigratedConfigFile#1)
    //#pre[1] (void pluginUpdated()): (soft) init'ed(this.metaData)
    //#pre[6] (void pluginUpdated()): (soft) this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[10] (void pluginUpdated()): (soft) this.myClasses != null
    //#pre[12] (void pluginUpdated()): (soft) this.url != null
    //#presumption(void pluginUpdated()): com.dmdirc.util.resourcemanager.ResourceManager:getResourcesStartingWith(...)@405 != null
    //#presumption(void pluginUpdated()): java.util.Iterator:next(...)@405 != null
    //#post(void pluginUpdated()): this.metaData == One-of{&new ConfigFile(getConfigFile#1), &new ConfigFile(getMigratedConfigFile#1), null, old this.metaData}
    //#post(void pluginUpdated()): init'ed(this.metaData)
    //#post(void pluginUpdated()): possibly_updated(this.migrated)
    //#post(void pluginUpdated()): possibly_updated(this.myResourceManager)
    //#post(void pluginUpdated()): new ConfigFile(getConfigFile#1) num objects <= 1
    //#post(void pluginUpdated()): new ConfigFile(getMigratedConfigFile#1) num objects <= 1
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.Properties:getProperty
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.net.URL:getPath
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.Map:get
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.List:add
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.lang.String:toLowerCase
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.lang.String:startsWith
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.lang.String:substring
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:getResourceManager
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.Timer
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.TimerTask
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.Timer:schedule
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.logging.Logger:finer
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:com.dmdirc.config.IdentityManager:getAddonIdentity
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.Map:entrySet
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.Set:iterator
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.Map$Entry:getKey
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.lang.Object:toString
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.Map$Entry:getValue
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:com.dmdirc.config.Identity:setOption
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:getConfigFile
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.Map:put
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:getResourceInputStream
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:com.dmdirc.util.ConfigFile
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.Properties
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.Properties:load
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.HashMap
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.Properties:containsKey
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.util.Properties:entrySet
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:com.dmdirc.util.ConfigFile:addDomain
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:resourceExists
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:com.dmdirc.util.ConfigFile:read
    //#unanalyzed(void pluginUpdated()): Effects-of-calling:java.io.IOException
    //#test_vector(void pluginUpdated()): java.lang.String:matches(...)@407: {0}, {1}
    //#test_vector(void pluginUpdated()): java.util.Iterator:hasNext(...)@405: {0}, {1}
			
			myClasses.clear();
			for (final String classfilename : res.getResourcesStartingWith("")) {
    //#PluginInfo.java:405: ?null dereference
    //#    res != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void pluginUpdated()
    //#    basic block: bb_2
    //#    assertion: res != null
    //#    VN: getResourceManager(...)
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:405: Warning: method not available - call not analyzed
    //#    call on List com.dmdirc.util.resourcemanager.ResourceManager:getResourcesStartingWith(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void pluginUpdated()
    //#    unanalyzed callee: List com.dmdirc.util.resourcemanager.ResourceManager:getResourcesStartingWith(String)
				String classname = classfilename.replace('/', '.');
				if (classname.matches("^.*\\.class$")) {
					classname = classname.replaceAll("\\.class$", "");
					myClasses.add(classname);
				}
			}
			updateMetaData();
			updateProvides();
    //#PluginInfo.java:413: Warning: call too complex - analysis skipped
    //#    call on void updateProvides()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void pluginUpdated()
    //#    unanalyzed callee: void updateProvides()
			getDefaults();
		} catch (IOException ioe) {
		}
	}
    //#PluginInfo.java:417: end of method: void com.dmdirc.plugins.PluginInfo.pluginUpdated()
	
	/**
	 * Check if this plugin was migrated or not.
	 *
	 * @return true if the plugins config file was a plugin.info not a plugin.config
	 */
	public boolean isMigrated() {
		return migrated;
    //#PluginInfo.java:425: method: bool com.dmdirc.plugins.PluginInfo.isMigrated()
    //#input(bool isMigrated()): this
    //#input(bool isMigrated()): this.migrated
    //#output(bool isMigrated()): return_value
    //#pre[2] (bool isMigrated()): init'ed(this.migrated)
    //#post(bool isMigrated()): return_value == this.migrated
    //#post(bool isMigrated()): init'ed(return_value)
    //#PluginInfo.java:425: end of method: bool com.dmdirc.plugins.PluginInfo.isMigrated()
	}
	
	/**
	 * Try to reload the metaData from the plugin.config file.
	 * If this fails, the old data will be used still.
	 *
	 * @return true if metaData was reloaded ok, else false.
	 */
	private boolean updateMetaData() {
		// Force a new resourcemanager just incase.
		try {
			final ResourceManager res = getResourceManager(true);
    //#PluginInfo.java:437: method: bool com.dmdirc.plugins.PluginInfo.updateMetaData()
    //#PluginInfo.java:437: Warning: unused assignment
    //#    Unused assignment into res
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool updateMetaData()
    //#input(bool updateMetaData()): "-"._tainted
    //#input(bool updateMetaData()): "-resourcemanagerTimer"._tainted
    //#input(bool updateMetaData()): "jar:.."._tainted
    //#input(bool updateMetaData()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(bool updateMetaData()): __Descendant_Table[others]
    //#input(bool updateMetaData()): __Dispatch_Table.getFullFilename()Ljava/lang/String;
    //#input(bool updateMetaData()): __Dispatch_Table.getResourceManager()Lcom/dmdirc/util/resourcemanager/ResourceManager;
    //#input(bool updateMetaData()): __Dispatch_Table.getResourceManager(Z)Lcom/dmdirc/util/resourcemanager/ResourceManager;
    //#input(bool updateMetaData()): this
    //#input(bool updateMetaData()): this.__Tag
    //#input(bool updateMetaData()): this.filename
    //#input(bool updateMetaData()): this.filename._tainted
    //#input(bool updateMetaData()): this.myResourceManager
    //#input(bool updateMetaData()): this.url
    //#output(bool updateMetaData()): new ConfigFile(getConfigFile#1) num objects
    //#output(bool updateMetaData()): new ConfigFile(getMigratedConfigFile#1) num objects
    //#output(bool updateMetaData()): return_value
    //#output(bool updateMetaData()): this.metaData
    //#output(bool updateMetaData()): this.migrated
    //#output(bool updateMetaData()): this.myResourceManager
    //#new obj(bool updateMetaData()): new ConfigFile(getConfigFile#1)
    //#new obj(bool updateMetaData()): new ConfigFile(getMigratedConfigFile#1)
    //#pre[3] (bool updateMetaData()): (soft) init'ed(this.myResourceManager)
    //#pre[6] (bool updateMetaData()): (soft) this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[9] (bool updateMetaData()): (soft) this.url != null
    //#post(bool updateMetaData()): init'ed(return_value)
    //#post(bool updateMetaData()): this.metaData == One-of{&new ConfigFile(getConfigFile#1), &new ConfigFile(getMigratedConfigFile#1), null, old this.metaData}
    //#post(bool updateMetaData()): possibly_updated(this.migrated)
    //#post(bool updateMetaData()): init'ed(this.myResourceManager)
    //#post(bool updateMetaData()): new ConfigFile(getConfigFile#1) num objects <= 1
    //#post(bool updateMetaData()): new ConfigFile(getMigratedConfigFile#1) num objects <= 1
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.util.Properties:getProperty
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.net.URL:getPath
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.util.List:add
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.lang.String:toLowerCase
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.lang.String:startsWith
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.lang.String:substring
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:getResourceManager
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.util.Timer
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.util.TimerTask
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.util.Timer:schedule
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.util.Set:iterator
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.util.Map$Entry:getKey
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.lang.Object:toString
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.util.Map$Entry:getValue
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.util.Map:put
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:getResourceInputStream
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:com.dmdirc.util.ConfigFile
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.util.Properties
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.util.Properties:load
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.util.HashMap
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.util.Properties:containsKey
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.util.Properties:entrySet
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:com.dmdirc.util.ConfigFile:addDomain
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:resourceExists
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:com.dmdirc.util.ConfigFile:read
    //#unanalyzed(bool updateMetaData()): Effects-of-calling:java.io.IOException
			final ConfigFile newMetaData = getConfigFile();
			if (newMetaData != null) {
				metaData = newMetaData;
				return true;
			}
		} catch (IOException ioe) { }
		
		return false;
    //#PluginInfo.java:445: end of method: bool com.dmdirc.plugins.PluginInfo.updateMetaData()
	}

	/**
	 * Get the contents of requirementsError
	 *
	 * @return requirementsError
	 */
	public String getRequirementsError() {
		return requirementsError;
    //#PluginInfo.java:454: method: String com.dmdirc.plugins.PluginInfo.getRequirementsError()
    //#input(String getRequirementsError()): this
    //#input(String getRequirementsError()): this.requirementsError
    //#output(String getRequirementsError()): return_value
    //#pre[2] (String getRequirementsError()): init'ed(this.requirementsError)
    //#post(String getRequirementsError()): return_value == this.requirementsError
    //#post(String getRequirementsError()): init'ed(return_value)
    //#PluginInfo.java:454: end of method: String com.dmdirc.plugins.PluginInfo.getRequirementsError()
	}

	/**
	 * Gets a resource manager for this plugin
	 *
	 * @return The resource manager for this plugin
	 * @throws IOException if there is any problem getting a ResourceManager for this plugin
	 */
	public synchronized ResourceManager getResourceManager() throws IOException {
		return getResourceManager(false);
    //#PluginInfo.java:464: method: ResourceManager com.dmdirc.plugins.PluginInfo.getResourceManager()
    //#input(ResourceManager getResourceManager()): "-resourcemanagerTimer"._tainted
    //#input(ResourceManager getResourceManager()): "jar:.."._tainted
    //#input(ResourceManager getResourceManager()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(ResourceManager getResourceManager()): __Descendant_Table[others]
    //#input(ResourceManager getResourceManager()): __Dispatch_Table.getFullFilename()Ljava/lang/String;
    //#input(ResourceManager getResourceManager()): __Dispatch_Table.getResourceManager(Z)Lcom/dmdirc/util/resourcemanager/ResourceManager;
    //#input(ResourceManager getResourceManager()): this
    //#input(ResourceManager getResourceManager()): this.__Tag
    //#input(ResourceManager getResourceManager()): this.filename
    //#input(ResourceManager getResourceManager()): this.filename._tainted
    //#input(ResourceManager getResourceManager()): this.myResourceManager
    //#input(ResourceManager getResourceManager()): this.url
    //#output(ResourceManager getResourceManager()): return_value
    //#output(ResourceManager getResourceManager()): this.myResourceManager
    //#pre[1] (ResourceManager getResourceManager()): init'ed(this.myResourceManager)
    //#pre[4] (ResourceManager getResourceManager()): (soft) this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[7] (ResourceManager getResourceManager()): (soft) this.url != null
    //#post(ResourceManager getResourceManager()): init'ed(return_value)
    //#post(ResourceManager getResourceManager()): this.myResourceManager == return_value
    //#unanalyzed(ResourceManager getResourceManager()): Effects-of-calling:java.net.URL:getPath
    //#unanalyzed(ResourceManager getResourceManager()): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(ResourceManager getResourceManager()): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(ResourceManager getResourceManager()): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(ResourceManager getResourceManager()): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:getResourceManager
    //#unanalyzed(ResourceManager getResourceManager()): Effects-of-calling:java.util.Timer
    //#unanalyzed(ResourceManager getResourceManager()): Effects-of-calling:java.util.TimerTask
    //#unanalyzed(ResourceManager getResourceManager()): Effects-of-calling:java.util.Timer:schedule
    //#PluginInfo.java:464: end of method: ResourceManager com.dmdirc.plugins.PluginInfo.getResourceManager()
	}
	
	/**
	 * Get the resource manager for this plugin
	 *
	 * @return The resource manager for this plugin
	 * @param forceNew Force a new resource manager rather than using the old one.
	 * @throws IOException if there is any problem getting a ResourceManager for this plugin
	 * @since 0.6
	 */
	public synchronized ResourceManager getResourceManager(final boolean forceNew) throws IOException {
		if (myResourceManager == null || forceNew) {
    //#PluginInfo.java:476: method: ResourceManager com.dmdirc.plugins.PluginInfo.getResourceManager(bool)
    //#input(ResourceManager getResourceManager(bool)): "-resourcemanagerTimer"._tainted
    //#input(ResourceManager getResourceManager(bool)): "jar:.."._tainted
    //#input(ResourceManager getResourceManager(bool)): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(ResourceManager getResourceManager(bool)): __Descendant_Table[others]
    //#input(ResourceManager getResourceManager(bool)): __Dispatch_Table.getFullFilename()Ljava/lang/String;
    //#input(ResourceManager getResourceManager(bool)): forceNew
    //#input(ResourceManager getResourceManager(bool)): this
    //#input(ResourceManager getResourceManager(bool)): this.__Tag
    //#input(ResourceManager getResourceManager(bool)): this.filename
    //#input(ResourceManager getResourceManager(bool)): this.filename._tainted
    //#input(ResourceManager getResourceManager(bool)): this.myResourceManager
    //#input(ResourceManager getResourceManager(bool)): this.url
    //#output(ResourceManager getResourceManager(bool)): return_value
    //#output(ResourceManager getResourceManager(bool)): this.myResourceManager
    //#pre[6] (ResourceManager getResourceManager(bool)): init'ed(this.myResourceManager)
    //#pre[9] (ResourceManager getResourceManager(bool)): (soft) this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[12] (ResourceManager getResourceManager(bool)): (soft) this.url != null
    //#post(ResourceManager getResourceManager(bool)): init'ed(return_value)
    //#post(ResourceManager getResourceManager(bool)): this.myResourceManager == return_value
    //#unanalyzed(ResourceManager getResourceManager(bool)): Effects-of-calling:java.net.URL:getPath
    //#unanalyzed(ResourceManager getResourceManager(bool)): Effects-of-calling:java.util.TimerTask
    //#test_vector(ResourceManager getResourceManager(bool)): forceNew: {0}, {1}
			myResourceManager = ResourceManager.getResourceManager("jar://"+getFullFilename());
    //#PluginInfo.java:477: Warning: method not available - call not analyzed
    //#    call on ResourceManager com.dmdirc.util.resourcemanager.ResourceManager:getResourceManager(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: ResourceManager getResourceManager(bool)
    //#    unanalyzed callee: ResourceManager com.dmdirc.util.resourcemanager.ResourceManager:getResourceManager(String)
			
			// Clear the resourcemanager in 10 seconds to stop us holding the file open
			new Timer(filename+"-resourcemanagerTimer").schedule(new TimerTask(){
    //#PluginInfo.java:480: method: void com.dmdirc.plugins.PluginInfo$1.com.dmdirc.plugins.PluginInfo$1(PluginInfo)
    //#input(void com.dmdirc.plugins.PluginInfo$1(PluginInfo)): Param_1
    //#input(void com.dmdirc.plugins.PluginInfo$1(PluginInfo)): this
    //#output(void com.dmdirc.plugins.PluginInfo$1(PluginInfo)): this.this$0
    //#post(void com.dmdirc.plugins.PluginInfo$1(PluginInfo)): this.this$0 == Param_1
    //#post(void com.dmdirc.plugins.PluginInfo$1(PluginInfo)): init'ed(this.this$0)
    //#PluginInfo.java:480: end of method: void com.dmdirc.plugins.PluginInfo$1.com.dmdirc.plugins.PluginInfo$1(PluginInfo)
				/** {@inheritDoc} */
				@Override
				public void run() {
					myResourceManager = null;
    //#PluginInfo.java:484: method: void com.dmdirc.plugins.PluginInfo$1.run()
    //#input(void run()): this
    //#input(void run()): this.this$0
    //#output(void run()): this.this$0.myResourceManager
    //#pre[2] (void run()): this.this$0 != null
    //#post(void run()): this.this$0.myResourceManager == null
				}
    //#PluginInfo.java:485: end of method: void com.dmdirc.plugins.PluginInfo$1.run()
			}, 10000);
		}
		return myResourceManager;
    //#PluginInfo.java:488: end of method: ResourceManager com.dmdirc.plugins.PluginInfo.getResourceManager(bool)
	}

	/**
	 * Checks to see if the minimum version requirement of the plugin is
	 * satisfied.
	 * If either version is non-positive, the test passes.
	 * On failure, the requirementsError field will contain a user-friendly
	 * error message.
	 *
	 * @param desired The desired minimum version of DMDirc.
	 * @param actual The actual current version of DMDirc.
	 * @return True if the test passed, false otherwise
	 */
	protected boolean checkMinimumVersion(final String desired, final int actual) {
		int idesired;
		
		if (desired.isEmpty()) {
    //#PluginInfo.java:505: method: bool com.dmdirc.plugins.PluginInfo.checkMinimumVersion(String, int)
    //#input(bool checkMinimumVersion(String, int)): actual
    //#input(bool checkMinimumVersion(String, int)): desired
    //#input(bool checkMinimumVersion(String, int)): this
    //#output(bool checkMinimumVersion(String, int)): return_value
    //#output(bool checkMinimumVersion(String, int)): this.requirementsError
    //#pre[2] (bool checkMinimumVersion(String, int)): desired != null
    //#post(bool checkMinimumVersion(String, int)): init'ed(return_value)
    //#post(bool checkMinimumVersion(String, int)): this.requirementsError == One-of{old this.requirementsError, &"'minversion' is a non-integer", &"Plugin is for a newer version of DMDirc"}
    //#test_vector(bool checkMinimumVersion(String, int)): actual: {-2_147_483_648..0}, {1..4_294_967_294}
    //#test_vector(bool checkMinimumVersion(String, int)): java.lang.Integer:parseInt(...)@510: {-2_147_483_648..0}, {2..4_294_967_295}
    //#test_vector(bool checkMinimumVersion(String, int)): java.lang.String:isEmpty(...)@505: {0}, {1}
			return true;
		}
		
		try {
			idesired = Integer.parseInt(desired);
		} catch (NumberFormatException ex) {
			requirementsError = "'minversion' is a non-integer";
			return false;
		}
		
		if (actual > 0 && idesired > 0 && actual < idesired) {
			requirementsError = "Plugin is for a newer version of DMDirc";
			return false;
		} else {
			return true;
    //#PluginInfo.java:520: end of method: bool com.dmdirc.plugins.PluginInfo.checkMinimumVersion(String, int)
		}
	}

	/**
	 * Checks to see if the maximum version requirement of the plugin is
	 * satisfied.
	 * If either version is non-positive, the test passes.
	 * If the desired version is empty, the test passes.
	 * On failure, the requirementsError field will contain a user-friendly
	 * error message.
	 *
	 * @param desired The desired maximum version of DMDirc.
	 * @param actual The actual current version of DMDirc.
	 * @return True if the test passed, false otherwise
	 */
	protected boolean checkMaximumVersion(final String desired, final int actual) {
		int idesired;
		
		if (desired.isEmpty()) {
    //#PluginInfo.java:539: method: bool com.dmdirc.plugins.PluginInfo.checkMaximumVersion(String, int)
    //#input(bool checkMaximumVersion(String, int)): actual
    //#input(bool checkMaximumVersion(String, int)): desired
    //#input(bool checkMaximumVersion(String, int)): this
    //#output(bool checkMaximumVersion(String, int)): return_value
    //#output(bool checkMaximumVersion(String, int)): this.requirementsError
    //#pre[2] (bool checkMaximumVersion(String, int)): desired != null
    //#post(bool checkMaximumVersion(String, int)): init'ed(return_value)
    //#post(bool checkMaximumVersion(String, int)): this.requirementsError == One-of{old this.requirementsError, &"'maxversion' is a non-integer", &"Plugin is for an older version of DMDirc"}
    //#test_vector(bool checkMaximumVersion(String, int)): actual: {-2_147_483_648..0}, {2..4_294_967_295}
    //#test_vector(bool checkMaximumVersion(String, int)): java.lang.Integer:parseInt(...)@544: {-2_147_483_648..0}, {1..4_294_967_294}
    //#test_vector(bool checkMaximumVersion(String, int)): java.lang.String:isEmpty(...)@539: {0}, {1}
			return true;
		}
		
		try {
			idesired = Integer.parseInt(desired);
		} catch (NumberFormatException ex) {
			requirementsError = "'maxversion' is a non-integer";
			return false;
		}
		
		if (actual > 0 && idesired > 0 && actual > idesired) {
			requirementsError = "Plugin is for an older version of DMDirc";
			return false;
		} else {
			return true;
    //#PluginInfo.java:554: end of method: bool com.dmdirc.plugins.PluginInfo.checkMaximumVersion(String, int)
		}
	}
	
	/**
	 * Checks to see if the OS requirements of the plugin are satisfied.
	 * If the desired string is empty, the test passes.
	 * Otherwise it is used as one to three colon-delimited regular expressions,
	 * to test the name, version and architecture of the OS, respectively.
	 * On failure, the requirementsError field will contain a user-friendly
	 * error message.
	 *
	 * @param desired The desired OS requirements
	 * @param actualName The actual name of the OS
	 * @param actualVersion The actual version of the OS
	 * @param actualArch The actual architecture of the OS
	 * @return True if the test passes, false otherwise
	 */
	protected boolean checkOS(final String desired, final String actualName, final String actualVersion, final String actualArch) {
		if (desired.isEmpty()) {
    //#PluginInfo.java:573: method: bool com.dmdirc.plugins.PluginInfo.checkOS(String, String, String, String)
    //#input(bool checkOS(String, String, String, String)): "')"._tainted
    //#input(bool checkOS(String, String, String, String)): "', actual: '"._tainted
    //#input(bool checkOS(String, String, String, String)): "Invalid OS architecture. (Wanted: '"._tainted
    //#input(bool checkOS(String, String, String, String)): "Invalid OS version. (Wanted: '"._tainted
    //#input(bool checkOS(String, String, String, String)): "Invalid OS. (Wanted: '"._tainted
    //#input(bool checkOS(String, String, String, String)): actualArch
    //#input(bool checkOS(String, String, String, String)): actualArch._tainted
    //#input(bool checkOS(String, String, String, String)): actualName
    //#input(bool checkOS(String, String, String, String)): actualName._tainted
    //#input(bool checkOS(String, String, String, String)): actualVersion
    //#input(bool checkOS(String, String, String, String)): actualVersion._tainted
    //#input(bool checkOS(String, String, String, String)): desired
    //#input(bool checkOS(String, String, String, String)): desired._tainted
    //#input(bool checkOS(String, String, String, String)): this
    //#output(bool checkOS(String, String, String, String)): java.lang.StringBuilder:toString(...)._tainted
    //#output(bool checkOS(String, String, String, String)): return_value
    //#output(bool checkOS(String, String, String, String)): this.requirementsError
    //#new obj(bool checkOS(String, String, String, String)): java.lang.StringBuilder:toString(...)
    //#pre[7] (bool checkOS(String, String, String, String)): desired != null
    //#pre[3] (bool checkOS(String, String, String, String)): (soft) actualName != null
    //#post(bool checkOS(String, String, String, String)): init'ed(java.lang.StringBuilder:toString(...)._tainted)
    //#post(bool checkOS(String, String, String, String)): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(bool checkOS(String, String, String, String)): init'ed(return_value)
    //#post(bool checkOS(String, String, String, String)): this.requirementsError == One-of{old this.requirementsError, &java.lang.StringBuilder:toString(...)}
    //#test_vector(bool checkOS(String, String, String, String)): java.lang.String:isEmpty(...)@573: {0}, {1}
    //#test_vector(bool checkOS(String, String, String, String)): java.lang.String:matches(...)@579: {1}, {0}
			return true;
		}
		
		final String[] desiredParts = desired.split(":");
		
		if (!actualName.toLowerCase().matches(desiredParts[0])) {
    //#PluginInfo.java:579: ?use of default init
    //#    init'ed(desiredParts.length)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkOS(String, String, String, String)
    //#    basic block: bb_3
    //#    assertion: init'ed(desiredParts.length)
    //#    VN: undefined
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#PluginInfo.java:579: ?use of default init
    //#    init'ed(desiredParts[0])
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkOS(String, String, String, String)
    //#    basic block: bb_3
    //#    assertion: init'ed(desiredParts[0])
    //#    VN: undefined
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
			requirementsError = "Invalid OS. (Wanted: '" + desiredParts[0] + "', actual: '" + actualName + "')";
    //#PluginInfo.java:580: ?use of default init
    //#    init'ed(desiredParts.length)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkOS(String, String, String, String)
    //#    basic block: bb_4
    //#    assertion: init'ed(desiredParts.length)
    //#    VN: undefined
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#PluginInfo.java:580: ?use of default init
    //#    init'ed(desiredParts[0])
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkOS(String, String, String, String)
    //#    basic block: bb_4
    //#    assertion: init'ed(desiredParts[0])
    //#    VN: undefined
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
			return false;
		} else if (desiredParts.length > 1 && !actualVersion.toLowerCase().matches(desiredParts[1])) {
    //#PluginInfo.java:582: ?use of default init
    //#    init'ed(desiredParts.length)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkOS(String, String, String, String)
    //#    basic block: bb_5
    //#    assertion: init'ed(desiredParts.length)
    //#    VN: undefined
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#PluginInfo.java:582: Warning: test always goes same way
    //#    Test predetermined because desiredParts.length == 0
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkOS(String, String, String, String)
    //#    from bb: bb_5
    //#    live edge: bb_5-->bb_8
    //#    tested vn: undefined - 1
    //#    tested vn values: {-1}
    //#PluginInfo.java:582: Warning: dead code
    //#    Dead code here because desiredParts.length == 0
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkOS(String, String, String, String)
    //#    dead bb: bb_6
			requirementsError = "Invalid OS version. (Wanted: '" + desiredParts[1] + "', actual: '" + actualVersion + "')";
    //#PluginInfo.java:583: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkOS(String, String, String, String)
    //#    dead bb: bb_7
			return false;
		} else if (desiredParts.length > 2 && !actualArch.toLowerCase().matches(desiredParts[2])) {
    //#PluginInfo.java:585: ?use of default init
    //#    init'ed(desiredParts.length)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkOS(String, String, String, String)
    //#    basic block: bb_8
    //#    assertion: init'ed(desiredParts.length)
    //#    VN: undefined
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#PluginInfo.java:585: Warning: test always goes same way
    //#    Test predetermined because desiredParts.length == 0
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkOS(String, String, String, String)
    //#    from bb: bb_8
    //#    live edge: bb_8-->bb_11
    //#    tested vn: undefined - 2
    //#    tested vn values: {-2}
    //#PluginInfo.java:585: Warning: dead code
    //#    Dead code here because desiredParts.length == 0
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkOS(String, String, String, String)
    //#    dead bb: bb_9
			requirementsError = "Invalid OS architecture. (Wanted: '" + desiredParts[2] + "', actual: '" + actualArch + "')";
    //#PluginInfo.java:586: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkOS(String, String, String, String)
    //#    dead bb: bb_10
			return false;
		}
		
		return true;
    //#PluginInfo.java:590: end of method: bool com.dmdirc.plugins.PluginInfo.checkOS(String, String, String, String)
	}
	
	/**
	 * Checks to see if the UI requirements of the plugin are satisfied.
	 * If the desired string is empty, the test passes.
	 * Otherwise it is used as a regular expressions against the package of the
	 * UIController to test what UI is currently in use.
	 * On failure, the requirementsError field will contain a user-friendly
	 * error message.
	 *
	 * @param desired The desired UI requirements
	 * @param actual The package of the current UI in use.
	 * @return True if the test passes, false otherwise
	 */
	protected boolean checkUI(final String desired, final String actual) {
		if (desired.isEmpty()) {
    //#PluginInfo.java:606: method: bool com.dmdirc.plugins.PluginInfo.checkUI(String, String)
    //#input(bool checkUI(String, String)): "')"._tainted
    //#input(bool checkUI(String, String)): "', actual: '"._tainted
    //#input(bool checkUI(String, String)): "Invalid UI. (Wanted: '"._tainted
    //#input(bool checkUI(String, String)): actual
    //#input(bool checkUI(String, String)): actual._tainted
    //#input(bool checkUI(String, String)): desired
    //#input(bool checkUI(String, String)): desired._tainted
    //#input(bool checkUI(String, String)): this
    //#output(bool checkUI(String, String)): java.lang.StringBuilder:toString(...)._tainted
    //#output(bool checkUI(String, String)): return_value
    //#output(bool checkUI(String, String)): this.requirementsError
    //#new obj(bool checkUI(String, String)): java.lang.StringBuilder:toString(...)
    //#pre[3] (bool checkUI(String, String)): desired != null
    //#pre[1] (bool checkUI(String, String)): (soft) actual != null
    //#post(bool checkUI(String, String)): init'ed(java.lang.StringBuilder:toString(...)._tainted)
    //#post(bool checkUI(String, String)): init'ed(return_value)
    //#post(bool checkUI(String, String)): this.requirementsError == One-of{old this.requirementsError, &java.lang.StringBuilder:toString(...)}
    //#test_vector(bool checkUI(String, String)): java.lang.String:isEmpty(...)@606: {0}, {1}
    //#test_vector(bool checkUI(String, String)): java.lang.String:matches(...)@610: {1}, {0}
			return true;
		}
		
		if (!actual.toLowerCase().matches(desired)) {
			requirementsError = "Invalid UI. (Wanted: '" + desired + "', actual: '" + actual + "')";
			return false;
		}
		return true;
    //#PluginInfo.java:614: end of method: bool com.dmdirc.plugins.PluginInfo.checkUI(String, String)
	}
	
	/**
	 * Checks to see if the file requirements of the plugin are satisfied.
	 * If the desired string is empty, the test passes.
	 * Otherwise it is passed to File.exists() to see if the file is valid.
	 * Multiple files can be specified by using a "," to separate. And either/or
	 * files can be specified using a "|" (eg /usr/bin/bash|/bin/bash)
	 * If the test fails, the requirementsError field will contain a
	 * user-friendly error message.
	 *
	 * @param desired The desired file requirements
	 * @return True if the test passes, false otherwise
	 */
	protected boolean checkFiles(final String desired) {
		if (desired.isEmpty()) {
    //#PluginInfo.java:630: method: bool com.dmdirc.plugins.PluginInfo.checkFiles(String)
    //#input(bool checkFiles(String)): "' not found"._tainted
    //#input(bool checkFiles(String)): "Required file '"._tainted
    //#input(bool checkFiles(String)): desired
    //#input(bool checkFiles(String)): desired._tainted
    //#input(bool checkFiles(String)): this
    //#output(bool checkFiles(String)): java.lang.StringBuilder:toString(...)._tainted
    //#output(bool checkFiles(String)): return_value
    //#output(bool checkFiles(String)): this.requirementsError
    //#new obj(bool checkFiles(String)): java.lang.StringBuilder:toString(...)
    //#pre[1] (bool checkFiles(String)): desired != null
    //#post(bool checkFiles(String)): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(bool checkFiles(String)): return_value == 1
    //#post(bool checkFiles(String)): this.requirementsError == One-of{old this.requirementsError, &java.lang.StringBuilder:toString(...)}
    //#test_vector(bool checkFiles(String)): java.lang.String:isEmpty(...)@630: {0}, {1}
			return true;
		}
	
		for (String files : desired.split(",")) {
    //#PluginInfo.java:634: ?use of default init
    //#    init'ed(arr$.length)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkFiles(String)
    //#    basic block: bb_3
    //#    assertion: init'ed(arr$.length)
    //#    VN: undefined
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#PluginInfo.java:634: ?use of default init
    //#    init'ed(len$)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkFiles(String)
    //#    basic block: bb_4
    //#    assertion: init'ed(len$)
    //#    VN: undefined
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#PluginInfo.java:634: Warning: test always goes same way
    //#    Test predetermined because i$ == len$
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkFiles(String)
    //#    from bb: bb_4
    //#    live edge: bb_4-->bb_13
    //#    tested vn: i$ - undefined
    //#    tested vn values: {0}
    //#PluginInfo.java:634: Warning: dead code
    //#    Dead code here because i$ == len$
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkFiles(String)
    //#    dead bb: bb_5
    //#PluginInfo.java:634: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkFiles(String)
    //#    dead bb: bb_12
			final String[] filelist = files.split("\\|");
			boolean foundFile = false;
			for (String file : filelist) {
    //#PluginInfo.java:637: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkFiles(String)
    //#    dead bb: bb_6
    //#PluginInfo.java:637: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkFiles(String)
    //#    dead bb: bb_7
    //#PluginInfo.java:637: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkFiles(String)
    //#    dead bb: bb_9
				if ((new File(file)).exists()) {
					foundFile = true;
    //#PluginInfo.java:639: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkFiles(String)
    //#    dead bb: bb_8
					break;
				}
			}
			if (!foundFile) {
    //#PluginInfo.java:643: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkFiles(String)
    //#    dead bb: bb_10
				requirementsError = "Required file '"+files+"' not found";
    //#PluginInfo.java:644: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkFiles(String)
    //#    dead bb: bb_11
				return false;
			}
		}
		return true;
    //#PluginInfo.java:648: end of method: bool com.dmdirc.plugins.PluginInfo.checkFiles(String)
	}
	
	/**
	 * Checks to see if the plugin requirements of the plugin are satisfied.
	 * If the desired string is empty, the test passes.
	 * Plugins should be specified as:
	 * plugin1[:minversion[:maxversion]],plugin2[:minversion[:maxversion]]
	 * Plugins will be attempted to be loaded if not loaded, else the test will
	 * fail if the versions don't match, or the plugin isn't known.
	 * If the test fails, the requirementsError field will contain a
	 * user-friendly error message.
	 *
	 * @param desired The desired file requirements
	 * @return True if the test passes, false otherwise
	 */
	protected boolean checkPlugins(final String desired) {
		if (desired.isEmpty()) {
    //#PluginInfo.java:665: method: bool com.dmdirc.plugins.PluginInfo.checkPlugins(String)
    //#input(bool checkPlugins(String)): "' is too new (Required Version: "._tainted
    //#input(bool checkPlugins(String)): "' is too old (Required Version: "._tainted
    //#input(bool checkPlugins(String)): "' was not found"._tainted
    //#input(bool checkPlugins(String)): ")"._tainted
    //#input(bool checkPlugins(String)): ", Actual Version: "._tainted
    //#input(bool checkPlugins(String)): "Plugin '"._tainted
    //#input(bool checkPlugins(String)): "Required plugin '"._tainted
    //#input(bool checkPlugins(String)): "plugins"._tainted
    //#input(bool checkPlugins(String)): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(bool checkPlugins(String)): __Descendant_Table[others]
    //#input(bool checkPlugins(String)): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(bool checkPlugins(String)): __Dispatch_Table.getName()Ljava/lang/String;
    //#input(bool checkPlugins(String)): __Dispatch_Table.getVersion()Lcom/dmdirc/updater/Version;
    //#input(bool checkPlugins(String)): com/dmdirc/plugins/PluginManager.__Class_Obj.__Lock
    //#input(bool checkPlugins(String)): com/dmdirc/plugins/PluginManager.__Descendant_Table[com/dmdirc/plugins/PluginManager]
    //#input(bool checkPlugins(String)): com/dmdirc/plugins/PluginManager.__Descendant_Table[others]
    //#input(bool checkPlugins(String)): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getPluginInfoByName(Ljava/lang/String;)Lcom/dmdirc/plugins/PluginInfo;
    //#input(bool checkPlugins(String)): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getPluginInfos()Ljava/util/Collection;
    //#input(bool checkPlugins(String)): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getPossiblePluginInfos(Z)Ljava/util/List;
    //#input(bool checkPlugins(String)): com/dmdirc/plugins/PluginManager.com.dmdirc.actions.CoreActionType.CLIENT_PREFS_CLOSED
    //#input(bool checkPlugins(String)): com/dmdirc/plugins/PluginManager.com.dmdirc.actions.CoreActionType.CLIENT_PREFS_OPENED
    //#input(bool checkPlugins(String)): com/dmdirc/plugins/PluginManager.me.__Tag
    //#input(bool checkPlugins(String)): com/dmdirc/plugins/PluginManager.me.knownPlugins
    //#input(bool checkPlugins(String)): desired
    //#input(bool checkPlugins(String)): desired._tainted
    //#input(bool checkPlugins(String)): this
    //#output(bool checkPlugins(String)): com/dmdirc/plugins/PluginManager.me
    //#output(bool checkPlugins(String)): java.lang.StringBuilder:toString(...)._tainted
    //#output(bool checkPlugins(String)): new HashMap(PluginManager#2) num objects
    //#output(bool checkPlugins(String)): new Hashtable(PluginManager#1) num objects
    //#output(bool checkPlugins(String)): new PluginClassLoader(getSubClassLoader#1) num objects
    //#output(bool checkPlugins(String)): new PluginClassLoader(getSubClassLoader#1).__Tag
    //#output(bool checkPlugins(String)): new PluginClassLoader(getSubClassLoader#1).pluginInfo
    //#output(bool checkPlugins(String)): new PluginManager(getPluginManager#1) num objects
    //#output(bool checkPlugins(String)): new PluginManager(getPluginManager#1).__Tag
    //#output(bool checkPlugins(String)): new PluginManager(getPluginManager#1).knownPlugins
    //#output(bool checkPlugins(String)): new PluginManager(getPluginManager#1).myDir
    //#output(bool checkPlugins(String)): new PluginManager(getPluginManager#1).services
    //#output(bool checkPlugins(String)): return_value
    //#output(bool checkPlugins(String)): this.requirementsError
    //#new obj(bool checkPlugins(String)): java.lang.StringBuilder:toString(...)
    //#new obj(bool checkPlugins(String)): new HashMap(PluginManager#2)
    //#new obj(bool checkPlugins(String)): new Hashtable(PluginManager#1)
    //#new obj(bool checkPlugins(String)): new PluginClassLoader(getSubClassLoader#1)
    //#new obj(bool checkPlugins(String)): new PluginManager(getPluginManager#1)
    //#pre[5] (bool checkPlugins(String)): desired != null
    //#post(bool checkPlugins(String)): possibly_updated(com/dmdirc/plugins/PluginManager.me)
    //#post(bool checkPlugins(String)): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(bool checkPlugins(String)): return_value == 1
    //#post(bool checkPlugins(String)): this.requirementsError == One-of{old this.requirementsError, &java.lang.StringBuilder:toString(...)}
    //#post(bool checkPlugins(String)): new HashMap(PluginManager#2) num objects == 0
    //#post(bool checkPlugins(String)): new Hashtable(PluginManager#1) num objects == 0
    //#post(bool checkPlugins(String)): new PluginClassLoader(getSubClassLoader#1) num objects == 0
    //#post(bool checkPlugins(String)): new PluginClassLoader(getSubClassLoader#1).__Tag not init'ed, if init'ed
    //#post(bool checkPlugins(String)): new PluginClassLoader(getSubClassLoader#1).pluginInfo == null
    //#post(bool checkPlugins(String)): new PluginManager(getPluginManager#1) num objects == 0
    //#post(bool checkPlugins(String)): init'ed(new PluginManager(getPluginManager#1).__Tag)
    //#post(bool checkPlugins(String)): init'ed(new PluginManager(getPluginManager#1).knownPlugins)
    //#post(bool checkPlugins(String)): init'ed(new PluginManager(getPluginManager#1).myDir)
    //#post(bool checkPlugins(String)): init'ed(new PluginManager(getPluginManager#1).services)
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.lang.String:isEmpty
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.net.URL:getPath
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.util.List:remove
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.util.Map:get
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:com.dmdirc.util.ConfigFile:isFlatDomain
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:com.dmdirc.util.ConfigFile:getFlatDomain
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.util.List:contains
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:getPluginManager
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:addError
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:com.dmdirc.actions.ActionManager:processEvent
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:getPluginInfoByName
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:com.dmdirc.updater.Version
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.util.List:iterator
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.lang.ClassLoader
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.lang.String:equalsIgnoreCase
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:unloadPlugin
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:delProvider
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.util.List:clear
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:isUnloadable
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:onUnload
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.lang.Exception:getMessage
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.lang.Exception:printStackTrace
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.lang.Exception
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:com.dmdirc.plugins.PluginInfo
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.util.Hashtable
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.util.HashMap
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.lang.System:getProperty
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:com.dmdirc.Main:getConfigDir
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:com.dmdirc.actions.ActionManager:addListener
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.util.Map:values
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.util.Collection:iterator
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.lang.String:toLowerCase
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.util.Map:put
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.util.LinkedList
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.io.File
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.util.LinkedList:add
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.util.LinkedList:isEmpty
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.util.LinkedList:pop
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.io.File:isDirectory
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.io.File:listFiles
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.io.File:isFile
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.io.File:getName
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.lang.String:endsWith
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.io.File:getPath
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.lang.String:length
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.lang.String:substring
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:addPlugin
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.net.URL
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.net.MalformedURLException:getMessage
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.io.File:exists
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:delPlugin
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:com.dmdirc.updater.components.PluginComponent
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:com.dmdirc.plugins.PluginException:getMessage
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:java.util.Map:remove
    //#unanalyzed(bool checkPlugins(String)): Effects-of-calling:getPossiblePluginInfos
    //#test_vector(bool checkPlugins(String)): java.lang.String:isEmpty(...)@665: {0}, {1}
			return true;
		}
	
		for (String plugin : desired.split(",")) {
    //#PluginInfo.java:669: ?use of default init
    //#    init'ed(arr$.length)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkPlugins(String)
    //#    basic block: bb_3
    //#    assertion: init'ed(arr$.length)
    //#    VN: undefined
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#PluginInfo.java:669: ?use of default init
    //#    init'ed(len$)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkPlugins(String)
    //#    basic block: bb_4
    //#    assertion: init'ed(len$)
    //#    VN: undefined
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#PluginInfo.java:669: Warning: test always goes same way
    //#    Test predetermined because i$ == len$
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkPlugins(String)
    //#    from bb: bb_4
    //#    live edge: bb_4-->bb_14
    //#    tested vn: i$ - undefined
    //#    tested vn values: {0}
    //#PluginInfo.java:669: Warning: dead code
    //#    Dead code here because i$ == len$
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkPlugins(String)
    //#    dead bb: bb_5
    //#PluginInfo.java:669: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkPlugins(String)
    //#    dead bb: bb_13
			final String[] data = plugin.split(":");
			final PluginInfo pi = PluginManager.getPluginManager().getPluginInfoByName(data[0]);
			if (pi == null) {
				requirementsError = "Required plugin '"+data[0]+"' was not found";
    //#PluginInfo.java:673: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkPlugins(String)
    //#    dead bb: bb_6
				return false;
			} else {
				if (data.length > 1) {
    //#PluginInfo.java:676: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkPlugins(String)
    //#    dead bb: bb_7
					// Check plugin minimum version matches.
                    if (pi.getVersion().compareTo(new Version(data[1])) < 0) {
    //#PluginInfo.java:678: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkPlugins(String)
    //#    dead bb: bb_8
                        requirementsError = "Plugin '"+data[0]+"' is too old (Required Version: "+data[1]+", Actual Version: "+pi.getVersion()+")";
    //#PluginInfo.java:679: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkPlugins(String)
    //#    dead bb: bb_9
                        return false;
                    } else {
                        if (data.length > 2) {
    //#PluginInfo.java:682: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkPlugins(String)
    //#    dead bb: bb_10
                            // Check plugin maximum version matches.
                            if (pi.getVersion().compareTo(new Version(data[2])) > 0) {
    //#PluginInfo.java:684: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkPlugins(String)
    //#    dead bb: bb_11
                                requirementsError = "Plugin '"+data[0]+"' is too new (Required Version: "+data[2]+", Actual Version: "+pi.getVersion()+")";
    //#PluginInfo.java:685: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkPlugins(String)
    //#    dead bb: bb_12
                                return false;
                            }
                        }
                    }
				}
			}
		}
		return true;
    //#PluginInfo.java:693: end of method: bool com.dmdirc.plugins.PluginInfo.checkPlugins(String)
	}

	/**
	 * Are the requirements for this plugin met?
	 *
	 * @param preliminary Is this a preliminary check?
	 * @return true/false (Actual error if false is in the requirementsError field)
	 */
	public boolean checkRequirements(final boolean preliminary) {
		if (metaData == null) {
    //#PluginInfo.java:703: method: bool com.dmdirc.plugins.PluginInfo.checkRequirements(bool)
    //#input(bool checkRequirements(bool)): ""._tainted
    //#input(bool checkRequirements(bool)): "' not found"._tainted
    //#input(bool checkRequirements(bool)): "')"._tainted
    //#input(bool checkRequirements(bool)): "', actual: '"._tainted
    //#input(bool checkRequirements(bool)): "Invalid OS architecture. (Wanted: '"._tainted
    //#input(bool checkRequirements(bool)): "Invalid OS version. (Wanted: '"._tainted
    //#input(bool checkRequirements(bool)): "Invalid OS. (Wanted: '"._tainted
    //#input(bool checkRequirements(bool)): "Required file '"._tainted
    //#input(bool checkRequirements(bool)): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(bool checkRequirements(bool)): __Descendant_Table[others]
    //#input(bool checkRequirements(bool)): __Dispatch_Table.checkFiles(Ljava/lang/String;)Z
    //#input(bool checkRequirements(bool)): __Dispatch_Table.checkOS(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
    //#input(bool checkRequirements(bool)): __Dispatch_Table.checkPlugins(Ljava/lang/String;)Z
    //#input(bool checkRequirements(bool)): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(bool checkRequirements(bool)): preliminary
    //#input(bool checkRequirements(bool)): this
    //#input(bool checkRequirements(bool)): this.__Tag
    //#input(bool checkRequirements(bool)): this.metaData
    //#output(bool checkRequirements(bool)): java.lang.StringBuilder:toString(...)._tainted
    //#output(bool checkRequirements(bool)): return_value
    //#output(bool checkRequirements(bool)): this.requirementsError
    //#new obj(bool checkRequirements(bool)): java.lang.StringBuilder:toString(...)
    //#pre[5] (bool checkRequirements(bool)): init'ed(this.metaData)
    //#pre[4] (bool checkRequirements(bool)): (soft) this.__Tag == com/dmdirc/plugins/PluginInfo
    //#presumption(bool checkRequirements(bool)): java.lang.System:getProperty(...)@720 != null
    //#post(bool checkRequirements(bool)): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(bool checkRequirements(bool)): init'ed(return_value)
    //#post(bool checkRequirements(bool)): this.requirementsError == One-of{old this.requirementsError, &java.lang.StringBuilder:toString(...)}
    //#unanalyzed(bool checkRequirements(bool)): Effects-of-calling:java.lang.String:isEmpty
    //#unanalyzed(bool checkRequirements(bool)): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(bool checkRequirements(bool)): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(bool checkRequirements(bool)): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(bool checkRequirements(bool)): Effects-of-calling:java.util.Map:get
    //#unanalyzed(bool checkRequirements(bool)): Effects-of-calling:java.lang.String:split
    //#unanalyzed(bool checkRequirements(bool)): Effects-of-calling:java.lang.String:toLowerCase
    //#unanalyzed(bool checkRequirements(bool)): Effects-of-calling:java.lang.String:matches
    //#unanalyzed(bool checkRequirements(bool)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(bool checkRequirements(bool)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(bool checkRequirements(bool)): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(bool checkRequirements(bool)): Effects-of-calling:java.io.File
    //#unanalyzed(bool checkRequirements(bool)): Effects-of-calling:java.io.File:exists
    //#test_vector(bool checkRequirements(bool)): preliminary: {1}, {0}
    //#test_vector(bool checkRequirements(bool)): this.metaData: Inverse{null}, Addr_Set{null}
    //#test_vector(bool checkRequirements(bool)): checkPlugins(...)@720: {0}, {1}
    //#test_vector(bool checkRequirements(bool)): checkServices(...)@720: {1}, {0}
			// No meta-data, so no requirements.
			return true;
		}
		
/*		final String uiPackage;
		if (Main.getUI().getClass().getPackage() != null) {
			uiPackage = Main.getUI().getClass().getPackage().getName();
		} else {
			final String uiController = Main.getUI().getClass().getName();
			if (uiController.lastIndexOf('.') >= 0) {
				uiPackage = uiController.substring(0,uiController.lastIndexOf('.'));
			} else {
				uiPackage = uiController;
			}
		} */
		
		if (/*!checkMinimumVersion(getMinVersion(), Main.SVN_REVISION) ||
    //#PluginInfo.java:720: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.checkOS: desired != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkRequirements(bool)
    //#    basic block: bb_3
    //#    assertion: getKeyValue(...) != null
    //#    callee: bool com/dmdirc/plugins/PluginInfo.checkOS(String, String, String, String)
    //#    callee assertion: desired != null
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [7]
    //#    callee srcpos: 573
    //#    VN: getKeyValue(...)
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:720: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.checkFiles: desired != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkRequirements(bool)
    //#    basic block: bb_4
    //#    assertion: getKeyValue(...) != null
    //#    callee: bool com/dmdirc/plugins/PluginInfo.checkFiles(String)
    //#    callee assertion: desired != null
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [1]
    //#    callee srcpos: 630
    //#    VN: getKeyValue(...)
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:720: Warning: test always goes same way
    //#    Test predetermined because checkFiles(...) == 1
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkRequirements(bool)
    //#    from bb: bb_4
    //#    live edge: bb_4-->bb_5
    //#    tested vn: checkFiles(...)
    //#    tested vn values: {1}
    //#PluginInfo.java:720: Warning: call too complex - analysis skipped
    //#    call on bool checkPlugins(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkRequirements(bool)
    //#    unanalyzed callee: bool checkPlugins(String)
    //#PluginInfo.java:720: Warning: method not available - call not analyzed
    //#    call on List com.dmdirc.util.ConfigFile:getFlatDomain(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkRequirements(bool)
    //#    unanalyzed callee: List com.dmdirc.util.ConfigFile:getFlatDomain(String)
    //#PluginInfo.java:720: Warning: call too complex - analysis skipped
    //#    call on bool checkServices(List)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkRequirements(bool)
    //#    unanalyzed callee: bool checkServices(List)
		    !checkMaximumVersion(getMaxVersion(), Main.SVN_REVISION) ||*/
		    !checkOS(getKeyValue("requires", "os", ""), System.getProperty("os.name"), System.getProperty("os.version"), System.getProperty("os.arch")) ||
		    !checkFiles(getKeyValue("requires", "files", "")) ||
		    (!preliminary && !checkPlugins(getKeyValue("requires", "plugins", ""))) ||
		    (!preliminary && !checkServices(metaData.getFlatDomain("required-services")))
		    ) {
			return false;
		}
		
		// All requirements passed, woo \o
		return true;
    //#PluginInfo.java:731: end of method: bool com.dmdirc.plugins.PluginInfo.checkRequirements(bool)
	}
	
	/**
	 * Check if the services required by this plugin are available.
	 *
	 * @param services Required services
	 * @return true if all services are available
	 */
	private boolean checkServices(final List<String> services) {
		if (services == null || services.size() < 1) { return true; }
    //#PluginInfo.java:741: method: bool com.dmdirc.plugins.PluginInfo.checkServices(List)
    //#input(bool checkServices(List)): "plugins"._tainted
    //#input(bool checkServices(List)): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(bool checkServices(List)): __Descendant_Table[others]
    //#input(bool checkServices(List)): __Dispatch_Table.activateServices()V
    //#input(bool checkServices(List)): __Dispatch_Table.isActive()Z
    //#input(bool checkServices(List)): __Dispatch_Table.isLoaded()Z
    //#input(bool checkServices(List)): __Dispatch_Table.loadPlugin()V
    //#input(bool checkServices(List)): com/dmdirc/plugins/PluginManager.__Class_Obj.__Lock
    //#input(bool checkServices(List)): com/dmdirc/plugins/PluginManager.__Descendant_Table[com/dmdirc/plugins/PluginManager]
    //#input(bool checkServices(List)): com/dmdirc/plugins/PluginManager.__Descendant_Table[others]
    //#input(bool checkServices(List)): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getPossiblePluginInfos(Z)Ljava/util/List;
    //#input(bool checkServices(List)): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getService(Ljava/lang/String;Ljava/lang/String;Z)Lcom/dmdirc/plugins/Service;
    //#input(bool checkServices(List)): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getServicesByType(Ljava/lang/String;)Ljava/util/List;
    //#input(bool checkServices(List)): com/dmdirc/plugins/PluginManager.com.dmdirc.actions.CoreActionType.CLIENT_PREFS_CLOSED
    //#input(bool checkServices(List)): com/dmdirc/plugins/PluginManager.com.dmdirc.actions.CoreActionType.CLIENT_PREFS_OPENED
    //#input(bool checkServices(List)): com/dmdirc/plugins/PluginManager.me
    //#input(bool checkServices(List)): com/dmdirc/plugins/PluginManager.me.__Tag
    //#input(bool checkServices(List)): com/dmdirc/plugins/PluginManager.me.services
    //#input(bool checkServices(List)): com/dmdirc/plugins/Service.__Descendant_Table[com/dmdirc/plugins/Service]
    //#input(bool checkServices(List)): com/dmdirc/plugins/Service.__Descendant_Table[others]
    //#input(bool checkServices(List)): com/dmdirc/plugins/Service.__Dispatch_Table.activate()Z
    //#input(bool checkServices(List)): com/dmdirc/plugins/Service.__Dispatch_Table.getProviders()Ljava/util/List;
    //#input(bool checkServices(List)): com/dmdirc/plugins/Service.__Dispatch_Table.isActive()Z
    //#input(bool checkServices(List)): com/dmdirc/plugins/ServiceProvider.__Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(bool checkServices(List)): com/dmdirc/plugins/ServiceProvider.__Descendant_Table[com/dmdirc/plugins/ServiceProvider]
    //#input(bool checkServices(List)): com/dmdirc/plugins/ServiceProvider.__Descendant_Table[others]
    //#input(bool checkServices(List)): com/dmdirc/plugins/ServiceProvider.__Dispatch_Table.activateServices()V
    //#input(bool checkServices(List)): com/dmdirc/plugins/ServiceProvider.__Dispatch_Table.isActive()Z
    //#input(bool checkServices(List)): services
    //#output(bool checkServices(List)): com/dmdirc/plugins/PluginManager.me
    //#output(bool checkServices(List)): java.lang.StringBuilder:toString(...)._tainted
    //#output(bool checkServices(List)): new HashMap(PluginManager#2) num objects
    //#output(bool checkServices(List)): new Hashtable(PluginManager#1) num objects
    //#output(bool checkServices(List)): new PluginClassLoader(getSubClassLoader#1) num objects
    //#output(bool checkServices(List)): new PluginClassLoader(getSubClassLoader#1).__Tag
    //#output(bool checkServices(List)): new PluginClassLoader(getSubClassLoader#1).pluginInfo
    //#output(bool checkServices(List)): new PluginManager(getPluginManager#1) num objects
    //#output(bool checkServices(List)): new PluginManager(getPluginManager#1).__Tag
    //#output(bool checkServices(List)): new PluginManager(getPluginManager#1).knownPlugins
    //#output(bool checkServices(List)): new PluginManager(getPluginManager#1).myDir
    //#output(bool checkServices(List)): new PluginManager(getPluginManager#1).services
    //#output(bool checkServices(List)): return_value
    //#new obj(bool checkServices(List)): java.lang.StringBuilder:toString(...)
    //#new obj(bool checkServices(List)): new HashMap(PluginManager#2)
    //#new obj(bool checkServices(List)): new Hashtable(PluginManager#1)
    //#new obj(bool checkServices(List)): new PluginClassLoader(getSubClassLoader#1)
    //#new obj(bool checkServices(List)): new PluginManager(getPluginManager#1)
    //#pre[5] (bool checkServices(List)): (soft) init'ed(com/dmdirc/plugins/PluginManager.me)
    //#presumption(bool checkServices(List)): getPluginManager(...).__Tag == com/dmdirc/plugins/PluginManager
    //#presumption(bool checkServices(List)): getPluginManager(...).__Tag == com/dmdirc/plugins/PluginManager
    //#presumption(bool checkServices(List)): getPluginManager(...).services != null
    //#presumption(bool checkServices(List)): getPluginManager(...).services != null
    //#presumption(bool checkServices(List)): java.util.Iterator:next(...).__Tag@758 == com/dmdirc/plugins/Service
    //#presumption(bool checkServices(List)): java.util.Iterator:next(...)@743 != null
    //#presumption(bool checkServices(List)): java.util.List:get(...).__Tag@755 == com/dmdirc/plugins/Service
    //#presumption(bool checkServices(List)): java.util.List:get(...)@755 != null
    //#presumption(bool checkServices(List)): service.__Tag@767 == com/dmdirc/plugins/Service
    //#post(bool checkServices(List)): init'ed(com/dmdirc/plugins/PluginManager.me)
    //#post(bool checkServices(List)): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(bool checkServices(List)): init'ed(return_value)
    //#post(bool checkServices(List)): init'ed(new HashMap(PluginManager#2) num objects)
    //#post(bool checkServices(List)): init'ed(new Hashtable(PluginManager#1) num objects)
    //#post(bool checkServices(List)): init'ed(new PluginClassLoader(getSubClassLoader#1) num objects)
    //#post(bool checkServices(List)): possibly_updated(new PluginClassLoader(getSubClassLoader#1).__Tag)
    //#post(bool checkServices(List)): possibly_updated(new PluginClassLoader(getSubClassLoader#1).pluginInfo)
    //#post(bool checkServices(List)): init'ed(new PluginManager(getPluginManager#1) num objects)
    //#post(bool checkServices(List)): init'ed(new PluginManager(getPluginManager#1).__Tag)
    //#post(bool checkServices(List)): init'ed(new PluginManager(getPluginManager#1).knownPlugins)
    //#post(bool checkServices(List)): init'ed(new PluginManager(getPluginManager#1).myDir)
    //#post(bool checkServices(List)): init'ed(new PluginManager(getPluginManager#1).services)
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.lang.String:isEmpty
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.net.URL:getPath
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.util.List:remove
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.util.Map:get
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:com.dmdirc.util.ConfigFile:isFlatDomain
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:com.dmdirc.util.ConfigFile:getFlatDomain
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.util.List:contains
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:getPluginManager
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:updateProvides
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:checkRequirements
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:loadRequired
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:onLoad
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:getName
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.lang.Throwable:getMessage
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:addError
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:unloadPlugin
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:getMainClass
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:loadClass
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:com.dmdirc.actions.ActionManager:processEvent
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:loadPlugin
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:getPluginInfoByName
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.util.List:iterator
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.lang.ClassLoader
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.lang.String:equalsIgnoreCase
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:isActive
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:delProvider
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.util.List:clear
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:isUnloadable
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:onUnload
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.lang.Exception:getMessage
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.lang.Exception:printStackTrace
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.lang.Exception
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:com.dmdirc.plugins.PluginInfo
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.util.Hashtable
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.util.HashMap
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.lang.System:getProperty
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:com.dmdirc.Main:getConfigDir
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:com.dmdirc.actions.ActionManager:addListener
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.util.Map:values
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.util.Collection:iterator
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.lang.String:toLowerCase
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.util.Map:put
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.util.LinkedList
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.io.File
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.util.LinkedList:add
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.util.LinkedList:isEmpty
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.util.LinkedList:pop
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.io.File:isDirectory
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.io.File:listFiles
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.io.File:isFile
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.io.File:getName
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.lang.String:endsWith
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.io.File:getPath
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.lang.String:length
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.lang.String:substring
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:addPlugin
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.net.URL
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.net.MalformedURLException:getMessage
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.io.File:exists
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:delPlugin
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:com.dmdirc.updater.components.PluginComponent
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:com.dmdirc.plugins.PluginException:getMessage
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:java.util.Map:remove
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:getPossiblePluginInfos
    //#unanalyzed(bool checkServices(List)): Effects-of-calling:activateServices
    //#test_vector(bool checkServices(List)): services: Addr_Set{null}, Inverse{null}
    //#test_vector(bool checkServices(List)): java.lang.String:equalsIgnoreCase(...)@751: {0}, {1}
    //#test_vector(bool checkServices(List)): java.util.Iterator:hasNext(...)@743: {0}, {1}
    //#test_vector(bool checkServices(List)): java.util.List:size(...)@741: {1..4_294_967_295}, {-2_147_483_648..0}
		
		for (String requirement : services) {
			boolean available = false;
			final String[] bits = requirement.split(" ");
			final String name = bits[0];
    //#PluginInfo.java:746: ?use of default init
    //#    init'ed(bits.length)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkServices(List)
    //#    basic block: bb_6
    //#    assertion: init'ed(bits.length)
    //#    VN: undefined
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#PluginInfo.java:746: ?use of default init
    //#    init'ed(bits[0])
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkServices(List)
    //#    basic block: bb_6
    //#    assertion: init'ed(bits[0])
    //#    VN: undefined
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
			final String type = (bits.length > 1) ? bits[1] : "misc";
    //#PluginInfo.java:747: ?use of default init
    //#    init'ed(bits.length)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkServices(List)
    //#    basic block: bb_6
    //#    assertion: init'ed(bits.length)
    //#    VN: undefined
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
			
			// System.out.println(toString()+" Looking for: "+requirement);
			Service service = null;
			if (name.equalsIgnoreCase("any")) {
    //#PluginInfo.java:751: ?use of default init
    //#    init'ed(name)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkServices(List)
    //#    basic block: bb_9
    //#    assertion: init'ed(name)
    //#    VN: undefined
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
    //#PluginInfo.java:751: ?null dereference
    //#    not_init'ed(name)
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkServices(List)
    //#    basic block: bb_9
    //#    assertion: not_init'ed(name)
    //#    VN: undefined
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
				final List<Service> serviceList = PluginManager.getPluginManager().getServicesByType(type);
				if (serviceList.size() > 0) {
					// Default to the first Service in the list
					service = serviceList.get(0);
					if (serviceList.size() > 1) {
						// Check to see if any of the others are already active
						for (Service serv : serviceList) {
    //#PluginInfo.java:758: Warning: unused assignment
    //#    Unused assignment into serv
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkServices(List)
							if (service.isActive()) {
								// Already active, abort.
								available = true;
							}
						}
					}
				}
			} else {
				service = PluginManager.getPluginManager().getService(type, name, false);
    //#PluginInfo.java:767: ?use of default init
    //#    init'ed(name)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkServices(List)
    //#    basic block: bb_18
    //#    assertion: init'ed(name)
    //#    VN: undefined
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
			}
			// System.out.println("\tSatisfied by: "+service+" "+(PluginInfo)service.getActiveProvider());
			if (service != null) {
				available = service.activate();
    //#PluginInfo.java:771: ?use of default init
    //#    init'ed(service.__Tag)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkServices(List)
    //#    basic block: bb_20
    //#    assertion: init'ed(service.__Tag)
    //#    VN: service.__Tag
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#PluginInfo.java:771: ?null dereference
    //#    com/dmdirc/plugins/Service.__Descendant_Table[service.__Tag] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkServices(List)
    //#    basic block: bb_20
    //#    assertion: com/dmdirc/plugins/Service.__Descendant_Table[service.__Tag] != null
    //#    VN: com/dmdirc/plugins/Service.__Descendant_Table[service.__Tag]
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:771: ?precondition failure
    //#    com/dmdirc/plugins/Service.activate: (soft) init'ed(this.serviceproviders)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkServices(List)
    //#    basic block: bb_20
    //#    assertion: (soft) init'ed(service.serviceproviders)
    //#    callee: bool com/dmdirc/plugins/Service.activate()
    //#    callee assertion: (soft) init'ed(this.serviceproviders)
    //#    callee file: Service.java
    //#    callee precondition index: [3]
    //#    callee srcpos: 134
    //#    VN: service.serviceproviders
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid  Uncertain
			}
			
			if (!available) { return false; }
    //#PluginInfo.java:774: ?use of default init
    //#    init'ed(available)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool checkServices(List)
    //#    basic block: bb_21
    //#    assertion: init'ed(available)
    //#    VN: available
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
		}
		
		return true;
    //#PluginInfo.java:777: end of method: bool com.dmdirc.plugins.PluginInfo.checkServices(List)
	}
	
	/**
	 * Is this provider active at this time.
	 *
	 * @return true if the provider is able to provide its services
	 */
	@Override
	public final boolean isActive() { return isLoaded(); }
    //#PluginInfo.java:786: method: bool com.dmdirc.plugins.PluginInfo.isActive()
    //#input(bool isActive()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(bool isActive()): __Descendant_Table[others]
    //#input(bool isActive()): __Dispatch_Table.isLoaded()Z
    //#input(bool isActive()): this
    //#input(bool isActive()): this.__Tag
    //#input(bool isActive()): this.plugin
    //#input(bool isActive()): this.tempLoaded
    //#output(bool isActive()): return_value
    //#pre[6] (bool isActive()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[7] (bool isActive()): init'ed(this.plugin)
    //#pre[8] (bool isActive()): (soft) init'ed(this.tempLoaded)
    //#post(bool isActive()): init'ed(return_value)
    //#PluginInfo.java:786: end of method: bool com.dmdirc.plugins.PluginInfo.isActive()
	
	/** Activate the services. */
	@Override
	public void activateServices() { loadPlugin(); }
    //#PluginInfo.java:790: method: void com.dmdirc.plugins.PluginInfo.activateServices()
    //#PluginInfo.java:790: Warning: call too complex - analysis skipped
    //#    call on void loadPlugin()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void activateServices()
    //#    unanalyzed callee: void loadPlugin()
    //#input(void activateServices()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(void activateServices()): __Descendant_Table[others]
    //#input(void activateServices()): __Dispatch_Table.loadPlugin()V
    //#input(void activateServices()): this
    //#input(void activateServices()): this.__Tag
    //#output(void activateServices()): java.lang.StringBuilder:toString(...)._tainted
    //#output(void activateServices()): this.isLoading
    //#output(void activateServices()): this.lastError
    //#output(void activateServices()): this.tempLoaded
    //#new obj(void activateServices()): java.lang.StringBuilder:toString(...)
    //#pre[9] (void activateServices()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[11] (void activateServices()): (soft) init'ed(this.plugin)
    //#post(void activateServices()): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(void activateServices()): this.isLoading == old this.isLoading
    //#post(void activateServices()): this.lastError == old this.lastError
    //#post(void activateServices()): this.tempLoaded == old this.tempLoaded
    //#PluginInfo.java:790: end of method: void com.dmdirc.plugins.PluginInfo.activateServices()
	
	/** {@inheritDoc} */
	@Override
	public String getProviderName() { return "Plugin: "+getNiceName()+" ("+getName()+" / "+getFilename()+")"; }
    //#PluginInfo.java:794: method: String com.dmdirc.plugins.PluginInfo.getProviderName()
    //#input(String getProviderName()): " ("._tainted
    //#input(String getProviderName()): " . "._tainted
    //#input(String getProviderName()): ""._tainted
    //#input(String getProviderName()): ")"._tainted
    //#input(String getProviderName()): "Plugin: "._tainted
    //#input(String getProviderName()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(String getProviderName()): __Descendant_Table[others]
    //#input(String getProviderName()): __Dispatch_Table.getFilename()Ljava/lang/String;
    //#input(String getProviderName()): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(String getProviderName()): __Dispatch_Table.getName()Ljava/lang/String;
    //#input(String getProviderName()): __Dispatch_Table.getNiceName()Ljava/lang/String;
    //#input(String getProviderName()): this
    //#input(String getProviderName()): this.__Tag
    //#input(String getProviderName()): this.filename
    //#input(String getProviderName()): this.filename._tainted
    //#input(String getProviderName()): this.metaData
    //#output(String getProviderName()): java.lang.StringBuilder:toString(...)._tainted
    //#output(String getProviderName()): return_value
    //#new obj(String getProviderName()): java.lang.StringBuilder:toString(...)
    //#pre[2] (String getProviderName()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[5] (String getProviderName()): init'ed(this.metaData)
    //#post(String getProviderName()): init'ed(java.lang.StringBuilder:toString(...)._tainted)
    //#post(String getProviderName()): return_value == &java.lang.StringBuilder:toString(...)
    //#unanalyzed(String getProviderName()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(String getProviderName()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(String getProviderName()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(String getProviderName()): Effects-of-calling:java.util.Map:get
    //#PluginInfo.java:794: end of method: String com.dmdirc.plugins.PluginInfo.getProviderName()

	/**
	 * Get a list of services provided by this provider.
	 *
	 * @return A list of services provided by this provider.
	 */
	@Override
	public List<Service> getServices() {
		return new ArrayList<Service>(provides);
    //#PluginInfo.java:803: method: List com.dmdirc.plugins.PluginInfo.getServices()
    //#input(List getServices()): this
    //#input(List getServices()): this.provides
    //#output(List getServices()): new ArrayList(getServices#1) num objects
    //#output(List getServices()): return_value
    //#new obj(List getServices()): new ArrayList(getServices#1)
    //#post(List getServices()): return_value == &new ArrayList(getServices#1)
    //#post(List getServices()): new ArrayList(getServices#1) num objects == 1
    //#PluginInfo.java:803: end of method: List com.dmdirc.plugins.PluginInfo.getServices()
	}

	/**
	 * Is this plugin loaded?
	 *
	 * @return True if the plugin is currently (non-temporarily) loaded, false
	 * otherwise
	 */
	public boolean isLoaded() {
		return (plugin != null) && !tempLoaded;
    //#PluginInfo.java:813: method: bool com.dmdirc.plugins.PluginInfo.isLoaded()
    //#input(bool isLoaded()): this
    //#input(bool isLoaded()): this.plugin
    //#input(bool isLoaded()): this.tempLoaded
    //#output(bool isLoaded()): return_value
    //#pre[6] (bool isLoaded()): init'ed(this.plugin)
    //#pre[7] (bool isLoaded()): (soft) init'ed(this.tempLoaded)
    //#post(bool isLoaded()): init'ed(return_value)
    //#PluginInfo.java:813: end of method: bool com.dmdirc.plugins.PluginInfo.isLoaded()
	}

	/**
	 * Is this plugin temporarily loaded?
	 *
	 * @return True if this plugin is currently temporarily loaded, false
	 * otherwise
	 */
	public boolean isTempLoaded() {
		return (plugin != null) && tempLoaded;
    //#PluginInfo.java:823: method: bool com.dmdirc.plugins.PluginInfo.isTempLoaded()
    //#input(bool isTempLoaded()): this
    //#input(bool isTempLoaded()): this.plugin
    //#input(bool isTempLoaded()): this.tempLoaded
    //#output(bool isTempLoaded()): return_value
    //#pre[6] (bool isTempLoaded()): init'ed(this.plugin)
    //#pre[7] (bool isTempLoaded()): (soft) init'ed(this.tempLoaded)
    //#post(bool isTempLoaded()): init'ed(return_value)
    //#PluginInfo.java:823: end of method: bool com.dmdirc.plugins.PluginInfo.isTempLoaded()
	}

	/**
	 * Load entire plugin.
	 * This loads all files in the jar immediately.
	 *
	 * @throws PluginException if there is an error with the resourcemanager
	 */
	private void loadEntirePlugin() throws PluginException {
		// Load the main "Plugin" from the jar
		loadPlugin();
    //#PluginInfo.java:834: method: void com.dmdirc.plugins.PluginInfo.loadEntirePlugin()
    //#PluginInfo.java:834: Warning: call too complex - analysis skipped
    //#    call on void loadPlugin()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadEntirePlugin()
    //#    unanalyzed callee: void loadPlugin()
    //#input(void loadEntirePlugin()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(void loadEntirePlugin()): __Descendant_Table[others]
    //#input(void loadEntirePlugin()): __Dispatch_Table.loadPlugin()V
    //#input(void loadEntirePlugin()): this
    //#input(void loadEntirePlugin()): this.__Tag
    //#input(void loadEntirePlugin()): this.myClasses
    //#output(void loadEntirePlugin()): com/dmdirc/plugins/GlobalClassLoader.me
    //#output(void loadEntirePlugin()): java.lang.StringBuilder:toString(...)._tainted
    //#output(void loadEntirePlugin()): new GlobalClassLoader(getGlobalClassLoader#1) num objects
    //#output(void loadEntirePlugin()): new GlobalClassLoader(getGlobalClassLoader#1).__Tag
    //#output(void loadEntirePlugin()): new GlobalClassLoader(getGlobalClassLoader#1).resourcesList
    //#output(void loadEntirePlugin()): new HashMap(GlobalClassLoader#1) num objects
    //#output(void loadEntirePlugin()): new PluginClassLoader(getSubClassLoader#1) num objects
    //#output(void loadEntirePlugin()): new PluginClassLoader(getSubClassLoader#1).__Tag
    //#output(void loadEntirePlugin()): new PluginClassLoader(getSubClassLoader#1).pluginInfo
    //#output(void loadEntirePlugin()): new PluginClassLoader(loadClass#1) num objects
    //#output(void loadEntirePlugin()): new PluginClassLoader(loadClass#1).__Tag
    //#output(void loadEntirePlugin()): new PluginClassLoader(loadClass#1).pluginInfo
    //#output(void loadEntirePlugin()): this.classloader
    //#output(void loadEntirePlugin()): this.isLoading
    //#output(void loadEntirePlugin()): this.lastError
    //#output(void loadEntirePlugin()): this.plugin
    //#output(void loadEntirePlugin()): this.plugin.domainSet
    //#output(void loadEntirePlugin()): this.plugin.myDomain
    //#output(void loadEntirePlugin()): this.tempLoaded
    //#new obj(void loadEntirePlugin()): java.lang.StringBuilder:toString(...)
    //#new obj(void loadEntirePlugin()): new GlobalClassLoader(getGlobalClassLoader#1)
    //#new obj(void loadEntirePlugin()): new HashMap(GlobalClassLoader#1)
    //#new obj(void loadEntirePlugin()): new PluginClassLoader(getSubClassLoader#1)
    //#new obj(void loadEntirePlugin()): new PluginClassLoader(loadClass#1)
    //#pre[10] (void loadEntirePlugin()): (soft) init'ed(this.plugin)
    //#pre[16] (void loadEntirePlugin()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[22] (void loadEntirePlugin()): this.myClasses != null
    //#pre[6] (void loadEntirePlugin()): (soft) init'ed(com/dmdirc/plugins/GlobalClassLoader.me)
    //#pre[7] (void loadEntirePlugin()): (soft) init'ed(this.classloader)
    //#post(void loadEntirePlugin()): com/dmdirc/plugins/GlobalClassLoader.me == old com/dmdirc/plugins/GlobalClassLoader.me
    //#post(void loadEntirePlugin()): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(void loadEntirePlugin()): this.classloader == old this.classloader
    //#post(void loadEntirePlugin()): this.isLoading == old this.isLoading
    //#post(void loadEntirePlugin()): this.lastError == old this.lastError
    //#post(void loadEntirePlugin()): this.plugin == old this.plugin
    //#post(void loadEntirePlugin()): this.plugin.domainSet == old this.plugin.domainSet
    //#post(void loadEntirePlugin()): this.plugin.myDomain == old this.plugin.myDomain
    //#post(void loadEntirePlugin()): this.tempLoaded == old this.tempLoaded
    //#post(void loadEntirePlugin()): new GlobalClassLoader(getGlobalClassLoader#1) num objects == undefined
    //#post(void loadEntirePlugin()): new GlobalClassLoader(getGlobalClassLoader#1) num objects == 0, if init'ed
    //#post(void loadEntirePlugin()): new GlobalClassLoader(getGlobalClassLoader#1).__Tag == new GlobalClassLoader(getGlobalClassLoader#1) num objects
    //#post(void loadEntirePlugin()): new HashMap(GlobalClassLoader#1) num objects == new GlobalClassLoader(getGlobalClassLoader#1) num objects
    //#post(void loadEntirePlugin()): new PluginClassLoader(getSubClassLoader#1) num objects == new GlobalClassLoader(getGlobalClassLoader#1) num objects
    //#post(void loadEntirePlugin()): new PluginClassLoader(getSubClassLoader#1).__Tag == new GlobalClassLoader(getGlobalClassLoader#1) num objects
    //#post(void loadEntirePlugin()): new PluginClassLoader(loadClass#1) num objects == new GlobalClassLoader(getGlobalClassLoader#1) num objects
    //#post(void loadEntirePlugin()): new PluginClassLoader(loadClass#1).__Tag == new GlobalClassLoader(getGlobalClassLoader#1) num objects
    //#post(void loadEntirePlugin()): new GlobalClassLoader(getGlobalClassLoader#1).resourcesList == undefined
    //#post(void loadEntirePlugin()): new GlobalClassLoader(getGlobalClassLoader#1).resourcesList == null
    //#post(void loadEntirePlugin()): new PluginClassLoader(getSubClassLoader#1).pluginInfo == new GlobalClassLoader(getGlobalClassLoader#1).resourcesList
    //#post(void loadEntirePlugin()): new PluginClassLoader(loadClass#1).pluginInfo == new GlobalClassLoader(getGlobalClassLoader#1).resourcesList
    //#test_vector(void loadEntirePlugin()): java.util.Iterator:hasNext(...)@837: {0}, {1}

		// Now load all the rest.
		for (String classname : myClasses) {
			loadClass(classname);
    //#PluginInfo.java:838: Warning: call too complex - analysis skipped
    //#    call on void loadClass(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadEntirePlugin()
    //#    unanalyzed callee: void loadClass(String)
		}
	}
    //#PluginInfo.java:840: end of method: void com.dmdirc.plugins.PluginInfo.loadEntirePlugin()

	/**
	 * Try to Load the plugin files temporarily.
	 */
	public void loadPluginTemp() {
		tempLoaded = true;
    //#PluginInfo.java:846: method: void com.dmdirc.plugins.PluginInfo.loadPluginTemp()
    //#input(void loadPluginTemp()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(void loadPluginTemp()): __Descendant_Table[others]
    //#input(void loadPluginTemp()): __Dispatch_Table.loadPlugin()V
    //#input(void loadPluginTemp()): this
    //#input(void loadPluginTemp()): this.__Tag
    //#output(void loadPluginTemp()): java.lang.StringBuilder:toString(...)._tainted
    //#output(void loadPluginTemp()): this.isLoading
    //#output(void loadPluginTemp()): this.lastError
    //#output(void loadPluginTemp()): this.tempLoaded
    //#new obj(void loadPluginTemp()): java.lang.StringBuilder:toString(...)
    //#pre[4] (void loadPluginTemp()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#post(void loadPluginTemp()): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(void loadPluginTemp()): this.isLoading == old this.isLoading
    //#post(void loadPluginTemp()): this.lastError == old this.lastError
    //#post(void loadPluginTemp()): this.tempLoaded == 1
		loadPlugin();
    //#PluginInfo.java:847: Warning: call too complex - analysis skipped
    //#    call on void loadPlugin()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadPluginTemp()
    //#    unanalyzed callee: void loadPlugin()
	}
    //#PluginInfo.java:848: end of method: void com.dmdirc.plugins.PluginInfo.loadPluginTemp()

	/**
	 * Load any required plugins
	 */
	public void loadRequired() {
		final String required = getKeyValue("requires", "plugins", "");
    //#PluginInfo.java:854: method: void com.dmdirc.plugins.PluginInfo.loadRequired()
    //#input(void loadRequired()): ""._tainted
    //#input(void loadRequired()): "plugins"._tainted
    //#input(void loadRequired()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(void loadRequired()): __Descendant_Table[others]
    //#input(void loadRequired()): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(void loadRequired()): __Dispatch_Table.getName()Ljava/lang/String;
    //#input(void loadRequired()): __Dispatch_Table.loadPlugin()V
    //#input(void loadRequired()): __Dispatch_Table.loadPluginTemp()V
    //#input(void loadRequired()): com/dmdirc/plugins/PluginManager.__Class_Obj.__Lock
    //#input(void loadRequired()): com/dmdirc/plugins/PluginManager.__Descendant_Table[com/dmdirc/plugins/PluginManager]
    //#input(void loadRequired()): com/dmdirc/plugins/PluginManager.__Descendant_Table[others]
    //#input(void loadRequired()): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getPluginInfoByName(Ljava/lang/String;)Lcom/dmdirc/plugins/PluginInfo;
    //#input(void loadRequired()): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getPluginInfos()Ljava/util/Collection;
    //#input(void loadRequired()): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getPossiblePluginInfos(Z)Ljava/util/List;
    //#input(void loadRequired()): com/dmdirc/plugins/PluginManager.com.dmdirc.actions.CoreActionType.CLIENT_PREFS_CLOSED
    //#input(void loadRequired()): com/dmdirc/plugins/PluginManager.com.dmdirc.actions.CoreActionType.CLIENT_PREFS_OPENED
    //#input(void loadRequired()): com/dmdirc/plugins/PluginManager.me.__Tag
    //#input(void loadRequired()): com/dmdirc/plugins/PluginManager.me.knownPlugins
    //#input(void loadRequired()): this
    //#input(void loadRequired()): this.__Tag
    //#input(void loadRequired()): this.metaData
    //#output(void loadRequired()): com/dmdirc/plugins/PluginManager.me
    //#output(void loadRequired()): java.lang.StringBuilder:toString(...)._tainted
    //#output(void loadRequired()): new HashMap(PluginManager#2) num objects
    //#output(void loadRequired()): new Hashtable(PluginManager#1) num objects
    //#output(void loadRequired()): new PluginClassLoader(getSubClassLoader#1) num objects
    //#output(void loadRequired()): new PluginClassLoader(getSubClassLoader#1).__Tag
    //#output(void loadRequired()): new PluginClassLoader(getSubClassLoader#1).pluginInfo
    //#output(void loadRequired()): new PluginManager(getPluginManager#1) num objects
    //#output(void loadRequired()): new PluginManager(getPluginManager#1).__Tag
    //#output(void loadRequired()): new PluginManager(getPluginManager#1).knownPlugins
    //#output(void loadRequired()): new PluginManager(getPluginManager#1).myDir
    //#output(void loadRequired()): new PluginManager(getPluginManager#1).services
    //#new obj(void loadRequired()): java.lang.StringBuilder:toString(...)
    //#new obj(void loadRequired()): new HashMap(PluginManager#2)
    //#new obj(void loadRequired()): new Hashtable(PluginManager#1)
    //#new obj(void loadRequired()): new PluginClassLoader(getSubClassLoader#1)
    //#new obj(void loadRequired()): new PluginManager(getPluginManager#1)
    //#pre[7] (void loadRequired()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[8] (void loadRequired()): init'ed(this.metaData)
    //#post(void loadRequired()): possibly_updated(com/dmdirc/plugins/PluginManager.me)
    //#post(void loadRequired()): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(void loadRequired()): new HashMap(PluginManager#2) num objects == 0
    //#post(void loadRequired()): new Hashtable(PluginManager#1) num objects == 0
    //#post(void loadRequired()): new PluginClassLoader(getSubClassLoader#1) num objects == 0
    //#post(void loadRequired()): possibly_updated(new PluginClassLoader(getSubClassLoader#1).__Tag)
    //#post(void loadRequired()): possibly_updated(new PluginClassLoader(getSubClassLoader#1).pluginInfo)
    //#post(void loadRequired()): new PluginManager(getPluginManager#1) num objects == 0
    //#post(void loadRequired()): init'ed(new PluginManager(getPluginManager#1).__Tag)
    //#post(void loadRequired()): init'ed(new PluginManager(getPluginManager#1).knownPlugins)
    //#post(void loadRequired()): init'ed(new PluginManager(getPluginManager#1).myDir)
    //#post(void loadRequired()): init'ed(new PluginManager(getPluginManager#1).services)
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.lang.String:isEmpty
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.net.URL:getPath
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.util.List:remove
    //#unanalyzed(void loadRequired()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(void loadRequired()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.util.Map:get
    //#unanalyzed(void loadRequired()): Effects-of-calling:com.dmdirc.util.ConfigFile:isFlatDomain
    //#unanalyzed(void loadRequired()): Effects-of-calling:com.dmdirc.util.ConfigFile:getFlatDomain
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.util.List:contains
    //#unanalyzed(void loadRequired()): Effects-of-calling:getPluginManager
    //#unanalyzed(void loadRequired()): Effects-of-calling:updateProvides
    //#unanalyzed(void loadRequired()): Effects-of-calling:checkRequirements
    //#unanalyzed(void loadRequired()): Effects-of-calling:loadRequired
    //#unanalyzed(void loadRequired()): Effects-of-calling:onLoad
    //#unanalyzed(void loadRequired()): Effects-of-calling:getName
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.lang.Throwable:getMessage
    //#unanalyzed(void loadRequired()): Effects-of-calling:addError
    //#unanalyzed(void loadRequired()): Effects-of-calling:unloadPlugin
    //#unanalyzed(void loadRequired()): Effects-of-calling:getMainClass
    //#unanalyzed(void loadRequired()): Effects-of-calling:loadClass
    //#unanalyzed(void loadRequired()): Effects-of-calling:com.dmdirc.actions.ActionManager:processEvent
    //#unanalyzed(void loadRequired()): Effects-of-calling:loadPlugin
    //#unanalyzed(void loadRequired()): Effects-of-calling:getPluginInfoByName
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.util.List:iterator
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.lang.ClassLoader
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.lang.String:equalsIgnoreCase
    //#unanalyzed(void loadRequired()): Effects-of-calling:delProvider
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.util.List:clear
    //#unanalyzed(void loadRequired()): Effects-of-calling:isUnloadable
    //#unanalyzed(void loadRequired()): Effects-of-calling:onUnload
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.lang.Exception:getMessage
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.lang.Exception:printStackTrace
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.lang.Exception
    //#unanalyzed(void loadRequired()): Effects-of-calling:com.dmdirc.plugins.PluginInfo
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.util.Hashtable
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.util.HashMap
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.lang.System:getProperty
    //#unanalyzed(void loadRequired()): Effects-of-calling:com.dmdirc.Main:getConfigDir
    //#unanalyzed(void loadRequired()): Effects-of-calling:com.dmdirc.actions.ActionManager:addListener
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.util.Map:values
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.util.Collection:iterator
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.lang.String:toLowerCase
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.util.Map:put
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.util.LinkedList
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.io.File
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.util.LinkedList:add
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.util.LinkedList:isEmpty
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.util.LinkedList:pop
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.io.File:isDirectory
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.io.File:listFiles
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.io.File:isFile
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.io.File:getName
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.lang.String:endsWith
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.io.File:getPath
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.lang.String:length
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.lang.String:substring
    //#unanalyzed(void loadRequired()): Effects-of-calling:addPlugin
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.net.URL
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.net.MalformedURLException:getMessage
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.io.File:exists
    //#unanalyzed(void loadRequired()): Effects-of-calling:delPlugin
    //#unanalyzed(void loadRequired()): Effects-of-calling:com.dmdirc.updater.components.PluginComponent
    //#unanalyzed(void loadRequired()): Effects-of-calling:com.dmdirc.plugins.PluginException:getMessage
    //#unanalyzed(void loadRequired()): Effects-of-calling:java.util.Map:remove
    //#unanalyzed(void loadRequired()): Effects-of-calling:getPossiblePluginInfos
		for (String plugin : required.split(",")) {
    //#PluginInfo.java:855: ?null dereference
    //#    required != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadRequired()
    //#    basic block: Entry_BB_1
    //#    assertion: required != null
    //#    VN: getKeyValue(...)
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:855: ?use of default init
    //#    init'ed(arr$.length)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadRequired()
    //#    basic block: Entry_BB_1
    //#    assertion: init'ed(arr$.length)
    //#    VN: undefined
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#PluginInfo.java:855: ?use of default init
    //#    init'ed(len$)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadRequired()
    //#    basic block: bb_2
    //#    assertion: init'ed(len$)
    //#    VN: undefined
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#PluginInfo.java:855: Warning: test always goes same way
    //#    Test predetermined because i$ == len$
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadRequired()
    //#    from bb: bb_2
    //#    live edge: bb_2-->bb_10
    //#    tested vn: i$ - undefined
    //#    tested vn values: {0}
    //#PluginInfo.java:855: Warning: dead code
    //#    Dead code here because i$ == len$
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadRequired()
    //#    dead bb: bb_3
    //#PluginInfo.java:855: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadRequired()
    //#    dead bb: bb_9
			final String[] data = plugin.split(":");
			if (!data[0].trim().isEmpty()) {
				final PluginInfo pi = PluginManager.getPluginManager().getPluginInfoByName(data[0]);
    //#PluginInfo.java:858: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadRequired()
    //#    dead bb: bb_4
			
				if (pi == null) {
					return;
    //#PluginInfo.java:861: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadRequired()
    //#    dead bb: bb_5
				}
				if (tempLoaded) {
    //#PluginInfo.java:863: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadRequired()
    //#    dead bb: bb_6
					pi.loadPluginTemp();
    //#PluginInfo.java:864: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadRequired()
    //#    dead bb: bb_7
				} else {
					pi.loadPlugin();
    //#PluginInfo.java:866: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadRequired()
    //#    dead bb: bb_8
				}
			}
		}
	}
    //#PluginInfo.java:870: end of method: void com.dmdirc.plugins.PluginInfo.loadRequired()

	/**
	 * Load the plugin files.
	 */
	public void loadPlugin() {
		updateProvides();
    //#PluginInfo.java:876: method: void com.dmdirc.plugins.PluginInfo.loadPlugin()
    //#PluginInfo.java:876: Warning: call too complex - analysis skipped
    //#    call on void updateProvides()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadPlugin()
    //#    unanalyzed callee: void updateProvides()
    //#input(void loadPlugin()): " - "._tainted
    //#input(void loadPlugin()): ""._tainted
    //#input(void loadPlugin()): "&#09;"._tainted
    //#input(void loadPlugin()): "&#10;Which caused: "._tainted
    //#input(void loadPlugin()): "' not found"._tainted
    //#input(void loadPlugin()): "')"._tainted
    //#input(void loadPlugin()): "', actual: '"._tainted
    //#input(void loadPlugin()): ")"._tainted
    //#input(void loadPlugin()): "-"._tainted
    //#input(void loadPlugin()): ".log"._tainted
    //#input(void loadPlugin()): ": "._tainted
    //#input(void loadPlugin()): ":"._tainted
    //#input(void loadPlugin()): "A fatal error has occurred: "._tainted
    //#input(void loadPlugin()): "An error has occurred: "._tainted
    //#input(void loadPlugin()): "Date:"._tainted
    //#input(void loadPlugin()): "Description: "._tainted
    //#input(void loadPlugin()): "Error in onLoad for "._tainted
    //#input(void loadPlugin()): "Error in onUnload for "._tainted
    //#input(void loadPlugin()): "ID must be a positive integer: "._tainted
    //#input(void loadPlugin()): "Invalid OS architecture. (Wanted: '"._tainted
    //#input(void loadPlugin()): "Invalid OS version. (Wanted: '"._tainted
    //#input(void loadPlugin()): "Invalid OS. (Wanted: '"._tainted
    //#input(void loadPlugin()): "Level: "._tainted
    //#input(void loadPlugin()): "Not Loading: ("._tainted
    //#input(void loadPlugin()): "Required file '"._tainted
    //#input(void loadPlugin()): "Unable to loadPlugin, all requirements not met. ("._tainted
    //#input(void loadPlugin()): "errors"._tainted
    //#input(void loadPlugin()): "||"._tainted
    //#input(void loadPlugin()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(void loadPlugin()): __Descendant_Table[others]
    //#input(void loadPlugin()): __Dispatch_Table.checkFiles(Ljava/lang/String;)Z
    //#input(void loadPlugin()): __Dispatch_Table.checkOS(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
    //#input(void loadPlugin()): __Dispatch_Table.checkPlugins(Ljava/lang/String;)Z
    //#input(void loadPlugin()): __Dispatch_Table.checkRequirements(Z)Z
    //#input(void loadPlugin()): __Dispatch_Table.delChild(Lcom/dmdirc/plugins/PluginInfo;)V
    //#input(void loadPlugin()): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(void loadPlugin()): __Dispatch_Table.getMainClass()Ljava/lang/String;
    //#input(void loadPlugin()): __Dispatch_Table.getName()Ljava/lang/String;
    //#input(void loadPlugin()): __Dispatch_Table.getPluginClassLoader()Lcom/dmdirc/plugins/PluginClassLoader;
    //#input(void loadPlugin()): __Dispatch_Table.isLoaded()Z
    //#input(void loadPlugin()): __Dispatch_Table.isPersistent()Z
    //#input(void loadPlugin()): __Dispatch_Table.isTempLoaded()Z
    //#input(void loadPlugin()): __Dispatch_Table.isUnloadable()Z
    //#input(void loadPlugin()): __Dispatch_Table.loadRequired()V
    //#input(void loadPlugin()): __Dispatch_Table.unloadPlugin()V
    //#input(void loadPlugin()): com.dmdirc.actions.CoreActionType.PLUGIN_LOADED
    //#input(void loadPlugin()): com.dmdirc.actions.CoreActionType.PLUGIN_UNLOADED
    //#input(void loadPlugin()): com.dmdirc.logger.ErrorLevel__static_init.new ErrorLevel(ErrorLevel__static_init#3)._tainted
    //#input(void loadPlugin()): com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2).length
    //#input(void loadPlugin()): com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).errorListeners
    //#input(void loadPlugin()): com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).errors
    //#input(void loadPlugin()): com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).errors.__Lock
    //#input(void loadPlugin()): com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportQueue
    //#input(void loadPlugin()): com.dmdirc.logger.ErrorReportStatus__static_init.new ErrorReportStatus(ErrorReportStatus__static_init#1).terminal
    //#input(void loadPlugin()): com.dmdirc.logger.ErrorReportStatus__static_init.new ErrorReportStatus(ErrorReportStatus__static_init#5).terminal
    //#input(void loadPlugin()): com.dmdirc.logger.ErrorReportStatus__static_init.new ErrorReportStatus(ErrorReportStatus__static_init#6).terminal
    //#input(void loadPlugin()): com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1).length
    //#input(void loadPlugin()): com/dmdirc/logger/ErrorFixedStatus.INVALID
    //#input(void loadPlugin()): com/dmdirc/logger/ErrorFixedStatus.KNOWN
    //#input(void loadPlugin()): com/dmdirc/logger/ErrorFixedStatus.UNKNOWN
    //#input(void loadPlugin()): com/dmdirc/logger/ErrorFixedStatus.UNREPORTED
    //#input(void loadPlugin()): com/dmdirc/logger/ErrorLevel.FATAL
    //#input(void loadPlugin()): com/dmdirc/logger/ErrorLevel.MEDIUM
    //#input(void loadPlugin()): com/dmdirc/logger/ErrorListener.__Descendant_Table[com/dmdirc/logger/ErrorListener]
    //#input(void loadPlugin()): com/dmdirc/logger/ErrorListener.__Descendant_Table[com/dmdirc/ui/FatalErrorDialog]
    //#input(void loadPlugin()): com/dmdirc/logger/ErrorListener.__Descendant_Table[others]
    //#input(void loadPlugin()): com/dmdirc/logger/ErrorListener.__Dispatch_Table.errorAdded(Lcom/dmdirc/logger/ProgramError;)V
    //#input(void loadPlugin()): com/dmdirc/logger/ErrorListener.__Dispatch_Table.errorStatusChanged(Lcom/dmdirc/logger/ProgramError;)V
    //#input(void loadPlugin()): com/dmdirc/logger/ErrorListener.__Dispatch_Table.isReady()Z
    //#input(void loadPlugin()): com/dmdirc/logger/ErrorManager.BANNED_EXCEPTIONS
    //#input(void loadPlugin()): com/dmdirc/logger/ErrorManager.java.lang.System.err
    //#input(void loadPlugin()): com/dmdirc/logger/ErrorManager.me
    //#input(void loadPlugin()): com/dmdirc/logger/ErrorReportStatus.ERROR
    //#input(void loadPlugin()): com/dmdirc/logger/ErrorReportStatus.NOT_APPLICABLE
    //#input(void loadPlugin()): com/dmdirc/logger/ErrorReportStatus.QUEUED
    //#input(void loadPlugin()): com/dmdirc/logger/ErrorReportStatus.WAITING
    //#input(void loadPlugin()): com/dmdirc/logger/Logger.manager
    //#input(void loadPlugin()): com/dmdirc/logger/ProgramError.__Descendant_Table[com/dmdirc/logger/ProgramError]
    //#input(void loadPlugin()): com/dmdirc/logger/ProgramError.__Descendant_Table[others]
    //#input(void loadPlugin()): com/dmdirc/logger/ProgramError.java.lang.System.err
    //#input(void loadPlugin()): com/dmdirc/logger/ProgramError.writingSem
    //#input(void loadPlugin()): com/dmdirc/plugins/Plugin.__Descendant_Table[com/dmdirc/plugins/Plugin]
    //#input(void loadPlugin()): com/dmdirc/plugins/Plugin.__Descendant_Table[others]
    //#input(void loadPlugin()): com/dmdirc/plugins/Plugin.__Dispatch_Table.onLoad()V
    //#input(void loadPlugin()): com/dmdirc/plugins/Plugin.__Dispatch_Table.onUnload()V
    //#input(void loadPlugin()): com/dmdirc/plugins/PluginClassLoader.__Descendant_Table[com/dmdirc/plugins/PluginClassLoader]
    //#input(void loadPlugin()): com/dmdirc/plugins/PluginClassLoader.__Descendant_Table[others]
    //#input(void loadPlugin()): com/dmdirc/plugins/PluginClassLoader.__Dispatch_Table.getSubClassLoader(Lcom/dmdirc/plugins/PluginInfo;)Lcom/dmdirc/plugins/PluginClassLoader;
    //#input(void loadPlugin()): com/dmdirc/plugins/PluginManager.__Descendant_Table[com/dmdirc/plugins/PluginManager]
    //#input(void loadPlugin()): com/dmdirc/plugins/PluginManager.__Descendant_Table[others]
    //#input(void loadPlugin()): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getPluginInfoByName(Ljava/lang/String;)Lcom/dmdirc/plugins/PluginInfo;
    //#input(void loadPlugin()): com/dmdirc/plugins/Service.__Descendant_Table[com/dmdirc/plugins/Service]
    //#input(void loadPlugin()): com/dmdirc/plugins/Service.__Descendant_Table[others]
    //#input(void loadPlugin()): com/dmdirc/plugins/Service.__Dispatch_Table.delProvider(Lcom/dmdirc/plugins/ServiceProvider;)V
    //#input(void loadPlugin()): com/dmdirc/ui/FatalErrorDialog$4.$SwitchMap$com$dmdirc$logger$ErrorReportStatus
    //#input(void loadPlugin()): com/dmdirc/ui/FatalErrorDialog.__Dispatch_Table.errorAdded(Lcom/dmdirc/logger/ProgramError;)V
    //#input(void loadPlugin()): com/dmdirc/ui/FatalErrorDialog.__Dispatch_Table.errorStatusChanged(Lcom/dmdirc/logger/ProgramError;)V
    //#input(void loadPlugin()): com/dmdirc/ui/FatalErrorDialog.__Dispatch_Table.isReady()Z
    //#input(void loadPlugin()): this
    //#input(void loadPlugin()): this.__Tag
    //#input(void loadPlugin()): this.children
    //#input(void loadPlugin()): this.isLoading
    //#input(void loadPlugin()): this.lastError._tainted
    //#input(void loadPlugin()): this.metaData
    //#input(void loadPlugin()): this.plugin
    //#input(void loadPlugin()): this.plugin.__Tag
    //#input(void loadPlugin()): this.provides
    //#input(void loadPlugin()): this.requirementsError
    //#input(void loadPlugin()): this.requirementsError._tainted
    //#input(void loadPlugin()): this.tempLoaded
    //#output(void loadPlugin()): com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread
    //#output(void loadPlugin()): com/dmdirc/logger/ProgramError.errorDir
    //#output(void loadPlugin()): com/dmdirc/plugins/GlobalClassLoader.me
    //#output(void loadPlugin()): java.lang.StringBuilder:toString(...)._tainted
    //#output(void loadPlugin()): new ErrorReportingThread(sendError#1) num objects
    //#output(void loadPlugin()): new ErrorReportingThread(sendError#1).__Tag
    //#output(void loadPlugin()): new ErrorReportingThread(sendError#1).queue
    //#output(void loadPlugin()): new File(getErrorFile#1) num objects
    //#output(void loadPlugin()): new GlobalClassLoader(getGlobalClassLoader#1) num objects
    //#output(void loadPlugin()): new GlobalClassLoader(getGlobalClassLoader#1).__Tag
    //#output(void loadPlugin()): new GlobalClassLoader(getGlobalClassLoader#1).resourcesList
    //#output(void loadPlugin()): new HashMap(GlobalClassLoader#1) num objects
    //#output(void loadPlugin()): new PluginClassLoader(getSubClassLoader#1) num objects
    //#output(void loadPlugin()): new PluginClassLoader(getSubClassLoader#1).__Tag
    //#output(void loadPlugin()): new PluginClassLoader(getSubClassLoader#1).pluginInfo
    //#output(void loadPlugin()): new PluginClassLoader(loadClass#1) num objects
    //#output(void loadPlugin()): new PluginClassLoader(loadClass#1).__Tag
    //#output(void loadPlugin()): new PluginClassLoader(loadClass#1).pluginInfo
    //#output(void loadPlugin()): this.classloader
    //#output(void loadPlugin()): this.isLoading
    //#output(void loadPlugin()): this.lastError
    //#output(void loadPlugin()): this.plugin
    //#output(void loadPlugin()): this.plugin.domainSet
    //#output(void loadPlugin()): this.plugin.myDomain
    //#output(void loadPlugin()): this.requirementsError
    //#output(void loadPlugin()): this.tempLoaded
    //#new obj(void loadPlugin()): java.lang.StringBuilder:toString(...)
    //#new obj(void loadPlugin()): new ErrorReportingThread(sendError#1)
    //#new obj(void loadPlugin()): new File(getErrorFile#1)
    //#new obj(void loadPlugin()): new GlobalClassLoader(getGlobalClassLoader#1)
    //#new obj(void loadPlugin()): new HashMap(GlobalClassLoader#1)
    //#new obj(void loadPlugin()): new PluginClassLoader(getSubClassLoader#1)
    //#new obj(void loadPlugin()): new PluginClassLoader(loadClass#1)
    //#pre[22] (void loadPlugin()): init'ed(this.plugin)
    //#pre[29] (void loadPlugin()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[33] (void loadPlugin()): this.exports != null
    //#pre[39] (void loadPlugin()): this.provides != null
    //#pre[18] (void loadPlugin()): (soft) init'ed(com/dmdirc/plugins/GlobalClassLoader.me)
    //#pre[20] (void loadPlugin()): (soft) init'ed(this.isLoading)
    //#pre[25] (void loadPlugin()): (soft) init'ed(this.requirementsError)
    //#pre[26] (void loadPlugin()): (soft) init'ed(this.tempLoaded)
    //#pre[30] (void loadPlugin()): (soft) this.children != null
    //#pre[37] (void loadPlugin()): (soft) this.metaData != null
    //#pre[38] (void loadPlugin()): (soft) this.plugin.__Tag == com/dmdirc/plugins/Plugin
    //#presumption(void loadPlugin()): (soft) init'ed(com.dmdirc.actions.CoreActionType.PLUGIN_LOADED)
    //#post(void loadPlugin()): com/dmdirc/logger/ProgramError.errorDir == One-of{old com/dmdirc/logger/ProgramError.errorDir, &new File(getErrorFile#1)}
    //#post(void loadPlugin()): com/dmdirc/plugins/GlobalClassLoader.me == old com/dmdirc/plugins/GlobalClassLoader.me
    //#post(void loadPlugin()): init'ed(java.lang.StringBuilder:toString(...)._tainted)
    //#post(void loadPlugin()): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(void loadPlugin()): this.classloader == One-of{old this.classloader, null}
    //#post(void loadPlugin()): init'ed(this.isLoading)
    //#post(void loadPlugin()): possibly_updated(this.lastError)
    //#post(void loadPlugin()): this.plugin == One-of{old this.plugin, null}
    //#post(void loadPlugin()): init'ed(this.plugin)
    //#post(void loadPlugin()): this.plugin.domainSet == old this.plugin.domainSet
    //#post(void loadPlugin()): this.plugin.myDomain == old this.plugin.myDomain
    //#post(void loadPlugin()): this.requirementsError == One-of{old this.requirementsError, &java.lang.StringBuilder:toString(...)}
    //#post(void loadPlugin()): init'ed(this.requirementsError)
    //#post(void loadPlugin()): init'ed(this.tempLoaded)
    //#post(void loadPlugin()): com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread == old com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread
    //#post(void loadPlugin()): possibly_updated(new ErrorReportingThread(sendError#1) num objects)
    //#post(void loadPlugin()): possibly_updated(new ErrorReportingThread(sendError#1).__Tag)
    //#post(void loadPlugin()): possibly_updated(new ErrorReportingThread(sendError#1).queue)
    //#post(void loadPlugin()): possibly_updated(new File(getErrorFile#1) num objects)
    //#post(void loadPlugin()): new GlobalClassLoader(getGlobalClassLoader#1) num objects == undefined
    //#post(void loadPlugin()): new GlobalClassLoader(getGlobalClassLoader#1) num objects == 0, if init'ed
    //#post(void loadPlugin()): new GlobalClassLoader(getGlobalClassLoader#1).__Tag == new GlobalClassLoader(getGlobalClassLoader#1) num objects
    //#post(void loadPlugin()): new HashMap(GlobalClassLoader#1) num objects == new GlobalClassLoader(getGlobalClassLoader#1) num objects
    //#post(void loadPlugin()): new PluginClassLoader(getSubClassLoader#1) num objects == new GlobalClassLoader(getGlobalClassLoader#1) num objects
    //#post(void loadPlugin()): new PluginClassLoader(loadClass#1) num objects == new GlobalClassLoader(getGlobalClassLoader#1) num objects
    //#post(void loadPlugin()): new GlobalClassLoader(getGlobalClassLoader#1).resourcesList == undefined
    //#post(void loadPlugin()): new GlobalClassLoader(getGlobalClassLoader#1).resourcesList == null
    //#post(void loadPlugin()): new PluginClassLoader(getSubClassLoader#1).pluginInfo == new GlobalClassLoader(getGlobalClassLoader#1).resourcesList
    //#post(void loadPlugin()): new PluginClassLoader(loadClass#1).pluginInfo == new GlobalClassLoader(getGlobalClassLoader#1).resourcesList
    //#post(void loadPlugin()): init'ed(new PluginClassLoader(getSubClassLoader#1) num objects)
    //#post(void loadPlugin()): new PluginClassLoader(getSubClassLoader#1).__Tag not init'ed, if init'ed
    //#post(void loadPlugin()): possibly_updated(new PluginClassLoader(getSubClassLoader#1).__Tag)
    //#post(void loadPlugin()): possibly_updated(new PluginClassLoader(getSubClassLoader#1).pluginInfo)
    //#post(void loadPlugin()): new PluginClassLoader(loadClass#1).__Tag not init'ed, if init'ed
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.String:isEmpty
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.List:remove
    //#unanalyzed(void loadPlugin()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(void loadPlugin()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.Map:get
    //#unanalyzed(void loadPlugin()): Effects-of-calling:com.dmdirc.util.ConfigFile:isFlatDomain
    //#unanalyzed(void loadPlugin()): Effects-of-calling:com.dmdirc.util.ConfigFile:getFlatDomain
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.String:split
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.String:toLowerCase
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.String:matches
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.io.File
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.io.File:exists
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.List:contains
    //#unanalyzed(void loadPlugin()): Effects-of-calling:getPluginManager
    //#unanalyzed(void loadPlugin()): Effects-of-calling:getErrorManager
    //#unanalyzed(void loadPlugin()): Effects-of-calling:addError
    //#unanalyzed(void loadPlugin()): Effects-of-calling:com.dmdirc.actions.ActionManager:processEvent
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.System:getProperty
    //#unanalyzed(void loadPlugin()): Effects-of-calling:checkPlugins
    //#unanalyzed(void loadPlugin()): Effects-of-calling:checkServices
    //#unanalyzed(void loadPlugin()): Effects-of-calling:getPluginInfoByName
    //#unanalyzed(void loadPlugin()): Effects-of-calling:com.dmdirc.updater.Version
    //#unanalyzed(void loadPlugin()): Effects-of-calling:com.dmdirc.updater.Version:compareTo
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.List:iterator
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.ClassLoader
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.String:equalsIgnoreCase
    //#unanalyzed(void loadPlugin()): Effects-of-calling:unloadPlugin
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.List:size
    //#unanalyzed(void loadPlugin()): Effects-of-calling:getServicesByType
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.List:get
    //#unanalyzed(void loadPlugin()): Effects-of-calling:isActive
    //#unanalyzed(void loadPlugin()): Effects-of-calling:getService
    //#unanalyzed(void loadPlugin()): Effects-of-calling:activate
    //#unanalyzed(void loadPlugin()): Effects-of-calling:delProvider
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.List:clear
    //#unanalyzed(void loadPlugin()): Effects-of-calling:isUnloadable
    //#unanalyzed(void loadPlugin()): Effects-of-calling:onUnload
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.Exception:getMessage
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.Exception:printStackTrace
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.concurrent.atomic.AtomicLong:getAndIncrement
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.Date
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.IllegalArgumentException
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.Arrays:copyOf
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.Date:clone
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.List:add
    //#unanalyzed(void loadPlugin()): Effects-of-calling:com.dmdirc.logger.ErrorReportStatus:equals
    //#unanalyzed(void loadPlugin()): Effects-of-calling:fireErrorStatusChanged
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.Object:notifyAll
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.concurrent.BlockingQueue:add
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.Thread:isAlive
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.Thread
    //#unanalyzed(void loadPlugin()): Effects-of-calling:com.dmdirc.logger.ErrorReportingThread:setDaemon
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.Thread:start
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.awt.GraphicsEnvironment:isHeadless
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.io.PrintStream:println
    //#unanalyzed(void loadPlugin()): Effects-of-calling:javax.swing.SwingUtilities:invokeLater
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.concurrent.Semaphore
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.concurrent.Semaphore:acquireUninterruptibly
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.Object:wait
    //#unanalyzed(void loadPlugin()): Effects-of-calling:com.dmdirc.util.ListenerList:get
    //#unanalyzed(void loadPlugin()): Effects-of-calling:isReady
    //#unanalyzed(void loadPlugin()): Effects-of-calling:errorAdded
    //#unanalyzed(void loadPlugin()): Effects-of-calling:com.dmdirc.logger.ErrorFixedStatus:equals
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.String:startsWith
    //#unanalyzed(void loadPlugin()): Effects-of-calling:com.dmdirc.Main:getConfigDir
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.io.File:mkdirs
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.Date:getTime
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.io.File:renameTo
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.io.File:createNewFile
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.io.FileOutputStream
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.concurrent.Semaphore:release
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.io.IOException:printStackTrace
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.io.OutputStream
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.io.PrintWriter
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.io.PrintWriter:println
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.io.PrintWriter:close
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.Throwable:getStackTrace
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.Throwable:toString
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.StackTraceElement:toString
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.Throwable:getCause
    //#unanalyzed(void loadPlugin()): Effects-of-calling:getTrace
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.Object:getClass
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.Object:equals
    //#unanalyzed(void loadPlugin()): Effects-of-calling:com.dmdirc.logger.ErrorReportStatus:ordinal
    //#unanalyzed(void loadPlugin()): Effects-of-calling:javax.swing.JButton:setText
    //#unanalyzed(void loadPlugin()): Effects-of-calling:javax.swing.JButton:setEnabled
    //#unanalyzed(void loadPlugin()): Effects-of-calling:equals
    //#unanalyzed(void loadPlugin()): Effects-of-calling:getReportStatus
    //#unanalyzed(void loadPlugin()): Effects-of-calling:errorStatusChanged
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.lang.String:equals
    //#unanalyzed(void loadPlugin()): Effects-of-calling:java.util.Arrays:equals
    //#test_vector(void loadPlugin()): !(this.plugin == null) & this.tempLoaded != 0: {0}, {1}
    //#test_vector(void loadPlugin()): !(this.plugin == null) & this.tempLoaded == 0: {0}, {1}
    //#test_vector(void loadPlugin()): (!(this.plugin == null) & this.tempLoaded == 0) | this.plugin == null: {0}, {1}
    //#test_vector(void loadPlugin()): this.isLoading: {0}, {1}
    //#test_vector(void loadPlugin()): this.tempLoaded: {1}, {0}
		if (!checkRequirements(isTempLoaded() || tempLoaded)) {
			lastError = "Unable to loadPlugin, all requirements not met. ("+requirementsError+")";
			return;
		}
		if (isTempLoaded()) {
			tempLoaded = false;
			loadRequired();
    //#PluginInfo.java:883: Warning: call too complex - analysis skipped
    //#    call on void loadRequired()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadPlugin()
    //#    unanalyzed callee: void loadRequired()
			
			try {
				plugin.onLoad();
    //#PluginInfo.java:886: Warning: method not available - call not analyzed
    //#    call on void onLoad()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadPlugin()
    //#    unanalyzed callee: void onLoad()
			} catch (Throwable e) {
				lastError = "Error in onLoad for "+getName()+":"+e.getMessage();
				Logger.userError(ErrorLevel.MEDIUM, lastError, e);
    //#PluginInfo.java:889: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadPlugin()
    //#    basic block: bb_10
    //#    assertion: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    callee file: Logger.java
    //#    callee precondition index: [2]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295]
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad  Soft
    //#PluginInfo.java:889: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadPlugin()
    //#    basic block: bb_10
    //#    assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [6]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Bad only invalid
    //#PluginInfo.java:889: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadPlugin()
    //#    basic block: bb_10
    //#    assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee file: Logger.java
    //#    callee precondition index: [7]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:889: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadPlugin()
    //#    basic block: bb_10
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [8]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Soft  Bad only invalid
    //#PluginInfo.java:889: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadPlugin()
    //#    basic block: bb_10
    //#    assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee file: Logger.java
    //#    callee precondition index: [9]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295]
    //#    Expected: {-2_147_483_648..4_294_967_295}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Soft  Bad only invalid
    //#PluginInfo.java:889: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadPlugin()
    //#    basic block: bb_10
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee file: Logger.java
    //#    callee precondition index: [16]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
    //#PluginInfo.java:889: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadPlugin()
    //#    basic block: bb_10
    //#    assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee file: Logger.java
    //#    callee precondition index: [17]
    //#    callee srcpos: 69
    //#    VN: com/dmdirc/logger/ProgramError.errorDir
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
				unloadPlugin();
			}
		} else {
			if (isLoaded() || metaData == null || isLoading) {
    //#PluginInfo.java:893: Warning: test always goes same way
    //#    Test predetermined because this.metaData != null
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadPlugin()
    //#    from bb: bb_12
    //#    live edge: bb_12-->bb_13
    //#    tested vn: this.metaData == null
    //#    tested vn values: {0}
				lastError = "Not Loading: ("+isLoaded()+"||"+(metaData == null)+"||"+isLoading+")";
				return;
			}
			isLoading = true;
			loadRequired();
    //#PluginInfo.java:898: Warning: call too complex - analysis skipped
    //#    call on void loadRequired()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadPlugin()
    //#    unanalyzed callee: void loadRequired()
			loadClass(getMainClass());
    //#PluginInfo.java:899: Warning: call too complex - analysis skipped
    //#    call on void loadClass(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadPlugin()
    //#    unanalyzed callee: void loadClass(String)
			if (isLoaded()) {
    //#PluginInfo.java:900: Warning: test always goes same way
    //#    Test predetermined because isLoaded(...) == 0
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadPlugin()
    //#    from bb: bb_18
    //#    live edge: bb_18-->bb_20
    //#    tested vn: __Temp_Initially_1
    //#    tested vn values: {0}
				ActionManager.processEvent(CoreActionType.PLUGIN_LOADED, null, this);
    //#PluginInfo.java:901: Warning: dead code
    //#    Dead code here because isLoaded(...) == 0
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadPlugin()
    //#    dead bb: bb_19
			}
			isLoading = false;
		}
	}
    //#PluginInfo.java:905: end of method: void com.dmdirc.plugins.PluginInfo.loadPlugin()

	/**
	 * Add the given Plugin as a child of this plugin.
	 *
	 * @param child Child to add
	 */
	public void addChild(final PluginInfo child) {
		children.add(child);
    //#PluginInfo.java:913: method: void com.dmdirc.plugins.PluginInfo.addChild(PluginInfo)
    //#input(void addChild(PluginInfo)): child
    //#input(void addChild(PluginInfo)): this
    //#input(void addChild(PluginInfo)): this.children
    //#pre[3] (void addChild(PluginInfo)): this.children != null
	}
    //#PluginInfo.java:914: end of method: void com.dmdirc.plugins.PluginInfo.addChild(PluginInfo)
	
	/**
	 * Remove the given Plugin as a child of this plugin.
	 *
	 * @param child Child to remove
	 */
	public void delChild(final PluginInfo child) {
		children.remove(child);
    //#PluginInfo.java:922: method: void com.dmdirc.plugins.PluginInfo.delChild(PluginInfo)
    //#input(void delChild(PluginInfo)): child
    //#input(void delChild(PluginInfo)): this
    //#input(void delChild(PluginInfo)): this.children
    //#pre[3] (void delChild(PluginInfo)): this.children != null
	}
    //#PluginInfo.java:923: end of method: void com.dmdirc.plugins.PluginInfo.delChild(PluginInfo)

	/**
	 * Load the given classname.
	 *
	 * @param classname Class to load
	 */
	private void loadClass(final String classname) {
		try {
			if (classloader == null) {
    //#PluginInfo.java:932: method: void com.dmdirc.plugins.PluginInfo.loadClass(String)
    //#input(void loadClass(String)): " - "._tainted
    //#input(void loadClass(String)): ""._tainted
    //#input(void loadClass(String)): "&#09;"._tainted
    //#input(void loadClass(String)): "&#10;Which caused: "._tainted
    //#input(void loadClass(String)): "' (wanted by "._tainted
    //#input(void loadClass(String)): "' -> '"._tainted
    //#input(void loadClass(String)): "' was not found"._tainted
    //#input(void loadClass(String)): "'"._tainted
    //#input(void loadClass(String)): "') "._tainted
    //#input(void loadClass(String)): "') - "._tainted
    //#input(void loadClass(String)): "') - Incompatible: "._tainted
    //#input(void loadClass(String)): "') - Unable to find class: "._tainted
    //#input(void loadClass(String)): ") -> "._tainted
    //#input(void loadClass(String)): ") does not exist."._tainted
    //#input(void loadClass(String)): "-"._tainted
    //#input(void loadClass(String)): "-resourcemanagerTimer"._tainted
    //#input(void loadClass(String)): ".class"._tainted
    //#input(void loadClass(String)): ".log"._tainted
    //#input(void loadClass(String)): ": "._tainted
    //#input(void loadClass(String)): ": Setting domain 'plugin-"._tainted
    //#input(void loadClass(String)): ":"._tainted
    //#input(void loadClass(String)): "A fatal error has occurred: "._tainted
    //#input(void loadClass(String)): "An error has occurred: "._tainted
    //#input(void loadClass(String)): "Class not found ('"._tainted
    //#input(void loadClass(String)): "Classloader says we are already loaded."._tainted
    //#input(void loadClass(String)): "Constructor missing ('"._tainted
    //#input(void loadClass(String)): "Could not load "._tainted
    //#input(void loadClass(String)): "Date:"._tainted
    //#input(void loadClass(String)): "Description: "._tainted
    //#input(void loadClass(String)): "Error in onLoad for "._tainted
    //#input(void loadClass(String)): "Error in onUnload for "._tainted
    //#input(void loadClass(String)): "Error loading '"._tainted
    //#input(void loadClass(String)): "ID must be a positive integer: "._tainted
    //#input(void loadClass(String)): "Level: "._tainted
    //#input(void loadClass(String)): "Prerequisites for plugin not met. ('"._tainted
    //#input(void loadClass(String)): "Required parent '"._tainted
    //#input(void loadClass(String)): "Resource '"._tainted
    //#input(void loadClass(String)): "Unable to access constructor ('"._tainted
    //#input(void loadClass(String)): "Unable to instantiate plugin ('"._tainted
    //#input(void loadClass(String)): "Unable to invoke target ('"._tainted
    //#input(void loadClass(String)): "errors"._tainted
    //#input(void loadClass(String)): "jar:.."._tainted
    //#input(void loadClass(String)): "plugin-"._tainted
    //#input(void loadClass(String)): "plugins"._tainted
    //#input(void loadClass(String)): LOGGER
    //#input(void loadClass(String)): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(void loadClass(String)): __Descendant_Table[others]
    //#input(void loadClass(String)): __Dispatch_Table.addChild(Lcom/dmdirc/plugins/PluginInfo;)V
    //#input(void loadClass(String)): __Dispatch_Table.delChild(Lcom/dmdirc/plugins/PluginInfo;)V
    //#input(void loadClass(String)): __Dispatch_Table.getClassList()Ljava/util/List;
    //#input(void loadClass(String)): __Dispatch_Table.getFullFilename()Ljava/lang/String;
    //#input(void loadClass(String)): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(void loadClass(String)): __Dispatch_Table.getMainClass()Ljava/lang/String;
    //#input(void loadClass(String)): __Dispatch_Table.getName()Ljava/lang/String;
    //#input(void loadClass(String)): __Dispatch_Table.getPersistentClasses()Ljava/util/List;
    //#input(void loadClass(String)): __Dispatch_Table.getPluginClassLoader()Lcom/dmdirc/plugins/PluginClassLoader;
    //#input(void loadClass(String)): __Dispatch_Table.getResourceManager()Lcom/dmdirc/util/resourcemanager/ResourceManager;
    //#input(void loadClass(String)): __Dispatch_Table.getResourceManager(Z)Lcom/dmdirc/util/resourcemanager/ResourceManager;
    //#input(void loadClass(String)): __Dispatch_Table.isLoaded()Z
    //#input(void loadClass(String)): __Dispatch_Table.isPersistent()Z
    //#input(void loadClass(String)): __Dispatch_Table.isPersistent(Ljava/lang/String;)Z
    //#input(void loadClass(String)): __Dispatch_Table.isTempLoaded()Z
    //#input(void loadClass(String)): __Dispatch_Table.isUnloadable()Z
    //#input(void loadClass(String)): __Dispatch_Table.unloadPlugin()V
    //#input(void loadClass(String)): classname
    //#input(void loadClass(String)): classname._tainted
    //#input(void loadClass(String)): com.dmdirc.actions.CoreActionType.PLUGIN_UNLOADED
    //#input(void loadClass(String)): com.dmdirc.logger.ErrorLevel__static_init.new ErrorLevel(ErrorLevel__static_init#3)._tainted
    //#input(void loadClass(String)): com.dmdirc.logger.ErrorLevel__static_init.new ErrorLevel(ErrorLevel__static_init#4)._tainted
    //#input(void loadClass(String)): com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2).length
    //#input(void loadClass(String)): com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).errorListeners
    //#input(void loadClass(String)): com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).errors
    //#input(void loadClass(String)): com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).errors.__Lock
    //#input(void loadClass(String)): com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportQueue
    //#input(void loadClass(String)): com.dmdirc.logger.ErrorReportStatus__static_init.new ErrorReportStatus(ErrorReportStatus__static_init#1).terminal
    //#input(void loadClass(String)): com.dmdirc.logger.ErrorReportStatus__static_init.new ErrorReportStatus(ErrorReportStatus__static_init#5).terminal
    //#input(void loadClass(String)): com.dmdirc.logger.ErrorReportStatus__static_init.new ErrorReportStatus(ErrorReportStatus__static_init#6).terminal
    //#input(void loadClass(String)): com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1).length
    //#input(void loadClass(String)): com/dmdirc/logger/ErrorFixedStatus.INVALID
    //#input(void loadClass(String)): com/dmdirc/logger/ErrorFixedStatus.KNOWN
    //#input(void loadClass(String)): com/dmdirc/logger/ErrorFixedStatus.UNKNOWN
    //#input(void loadClass(String)): com/dmdirc/logger/ErrorFixedStatus.UNREPORTED
    //#input(void loadClass(String)): com/dmdirc/logger/ErrorLevel.FATAL
    //#input(void loadClass(String)): com/dmdirc/logger/ErrorLevel.LOW
    //#input(void loadClass(String)): com/dmdirc/logger/ErrorLevel.MEDIUM
    //#input(void loadClass(String)): com/dmdirc/logger/ErrorListener.__Descendant_Table[com/dmdirc/logger/ErrorListener]
    //#input(void loadClass(String)): com/dmdirc/logger/ErrorListener.__Descendant_Table[com/dmdirc/ui/FatalErrorDialog]
    //#input(void loadClass(String)): com/dmdirc/logger/ErrorListener.__Descendant_Table[others]
    //#input(void loadClass(String)): com/dmdirc/logger/ErrorListener.__Dispatch_Table.errorAdded(Lcom/dmdirc/logger/ProgramError;)V
    //#input(void loadClass(String)): com/dmdirc/logger/ErrorListener.__Dispatch_Table.errorStatusChanged(Lcom/dmdirc/logger/ProgramError;)V
    //#input(void loadClass(String)): com/dmdirc/logger/ErrorListener.__Dispatch_Table.isReady()Z
    //#input(void loadClass(String)): com/dmdirc/logger/ErrorManager.BANNED_EXCEPTIONS
    //#input(void loadClass(String)): com/dmdirc/logger/ErrorManager.java.lang.System.err
    //#input(void loadClass(String)): com/dmdirc/logger/ErrorManager.me
    //#input(void loadClass(String)): com/dmdirc/logger/ErrorReportStatus.ERROR
    //#input(void loadClass(String)): com/dmdirc/logger/ErrorReportStatus.NOT_APPLICABLE
    //#input(void loadClass(String)): com/dmdirc/logger/ErrorReportStatus.QUEUED
    //#input(void loadClass(String)): com/dmdirc/logger/ErrorReportStatus.WAITING
    //#input(void loadClass(String)): com/dmdirc/logger/Logger.manager
    //#input(void loadClass(String)): com/dmdirc/logger/ProgramError.__Descendant_Table[com/dmdirc/logger/ProgramError]
    //#input(void loadClass(String)): com/dmdirc/logger/ProgramError.__Descendant_Table[others]
    //#input(void loadClass(String)): com/dmdirc/logger/ProgramError.java.lang.System.err
    //#input(void loadClass(String)): com/dmdirc/logger/ProgramError.writingSem
    //#input(void loadClass(String)): com/dmdirc/plugins/GlobalClassLoader.__Class_Obj.__Lock
    //#input(void loadClass(String)): com/dmdirc/plugins/GlobalClassLoader.me
    //#input(void loadClass(String)): com/dmdirc/plugins/Plugin.__Descendant_Table[com/dmdirc/plugins/Plugin]
    //#input(void loadClass(String)): com/dmdirc/plugins/Plugin.__Descendant_Table[others]
    //#input(void loadClass(String)): com/dmdirc/plugins/Plugin.__Dispatch_Table.checkPrerequisites()Lcom/dmdirc/config/prefs/validator/ValidationResponse;
    //#input(void loadClass(String)): com/dmdirc/plugins/Plugin.__Dispatch_Table.domainUpdated()V
    //#input(void loadClass(String)): com/dmdirc/plugins/Plugin.__Dispatch_Table.onLoad()V
    //#input(void loadClass(String)): com/dmdirc/plugins/Plugin.__Dispatch_Table.onUnload()V
    //#input(void loadClass(String)): com/dmdirc/plugins/Plugin.__Dispatch_Table.setDomain(Ljava/lang/String;)V
    //#input(void loadClass(String)): com/dmdirc/plugins/PluginClassLoader.__Descendant_Table[com/dmdirc/plugins/PluginClassLoader]
    //#input(void loadClass(String)): com/dmdirc/plugins/PluginClassLoader.__Descendant_Table[others]
    //#input(void loadClass(String)): com/dmdirc/plugins/PluginClassLoader.__Dispatch_Table.getSubClassLoader(Lcom/dmdirc/plugins/PluginInfo;)Lcom/dmdirc/plugins/PluginClassLoader;
    //#input(void loadClass(String)): com/dmdirc/plugins/PluginClassLoader.__Dispatch_Table.isClassLoaded(Ljava/lang/String;Z)Z
    //#input(void loadClass(String)): com/dmdirc/plugins/PluginClassLoader.__Dispatch_Table.loadClass(Ljava/lang/String;)Ljava/lang/Class;
    //#input(void loadClass(String)): com/dmdirc/plugins/PluginClassLoader.__Dispatch_Table.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;
    //#input(void loadClass(String)): com/dmdirc/plugins/PluginManager.__Class_Obj.__Lock
    //#input(void loadClass(String)): com/dmdirc/plugins/PluginManager.__Descendant_Table[com/dmdirc/plugins/PluginManager]
    //#input(void loadClass(String)): com/dmdirc/plugins/PluginManager.__Descendant_Table[others]
    //#input(void loadClass(String)): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getPluginInfoByName(Ljava/lang/String;)Lcom/dmdirc/plugins/PluginInfo;
    //#input(void loadClass(String)): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getPluginInfos()Ljava/util/Collection;
    //#input(void loadClass(String)): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getPossiblePluginInfos(Z)Ljava/util/List;
    //#input(void loadClass(String)): com/dmdirc/plugins/PluginManager.com.dmdirc.actions.CoreActionType.CLIENT_PREFS_CLOSED
    //#input(void loadClass(String)): com/dmdirc/plugins/PluginManager.com.dmdirc.actions.CoreActionType.CLIENT_PREFS_OPENED
    //#input(void loadClass(String)): com/dmdirc/plugins/PluginManager.me.__Tag
    //#input(void loadClass(String)): com/dmdirc/plugins/PluginManager.me.knownPlugins
    //#input(void loadClass(String)): com/dmdirc/plugins/Service.__Descendant_Table[com/dmdirc/plugins/Service]
    //#input(void loadClass(String)): com/dmdirc/plugins/Service.__Descendant_Table[others]
    //#input(void loadClass(String)): com/dmdirc/plugins/Service.__Dispatch_Table.delProvider(Lcom/dmdirc/plugins/ServiceProvider;)V
    //#input(void loadClass(String)): com/dmdirc/ui/FatalErrorDialog$4.$SwitchMap$com$dmdirc$logger$ErrorReportStatus
    //#input(void loadClass(String)): com/dmdirc/ui/FatalErrorDialog.__Dispatch_Table.errorAdded(Lcom/dmdirc/logger/ProgramError;)V
    //#input(void loadClass(String)): com/dmdirc/ui/FatalErrorDialog.__Dispatch_Table.errorStatusChanged(Lcom/dmdirc/logger/ProgramError;)V
    //#input(void loadClass(String)): com/dmdirc/ui/FatalErrorDialog.__Dispatch_Table.isReady()Z
    //#input(void loadClass(String)): this
    //#input(void loadClass(String)): this...__Tag
    //#input(void loadClass(String)): this...filename
    //#input(void loadClass(String)): this...filename._tainted
    //#input(void loadClass(String)): this...url
    //#input(void loadClass(String)): this.__Tag
    //#input(void loadClass(String)): this.children
    //#input(void loadClass(String)): this.classloader
    //#input(void loadClass(String)): this.classloader.__Tag
    //#input(void loadClass(String)): this.classloader.pluginInfo
    //#input(void loadClass(String)): this.filename
    //#input(void loadClass(String)): this.filename._tainted
    //#input(void loadClass(String)): this.lastError._tainted
    //#input(void loadClass(String)): this.metaData
    //#input(void loadClass(String)): this.plugin.__Tag
    //#input(void loadClass(String)): this.provides
    //#input(void loadClass(String)): this.tempLoaded
    //#input(void loadClass(String)): this.url
    //#output(void loadClass(String)): com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread
    //#output(void loadClass(String)): com/dmdirc/logger/ProgramError.errorDir
    //#output(void loadClass(String)): com/dmdirc/plugins/GlobalClassLoader.me
    //#output(void loadClass(String)): com/dmdirc/plugins/PluginManager.me
    //#output(void loadClass(String)): java.lang.StringBuilder:toString(...)._tainted
    //#output(void loadClass(String)): new ErrorReportingThread(sendError#1) num objects
    //#output(void loadClass(String)): new ErrorReportingThread(sendError#1).__Tag
    //#output(void loadClass(String)): new ErrorReportingThread(sendError#1).queue
    //#output(void loadClass(String)): new File(getErrorFile#1) num objects
    //#output(void loadClass(String)): new GlobalClassLoader(getGlobalClassLoader#1) num objects
    //#output(void loadClass(String)): new GlobalClassLoader(getGlobalClassLoader#1).__Tag
    //#output(void loadClass(String)): new GlobalClassLoader(getGlobalClassLoader#1).resourcesList
    //#output(void loadClass(String)): new HashMap(GlobalClassLoader#1) num objects
    //#output(void loadClass(String)): new HashMap(PluginManager#2) num objects
    //#output(void loadClass(String)): new Hashtable(PluginManager#1) num objects
    //#output(void loadClass(String)): new PluginClassLoader(getSubClassLoader#1) num objects
    //#output(void loadClass(String)): new PluginClassLoader(getSubClassLoader#1).__Tag
    //#output(void loadClass(String)): new PluginClassLoader(getSubClassLoader#1).pluginInfo
    //#output(void loadClass(String)): new PluginClassLoader(loadClass#1) num objects
    //#output(void loadClass(String)): new PluginClassLoader(loadClass#1).__Tag
    //#output(void loadClass(String)): new PluginClassLoader(loadClass#1).pluginInfo
    //#output(void loadClass(String)): new PluginManager(getPluginManager#1) num objects
    //#output(void loadClass(String)): new PluginManager(getPluginManager#1).__Tag
    //#output(void loadClass(String)): new PluginManager(getPluginManager#1).knownPlugins
    //#output(void loadClass(String)): new PluginManager(getPluginManager#1).myDir
    //#output(void loadClass(String)): new PluginManager(getPluginManager#1).services
    //#output(void loadClass(String)): this...myResourceManager
    //#output(void loadClass(String)): this.classloader
    //#output(void loadClass(String)): this.lastError
    //#output(void loadClass(String)): this.myResourceManager
    //#output(void loadClass(String)): this.plugin
    //#output(void loadClass(String)): this.plugin.domainSet
    //#output(void loadClass(String)): this.plugin.myDomain
    //#output(void loadClass(String)): this.tempLoaded
    //#new obj(void loadClass(String)): java.lang.StringBuilder:toString(...)
    //#new obj(void loadClass(String)): new ErrorReportingThread(sendError#1)
    //#new obj(void loadClass(String)): new File(getErrorFile#1)
    //#new obj(void loadClass(String)): new GlobalClassLoader(getGlobalClassLoader#1)
    //#new obj(void loadClass(String)): new HashMap(GlobalClassLoader#1)
    //#new obj(void loadClass(String)): new HashMap(PluginManager#2)
    //#new obj(void loadClass(String)): new Hashtable(PluginManager#1)
    //#new obj(void loadClass(String)): new PluginClassLoader(getSubClassLoader#1)
    //#new obj(void loadClass(String)): new PluginClassLoader(loadClass#1)
    //#new obj(void loadClass(String)): new PluginManager(getPluginManager#1)
    //#pre[1] (void loadClass(String)): (soft) classname != null
    //#pre[16] (void loadClass(String)): (soft) init'ed(com/dmdirc/plugins/GlobalClassLoader.me)
    //#pre[19] (void loadClass(String)): (soft) init'ed(this.classloader)
    //#pre[25] (void loadClass(String)): (soft) init'ed(this.tempLoaded)
    //#pre[28] (void loadClass(String)): (soft) this...__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[34] (void loadClass(String)): (soft) this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[35] (void loadClass(String)): (soft) this.children != null
    //#pre[36] (void loadClass(String)): (soft) this.classloader.__Tag == com/dmdirc/plugins/PluginClassLoader
    //#pre[37] (void loadClass(String)): (soft) this.classloader.pluginInfo != null
    //#pre[40] (void loadClass(String)): (soft) init'ed(this.metaData)
    //#pre[41] (void loadClass(String)): (soft) this.provides != null
    //#presumption(void loadClass(String)): java.util.logging.Logger:getLogger(...)@52 != null
    //#post(void loadClass(String)): possibly_updated(com/dmdirc/logger/ProgramError.errorDir)
    //#post(void loadClass(String)): init'ed(com/dmdirc/plugins/GlobalClassLoader.me)
    //#post(void loadClass(String)): possibly_updated(com/dmdirc/plugins/PluginManager.me)
    //#post(void loadClass(String)): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(void loadClass(String)): init'ed(java.lang.StringBuilder:toString(...)._tainted)
    //#post(void loadClass(String)): possibly_updated(java.lang.StringBuilder:toString(...)._tainted)
    //#post(void loadClass(String)): possibly_updated(this...myResourceManager)
    //#post(void loadClass(String)): possibly_updated(this.classloader)
    //#post(void loadClass(String)): possibly_updated(this.lastError)
    //#post(void loadClass(String)): possibly_updated(this.myResourceManager)
    //#post(void loadClass(String)): possibly_updated(this.plugin)
    //#post(void loadClass(String)): init'ed(this.plugin.domainSet)
    //#post(void loadClass(String)): init'ed(this.plugin.myDomain)
    //#post(void loadClass(String)): init'ed(this.tempLoaded)
    //#post(void loadClass(String)): possibly_updated(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#post(void loadClass(String)): possibly_updated(new ErrorReportingThread(sendError#1) num objects)
    //#post(void loadClass(String)): possibly_updated(new ErrorReportingThread(sendError#1).__Tag)
    //#post(void loadClass(String)): possibly_updated(new ErrorReportingThread(sendError#1).queue)
    //#post(void loadClass(String)): possibly_updated(new File(getErrorFile#1) num objects)
    //#post(void loadClass(String)): new GlobalClassLoader(getGlobalClassLoader#1) num objects <= 1
    //#post(void loadClass(String)): new GlobalClassLoader(getGlobalClassLoader#1) num objects == 0
    //#post(void loadClass(String)): init'ed(new GlobalClassLoader(getGlobalClassLoader#1).__Tag)
    //#post(void loadClass(String)): init'ed(new GlobalClassLoader(getGlobalClassLoader#1).resourcesList)
    //#post(void loadClass(String)): new HashMap(GlobalClassLoader#1) num objects <= 1
    //#post(void loadClass(String)): new HashMap(GlobalClassLoader#1) num objects == 0
    //#post(void loadClass(String)): possibly_updated(new HashMap(PluginManager#2) num objects)
    //#post(void loadClass(String)): possibly_updated(new Hashtable(PluginManager#1) num objects)
    //#post(void loadClass(String)): possibly_updated(new PluginClassLoader(getSubClassLoader#1) num objects)
    //#post(void loadClass(String)): init'ed(new PluginClassLoader(getSubClassLoader#1) num objects)
    //#post(void loadClass(String)): possibly_updated(new PluginClassLoader(getSubClassLoader#1).__Tag)
    //#post(void loadClass(String)): possibly_updated(new PluginClassLoader(getSubClassLoader#1).pluginInfo)
    //#post(void loadClass(String)): possibly_updated(new PluginClassLoader(loadClass#1) num objects)
    //#post(void loadClass(String)): possibly_updated(new PluginClassLoader(loadClass#1).__Tag)
    //#post(void loadClass(String)): possibly_updated(new PluginClassLoader(loadClass#1).pluginInfo)
    //#post(void loadClass(String)): possibly_updated(new PluginManager(getPluginManager#1) num objects)
    //#post(void loadClass(String)): possibly_updated(new PluginManager(getPluginManager#1).__Tag)
    //#post(void loadClass(String)): possibly_updated(new PluginManager(getPluginManager#1).knownPlugins)
    //#post(void loadClass(String)): possibly_updated(new PluginManager(getPluginManager#1).myDir)
    //#post(void loadClass(String)): possibly_updated(new PluginManager(getPluginManager#1).services)
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.String:isEmpty
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.net.URL:getPath
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.List:remove
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.Map:get
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.util.ConfigFile:isFlatDomain
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.util.ConfigFile:getFlatDomain
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.List:add
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.String:matches
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.List:contains
    //#unanalyzed(void loadClass(String)): Effects-of-calling:getPluginManager
    //#unanalyzed(void loadClass(String)): Effects-of-calling:getFullFilename
    //#unanalyzed(void loadClass(String)): Effects-of-calling:getName
    //#unanalyzed(void loadClass(String)): Effects-of-calling:getErrorManager
    //#unanalyzed(void loadClass(String)): Effects-of-calling:addError
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.actions.ActionManager:processEvent
    //#unanalyzed(void loadClass(String)): Effects-of-calling:getPluginInfoByName
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:getResourceManager
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.Timer
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.TimerTask
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.Timer:schedule
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(void loadClass(String)): Effects-of-calling:getResourceManager
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:getResourcesStartingWith
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.List:iterator
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.String:replaceAll
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.String:replace
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.ClassLoader
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.plugins.PluginClassLoader:findLoadedClass
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.HashMap
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.plugins.GlobalClassLoader:findLoadedClass
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.plugins.PluginClassLoader:getParent
    //#unanalyzed(void loadClass(String)): Effects-of-calling:loadClass
    //#unanalyzed(void loadClass(String)): Effects-of-calling:isPersistent
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:resourceExists
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:getResourceBytes
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.plugins.GlobalClassLoader:defineClass
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.ClassLoader:loadClass
    //#unanalyzed(void loadClass(String)): Effects-of-calling:getPluginInfos
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.Collection:iterator
    //#unanalyzed(void loadClass(String)): Effects-of-calling:getClassList
    //#unanalyzed(void loadClass(String)): Effects-of-calling:getPluginClassLoader
    //#unanalyzed(void loadClass(String)): Effects-of-calling:getPersistentClasses
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.Map:put
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.NoClassDefFoundError:getMessage
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.ClassNotFoundException
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.plugins.PluginClassLoader:defineClass
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.plugins.PluginClassLoader:resolveClass
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.config.prefs.validator.ValidationResponse
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.String:equalsIgnoreCase
    //#unanalyzed(void loadClass(String)): Effects-of-calling:unloadPlugin
    //#unanalyzed(void loadClass(String)): Effects-of-calling:delProvider
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.List:clear
    //#unanalyzed(void loadClass(String)): Effects-of-calling:isUnloadable
    //#unanalyzed(void loadClass(String)): Effects-of-calling:onUnload
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.Exception:getMessage
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.Exception:printStackTrace
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.Exception
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.plugins.PluginInfo
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.Hashtable
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.System:getProperty
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.Main:getConfigDir
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.actions.ActionManager:addListener
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.Map:values
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.String:toLowerCase
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.LinkedList
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.io.File
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.LinkedList:add
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.LinkedList:isEmpty
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.LinkedList:pop
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.io.File:isDirectory
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.io.File:listFiles
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.io.File:isFile
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.io.File:getName
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.String:endsWith
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.io.File:getPath
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.String:length
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.String:substring
    //#unanalyzed(void loadClass(String)): Effects-of-calling:addPlugin
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.net.URL
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.net.MalformedURLException:getMessage
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.io.File:exists
    //#unanalyzed(void loadClass(String)): Effects-of-calling:delPlugin
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.updater.components.PluginComponent
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.plugins.PluginException:getMessage
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.Map:remove
    //#unanalyzed(void loadClass(String)): Effects-of-calling:getPossiblePluginInfos
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.concurrent.atomic.AtomicLong:getAndIncrement
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.Date
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.IllegalArgumentException
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.Arrays:copyOf
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.Date:clone
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.logger.ErrorReportStatus:equals
    //#unanalyzed(void loadClass(String)): Effects-of-calling:fireErrorStatusChanged
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.Object:notifyAll
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.concurrent.BlockingQueue:add
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.Thread:isAlive
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.Thread
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.logger.ErrorReportingThread:setDaemon
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.Thread:start
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.awt.GraphicsEnvironment:isHeadless
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.io.PrintStream:println
    //#unanalyzed(void loadClass(String)): Effects-of-calling:javax.swing.SwingUtilities:invokeLater
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.concurrent.Semaphore
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.concurrent.Semaphore:acquireUninterruptibly
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.Object:wait
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.util.ListenerList:get
    //#unanalyzed(void loadClass(String)): Effects-of-calling:isReady
    //#unanalyzed(void loadClass(String)): Effects-of-calling:errorAdded
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.logger.ErrorFixedStatus:equals
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.String:startsWith
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.io.File:mkdirs
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.Date:getTime
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.io.File:renameTo
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.io.File:createNewFile
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.io.FileOutputStream
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.concurrent.Semaphore:release
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.io.IOException:printStackTrace
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.io.OutputStream
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.io.PrintWriter
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.io.PrintWriter:println
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.io.PrintWriter:close
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.Throwable:getStackTrace
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.Throwable:toString
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.StackTraceElement:toString
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.Throwable:getCause
    //#unanalyzed(void loadClass(String)): Effects-of-calling:getTrace
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.Object:getClass
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.Object:equals
    //#unanalyzed(void loadClass(String)): Effects-of-calling:com.dmdirc.logger.ErrorReportStatus:ordinal
    //#unanalyzed(void loadClass(String)): Effects-of-calling:javax.swing.JButton:setText
    //#unanalyzed(void loadClass(String)): Effects-of-calling:javax.swing.JButton:setEnabled
    //#unanalyzed(void loadClass(String)): Effects-of-calling:equals
    //#unanalyzed(void loadClass(String)): Effects-of-calling:getReportStatus
    //#unanalyzed(void loadClass(String)): Effects-of-calling:errorStatusChanged
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.lang.String:equals
    //#unanalyzed(void loadClass(String)): Effects-of-calling:java.util.Arrays:equals
    //#test_vector(void loadClass(String)): this.classloader: Inverse{null}, Addr_Set{null}
    //#test_vector(void loadClass(String)): com.dmdirc.config.prefs.validator.ValidationResponse:isFailure(...)@964: {1}, {0}
    //#test_vector(void loadClass(String)): java.lang.String:equals(...)@959: {0}, {1}
    //#test_vector(void loadClass(String)): java.lang.String:isEmpty(...)@933: {0}, {1}
				if (getKeyValue("requires", "parent", "").isEmpty()) {
    //#PluginInfo.java:933: ?null dereference
    //#    getKeyValue(...) != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_3
    //#    assertion: getKeyValue(...) != null
    //#    VN: getKeyValue(...)
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
					classloader = new PluginClassLoader(this);
				} else {
					final String parentName = getKeyValue("requires", "parent", "");
					final PluginInfo pi = PluginManager.getPluginManager().getPluginInfoByName(parentName);
    //#PluginInfo.java:937: ?precondition failure
    //#    com/dmdirc/plugins/PluginManager.getPluginManager: init'ed(me)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_5
    //#    assertion: init'ed(com/dmdirc/plugins/PluginManager.me)
    //#    callee: PluginManager com/dmdirc/plugins/PluginManager.getPluginManager()
    //#    callee assertion: init'ed(me)
    //#    callee file: PluginManager.java
    //#    callee precondition index: [1]
    //#    callee srcpos: 233
    //#    VN: com/dmdirc/plugins/PluginManager.me
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
    //#PluginInfo.java:937: ?null dereference
    //#    com/dmdirc/plugins/PluginManager.__Descendant_Table[getPluginManager(...).__Tag] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_5
    //#    assertion: com/dmdirc/plugins/PluginManager.__Descendant_Table[getPluginManager(...).__Tag] != null
    //#    VN: com/dmdirc/plugins/PluginManager.__Descendant_Table[getPluginManager(...).__Tag]
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:937: ?precondition failure
    //#    com/dmdirc/plugins/PluginManager.getPluginInfoByName: this.knownPlugins != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_5
    //#    assertion: getPluginManager(...).knownPlugins != null
    //#    callee: PluginInfo com/dmdirc/plugins/PluginManager.getPluginInfoByName(String)
    //#    callee assertion: this.knownPlugins != null
    //#    callee file: PluginManager.java
    //#    callee precondition index: [4]
    //#    callee srcpos: 358
    //#    VN: getPluginManager(...).knownPlugins
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad  Uncertain
					if (pi == null) {
						lastError = "Required parent '"+parentName+"' was not found";
						return;
					} else {
						pi.addChild(this);
    //#PluginInfo.java:942: ?use of default init
    //#    init'ed(pi.__Tag)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_8
    //#    assertion: init'ed(pi.__Tag)
    //#    VN: pi.__Tag
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#PluginInfo.java:942: ?null dereference
    //#    __Descendant_Table[pi.__Tag] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_8
    //#    assertion: __Descendant_Table[pi.__Tag] != null
    //#    VN: __Descendant_Table[pi.__Tag]
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:942: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.addChild: this.children != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_8
    //#    assertion: pi.children@937 != null
    //#    callee: void com/dmdirc/plugins/PluginInfo.addChild(PluginInfo)
    //#    callee assertion: this.children != null
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [3]
    //#    callee srcpos: 913
    //#    VN: pi.children@937
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad  Uncertain
						classloader = pi.getPluginClassLoader().getSubClassLoader(this);
    //#PluginInfo.java:943: ?null dereference
    //#    getPluginClassLoader(...) != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_8
    //#    assertion: getPluginClassLoader(...) != null
    //#    VN: pi.classloader@942
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad  Uncertain
    //#PluginInfo.java:943: ?null dereference
    //#    com/dmdirc/plugins/PluginClassLoader.__Descendant_Table[getPluginClassLoader(...).__Tag] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_8
    //#    assertion: com/dmdirc/plugins/PluginClassLoader.__Descendant_Table[getPluginClassLoader(...).__Tag] != null
    //#    VN: com/dmdirc/plugins/PluginClassLoader.__Descendant_Table[getPluginClassLoader(...).__Tag]
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
					}
				}
			}

			// Don't reload a class if its already loaded.
			if (classloader.isClassLoaded(classname, true)) {
				lastError = "Classloader says we are already loaded.";
				return;
			}

			final Class<?> c = classloader.loadClass(classname);
    //#PluginInfo.java:954: ?precondition failure
    //#    com/dmdirc/plugins/PluginClassLoader.loadClass: (soft) com/dmdirc/plugins/GlobalClassLoader.me.resourcesList != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_12
    //#    assertion: (soft) com/dmdirc/plugins/GlobalClassLoader.me.resourcesList@949 != null
    //#    callee: Class com/dmdirc/plugins/PluginClassLoader.loadClass(String)
    //#    callee assertion: (soft) com/dmdirc/plugins/GlobalClassLoader.me.resourcesList != null
    //#    callee file: PluginClassLoader.java
    //#    callee precondition index: [1]
    //#    callee srcpos: 73
    //#    VN: com/dmdirc/plugins/GlobalClassLoader.me.resourcesList@949
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad  Soft  Uncertain
    //#PluginInfo.java:954: ?precondition failure
    //#    com/dmdirc/plugins/PluginClassLoader.loadClass: (soft) init'ed(this.pluginInfo.myResourceManager)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_12
    //#    assertion: (soft) init'ed(this.classloader.pluginInfo.myResourceManager)
    //#    callee: Class com/dmdirc/plugins/PluginClassLoader.loadClass(String)
    //#    callee assertion: (soft) init'ed(this.pluginInfo.myResourceManager)
    //#    callee file: PluginClassLoader.java
    //#    callee precondition index: [5]
    //#    callee srcpos: 73
    //#    VN: this.classloader.pluginInfo.myResourceManager
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
    //#PluginInfo.java:954: ?precondition failure
    //#    com/dmdirc/plugins/PluginClassLoader.loadClass: (soft) init'ed(this.pluginInfo.metaData)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_12
    //#    assertion: (soft) init'ed(this.classloader.pluginInfo.metaData)
    //#    callee: Class com/dmdirc/plugins/PluginClassLoader.loadClass(String)
    //#    callee assertion: (soft) init'ed(this.pluginInfo.metaData)
    //#    callee file: PluginClassLoader.java
    //#    callee precondition index: [13]
    //#    callee srcpos: 73
    //#    VN: this.classloader.pluginInfo.metaData
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
    //#PluginInfo.java:954: ?precondition failure
    //#    com/dmdirc/plugins/PluginClassLoader.loadClass: (soft) this.pluginInfo.url != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_12
    //#    assertion: (soft) this.classloader.pluginInfo.url != null
    //#    callee: Class com/dmdirc/plugins/PluginClassLoader.loadClass(String)
    //#    callee assertion: (soft) this.pluginInfo.url != null
    //#    callee file: PluginClassLoader.java
    //#    callee precondition index: [14]
    //#    callee srcpos: 73
    //#    VN: this.classloader.pluginInfo.url
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad  Soft
			final Constructor<?> constructor = c.getConstructor(new Class[] {});
    //#PluginInfo.java:955: ?null dereference
    //#    c != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_12
    //#    assertion: c != null
    //#    VN: loadClass(...)
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
			
			// Only try and construct the main class, anything else should be constructed
			// by the plugin itself.
			if (classname.equals(getMainClass())) {
				final Object temp = constructor.newInstance(new Object[] {});
    //#PluginInfo.java:960: ?null dereference
    //#    constructor != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_13
    //#    assertion: constructor != null
    //#    VN: java.lang.Class:getConstructor(...)@955
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad  Uncertain
	
				if (temp instanceof Plugin) {
					final ValidationResponse prerequisites = ((Plugin) temp).checkPrerequisites();
					if (!prerequisites.isFailure()) {
    //#PluginInfo.java:964: Warning: method not available - call not analyzed
    //#    call on bool com.dmdirc.config.prefs.validator.ValidationResponse:isFailure()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    unanalyzed callee: bool com.dmdirc.config.prefs.validator.ValidationResponse:isFailure()
						plugin = (Plugin) temp;
                        LOGGER.finer(getName() + ": Setting domain 'plugin-" + getName() + "'");
						plugin.setDomain("plugin-"+getName());
    //#PluginInfo.java:967: ?null dereference
    //#    com/dmdirc/plugins/Plugin.__Descendant_Table[this.plugin.__Tag] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_32
    //#    assertion: com/dmdirc/plugins/Plugin.__Descendant_Table[this.plugin.__Tag] != null
    //#    VN: com/dmdirc/plugins/Plugin.__Descendant_Table[this.plugin.__Tag]
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
						if (!tempLoaded) {
							try {
								plugin.onLoad();
    //#PluginInfo.java:970: Warning: method not available - call not analyzed
    //#    call on void onLoad()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    unanalyzed callee: void onLoad()
							} catch (Throwable e) {
								lastError = "Error in onLoad for "+getName()+":"+e.getMessage();
								Logger.userError(ErrorLevel.MEDIUM, lastError, e);
    //#PluginInfo.java:973: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_18
    //#    assertion: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    callee file: Logger.java
    //#    callee precondition index: [2]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295]
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad  Soft
    //#PluginInfo.java:973: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_18
    //#    assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [6]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Bad only invalid
    //#PluginInfo.java:973: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_18
    //#    assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee file: Logger.java
    //#    callee precondition index: [7]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:973: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_18
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [8]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Soft  Bad only invalid
    //#PluginInfo.java:973: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_18
    //#    assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee file: Logger.java
    //#    callee precondition index: [9]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295]
    //#    Expected: {-2_147_483_648..4_294_967_295}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Soft  Bad only invalid
    //#PluginInfo.java:973: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_18
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee file: Logger.java
    //#    callee precondition index: [16]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
    //#PluginInfo.java:973: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_18
    //#    assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee file: Logger.java
    //#    callee precondition index: [17]
    //#    callee srcpos: 69
    //#    VN: com/dmdirc/logger/ProgramError.errorDir
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
								unloadPlugin();
    //#PluginInfo.java:974: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.unloadPlugin: (soft) this.plugin.__Tag == com/dmdirc/plugins/Plugin
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_18
    //#    assertion: (soft) this.plugin.__Tag@972 == com/dmdirc/plugins/Plugin
    //#    callee: void com/dmdirc/plugins/PluginInfo.unloadPlugin()
    //#    callee assertion: (soft) this.plugin.__Tag == com/dmdirc/plugins/Plugin
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [13]
    //#    callee srcpos: 1016
    //#    VN: this.plugin.__Tag@972
    //#    Expected: {487_168}
    //#    Bad: {0..487_167, 487_169..+Inf}
    //#    Attribs:  Int  Exp singleton  Bad overlaps +/-1000  Soft  Bad < Exp  Bad > Exp  Uncertain
							}
						}
					} else {
						if (!tempLoaded) {
							lastError = "Prerequisites for plugin not met. ('"+filename+":"+getMainClass()+"' -> '"+prerequisites.getFailureReason()+"') ";
    //#PluginInfo.java:979: Warning: method not available - call not analyzed
    //#    call on String com.dmdirc.config.prefs.validator.ValidationResponse:getFailureReason()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    unanalyzed callee: String com.dmdirc.config.prefs.validator.ValidationResponse:getFailureReason()
							Logger.userError(ErrorLevel.LOW, lastError);
    //#PluginInfo.java:980: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_20
    //#    assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String)
    //#    callee assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [5]
    //#    callee srcpos: 45
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Bad only invalid
    //#PluginInfo.java:980: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_20
    //#    assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String)
    //#    callee assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee file: Logger.java
    //#    callee precondition index: [6]
    //#    callee srcpos: 45
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:980: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_20
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [7]
    //#    callee srcpos: 45
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Soft  Bad only invalid
    //#PluginInfo.java:980: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_20
    //#    assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String)
    //#    callee assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee file: Logger.java
    //#    callee precondition index: [8]
    //#    callee srcpos: 45
    //#    VN: com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295]
    //#    Expected: {-2_147_483_648..4_294_967_295}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Soft  Bad only invalid
    //#PluginInfo.java:980: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_20
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee file: Logger.java
    //#    callee precondition index: [13]
    //#    callee srcpos: 45
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
    //#PluginInfo.java:980: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_20
    //#    assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String)
    //#    callee assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee file: Logger.java
    //#    callee precondition index: [14]
    //#    callee srcpos: 45
    //#    VN: com/dmdirc/logger/ProgramError.errorDir
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
						}
					}
				}
			}
		} catch (ClassNotFoundException cnfe) {
			lastError = "Class not found ('"+filename+":"+classname+":"+classname.equals(getMainClass())+"') - "+cnfe.getMessage();
    //#PluginInfo.java:986: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.getMainClass: init'ed(this.metaData)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_22
    //#    assertion: init'ed(this.metaData)
    //#    callee: String com/dmdirc/plugins/PluginInfo.getMainClass()
    //#    callee assertion: init'ed(this.metaData)
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [3]
    //#    callee srcpos: 1117
    //#    VN: this.metaData
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
			Logger.userError(ErrorLevel.LOW, lastError, cnfe);
    //#PluginInfo.java:987: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_22
    //#    assertion: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    callee file: Logger.java
    //#    callee precondition index: [2]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295]
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad  Soft
    //#PluginInfo.java:987: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_22
    //#    assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [6]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Bad only invalid
    //#PluginInfo.java:987: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_22
    //#    assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee file: Logger.java
    //#    callee precondition index: [7]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:987: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_22
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [8]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Soft  Bad only invalid
    //#PluginInfo.java:987: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_22
    //#    assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee file: Logger.java
    //#    callee precondition index: [9]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295]
    //#    Expected: {-2_147_483_648..4_294_967_295}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Soft  Bad only invalid
    //#PluginInfo.java:987: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_22
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee file: Logger.java
    //#    callee precondition index: [16]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
    //#PluginInfo.java:987: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_22
    //#    assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee file: Logger.java
    //#    callee precondition index: [17]
    //#    callee srcpos: 69
    //#    VN: com/dmdirc/logger/ProgramError.errorDir
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
		} catch (NoSuchMethodException nsme) {
			// Don't moan about missing constructors for any class thats not the main Class
			lastError = "Constructor missing ('"+filename+":"+classname+":"+classname.equals(getMainClass())+"') - "+nsme.getMessage();
    //#PluginInfo.java:990: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.getMainClass: init'ed(this.metaData)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_23
    //#    assertion: init'ed(this.metaData)
    //#    callee: String com/dmdirc/plugins/PluginInfo.getMainClass()
    //#    callee assertion: init'ed(this.metaData)
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [3]
    //#    callee srcpos: 1117
    //#    VN: this.metaData
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
			if (classname.equals(getMainClass())) {
				Logger.userError(ErrorLevel.LOW, lastError, nsme);
    //#PluginInfo.java:992: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_24
    //#    assertion: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    callee file: Logger.java
    //#    callee precondition index: [2]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295]
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad  Soft
    //#PluginInfo.java:992: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_24
    //#    assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [6]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Bad only invalid
    //#PluginInfo.java:992: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_24
    //#    assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee file: Logger.java
    //#    callee precondition index: [7]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:992: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_24
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [8]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Soft  Bad only invalid
    //#PluginInfo.java:992: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_24
    //#    assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee file: Logger.java
    //#    callee precondition index: [9]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295]
    //#    Expected: {-2_147_483_648..4_294_967_295}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Soft  Bad only invalid
    //#PluginInfo.java:992: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_24
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee file: Logger.java
    //#    callee precondition index: [16]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
    //#PluginInfo.java:992: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_24
    //#    assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee file: Logger.java
    //#    callee precondition index: [17]
    //#    callee srcpos: 69
    //#    VN: com/dmdirc/logger/ProgramError.errorDir
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
			}
		} catch (IllegalAccessException iae) {
			lastError = "Unable to access constructor ('"+filename+":"+classname+":"+classname.equals(getMainClass())+"') - "+iae.getMessage();
    //#PluginInfo.java:995: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.getMainClass: init'ed(this.metaData)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_26
    //#    assertion: init'ed(this.metaData)
    //#    callee: String com/dmdirc/plugins/PluginInfo.getMainClass()
    //#    callee assertion: init'ed(this.metaData)
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [3]
    //#    callee srcpos: 1117
    //#    VN: this.metaData
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
			Logger.userError(ErrorLevel.LOW, lastError, iae);
    //#PluginInfo.java:996: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_26
    //#    assertion: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    callee file: Logger.java
    //#    callee precondition index: [2]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295]
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad  Soft
    //#PluginInfo.java:996: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_26
    //#    assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [6]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Bad only invalid
    //#PluginInfo.java:996: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_26
    //#    assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee file: Logger.java
    //#    callee precondition index: [7]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:996: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_26
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [8]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Soft  Bad only invalid
    //#PluginInfo.java:996: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_26
    //#    assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee file: Logger.java
    //#    callee precondition index: [9]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295]
    //#    Expected: {-2_147_483_648..4_294_967_295}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Soft  Bad only invalid
    //#PluginInfo.java:996: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_26
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee file: Logger.java
    //#    callee precondition index: [16]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
    //#PluginInfo.java:996: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_26
    //#    assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee file: Logger.java
    //#    callee precondition index: [17]
    //#    callee srcpos: 69
    //#    VN: com/dmdirc/logger/ProgramError.errorDir
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
		} catch (InvocationTargetException ite) {
			lastError = "Unable to invoke target ('"+filename+":"+classname+":"+classname.equals(getMainClass())+"') - "+ite.getMessage();
    //#PluginInfo.java:998: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.getMainClass: init'ed(this.metaData)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_27
    //#    assertion: init'ed(this.metaData)
    //#    callee: String com/dmdirc/plugins/PluginInfo.getMainClass()
    //#    callee assertion: init'ed(this.metaData)
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [3]
    //#    callee srcpos: 1117
    //#    VN: this.metaData
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
			Logger.userError(ErrorLevel.LOW, lastError, ite);
    //#PluginInfo.java:999: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_27
    //#    assertion: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    callee file: Logger.java
    //#    callee precondition index: [2]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295]
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad  Soft
    //#PluginInfo.java:999: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_27
    //#    assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [6]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Bad only invalid
    //#PluginInfo.java:999: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_27
    //#    assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee file: Logger.java
    //#    callee precondition index: [7]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:999: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_27
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [8]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Soft  Bad only invalid
    //#PluginInfo.java:999: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_27
    //#    assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee file: Logger.java
    //#    callee precondition index: [9]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295]
    //#    Expected: {-2_147_483_648..4_294_967_295}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Soft  Bad only invalid
    //#PluginInfo.java:999: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_27
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee file: Logger.java
    //#    callee precondition index: [16]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
    //#PluginInfo.java:999: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_27
    //#    assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee file: Logger.java
    //#    callee precondition index: [17]
    //#    callee srcpos: 69
    //#    VN: com/dmdirc/logger/ProgramError.errorDir
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
		} catch (InstantiationException ie) {
			lastError = "Unable to instantiate plugin ('"+filename+":"+classname+":"+classname.equals(getMainClass())+"') - "+ie.getMessage();
    //#PluginInfo.java:1001: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.getMainClass: init'ed(this.metaData)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_28
    //#    assertion: init'ed(this.metaData)
    //#    callee: String com/dmdirc/plugins/PluginInfo.getMainClass()
    //#    callee assertion: init'ed(this.metaData)
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [3]
    //#    callee srcpos: 1117
    //#    VN: this.metaData
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
			Logger.userError(ErrorLevel.LOW, lastError, ie);
    //#PluginInfo.java:1002: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_28
    //#    assertion: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    callee file: Logger.java
    //#    callee precondition index: [2]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295]
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad  Soft
    //#PluginInfo.java:1002: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_28
    //#    assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [6]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Bad only invalid
    //#PluginInfo.java:1002: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_28
    //#    assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee file: Logger.java
    //#    callee precondition index: [7]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:1002: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_28
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [8]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Soft  Bad only invalid
    //#PluginInfo.java:1002: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_28
    //#    assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee file: Logger.java
    //#    callee precondition index: [9]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295]
    //#    Expected: {-2_147_483_648..4_294_967_295}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Soft  Bad only invalid
    //#PluginInfo.java:1002: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_28
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee file: Logger.java
    //#    callee precondition index: [16]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
    //#PluginInfo.java:1002: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_28
    //#    assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee file: Logger.java
    //#    callee precondition index: [17]
    //#    callee srcpos: 69
    //#    VN: com/dmdirc/logger/ProgramError.errorDir
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
		} catch (NoClassDefFoundError ncdf) {
			lastError = "Unable to instantiate plugin ('"+filename+":"+classname+":"+classname.equals(getMainClass())+"') - Unable to find class: " + ncdf.getMessage();
    //#PluginInfo.java:1004: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.getMainClass: init'ed(this.metaData)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_29
    //#    assertion: init'ed(this.metaData)
    //#    callee: String com/dmdirc/plugins/PluginInfo.getMainClass()
    //#    callee assertion: init'ed(this.metaData)
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [3]
    //#    callee srcpos: 1117
    //#    VN: this.metaData
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
			Logger.userError(ErrorLevel.LOW, lastError, ncdf);
    //#PluginInfo.java:1005: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_29
    //#    assertion: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    callee file: Logger.java
    //#    callee precondition index: [2]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295]
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad  Soft
    //#PluginInfo.java:1005: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_29
    //#    assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [6]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Bad only invalid
    //#PluginInfo.java:1005: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_29
    //#    assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee file: Logger.java
    //#    callee precondition index: [7]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:1005: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_29
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [8]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Soft  Bad only invalid
    //#PluginInfo.java:1005: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_29
    //#    assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee file: Logger.java
    //#    callee precondition index: [9]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295]
    //#    Expected: {-2_147_483_648..4_294_967_295}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Soft  Bad only invalid
    //#PluginInfo.java:1005: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_29
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee file: Logger.java
    //#    callee precondition index: [16]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
    //#PluginInfo.java:1005: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_29
    //#    assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee file: Logger.java
    //#    callee precondition index: [17]
    //#    callee srcpos: 69
    //#    VN: com/dmdirc/logger/ProgramError.errorDir
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
		} catch (VerifyError ve) {
			lastError = "Unable to instantiate plugin ('"+filename+":"+classname+":"+classname.equals(getMainClass())+"') - Incompatible: "+ve.getMessage();
    //#PluginInfo.java:1007: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.getMainClass: init'ed(this.metaData)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_30
    //#    assertion: init'ed(this.metaData)
    //#    callee: String com/dmdirc/plugins/PluginInfo.getMainClass()
    //#    callee assertion: init'ed(this.metaData)
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [3]
    //#    callee srcpos: 1117
    //#    VN: this.metaData
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
			Logger.userError(ErrorLevel.LOW, lastError, ve);
    //#PluginInfo.java:1008: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_30
    //#    assertion: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    callee file: Logger.java
    //#    callee precondition index: [2]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295]
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad  Soft
    //#PluginInfo.java:1008: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_30
    //#    assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [6]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Bad only invalid
    //#PluginInfo.java:1008: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_30
    //#    assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee file: Logger.java
    //#    callee precondition index: [7]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:1008: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_30
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [8]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Soft  Bad only invalid
    //#PluginInfo.java:1008: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_30
    //#    assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee file: Logger.java
    //#    callee precondition index: [9]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295]
    //#    Expected: {-2_147_483_648..4_294_967_295}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Soft  Bad only invalid
    //#PluginInfo.java:1008: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_30
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee file: Logger.java
    //#    callee precondition index: [16]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
    //#PluginInfo.java:1008: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void loadClass(String)
    //#    basic block: bb_30
    //#    assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee file: Logger.java
    //#    callee precondition index: [17]
    //#    callee srcpos: 69
    //#    VN: com/dmdirc/logger/ProgramError.errorDir
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
		}
	}
    //#PluginInfo.java:1010: end of method: void com.dmdirc.plugins.PluginInfo.loadClass(String)

	/**
	 * Unload the plugin if possible.
	 */
	public void unloadPlugin() {
		unloadPlugin(false);
    //#PluginInfo.java:1016: method: void com.dmdirc.plugins.PluginInfo.unloadPlugin()
    //#input(void unloadPlugin()): " - "._tainted
    //#input(void unloadPlugin()): ""._tainted
    //#input(void unloadPlugin()): ":"._tainted
    //#input(void unloadPlugin()): "Error in onUnload for "._tainted
    //#input(void unloadPlugin()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(void unloadPlugin()): __Descendant_Table[others]
    //#input(void unloadPlugin()): __Dispatch_Table.delChild(Lcom/dmdirc/plugins/PluginInfo;)V
    //#input(void unloadPlugin()): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(void unloadPlugin()): __Dispatch_Table.getName()Ljava/lang/String;
    //#input(void unloadPlugin()): __Dispatch_Table.getPluginClassLoader()Lcom/dmdirc/plugins/PluginClassLoader;
    //#input(void unloadPlugin()): __Dispatch_Table.isLoaded()Z
    //#input(void unloadPlugin()): __Dispatch_Table.isPersistent()Z
    //#input(void unloadPlugin()): __Dispatch_Table.isTempLoaded()Z
    //#input(void unloadPlugin()): __Dispatch_Table.isUnloadable()Z
    //#input(void unloadPlugin()): com.dmdirc.actions.CoreActionType.PLUGIN_UNLOADED
    //#input(void unloadPlugin()): com/dmdirc/logger/ErrorLevel.MEDIUM
    //#input(void unloadPlugin()): com/dmdirc/logger/Logger.manager
    //#input(void unloadPlugin()): com/dmdirc/plugins/Plugin.__Descendant_Table[com/dmdirc/plugins/Plugin]
    //#input(void unloadPlugin()): com/dmdirc/plugins/Plugin.__Descendant_Table[others]
    //#input(void unloadPlugin()): com/dmdirc/plugins/Plugin.__Dispatch_Table.onUnload()V
    //#input(void unloadPlugin()): com/dmdirc/plugins/PluginClassLoader.__Descendant_Table[com/dmdirc/plugins/PluginClassLoader]
    //#input(void unloadPlugin()): com/dmdirc/plugins/PluginClassLoader.__Descendant_Table[others]
    //#input(void unloadPlugin()): com/dmdirc/plugins/PluginClassLoader.__Dispatch_Table.getSubClassLoader(Lcom/dmdirc/plugins/PluginInfo;)Lcom/dmdirc/plugins/PluginClassLoader;
    //#input(void unloadPlugin()): com/dmdirc/plugins/PluginManager.__Descendant_Table[com/dmdirc/plugins/PluginManager]
    //#input(void unloadPlugin()): com/dmdirc/plugins/PluginManager.__Descendant_Table[others]
    //#input(void unloadPlugin()): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getPluginInfoByName(Ljava/lang/String;)Lcom/dmdirc/plugins/PluginInfo;
    //#input(void unloadPlugin()): com/dmdirc/plugins/Service.__Descendant_Table[com/dmdirc/plugins/Service]
    //#input(void unloadPlugin()): com/dmdirc/plugins/Service.__Descendant_Table[others]
    //#input(void unloadPlugin()): com/dmdirc/plugins/Service.__Dispatch_Table.delProvider(Lcom/dmdirc/plugins/ServiceProvider;)V
    //#input(void unloadPlugin()): this
    //#input(void unloadPlugin()): this.__Tag
    //#input(void unloadPlugin()): this.children
    //#input(void unloadPlugin()): this.metaData
    //#input(void unloadPlugin()): this.plugin
    //#input(void unloadPlugin()): this.plugin.__Tag
    //#input(void unloadPlugin()): this.provides
    //#input(void unloadPlugin()): this.tempLoaded
    //#output(void unloadPlugin()): java.lang.StringBuilder:toString(...)._tainted
    //#output(void unloadPlugin()): new PluginClassLoader(getSubClassLoader#1) num objects
    //#output(void unloadPlugin()): new PluginClassLoader(getSubClassLoader#1).__Tag
    //#output(void unloadPlugin()): new PluginClassLoader(getSubClassLoader#1).pluginInfo
    //#output(void unloadPlugin()): this.classloader
    //#output(void unloadPlugin()): this.lastError
    //#output(void unloadPlugin()): this.plugin
    //#output(void unloadPlugin()): this.tempLoaded
    //#new obj(void unloadPlugin()): java.lang.StringBuilder:toString(...)
    //#new obj(void unloadPlugin()): new PluginClassLoader(getSubClassLoader#1)
    //#pre[10] (void unloadPlugin()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[7] (void unloadPlugin()): (soft) this.plugin != null
    //#pre[8] (void unloadPlugin()): (soft) init'ed(this.tempLoaded)
    //#pre[11] (void unloadPlugin()): (soft) this.children != null
    //#pre[12] (void unloadPlugin()): (soft) init'ed(this.metaData)
    //#pre[13] (void unloadPlugin()): (soft) this.plugin.__Tag == com/dmdirc/plugins/Plugin
    //#pre[14] (void unloadPlugin()): (soft) this.provides != null
    //#post(void unloadPlugin()): possibly_updated(java.lang.StringBuilder:toString(...)._tainted)
    //#post(void unloadPlugin()): this.classloader == One-of{old this.classloader, null}
    //#post(void unloadPlugin()): possibly_updated(this.lastError)
    //#post(void unloadPlugin()): this.plugin == One-of{old this.plugin, null}
    //#post(void unloadPlugin()): this.tempLoaded == One-of{old this.tempLoaded, 0}
    //#post(void unloadPlugin()): possibly_updated(new PluginClassLoader(getSubClassLoader#1) num objects)
    //#post(void unloadPlugin()): possibly_updated(new PluginClassLoader(getSubClassLoader#1).__Tag)
    //#post(void unloadPlugin()): possibly_updated(new PluginClassLoader(getSubClassLoader#1).pluginInfo)
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:java.lang.String:isEmpty
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:java.util.List:remove
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:java.util.Map:get
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:com.dmdirc.util.ConfigFile:isFlatDomain
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:com.dmdirc.util.ConfigFile:getFlatDomain
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:java.util.List:contains
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:getPluginManager
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:addError
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:com.dmdirc.actions.ActionManager:processEvent
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:getPluginInfoByName
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:java.util.List:iterator
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:java.lang.ClassLoader
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:java.lang.String:equalsIgnoreCase
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:unloadPlugin
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:delProvider
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:java.util.List:clear
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:isUnloadable
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:onUnload
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:java.lang.Exception:getMessage
    //#unanalyzed(void unloadPlugin()): Effects-of-calling:java.lang.Exception:printStackTrace
	}
    //#PluginInfo.java:1017: end of method: void com.dmdirc.plugins.PluginInfo.unloadPlugin()
	
	/**
	 * Can this plugin be unloaded?
	 * Will return false if:
	 *   - The plugin is persistent (all its classes are loaded into the global class loader)
	 *   - The plugin isn't currently loaded
	 *   - The metadata key "unloadable" is set to false, no or 0
	 *
	 * @return true if plugin can be unloaded
	 */
	public boolean isUnloadable() {
		if (isPersistent() || (!isLoaded() && !isTempLoaded())) {
    //#PluginInfo.java:1029: method: bool com.dmdirc.plugins.PluginInfo.isUnloadable()
    //#input(bool isUnloadable()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(bool isUnloadable()): __Descendant_Table[others]
    //#input(bool isUnloadable()): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(bool isUnloadable()): __Dispatch_Table.isLoaded()Z
    //#input(bool isUnloadable()): __Dispatch_Table.isPersistent()Z
    //#input(bool isUnloadable()): __Dispatch_Table.isTempLoaded()Z
    //#input(bool isUnloadable()): this
    //#input(bool isUnloadable()): this.__Tag
    //#input(bool isUnloadable()): this.metaData
    //#input(bool isUnloadable()): this.plugin
    //#input(bool isUnloadable()): this.tempLoaded
    //#output(bool isUnloadable()): return_value
    //#pre[8] (bool isUnloadable()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[9] (bool isUnloadable()): init'ed(this.metaData)
    //#pre[10] (bool isUnloadable()): (soft) init'ed(this.plugin)
    //#pre[11] (bool isUnloadable()): (soft) init'ed(this.tempLoaded)
    //#post(bool isUnloadable()): init'ed(return_value)
    //#unanalyzed(bool isUnloadable()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(bool isUnloadable()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(bool isUnloadable()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(bool isUnloadable()): Effects-of-calling:java.util.Map:get
    //#unanalyzed(bool isUnloadable()): Effects-of-calling:com.dmdirc.util.ConfigFile:isFlatDomain
    //#unanalyzed(bool isUnloadable()): Effects-of-calling:com.dmdirc.util.ConfigFile:getFlatDomain
    //#unanalyzed(bool isUnloadable()): Effects-of-calling:java.util.List:contains
    //#test_vector(bool isUnloadable()): !(this.plugin == null) & this.tempLoaded != 0: {0}, {1}
    //#test_vector(bool isUnloadable()): !(this.plugin == null) & this.tempLoaded == 0: {1}, {0}
    //#test_vector(bool isUnloadable()): (!(this.plugin == null) & this.tempLoaded != 0) | this.plugin == null: {0}, {1}
    //#test_vector(bool isUnloadable()): this.tempLoaded: {0}, {1}
			return false;
		} else {
			final String unloadable = getKeyValue("metadata", "unloadable", "true");
			return (unloadable.equalsIgnoreCase("yes") || unloadable.equalsIgnoreCase("true") || unloadable.equalsIgnoreCase("1"));
    //#PluginInfo.java:1033: ?null dereference
    //#    unloadable != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool isUnloadable()
    //#    basic block: bb_5
    //#    assertion: unloadable != null
    //#    VN: getKeyValue(...)
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:1033: end of method: bool com.dmdirc.plugins.PluginInfo.isUnloadable()
		}
	}
	
	/**
	 * Unload the plugin if possible.
	 *
	 * @param parentUnloading is our parent already unloading? (if so, don't call delChild)
	 */
	private void unloadPlugin(final boolean parentUnloading) {
		if (isUnloadable()) {
    //#PluginInfo.java:1043: method: void com.dmdirc.plugins.PluginInfo.unloadPlugin(bool)
    //#input(void unloadPlugin(bool)): " - "._tainted
    //#input(void unloadPlugin(bool)): ""._tainted
    //#input(void unloadPlugin(bool)): "&#09;"._tainted
    //#input(void unloadPlugin(bool)): "&#10;Which caused: "._tainted
    //#input(void unloadPlugin(bool)): "-"._tainted
    //#input(void unloadPlugin(bool)): ".log"._tainted
    //#input(void unloadPlugin(bool)): ": "._tainted
    //#input(void unloadPlugin(bool)): ":"._tainted
    //#input(void unloadPlugin(bool)): "A fatal error has occurred: "._tainted
    //#input(void unloadPlugin(bool)): "An error has occurred: "._tainted
    //#input(void unloadPlugin(bool)): "Date:"._tainted
    //#input(void unloadPlugin(bool)): "Description: "._tainted
    //#input(void unloadPlugin(bool)): "Error in onUnload for "._tainted
    //#input(void unloadPlugin(bool)): "ID must be a positive integer: "._tainted
    //#input(void unloadPlugin(bool)): "Level: "._tainted
    //#input(void unloadPlugin(bool)): "errors"._tainted
    //#input(void unloadPlugin(bool)): "plugins"._tainted
    //#input(void unloadPlugin(bool)): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(void unloadPlugin(bool)): __Descendant_Table[others]
    //#input(void unloadPlugin(bool)): __Dispatch_Table.delChild(Lcom/dmdirc/plugins/PluginInfo;)V
    //#input(void unloadPlugin(bool)): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(void unloadPlugin(bool)): __Dispatch_Table.getName()Ljava/lang/String;
    //#input(void unloadPlugin(bool)): __Dispatch_Table.getPluginClassLoader()Lcom/dmdirc/plugins/PluginClassLoader;
    //#input(void unloadPlugin(bool)): __Dispatch_Table.isLoaded()Z
    //#input(void unloadPlugin(bool)): __Dispatch_Table.isPersistent()Z
    //#input(void unloadPlugin(bool)): __Dispatch_Table.isTempLoaded()Z
    //#input(void unloadPlugin(bool)): __Dispatch_Table.isUnloadable()Z
    //#input(void unloadPlugin(bool)): com.dmdirc.actions.CoreActionType.PLUGIN_UNLOADED
    //#input(void unloadPlugin(bool)): com.dmdirc.logger.ErrorLevel__static_init.new ErrorLevel(ErrorLevel__static_init#3)._tainted
    //#input(void unloadPlugin(bool)): com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2).length
    //#input(void unloadPlugin(bool)): com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).errorListeners
    //#input(void unloadPlugin(bool)): com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).errors
    //#input(void unloadPlugin(bool)): com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).errors.__Lock
    //#input(void unloadPlugin(bool)): com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportQueue
    //#input(void unloadPlugin(bool)): com.dmdirc.logger.ErrorReportStatus__static_init.new ErrorReportStatus(ErrorReportStatus__static_init#1).terminal
    //#input(void unloadPlugin(bool)): com.dmdirc.logger.ErrorReportStatus__static_init.new ErrorReportStatus(ErrorReportStatus__static_init#5).terminal
    //#input(void unloadPlugin(bool)): com.dmdirc.logger.ErrorReportStatus__static_init.new ErrorReportStatus(ErrorReportStatus__static_init#6).terminal
    //#input(void unloadPlugin(bool)): com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1).length
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ErrorFixedStatus.INVALID
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ErrorFixedStatus.KNOWN
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ErrorFixedStatus.UNKNOWN
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ErrorFixedStatus.UNREPORTED
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ErrorLevel.FATAL
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ErrorLevel.MEDIUM
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ErrorListener.__Descendant_Table[com/dmdirc/logger/ErrorListener]
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ErrorListener.__Descendant_Table[com/dmdirc/ui/FatalErrorDialog]
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ErrorListener.__Descendant_Table[others]
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ErrorListener.__Dispatch_Table.errorAdded(Lcom/dmdirc/logger/ProgramError;)V
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ErrorListener.__Dispatch_Table.errorStatusChanged(Lcom/dmdirc/logger/ProgramError;)V
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ErrorListener.__Dispatch_Table.isReady()Z
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ErrorManager.BANNED_EXCEPTIONS
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ErrorManager.java.lang.System.err
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ErrorManager.me
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ErrorReportStatus.ERROR
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ErrorReportStatus.NOT_APPLICABLE
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ErrorReportStatus.QUEUED
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ErrorReportStatus.WAITING
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/Logger.manager
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ProgramError.__Descendant_Table[com/dmdirc/logger/ProgramError]
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ProgramError.__Descendant_Table[others]
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ProgramError.java.lang.System.err
    //#input(void unloadPlugin(bool)): com/dmdirc/logger/ProgramError.writingSem
    //#input(void unloadPlugin(bool)): com/dmdirc/plugins/Plugin.__Descendant_Table[com/dmdirc/plugins/Plugin]
    //#input(void unloadPlugin(bool)): com/dmdirc/plugins/Plugin.__Descendant_Table[others]
    //#input(void unloadPlugin(bool)): com/dmdirc/plugins/Plugin.__Dispatch_Table.onUnload()V
    //#input(void unloadPlugin(bool)): com/dmdirc/plugins/PluginClassLoader.__Descendant_Table[com/dmdirc/plugins/PluginClassLoader]
    //#input(void unloadPlugin(bool)): com/dmdirc/plugins/PluginClassLoader.__Descendant_Table[others]
    //#input(void unloadPlugin(bool)): com/dmdirc/plugins/PluginClassLoader.__Dispatch_Table.getSubClassLoader(Lcom/dmdirc/plugins/PluginInfo;)Lcom/dmdirc/plugins/PluginClassLoader;
    //#input(void unloadPlugin(bool)): com/dmdirc/plugins/PluginManager.__Class_Obj.__Lock
    //#input(void unloadPlugin(bool)): com/dmdirc/plugins/PluginManager.__Descendant_Table[com/dmdirc/plugins/PluginManager]
    //#input(void unloadPlugin(bool)): com/dmdirc/plugins/PluginManager.__Descendant_Table[others]
    //#input(void unloadPlugin(bool)): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getPluginInfoByName(Ljava/lang/String;)Lcom/dmdirc/plugins/PluginInfo;
    //#input(void unloadPlugin(bool)): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getPluginInfos()Ljava/util/Collection;
    //#input(void unloadPlugin(bool)): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getPossiblePluginInfos(Z)Ljava/util/List;
    //#input(void unloadPlugin(bool)): com/dmdirc/plugins/PluginManager.com.dmdirc.actions.CoreActionType.CLIENT_PREFS_CLOSED
    //#input(void unloadPlugin(bool)): com/dmdirc/plugins/PluginManager.com.dmdirc.actions.CoreActionType.CLIENT_PREFS_OPENED
    //#input(void unloadPlugin(bool)): com/dmdirc/plugins/PluginManager.me.__Tag
    //#input(void unloadPlugin(bool)): com/dmdirc/plugins/PluginManager.me.knownPlugins
    //#input(void unloadPlugin(bool)): com/dmdirc/plugins/Service.__Descendant_Table[com/dmdirc/plugins/Service]
    //#input(void unloadPlugin(bool)): com/dmdirc/plugins/Service.__Descendant_Table[others]
    //#input(void unloadPlugin(bool)): com/dmdirc/plugins/Service.__Dispatch_Table.delProvider(Lcom/dmdirc/plugins/ServiceProvider;)V
    //#input(void unloadPlugin(bool)): com/dmdirc/ui/FatalErrorDialog$4.$SwitchMap$com$dmdirc$logger$ErrorReportStatus
    //#input(void unloadPlugin(bool)): com/dmdirc/ui/FatalErrorDialog.__Dispatch_Table.errorAdded(Lcom/dmdirc/logger/ProgramError;)V
    //#input(void unloadPlugin(bool)): com/dmdirc/ui/FatalErrorDialog.__Dispatch_Table.errorStatusChanged(Lcom/dmdirc/logger/ProgramError;)V
    //#input(void unloadPlugin(bool)): com/dmdirc/ui/FatalErrorDialog.__Dispatch_Table.isReady()Z
    //#input(void unloadPlugin(bool)): parentUnloading
    //#input(void unloadPlugin(bool)): this
    //#input(void unloadPlugin(bool)): this.__Tag
    //#input(void unloadPlugin(bool)): this.children
    //#input(void unloadPlugin(bool)): this.lastError._tainted
    //#input(void unloadPlugin(bool)): this.metaData
    //#input(void unloadPlugin(bool)): this.plugin
    //#input(void unloadPlugin(bool)): this.plugin.__Tag
    //#input(void unloadPlugin(bool)): this.provides
    //#input(void unloadPlugin(bool)): this.tempLoaded
    //#output(void unloadPlugin(bool)): com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread
    //#output(void unloadPlugin(bool)): com/dmdirc/logger/ProgramError.errorDir
    //#output(void unloadPlugin(bool)): com/dmdirc/plugins/PluginManager.me
    //#output(void unloadPlugin(bool)): java.lang.StringBuilder:toString(...)._tainted
    //#output(void unloadPlugin(bool)): new ErrorReportingThread(sendError#1) num objects
    //#output(void unloadPlugin(bool)): new ErrorReportingThread(sendError#1).__Tag
    //#output(void unloadPlugin(bool)): new ErrorReportingThread(sendError#1).queue
    //#output(void unloadPlugin(bool)): new File(getErrorFile#1) num objects
    //#output(void unloadPlugin(bool)): new HashMap(PluginManager#2) num objects
    //#output(void unloadPlugin(bool)): new Hashtable(PluginManager#1) num objects
    //#output(void unloadPlugin(bool)): new PluginClassLoader(getSubClassLoader#1) num objects
    //#output(void unloadPlugin(bool)): new PluginClassLoader(getSubClassLoader#1).__Tag
    //#output(void unloadPlugin(bool)): new PluginClassLoader(getSubClassLoader#1).pluginInfo
    //#output(void unloadPlugin(bool)): new PluginManager(getPluginManager#1) num objects
    //#output(void unloadPlugin(bool)): new PluginManager(getPluginManager#1).__Tag
    //#output(void unloadPlugin(bool)): new PluginManager(getPluginManager#1).knownPlugins
    //#output(void unloadPlugin(bool)): new PluginManager(getPluginManager#1).myDir
    //#output(void unloadPlugin(bool)): new PluginManager(getPluginManager#1).services
    //#output(void unloadPlugin(bool)): this.classloader
    //#output(void unloadPlugin(bool)): this.lastError
    //#output(void unloadPlugin(bool)): this.plugin
    //#output(void unloadPlugin(bool)): this.tempLoaded
    //#new obj(void unloadPlugin(bool)): java.lang.StringBuilder:toString(...)
    //#new obj(void unloadPlugin(bool)): new ErrorReportingThread(sendError#1)
    //#new obj(void unloadPlugin(bool)): new File(getErrorFile#1)
    //#new obj(void unloadPlugin(bool)): new HashMap(PluginManager#2)
    //#new obj(void unloadPlugin(bool)): new Hashtable(PluginManager#1)
    //#new obj(void unloadPlugin(bool)): new PluginClassLoader(getSubClassLoader#1)
    //#new obj(void unloadPlugin(bool)): new PluginManager(getPluginManager#1)
    //#pre[25] (void unloadPlugin(bool)): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[21] (void unloadPlugin(bool)): (soft) this.plugin != null
    //#pre[22] (void unloadPlugin(bool)): (soft) init'ed(this.tempLoaded)
    //#pre[26] (void unloadPlugin(bool)): (soft) this.children != null
    //#pre[28] (void unloadPlugin(bool)): (soft) init'ed(this.metaData)
    //#pre[29] (void unloadPlugin(bool)): (soft) this.plugin.__Tag == com/dmdirc/plugins/Plugin
    //#pre[30] (void unloadPlugin(bool)): (soft) this.provides != null
    //#presumption(void unloadPlugin(bool)): init'ed(com.dmdirc.actions.CoreActionType.PLUGIN_UNLOADED)
    //#post(void unloadPlugin(bool)): com/dmdirc/logger/ProgramError.errorDir == One-of{old com/dmdirc/logger/ProgramError.errorDir, &new File(getErrorFile#1)}
    //#post(void unloadPlugin(bool)): com/dmdirc/plugins/PluginManager.me == One-of{old com/dmdirc/plugins/PluginManager.me, &new PluginManager(getPluginManager#1)}
    //#post(void unloadPlugin(bool)): init'ed(java.lang.StringBuilder:toString(...)._tainted)
    //#post(void unloadPlugin(bool)): possibly_updated(java.lang.StringBuilder:toString(...)._tainted)
    //#post(void unloadPlugin(bool)): this.classloader == One-of{old this.classloader, null}
    //#post(void unloadPlugin(bool)): possibly_updated(this.lastError)
    //#post(void unloadPlugin(bool)): this.plugin == One-of{old this.plugin, null}
    //#post(void unloadPlugin(bool)): init'ed(this.plugin)
    //#post(void unloadPlugin(bool)): init'ed(this.tempLoaded)
    //#post(void unloadPlugin(bool)): com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread == old com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread
    //#post(void unloadPlugin(bool)): possibly_updated(new ErrorReportingThread(sendError#1) num objects)
    //#post(void unloadPlugin(bool)): possibly_updated(new ErrorReportingThread(sendError#1).__Tag)
    //#post(void unloadPlugin(bool)): possibly_updated(new ErrorReportingThread(sendError#1).queue)
    //#post(void unloadPlugin(bool)): possibly_updated(new File(getErrorFile#1) num objects)
    //#post(void unloadPlugin(bool)): possibly_updated(new HashMap(PluginManager#2) num objects)
    //#post(void unloadPlugin(bool)): possibly_updated(new Hashtable(PluginManager#1) num objects)
    //#post(void unloadPlugin(bool)): new PluginClassLoader(getSubClassLoader#1) num objects <= 1
    //#post(void unloadPlugin(bool)): init'ed(new PluginClassLoader(getSubClassLoader#1) num objects)
    //#post(void unloadPlugin(bool)): init'ed(new PluginClassLoader(getSubClassLoader#1).__Tag)
    //#post(void unloadPlugin(bool)): init'ed(new PluginClassLoader(getSubClassLoader#1).pluginInfo)
    //#post(void unloadPlugin(bool)): possibly_updated(new PluginManager(getPluginManager#1) num objects)
    //#post(void unloadPlugin(bool)): possibly_updated(new PluginManager(getPluginManager#1).__Tag)
    //#post(void unloadPlugin(bool)): possibly_updated(new PluginManager(getPluginManager#1).knownPlugins)
    //#post(void unloadPlugin(bool)): possibly_updated(new PluginManager(getPluginManager#1).myDir)
    //#post(void unloadPlugin(bool)): possibly_updated(new PluginManager(getPluginManager#1).services)
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.String:isEmpty
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.net.URL:getPath
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.List:remove
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.Map:get
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:com.dmdirc.util.ConfigFile:isFlatDomain
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:com.dmdirc.util.ConfigFile:getFlatDomain
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.List:contains
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:getPluginManager
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:getErrorManager
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:addError
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:com.dmdirc.actions.ActionManager:processEvent
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:getPluginInfoByName
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.List:iterator
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.ClassLoader
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.String:equalsIgnoreCase
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:unloadPlugin
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:delProvider
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.List:clear
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:isUnloadable
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:onUnload
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.Exception:getMessage
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.Exception:printStackTrace
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.Exception
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:com.dmdirc.plugins.PluginInfo
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.Hashtable
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.HashMap
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.System:getProperty
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:com.dmdirc.Main:getConfigDir
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:com.dmdirc.actions.ActionManager:addListener
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.Map:values
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.Collection:iterator
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.String:toLowerCase
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.Map:put
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.LinkedList
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.io.File
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.LinkedList:add
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.LinkedList:isEmpty
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.LinkedList:pop
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.io.File:isDirectory
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.io.File:listFiles
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.io.File:isFile
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.io.File:getName
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.String:endsWith
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.io.File:getPath
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.String:length
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.String:substring
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:addPlugin
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.net.URL
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.net.MalformedURLException:getMessage
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.io.File:exists
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:delPlugin
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:com.dmdirc.updater.components.PluginComponent
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:com.dmdirc.plugins.PluginException:getMessage
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.Map:remove
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:getPossiblePluginInfos
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.concurrent.atomic.AtomicLong:getAndIncrement
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.Date
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.IllegalArgumentException
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.Arrays:copyOf
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.Date:clone
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.List:add
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:com.dmdirc.logger.ErrorReportStatus:equals
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:fireErrorStatusChanged
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.Object:notifyAll
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.concurrent.BlockingQueue:add
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.Thread:isAlive
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.Thread
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:com.dmdirc.logger.ErrorReportingThread:setDaemon
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.Thread:start
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.awt.GraphicsEnvironment:isHeadless
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.io.PrintStream:println
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:javax.swing.SwingUtilities:invokeLater
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.concurrent.Semaphore
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.concurrent.Semaphore:acquireUninterruptibly
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.Object:wait
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:com.dmdirc.util.ListenerList:get
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:isReady
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:errorAdded
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:com.dmdirc.logger.ErrorFixedStatus:equals
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.String:startsWith
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.io.File:mkdirs
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.Date:getTime
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.io.File:renameTo
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.io.File:createNewFile
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.io.FileOutputStream
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.concurrent.Semaphore:release
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.io.IOException:printStackTrace
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.io.OutputStream
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.io.PrintWriter
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.io.PrintWriter:println
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.io.PrintWriter:close
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.Throwable:getStackTrace
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.Throwable:toString
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.StackTraceElement:toString
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.Throwable:getCause
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:getTrace
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.Object:getClass
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.Object:equals
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:com.dmdirc.logger.ErrorReportStatus:ordinal
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:javax.swing.JButton:setText
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:javax.swing.JButton:setEnabled
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:equals
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:getReportStatus
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:errorStatusChanged
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.lang.String:equals
    //#unanalyzed(void unloadPlugin(bool)): Effects-of-calling:java.util.Arrays:equals
    //#test_vector(void unloadPlugin(bool)): !(this.plugin == null) & this.tempLoaded != 0: {1}, {0}
    //#test_vector(void unloadPlugin(bool)): !(this.plugin == null) & this.tempLoaded == 0: {0}, {1}
    //#test_vector(void unloadPlugin(bool)): (!(this.plugin == null) & this.tempLoaded != 0) | this.plugin == null: {1}, {0}
    //#test_vector(void unloadPlugin(bool)): (!(this.plugin == null) & this.tempLoaded == 0) | this.plugin == null: {0}, {1}
    //#test_vector(void unloadPlugin(bool)): this.tempLoaded: {1}, {0}
    //#test_vector(void unloadPlugin(bool)): parentUnloading: {1}, {0}
    //#test_vector(void unloadPlugin(bool)): java.lang.String:isEmpty(...)@1050: {1}, {0}
    //#test_vector(void unloadPlugin(bool)): java.util.Iterator:hasNext(...)@1046: {0}, {1}
    //#test_vector(void unloadPlugin(bool)): java.util.Iterator:hasNext(...)@1067: {0}, {1}
			if (!isTempLoaded()) {
				// Unload all children
				for (PluginInfo child : children) {
    //#PluginInfo.java:1046: ?ClassCastException check
    //#    __Descendant_Table[java/util/Iterator:next(...).__Tag] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_22
    //#    assertion: __Descendant_Table[java/util/Iterator:next(...).__Tag] != null
    //#    VN: java.util.Iterator:next(...).__Tag@1046 == com/dmdirc/plugins/PluginInfo
    //#    Expected: {-Inf..-1, 1..+Inf}
    //#    Bad: {0}
    //#    Attribs:  Int  Bad singleton  Bad overlaps +/-1000  Bad > Exp  Uncertain
					child.unloadPlugin(true);
    //#PluginInfo.java:1047: ?null dereference
    //#    child != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_21
    //#    assertion: child != null
    //#    VN: java.util.Iterator:next(...)@1046
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad  Uncertain
    //#PluginInfo.java:1047: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.unloadPlugin: (soft) this.plugin != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_21
    //#    assertion: (soft) child.plugin@1046 != null
    //#    callee: void com/dmdirc/plugins/PluginInfo.unloadPlugin(bool)
    //#    callee assertion: (soft) this.plugin != null
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [21]
    //#    callee srcpos: 1043
    //#    VN: child.plugin@1046
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad  Soft  Uncertain
    //#PluginInfo.java:1047: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.unloadPlugin: this.__Tag == com/dmdirc/plugins/PluginInfo
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_21
    //#    assertion: java.util.Iterator:next(...).__Tag@1046 == com/dmdirc/plugins/PluginInfo
    //#    callee: void com/dmdirc/plugins/PluginInfo.unloadPlugin(bool)
    //#    callee assertion: this.__Tag == com/dmdirc/plugins/PluginInfo
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [25]
    //#    callee srcpos: 1043
    //#    VN: java.util.Iterator:next(...).__Tag@1046
    //#    Expected: {488_704}
    //#    Bad: {0..488_703, 488_705..+Inf}
    //#    Attribs:  Int  Exp singleton  Bad overlaps +/-1000  Bad < Exp  Bad > Exp  Uncertain
    //#PluginInfo.java:1047: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.unloadPlugin: (soft) this.children != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_21
    //#    assertion: (soft) child.children@1046 != null
    //#    callee: void com/dmdirc/plugins/PluginInfo.unloadPlugin(bool)
    //#    callee assertion: (soft) this.children != null
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [26]
    //#    callee srcpos: 1043
    //#    VN: child.children@1046
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad  Soft  Uncertain
    //#PluginInfo.java:1047: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.unloadPlugin: (soft) this.plugin.__Tag == com/dmdirc/plugins/Plugin
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_21
    //#    assertion: (soft) child.plugin.__Tag@1046 == com/dmdirc/plugins/Plugin
    //#    callee: void com/dmdirc/plugins/PluginInfo.unloadPlugin(bool)
    //#    callee assertion: (soft) this.plugin.__Tag == com/dmdirc/plugins/Plugin
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [29]
    //#    callee srcpos: 1043
    //#    VN: child.plugin.__Tag@1046
    //#    Expected: {487_168}
    //#    Bad: {0..487_167, 487_169..+Inf}
    //#    Attribs:  Int  Exp singleton  Bad overlaps +/-1000  Soft  Bad < Exp  Bad > Exp  Uncertain
    //#PluginInfo.java:1047: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.unloadPlugin: (soft) this.provides != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_21
    //#    assertion: (soft) child.provides@1046 != null
    //#    callee: void com/dmdirc/plugins/PluginInfo.unloadPlugin(bool)
    //#    callee assertion: (soft) this.provides != null
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [30]
    //#    callee srcpos: 1043
    //#    VN: child.provides@1046
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad  Soft  Uncertain
				}
				// Delete ourself as a child of our parent.
				if (!parentUnloading && !getKeyValue("requires", "parent", "").isEmpty()) {
    //#PluginInfo.java:1050: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.getKeyValue: init'ed(this.metaData)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_7
    //#    assertion: init'ed(this.metaData)
    //#    callee: String com/dmdirc/plugins/PluginInfo.getKeyValue(String, String, String)
    //#    callee assertion: init'ed(this.metaData)
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [5]
    //#    callee srcpos: 1104
    //#    VN: this.metaData
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
    //#PluginInfo.java:1050: ?null dereference
    //#    getKeyValue(...) != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_7
    //#    assertion: getKeyValue(...) != null
    //#    VN: getKeyValue(...)
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
					final String parentName = getKeyValue("requires", "parent", "");
					final PluginInfo pi = PluginManager.getPluginManager().getPluginInfoByName(parentName);
    //#PluginInfo.java:1052: ?precondition failure
    //#    com/dmdirc/plugins/PluginManager.getPluginManager: init'ed(me)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_8
    //#    assertion: init'ed(com/dmdirc/plugins/PluginManager.me)
    //#    callee: PluginManager com/dmdirc/plugins/PluginManager.getPluginManager()
    //#    callee assertion: init'ed(me)
    //#    callee file: PluginManager.java
    //#    callee precondition index: [1]
    //#    callee srcpos: 233
    //#    VN: com/dmdirc/plugins/PluginManager.me
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
    //#PluginInfo.java:1052: ?null dereference
    //#    com/dmdirc/plugins/PluginManager.__Descendant_Table[getPluginManager(...).__Tag] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_8
    //#    assertion: com/dmdirc/plugins/PluginManager.__Descendant_Table[getPluginManager(...).__Tag] != null
    //#    VN: com/dmdirc/plugins/PluginManager.__Descendant_Table[getPluginManager(...).__Tag]
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:1052: ?precondition failure
    //#    com/dmdirc/plugins/PluginManager.getPluginInfoByName: this.knownPlugins != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_8
    //#    assertion: getPluginManager(...).knownPlugins != null
    //#    callee: PluginInfo com/dmdirc/plugins/PluginManager.getPluginInfoByName(String)
    //#    callee assertion: this.knownPlugins != null
    //#    callee file: PluginManager.java
    //#    callee precondition index: [4]
    //#    callee srcpos: 358
    //#    VN: getPluginManager(...).knownPlugins
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad  Uncertain
					if (pi != null) {
						pi.delChild(this);
    //#PluginInfo.java:1054: ?use of default init
    //#    init'ed(pi.__Tag)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_9
    //#    assertion: init'ed(pi.__Tag)
    //#    VN: pi.__Tag
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#PluginInfo.java:1054: ?null dereference
    //#    __Descendant_Table[pi.__Tag] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_9
    //#    assertion: __Descendant_Table[pi.__Tag] != null
    //#    VN: __Descendant_Table[pi.__Tag]
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:1054: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.delChild: this.children != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_9
    //#    assertion: pi.children@1052 != null
    //#    callee: void com/dmdirc/plugins/PluginInfo.delChild(PluginInfo)
    //#    callee assertion: this.children != null
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [3]
    //#    callee srcpos: 922
    //#    VN: pi.children@1052
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad  Uncertain
						classloader = pi.getPluginClassLoader().getSubClassLoader(this);
    //#PluginInfo.java:1055: ?null dereference
    //#    getPluginClassLoader(...) != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_9
    //#    assertion: getPluginClassLoader(...) != null
    //#    VN: pi.classloader@1054
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad  Uncertain
    //#PluginInfo.java:1055: ?null dereference
    //#    com/dmdirc/plugins/PluginClassLoader.__Descendant_Table[getPluginClassLoader(...).__Tag] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_9
    //#    assertion: com/dmdirc/plugins/PluginClassLoader.__Descendant_Table[getPluginClassLoader(...).__Tag] != null
    //#    VN: com/dmdirc/plugins/PluginClassLoader.__Descendant_Table[getPluginClassLoader(...).__Tag]
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
					}
				}
				// Now unload ourself
				try {
					plugin.onUnload();
    //#PluginInfo.java:1060: ?null dereference
    //#    this.plugin != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_11
    //#    assertion: this.plugin != null
    //#    VN: this.plugin
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:1060: Warning: method not available - call not analyzed
    //#    call on void onUnload()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    unanalyzed callee: void onUnload()
				} catch (Exception e) {
					lastError = "Error in onUnload for "+getName()+":"+e+" - "+e.getMessage();
    //#PluginInfo.java:1062: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.getName: init'ed(this.metaData)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_12
    //#    assertion: init'ed(this.metaData)
    //#    callee: String com/dmdirc/plugins/PluginInfo.getName()
    //#    callee assertion: init'ed(this.metaData)
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [3]
    //#    callee srcpos: 1317
    //#    VN: this.metaData
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
					Logger.userError(ErrorLevel.MEDIUM, lastError, e);
    //#PluginInfo.java:1063: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_12
    //#    assertion: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295] != null
    //#    callee file: Logger.java
    //#    callee precondition index: [2]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new Class[](ErrorManager__static_init#2)[0..4_294_967_295]
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad  Soft
    //#PluginInfo.java:1063: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_12
    //#    assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [6]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).logReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Bad only invalid
    //#PluginInfo.java:1063: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_12
    //#    assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID != null
    //#    callee file: Logger.java
    //#    callee precondition index: [7]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).nextErrorID
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null, Invalid}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:1063: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_12
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports)
    //#    callee file: Logger.java
    //#    callee precondition index: [8]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).sendReports
    //#    Expected: {0,1}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Exp in +/-1000  Soft  Bad only invalid
    //#PluginInfo.java:1063: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_12
    //#    assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295])
    //#    callee file: Logger.java
    //#    callee precondition index: [9]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.ui.FatalErrorDialog$4__static_init.new int[](FatalErrorDialog$4__static_init#1)[0..4_294_967_295]
    //#    Expected: {-2_147_483_648..4_294_967_295}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Soft  Bad only invalid
    //#PluginInfo.java:1063: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_12
    //#    assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread)
    //#    callee file: Logger.java
    //#    callee precondition index: [16]
    //#    callee srcpos: 69
    //#    VN: com.dmdirc.logger.ErrorManager__static_init.new ErrorManager(ErrorManager__static_init#1).reportThread
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
    //#PluginInfo.java:1063: ?precondition failure
    //#    com/dmdirc/logger/Logger.userError: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_12
    //#    assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee: void com/dmdirc/logger/Logger.userError(ErrorLevel, String, Throwable)
    //#    callee assertion: (soft) init'ed(com/dmdirc/logger/ProgramError.errorDir)
    //#    callee file: Logger.java
    //#    callee precondition index: [17]
    //#    callee srcpos: 69
    //#    VN: com/dmdirc/logger/ProgramError.errorDir
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Soft  Bad only invalid
					e.printStackTrace();
				}
				ActionManager.processEvent(CoreActionType.PLUGIN_UNLOADED, null, this);
    //#PluginInfo.java:1066: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.actions.ActionManager:processEvent(ActionType, StringBuffer, Object[])
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    unanalyzed callee: void com.dmdirc.actions.ActionManager:processEvent(ActionType, StringBuffer, Object[])
				for (Service service : provides) {
    //#PluginInfo.java:1067: ?use of default init
    //#    init'ed(this.provides)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_13
    //#    assertion: init'ed(this.provides)
    //#    VN: this.provides
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
    //#PluginInfo.java:1067: ?null dereference
    //#    this.provides != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_13
    //#    assertion: this.provides != null
    //#    VN: this.provides
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:1067: ?ClassCastException check
    //#    com/dmdirc/plugins/Service.__Descendant_Table[java/util/Iterator:next(...).__Tag] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_20
    //#    assertion: com/dmdirc/plugins/Service.__Descendant_Table[java/util/Iterator:next(...).__Tag] != null
    //#    VN: java.util.Iterator:next(...).__Tag@1067 == com/dmdirc/plugins/Service
    //#    Expected: {-Inf..-1, 1..+Inf}
    //#    Bad: {0}
    //#    Attribs:  Int  Bad singleton  Bad overlaps +/-1000  Bad > Exp  Uncertain
					service.delProvider(this);
    //#PluginInfo.java:1068: ?null dereference
    //#    service != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_19
    //#    assertion: service != null
    //#    VN: java.util.Iterator:next(...)@1067
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad  Uncertain
    //#PluginInfo.java:1068: ?null dereference
    //#    com/dmdirc/plugins/Service.__Descendant_Table[service.__Tag] != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_19
    //#    assertion: com/dmdirc/plugins/Service.__Descendant_Table[service.__Tag] != null
    //#    VN: com/dmdirc/plugins/Service.__Descendant_Table[java.util.Iterator:next(...).__Tag]
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:1068: ?precondition failure
    //#    com/dmdirc/plugins/Service.delProvider: this.serviceproviders != null
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void unloadPlugin(bool)
    //#    basic block: bb_19
    //#    assertion: service.serviceproviders@1067 != null
    //#    callee: void com/dmdirc/plugins/Service.delProvider(ServiceProvider)
    //#    callee assertion: this.serviceproviders != null
    //#    callee file: Service.java
    //#    callee precondition index: [3]
    //#    callee srcpos: 84
    //#    VN: service.serviceproviders@1067
    //#    Expected: Inverse{null}
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad  Uncertain
				}
				provides.clear();
			}
			tempLoaded = false;
			plugin = null;
			classloader = null;
		}
	}
    //#PluginInfo.java:1076: end of method: void com.dmdirc.plugins.PluginInfo.unloadPlugin(bool)
	
	/**
	 * Get the last Error
	 *
	 * @return last Error
	 * @since 0.6
	 */
	public String getLastError() { return lastError; }
    //#PluginInfo.java:1084: method: String com.dmdirc.plugins.PluginInfo.getLastError()
    //#input(String getLastError()): this
    //#input(String getLastError()): this.lastError
    //#output(String getLastError()): return_value
    //#pre[2] (String getLastError()): init'ed(this.lastError)
    //#post(String getLastError()): return_value == this.lastError
    //#post(String getLastError()): init'ed(return_value)
    //#PluginInfo.java:1084: end of method: String com.dmdirc.plugins.PluginInfo.getLastError()

	/**
	 * Get the list of Classes
	 *
	 * @return Classes this plugin has
	 */
	public List<String> getClassList() {
		return myClasses;
    //#PluginInfo.java:1092: method: List com.dmdirc.plugins.PluginInfo.getClassList()
    //#input(List getClassList()): this
    //#input(List getClassList()): this.myClasses
    //#output(List getClassList()): return_value
    //#pre[2] (List getClassList()): init'ed(this.myClasses)
    //#post(List getClassList()): return_value == this.myClasses
    //#post(List getClassList()): init'ed(return_value)
    //#PluginInfo.java:1092: end of method: List com.dmdirc.plugins.PluginInfo.getClassList()
	}
	
	/**
	 * Get the value of the given key from the given keysection, or fallback.
	 *
	 * @param section Section to look in
	 * @param key Key to check
	 * @param fallback Value to use if key doesn't exist.
	 * @return Value of the key in the keysection, or the fallback if not present
	 */
	public String getKeyValue(final String section, final String key, final String fallback) {
		if (metaData != null && metaData.isKeyDomain(section)) {
    //#PluginInfo.java:1104: method: String com.dmdirc.plugins.PluginInfo.getKeyValue(String, String, String)
    //#PluginInfo.java:1104: Warning: method not available - call not analyzed
    //#    call on bool com.dmdirc.util.ConfigFile:isKeyDomain(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: String getKeyValue(String, String, String)
    //#    unanalyzed callee: bool com.dmdirc.util.ConfigFile:isKeyDomain(String)
    //#input(String getKeyValue(String, String, String)): fallback
    //#input(String getKeyValue(String, String, String)): key
    //#input(String getKeyValue(String, String, String)): section
    //#input(String getKeyValue(String, String, String)): this
    //#input(String getKeyValue(String, String, String)): this.metaData
    //#output(String getKeyValue(String, String, String)): return_value
    //#pre[5] (String getKeyValue(String, String, String)): init'ed(this.metaData)
    //#presumption(String getKeyValue(String, String, String)): com.dmdirc.util.ConfigFile:getKeyDomain(...)@1105 != null
    //#post(String getKeyValue(String, String, String)): init'ed(return_value)
    //#test_vector(String getKeyValue(String, String, String)): this.metaData: Addr_Set{null}, Inverse{null}
    //#test_vector(String getKeyValue(String, String, String)): com.dmdirc.util.ConfigFile:isKeyDomain(...)@1104: {0}, {1}
			final Map<String, String> keysection = metaData.getKeyDomain(section);
    //#PluginInfo.java:1105: Warning: method not available - call not analyzed
    //#    call on Map com.dmdirc.util.ConfigFile:getKeyDomain(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: String getKeyValue(String, String, String)
    //#    unanalyzed callee: Map com.dmdirc.util.ConfigFile:getKeyDomain(String)
			return keysection.containsKey(key) ? keysection.get(key) : fallback;
		}
		
		return fallback;
    //#PluginInfo.java:1109: end of method: String com.dmdirc.plugins.PluginInfo.getKeyValue(String, String, String)
	}

	/**
	 * Get the main Class
	 *
	 * @return Main Class to begin loading.
	 */
	public String getMainClass() { return getKeyValue("metadata", "mainclass", ""); }
    //#PluginInfo.java:1117: method: String com.dmdirc.plugins.PluginInfo.getMainClass()
    //#input(String getMainClass()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(String getMainClass()): __Descendant_Table[others]
    //#input(String getMainClass()): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(String getMainClass()): this
    //#input(String getMainClass()): this.__Tag
    //#input(String getMainClass()): this.metaData
    //#output(String getMainClass()): return_value
    //#pre[2] (String getMainClass()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[3] (String getMainClass()): init'ed(this.metaData)
    //#post(String getMainClass()): init'ed(return_value)
    //#unanalyzed(String getMainClass()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(String getMainClass()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(String getMainClass()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(String getMainClass()): Effects-of-calling:java.util.Map:get
    //#PluginInfo.java:1117: end of method: String com.dmdirc.plugins.PluginInfo.getMainClass()

	/**
	 * Get the Plugin for this plugin.
	 *
	 * @return Plugin
	 */
	public Plugin getPlugin() { return plugin; }
    //#PluginInfo.java:1124: method: Plugin com.dmdirc.plugins.PluginInfo.getPlugin()
    //#input(Plugin getPlugin()): this
    //#input(Plugin getPlugin()): this.plugin
    //#output(Plugin getPlugin()): return_value
    //#pre[2] (Plugin getPlugin()): init'ed(this.plugin)
    //#post(Plugin getPlugin()): return_value == this.plugin
    //#post(Plugin getPlugin()): init'ed(return_value)
    //#PluginInfo.java:1124: end of method: Plugin com.dmdirc.plugins.PluginInfo.getPlugin()

	/**
	 * Get the PluginClassLoader for this plugin.
	 *
	 * @return PluginClassLoader
	 */
	protected PluginClassLoader getPluginClassLoader() { return classloader; }
    //#PluginInfo.java:1131: method: PluginClassLoader com.dmdirc.plugins.PluginInfo.getPluginClassLoader()
    //#input(PluginClassLoader getPluginClassLoader()): this
    //#input(PluginClassLoader getPluginClassLoader()): this.classloader
    //#output(PluginClassLoader getPluginClassLoader()): return_value
    //#pre[2] (PluginClassLoader getPluginClassLoader()): init'ed(this.classloader)
    //#post(PluginClassLoader getPluginClassLoader()): return_value == this.classloader
    //#post(PluginClassLoader getPluginClassLoader()): init'ed(return_value)
    //#PluginInfo.java:1131: end of method: PluginClassLoader com.dmdirc.plugins.PluginInfo.getPluginClassLoader()

	/**
	 * Get the plugin friendly version
	 *
	 * @return Plugin friendly Version
	 */
	public String getFriendlyVersion() { return getKeyValue("version", "friendly", String.valueOf(getVersion())); }
    //#PluginInfo.java:1138: method: String com.dmdirc.plugins.PluginInfo.getFriendlyVersion()
    //#input(String getFriendlyVersion()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(String getFriendlyVersion()): __Descendant_Table[others]
    //#input(String getFriendlyVersion()): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(String getFriendlyVersion()): __Dispatch_Table.getVersion()Lcom/dmdirc/updater/Version;
    //#input(String getFriendlyVersion()): this
    //#input(String getFriendlyVersion()): this.__Tag
    //#input(String getFriendlyVersion()): this.metaData
    //#output(String getFriendlyVersion()): java.lang.String:valueOf(...)._tainted
    //#output(String getFriendlyVersion()): return_value
    //#new obj(String getFriendlyVersion()): java.lang.String:valueOf(...)
    //#pre[2] (String getFriendlyVersion()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[3] (String getFriendlyVersion()): init'ed(this.metaData)
    //#post(String getFriendlyVersion()): java.lang.String:valueOf(...)._tainted == 0
    //#post(String getFriendlyVersion()): init'ed(return_value)
    //#unanalyzed(String getFriendlyVersion()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(String getFriendlyVersion()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(String getFriendlyVersion()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(String getFriendlyVersion()): Effects-of-calling:java.util.Map:get
    //#unanalyzed(String getFriendlyVersion()): Effects-of-calling:com.dmdirc.updater.Version
    //#PluginInfo.java:1138: end of method: String com.dmdirc.plugins.PluginInfo.getFriendlyVersion()

	/**
	 * Get the plugin version
	 *
	 * @return Plugin Version
	 */
	public Version getVersion() {
        return new Version(getKeyValue("version", "number", "0"));
    //#PluginInfo.java:1146: method: Version com.dmdirc.plugins.PluginInfo.getVersion()
    //#PluginInfo.java:1146: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.updater.Version(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: Version getVersion()
    //#    unanalyzed callee: void com.dmdirc.updater.Version(String)
    //#input(Version getVersion()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(Version getVersion()): __Descendant_Table[others]
    //#input(Version getVersion()): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(Version getVersion()): this
    //#input(Version getVersion()): this.__Tag
    //#input(Version getVersion()): this.metaData
    //#output(Version getVersion()): new Version(getVersion#1) num objects
    //#output(Version getVersion()): return_value
    //#new obj(Version getVersion()): new Version(getVersion#1)
    //#pre[2] (Version getVersion()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[3] (Version getVersion()): init'ed(this.metaData)
    //#post(Version getVersion()): return_value == &new Version(getVersion#1)
    //#post(Version getVersion()): new Version(getVersion#1) num objects == 1
    //#unanalyzed(Version getVersion()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(Version getVersion()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(Version getVersion()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(Version getVersion()): Effects-of-calling:java.util.Map:get
    //#PluginInfo.java:1146: end of method: Version com.dmdirc.plugins.PluginInfo.getVersion()
	}

	/**
	 * Get the id for this plugin on the addons site.
	 * If a plugin has been submitted to addons.dmdirc.com, and plugin.config
	 * contains a property addonid then this will return it.
	 * This is used along with the version property to allow the auto-updater to
	 * update the addon if the author submits a new version to the addons site.
	 *
	 * @return Addon Site ID number
	 *         -1 If not present
	 *         -2 If non-integer
	 */
	public int getAddonID() {
		try {
			return Integer.parseInt(getKeyValue("updates", "id", "-1"));
    //#PluginInfo.java:1162: method: int com.dmdirc.plugins.PluginInfo.getAddonID()
    //#input(int getAddonID()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(int getAddonID()): __Descendant_Table[others]
    //#input(int getAddonID()): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(int getAddonID()): this
    //#input(int getAddonID()): this.__Tag
    //#input(int getAddonID()): this.metaData
    //#output(int getAddonID()): return_value
    //#pre[2] (int getAddonID()): (soft) this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[3] (int getAddonID()): (soft) init'ed(this.metaData)
    //#post(int getAddonID()): init'ed(return_value)
    //#unanalyzed(int getAddonID()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(int getAddonID()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(int getAddonID()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(int getAddonID()): Effects-of-calling:java.util.Map:get
		} catch (NumberFormatException nfe) {
			return -2;
    //#PluginInfo.java:1164: end of method: int com.dmdirc.plugins.PluginInfo.getAddonID()
		}
	}

	/**
	 * Is this a persistent plugin?
	 *
	 * @return true if persistent, else false
	 */
	public boolean isPersistent() {
		if (metaData != null && metaData.isFlatDomain("persistent")) {
    //#PluginInfo.java:1174: method: bool com.dmdirc.plugins.PluginInfo.isPersistent()
    //#PluginInfo.java:1174: Warning: method not available - call not analyzed
    //#    call on bool com.dmdirc.util.ConfigFile:isFlatDomain(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool isPersistent()
    //#    unanalyzed callee: bool com.dmdirc.util.ConfigFile:isFlatDomain(String)
    //#input(bool isPersistent()): this
    //#input(bool isPersistent()): this.metaData
    //#output(bool isPersistent()): return_value
    //#pre[2] (bool isPersistent()): init'ed(this.metaData)
    //#presumption(bool isPersistent()): com.dmdirc.util.ConfigFile:getFlatDomain(...)@1175 != null
    //#post(bool isPersistent()): init'ed(return_value)
    //#test_vector(bool isPersistent()): this.metaData: Addr_Set{null}, Inverse{null}
    //#test_vector(bool isPersistent()): com.dmdirc.util.ConfigFile:isFlatDomain(...)@1174: {0}, {1}
			final List<String> items = metaData.getFlatDomain("persistent");
    //#PluginInfo.java:1175: Warning: method not available - call not analyzed
    //#    call on List com.dmdirc.util.ConfigFile:getFlatDomain(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool isPersistent()
    //#    unanalyzed callee: List com.dmdirc.util.ConfigFile:getFlatDomain(String)
			return items.contains("*");
		}
		
		return false;
    //#PluginInfo.java:1179: end of method: bool com.dmdirc.plugins.PluginInfo.isPersistent()
	}

	/**
	 * Does this plugin contain any persistent classes?
	 *
	 * @return true if this plugin contains any persistent classes, else false
	 */
	public boolean hasPersistent() {
		if (metaData != null && metaData.isFlatDomain("persistent")) {
    //#PluginInfo.java:1188: method: bool com.dmdirc.plugins.PluginInfo.hasPersistent()
    //#PluginInfo.java:1188: Warning: method not available - call not analyzed
    //#    call on bool com.dmdirc.util.ConfigFile:isFlatDomain(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool hasPersistent()
    //#    unanalyzed callee: bool com.dmdirc.util.ConfigFile:isFlatDomain(String)
    //#input(bool hasPersistent()): this
    //#input(bool hasPersistent()): this.metaData
    //#output(bool hasPersistent()): return_value
    //#pre[2] (bool hasPersistent()): init'ed(this.metaData)
    //#presumption(bool hasPersistent()): com.dmdirc.util.ConfigFile:getFlatDomain(...)@1189 != null
    //#post(bool hasPersistent()): init'ed(return_value)
    //#test_vector(bool hasPersistent()): this.metaData: Addr_Set{null}, Inverse{null}
    //#test_vector(bool hasPersistent()): com.dmdirc.util.ConfigFile:isFlatDomain(...)@1188: {0}, {1}
			final List<String> items = metaData.getFlatDomain("persistent");
    //#PluginInfo.java:1189: Warning: method not available - call not analyzed
    //#    call on List com.dmdirc.util.ConfigFile:getFlatDomain(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool hasPersistent()
    //#    unanalyzed callee: List com.dmdirc.util.ConfigFile:getFlatDomain(String)
			return !items.isEmpty();
		}
		
		return false;
    //#PluginInfo.java:1193: end of method: bool com.dmdirc.plugins.PluginInfo.hasPersistent()
	}

	/**
	 * Get a list of all persistent classes in this plugin
	 *
	 * @return List of all persistent classes in this plugin
	 */
	public List<String> getPersistentClasses() {
		final List<String> result = new ArrayList<String>();
    //#PluginInfo.java:1202: method: List com.dmdirc.plugins.PluginInfo.getPersistentClasses()
    //#input(List getPersistentClasses()): "-resourcemanagerTimer"._tainted
    //#input(List getPersistentClasses()): "jar:.."._tainted
    //#input(List getPersistentClasses()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(List getPersistentClasses()): __Descendant_Table[others]
    //#input(List getPersistentClasses()): __Dispatch_Table.getFullFilename()Ljava/lang/String;
    //#input(List getPersistentClasses()): __Dispatch_Table.getResourceManager()Lcom/dmdirc/util/resourcemanager/ResourceManager;
    //#input(List getPersistentClasses()): __Dispatch_Table.getResourceManager(Z)Lcom/dmdirc/util/resourcemanager/ResourceManager;
    //#input(List getPersistentClasses()): __Dispatch_Table.isPersistent()Z
    //#input(List getPersistentClasses()): this
    //#input(List getPersistentClasses()): this.__Tag
    //#input(List getPersistentClasses()): this.filename
    //#input(List getPersistentClasses()): this.filename._tainted
    //#input(List getPersistentClasses()): this.metaData
    //#input(List getPersistentClasses()): this.url
    //#output(List getPersistentClasses()): new ArrayList(getPersistentClasses#1) num objects
    //#output(List getPersistentClasses()): return_value
    //#output(List getPersistentClasses()): this.myResourceManager
    //#new obj(List getPersistentClasses()): new ArrayList(getPersistentClasses#1)
    //#pre[4] (List getPersistentClasses()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[7] (List getPersistentClasses()): init'ed(this.metaData)
    //#pre[8] (List getPersistentClasses()): (soft) this.url != null
    //#presumption(List getPersistentClasses()): com.dmdirc.util.resourcemanager.ResourceManager:getResourcesStartingWith(...)@1208 != null
    //#presumption(List getPersistentClasses()): java.util.Iterator:next(...)@1208 != null
    //#post(List getPersistentClasses()): init'ed(return_value)
    //#post(List getPersistentClasses()): possibly_updated(this.myResourceManager)
    //#post(List getPersistentClasses()): new ArrayList(getPersistentClasses#1) num objects == 1
    //#unanalyzed(List getPersistentClasses()): Effects-of-calling:java.net.URL:getPath
    //#unanalyzed(List getPersistentClasses()): Effects-of-calling:com.dmdirc.util.ConfigFile:isFlatDomain
    //#unanalyzed(List getPersistentClasses()): Effects-of-calling:com.dmdirc.util.ConfigFile:getFlatDomain
    //#unanalyzed(List getPersistentClasses()): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(List getPersistentClasses()): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(List getPersistentClasses()): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(List getPersistentClasses()): Effects-of-calling:java.util.List:contains
    //#unanalyzed(List getPersistentClasses()): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:getResourceManager
    //#unanalyzed(List getPersistentClasses()): Effects-of-calling:java.util.Timer
    //#unanalyzed(List getPersistentClasses()): Effects-of-calling:java.util.TimerTask
    //#unanalyzed(List getPersistentClasses()): Effects-of-calling:java.util.Timer:schedule
    //#test_vector(List getPersistentClasses()): this.metaData: Addr_Set{null}, Inverse{null}
    //#test_vector(List getPersistentClasses()): com.dmdirc.util.ConfigFile:isFlatDomain(...)@1216: {0}, {1}
    //#test_vector(List getPersistentClasses()): java.lang.String:matches(...)@1209: {0}, {1}
		
		if (isPersistent()) {
			try {
				ResourceManager res = getResourceManager();
    //#PluginInfo.java:1206: ?precondition failure
    //#    com/dmdirc/plugins/PluginInfo.getResourceManager: init'ed(this.myResourceManager)
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: List getPersistentClasses()
    //#    basic block: bb_3
    //#    assertion: init'ed(this.myResourceManager)
    //#    callee: ResourceManager com/dmdirc/plugins/PluginInfo.getResourceManager()
    //#    callee assertion: init'ed(this.myResourceManager)
    //#    callee file: PluginInfo.java
    //#    callee precondition index: [1]
    //#    callee srcpos: 464
    //#    VN: this.myResourceManager
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid

				for (final String filename : res.getResourcesStartingWith("")) {
    //#PluginInfo.java:1208: ?null dereference
    //#    res != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: List getPersistentClasses()
    //#    basic block: bb_3
    //#    assertion: res != null
    //#    VN: getResourceManager(...)
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:1208: Warning: method not available - call not analyzed
    //#    call on List com.dmdirc.util.resourcemanager.ResourceManager:getResourcesStartingWith(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: List getPersistentClasses()
    //#    unanalyzed callee: List com.dmdirc.util.resourcemanager.ResourceManager:getResourcesStartingWith(String)
					if (filename.matches("^.*\\.class$")) {
						result.add(filename.replaceAll("\\.class$", "").replace('/', '.'));
					}
				}
			} catch (IOException e) {
				// Jar no longer exists?
			}
		} else if (metaData != null && metaData.isFlatDomain("persistent")) {
    //#PluginInfo.java:1216: Warning: method not available - call not analyzed
    //#    call on bool com.dmdirc.util.ConfigFile:isFlatDomain(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: List getPersistentClasses()
    //#    unanalyzed callee: bool com.dmdirc.util.ConfigFile:isFlatDomain(String)
			return metaData.getFlatDomain("persistent");
    //#PluginInfo.java:1217: Warning: method not available - call not analyzed
    //#    call on List com.dmdirc.util.ConfigFile:getFlatDomain(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: List getPersistentClasses()
    //#    unanalyzed callee: List com.dmdirc.util.ConfigFile:getFlatDomain(String)
		}
		
		return result;
    //#PluginInfo.java:1220: end of method: List com.dmdirc.plugins.PluginInfo.getPersistentClasses()
	}

	/**
	 * Is this a persistent class?
	 *
	 * @param classname class to check persistence of
	 * @return true if file (or whole plugin) is persistent, else false
	 */
	public boolean isPersistent(final String classname) {
		if (isPersistent()) {
    //#PluginInfo.java:1230: method: bool com.dmdirc.plugins.PluginInfo.isPersistent(String)
    //#input(bool isPersistent(String)): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(bool isPersistent(String)): __Descendant_Table[others]
    //#input(bool isPersistent(String)): __Dispatch_Table.isPersistent()Z
    //#input(bool isPersistent(String)): classname
    //#input(bool isPersistent(String)): this
    //#input(bool isPersistent(String)): this.__Tag
    //#input(bool isPersistent(String)): this.metaData
    //#output(bool isPersistent(String)): return_value
    //#pre[3] (bool isPersistent(String)): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[4] (bool isPersistent(String)): init'ed(this.metaData)
    //#presumption(bool isPersistent(String)): com.dmdirc.util.ConfigFile:getFlatDomain(...)@1233 != null
    //#post(bool isPersistent(String)): init'ed(return_value)
    //#unanalyzed(bool isPersistent(String)): Effects-of-calling:com.dmdirc.util.ConfigFile:isFlatDomain
    //#unanalyzed(bool isPersistent(String)): Effects-of-calling:com.dmdirc.util.ConfigFile:getFlatDomain
    //#unanalyzed(bool isPersistent(String)): Effects-of-calling:java.util.List:contains
    //#test_vector(bool isPersistent(String)): this.metaData: Addr_Set{null}, Inverse{null}
    //#test_vector(bool isPersistent(String)): com.dmdirc.util.ConfigFile:isFlatDomain(...)@1232: {0}, {1}
			return true;
		} else if (metaData != null && metaData.isFlatDomain("persistent")) {
    //#PluginInfo.java:1232: Warning: method not available - call not analyzed
    //#    call on bool com.dmdirc.util.ConfigFile:isFlatDomain(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool isPersistent(String)
    //#    unanalyzed callee: bool com.dmdirc.util.ConfigFile:isFlatDomain(String)
			final List<String> items = metaData.getFlatDomain("persistent");
    //#PluginInfo.java:1233: Warning: method not available - call not analyzed
    //#    call on List com.dmdirc.util.ConfigFile:getFlatDomain(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool isPersistent(String)
    //#    unanalyzed callee: List com.dmdirc.util.ConfigFile:getFlatDomain(String)
			return items.contains(classname);
		} else {
			return false;
    //#PluginInfo.java:1236: end of method: bool com.dmdirc.plugins.PluginInfo.isPersistent(String)
		}
	}

	/**
	 * Get the plugin Filename.
	 *
	 * @return Filename of plugin
	 */
	public String getFilename() { return filename; }
    //#PluginInfo.java:1245: method: String com.dmdirc.plugins.PluginInfo.getFilename()
    //#input(String getFilename()): this
    //#input(String getFilename()): this.filename
    //#output(String getFilename()): return_value
    //#post(String getFilename()): return_value == this.filename
    //#post(String getFilename()): init'ed(return_value)
    //#PluginInfo.java:1245: end of method: String com.dmdirc.plugins.PluginInfo.getFilename()

	/**
	 * Get the full plugin Filename (inc dirname)
	 *
	 * @return Filename of plugin
	 */
	public String getFullFilename() { return url.getPath(); }
    //#PluginInfo.java:1252: method: String com.dmdirc.plugins.PluginInfo.getFullFilename()
    //#input(String getFullFilename()): this
    //#input(String getFullFilename()): this.url
    //#output(String getFullFilename()): return_value
    //#pre[2] (String getFullFilename()): this.url != null
    //#post(String getFullFilename()): init'ed(return_value)
    //#PluginInfo.java:1252: end of method: String com.dmdirc.plugins.PluginInfo.getFullFilename()

    /**
     * Retrieves the path to this plugin relative to the main plugin directory,
     * if appropriate.
     *
     * @return A relative path to the plugin if it is situated under the main
     * plugin directory, or an absolute path otherwise.
     */
    public String getRelativeFilename() {
        final String dir = PluginManager.getPluginManager().getDirectory();
    //#PluginInfo.java:1262: method: String com.dmdirc.plugins.PluginInfo.getRelativeFilename()
    //#input(String getRelativeFilename()): "plugins"._tainted
    //#input(String getRelativeFilename()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(String getRelativeFilename()): __Descendant_Table[others]
    //#input(String getRelativeFilename()): __Dispatch_Table.getFullFilename()Ljava/lang/String;
    //#input(String getRelativeFilename()): com/dmdirc/plugins/PluginManager.__Class_Obj.__Lock
    //#input(String getRelativeFilename()): com/dmdirc/plugins/PluginManager.__Descendant_Table[com/dmdirc/plugins/PluginManager]
    //#input(String getRelativeFilename()): com/dmdirc/plugins/PluginManager.__Descendant_Table[others]
    //#input(String getRelativeFilename()): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getDirectory()Ljava/lang/String;
    //#input(String getRelativeFilename()): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getPossiblePluginInfos(Z)Ljava/util/List;
    //#input(String getRelativeFilename()): com/dmdirc/plugins/PluginManager.com.dmdirc.actions.CoreActionType.CLIENT_PREFS_CLOSED
    //#input(String getRelativeFilename()): com/dmdirc/plugins/PluginManager.com.dmdirc.actions.CoreActionType.CLIENT_PREFS_OPENED
    //#input(String getRelativeFilename()): com/dmdirc/plugins/PluginManager.me
    //#input(String getRelativeFilename()): com/dmdirc/plugins/PluginManager.me.__Tag
    //#input(String getRelativeFilename()): com/dmdirc/plugins/PluginManager.me.myDir
    //#input(String getRelativeFilename()): this
    //#input(String getRelativeFilename()): this.__Tag
    //#input(String getRelativeFilename()): this.url
    //#output(String getRelativeFilename()): com/dmdirc/plugins/PluginManager.me
    //#output(String getRelativeFilename()): java.lang.String:substring(...)._tainted
    //#output(String getRelativeFilename()): java.lang.StringBuilder:toString(...)._tainted
    //#output(String getRelativeFilename()): new HashMap(PluginManager#2) num objects
    //#output(String getRelativeFilename()): new Hashtable(PluginManager#1) num objects
    //#output(String getRelativeFilename()): new PluginClassLoader(getSubClassLoader#1) num objects
    //#output(String getRelativeFilename()): new PluginClassLoader(getSubClassLoader#1).__Tag
    //#output(String getRelativeFilename()): new PluginClassLoader(getSubClassLoader#1).pluginInfo
    //#output(String getRelativeFilename()): new PluginManager(getPluginManager#1) num objects
    //#output(String getRelativeFilename()): new PluginManager(getPluginManager#1).__Tag
    //#output(String getRelativeFilename()): new PluginManager(getPluginManager#1).knownPlugins
    //#output(String getRelativeFilename()): new PluginManager(getPluginManager#1).myDir
    //#output(String getRelativeFilename()): new PluginManager(getPluginManager#1).services
    //#output(String getRelativeFilename()): return_value
    //#new obj(String getRelativeFilename()): java.lang.String:substring(...)
    //#new obj(String getRelativeFilename()): java.lang.StringBuilder:toString(...)
    //#new obj(String getRelativeFilename()): new HashMap(PluginManager#2)
    //#new obj(String getRelativeFilename()): new Hashtable(PluginManager#1)
    //#new obj(String getRelativeFilename()): new PluginClassLoader(getSubClassLoader#1)
    //#new obj(String getRelativeFilename()): new PluginManager(getPluginManager#1)
    //#pre[5] (String getRelativeFilename()): init'ed(com/dmdirc/plugins/PluginManager.me)
    //#pre[7] (String getRelativeFilename()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[8] (String getRelativeFilename()): this.url != null
    //#presumption(String getRelativeFilename()): getPluginManager(...).__Tag == com/dmdirc/plugins/PluginManager
    //#presumption(String getRelativeFilename()): getPluginManager(...).myDir != null
    //#presumption(String getRelativeFilename()): getPluginManager(...)@1262 init'ed
    //#presumption(String getRelativeFilename()): java.net.URL:getPath(...)@1252 != null
    //#presumption(String getRelativeFilename()): java.net.URL:getPath(...)@1252 != null
    //#post(String getRelativeFilename()): com/dmdirc/plugins/PluginManager.me == One-of{old com/dmdirc/plugins/PluginManager.me, &new PluginManager(getPluginManager#1)}
    //#post(String getRelativeFilename()): com/dmdirc/plugins/PluginManager.me != null
    //#post(String getRelativeFilename()): java.lang.String:substring(...)._tainted == 0
    //#post(String getRelativeFilename()): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(String getRelativeFilename()): init'ed(return_value)
    //#post(String getRelativeFilename()): new HashMap(PluginManager#2) num objects <= 1
    //#post(String getRelativeFilename()): new Hashtable(PluginManager#1) num objects == new HashMap(PluginManager#2) num objects
    //#post(String getRelativeFilename()): new PluginManager(getPluginManager#1) num objects == new HashMap(PluginManager#2) num objects
    //#post(String getRelativeFilename()): new PluginClassLoader(getSubClassLoader#1) num objects == undefined
    //#post(String getRelativeFilename()): new PluginClassLoader(getSubClassLoader#1) num objects == 0, if init'ed
    //#post(String getRelativeFilename()): new PluginClassLoader(getSubClassLoader#1).__Tag == new PluginClassLoader(getSubClassLoader#1) num objects
    //#post(String getRelativeFilename()): new PluginClassLoader(getSubClassLoader#1).pluginInfo == undefined
    //#post(String getRelativeFilename()): new PluginClassLoader(getSubClassLoader#1).pluginInfo == null
    //#post(String getRelativeFilename()): new PluginManager(getPluginManager#1).__Tag == com/dmdirc/plugins/PluginManager
    //#post(String getRelativeFilename()): new PluginManager(getPluginManager#1).knownPlugins == &new Hashtable(PluginManager#1)
    //#post(String getRelativeFilename()): new PluginManager(getPluginManager#1).myDir == &java.lang.StringBuilder:toString(...)
    //#post(String getRelativeFilename()): new PluginManager(getPluginManager#1).services == &new HashMap(PluginManager#2)
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.lang.String:isEmpty
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.net.URL:getPath
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.util.List:remove
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.util.Map:get
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:com.dmdirc.util.ConfigFile:isFlatDomain
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:com.dmdirc.util.ConfigFile:getFlatDomain
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.util.List:contains
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:getPluginManager
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:addError
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:com.dmdirc.actions.ActionManager:processEvent
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:getPluginInfoByName
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.util.List:iterator
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.lang.ClassLoader
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.lang.String:equalsIgnoreCase
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:unloadPlugin
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:delProvider
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.util.List:clear
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:isUnloadable
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:onUnload
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.lang.Exception:getMessage
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.lang.Exception:printStackTrace
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.lang.Exception
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:com.dmdirc.plugins.PluginInfo
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.util.Hashtable
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.util.HashMap
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.lang.System:getProperty
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:com.dmdirc.Main:getConfigDir
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:com.dmdirc.actions.ActionManager:addListener
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.util.Map:values
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.util.Collection:iterator
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.lang.String:toLowerCase
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.util.Map:put
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.util.LinkedList
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.io.File
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.util.LinkedList:add
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.util.LinkedList:isEmpty
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.util.LinkedList:pop
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.io.File:isDirectory
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.io.File:listFiles
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.io.File:isFile
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.io.File:getName
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.lang.String:endsWith
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.io.File:getPath
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.lang.String:length
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.lang.String:substring
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:addPlugin
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.net.URL
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.net.MalformedURLException:getMessage
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.io.File:exists
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:delPlugin
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:com.dmdirc.updater.components.PluginComponent
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:com.dmdirc.plugins.PluginException:getMessage
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:java.util.Map:remove
    //#unanalyzed(String getRelativeFilename()): Effects-of-calling:getPossiblePluginInfos
    //#test_vector(String getRelativeFilename()): java.lang.String:startsWith(...)@1263: {0}, {1}
        return getFullFilename().startsWith(dir) ? getFullFilename().substring(dir.length()) : getFullFilename();
    //#PluginInfo.java:1263: end of method: String com.dmdirc.plugins.PluginInfo.getRelativeFilename()
    }

	/**
	 * Get the plugin Author.
	 *
	 * @return Author of plugin
	 */
	public String getAuthor() { return getKeyValue("metadata", "author", ""); }
    //#PluginInfo.java:1271: method: String com.dmdirc.plugins.PluginInfo.getAuthor()
    //#input(String getAuthor()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(String getAuthor()): __Descendant_Table[others]
    //#input(String getAuthor()): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(String getAuthor()): this
    //#input(String getAuthor()): this.__Tag
    //#input(String getAuthor()): this.metaData
    //#output(String getAuthor()): return_value
    //#pre[2] (String getAuthor()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[3] (String getAuthor()): init'ed(this.metaData)
    //#post(String getAuthor()): init'ed(return_value)
    //#unanalyzed(String getAuthor()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(String getAuthor()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(String getAuthor()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(String getAuthor()): Effects-of-calling:java.util.Map:get
    //#PluginInfo.java:1271: end of method: String com.dmdirc.plugins.PluginInfo.getAuthor()

	/**
	 * Get the plugin Description.
	 *
	 * @return Description of plugin
	 */
	public String getDescription() { return getKeyValue("metadata", "description", ""); }
    //#PluginInfo.java:1278: method: String com.dmdirc.plugins.PluginInfo.getDescription()
    //#input(String getDescription()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(String getDescription()): __Descendant_Table[others]
    //#input(String getDescription()): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(String getDescription()): this
    //#input(String getDescription()): this.__Tag
    //#input(String getDescription()): this.metaData
    //#output(String getDescription()): return_value
    //#pre[2] (String getDescription()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[3] (String getDescription()): init'ed(this.metaData)
    //#post(String getDescription()): init'ed(return_value)
    //#unanalyzed(String getDescription()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(String getDescription()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(String getDescription()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(String getDescription()): Effects-of-calling:java.util.Map:get
    //#PluginInfo.java:1278: end of method: String com.dmdirc.plugins.PluginInfo.getDescription()

	/**
	 * Get the minimum dmdirc version required to run the plugin.
	 *
	 * @return minimum dmdirc version required to run the plugin.
	 */
	public String getMinVersion() {
		final String requiredVersion = getKeyValue("requires", "dmdirc", "");
    //#PluginInfo.java:1286: method: String com.dmdirc.plugins.PluginInfo.getMinVersion()
    //#input(String getMinVersion()): ""._tainted
    //#input(String getMinVersion()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(String getMinVersion()): __Descendant_Table[others]
    //#input(String getMinVersion()): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(String getMinVersion()): this
    //#input(String getMinVersion()): this.__Tag
    //#input(String getMinVersion()): this.metaData
    //#output(String getMinVersion()): return_value
    //#pre[2] (String getMinVersion()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[3] (String getMinVersion()): init'ed(this.metaData)
    //#post(String getMinVersion()): return_value in Addr_Set{null,&""}
    //#unanalyzed(String getMinVersion()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(String getMinVersion()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(String getMinVersion()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(String getMinVersion()): Effects-of-calling:java.util.Map:get
    //#test_vector(String getMinVersion()): java.lang.String:isEmpty(...)@1287: {1}, {0}
		if (!requiredVersion.isEmpty()) {
    //#PluginInfo.java:1287: ?null dereference
    //#    requiredVersion != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: String getMinVersion()
    //#    basic block: Entry_BB_1
    //#    assertion: requiredVersion != null
    //#    VN: getKeyValue(...)
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
			final String[] bits = requiredVersion.split("-");
			return bits[0];
    //#PluginInfo.java:1289: ?use of default init
    //#    init'ed(bits.length)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: String getMinVersion()
    //#    basic block: bb_2
    //#    assertion: init'ed(bits.length)
    //#    VN: undefined
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#PluginInfo.java:1289: ?use of default init
    //#    init'ed(bits[0])
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: String getMinVersion()
    //#    basic block: bb_2
    //#    assertion: init'ed(bits[0])
    //#    VN: undefined
    //#    Expected: Univ-VN-Set
    //#    Bad: {Invalid}
    //#    Attribs:  Ptr  Bad only invalid
		}
		
		return "";
    //#PluginInfo.java:1292: end of method: String com.dmdirc.plugins.PluginInfo.getMinVersion()
	}

	/**
	 * Get the (optional) maximum dmdirc version on which this plugin can run
	 *
	 * @return optional maximum dmdirc version on which this plugin can run
	 */
	public String getMaxVersion() {
		final String requiredVersion = getKeyValue("requires", "dmdirc", "");
    //#PluginInfo.java:1301: method: String com.dmdirc.plugins.PluginInfo.getMaxVersion()
    //#input(String getMaxVersion()): ""._tainted
    //#input(String getMaxVersion()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(String getMaxVersion()): __Descendant_Table[others]
    //#input(String getMaxVersion()): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(String getMaxVersion()): this
    //#input(String getMaxVersion()): this.__Tag
    //#input(String getMaxVersion()): this.metaData
    //#output(String getMaxVersion()): return_value
    //#pre[2] (String getMaxVersion()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[3] (String getMaxVersion()): init'ed(this.metaData)
    //#post(String getMaxVersion()): return_value == &""
    //#unanalyzed(String getMaxVersion()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(String getMaxVersion()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(String getMaxVersion()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(String getMaxVersion()): Effects-of-calling:java.util.Map:get
    //#test_vector(String getMaxVersion()): java.lang.String:isEmpty(...)@1302: {1}, {0}
		if (!requiredVersion.isEmpty()) {
    //#PluginInfo.java:1302: ?null dereference
    //#    requiredVersion != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: String getMaxVersion()
    //#    basic block: Entry_BB_1
    //#    assertion: requiredVersion != null
    //#    VN: getKeyValue(...)
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
			final String[] bits = requiredVersion.split("-");
			if (bits.length > 1) {
    //#PluginInfo.java:1304: ?use of default init
    //#    init'ed(bits.length)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: String getMaxVersion()
    //#    basic block: bb_2
    //#    assertion: init'ed(bits.length)
    //#    VN: undefined
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#PluginInfo.java:1304: Warning: test always goes same way
    //#    Test predetermined because bits.length == 0
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: String getMaxVersion()
    //#    from bb: bb_2
    //#    live edge: bb_2-->bb_4
    //#    tested vn: undefined - 1
    //#    tested vn values: {-1}
				return bits[1];
    //#PluginInfo.java:1305: Warning: dead code
    //#    Dead code here because bits.length == 0
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: String getMaxVersion()
    //#    dead bb: bb_3
			}
		}
		
		return "";
    //#PluginInfo.java:1309: end of method: String com.dmdirc.plugins.PluginInfo.getMaxVersion()
	}

	/**
	 * Get the name of the plugin. (Used to identify the plugin)
	 *
	 * @return Name of plugin
	 */
	public String getName() { return getKeyValue("metadata", "name", ""); }
    //#PluginInfo.java:1317: method: String com.dmdirc.plugins.PluginInfo.getName()
    //#input(String getName()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(String getName()): __Descendant_Table[others]
    //#input(String getName()): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(String getName()): this
    //#input(String getName()): this.__Tag
    //#input(String getName()): this.metaData
    //#output(String getName()): return_value
    //#pre[2] (String getName()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[3] (String getName()): init'ed(this.metaData)
    //#post(String getName()): init'ed(return_value)
    //#unanalyzed(String getName()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(String getName()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(String getName()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(String getName()): Effects-of-calling:java.util.Map:get
    //#PluginInfo.java:1317: end of method: String com.dmdirc.plugins.PluginInfo.getName()

	/**
	 * Get the nice name of the plugin. (Displayed to users)
	 *
	 * @return Nice Name of plugin
	 */
	public String getNiceName() { return getKeyValue("metadata", "nicename", getName()); }
    //#PluginInfo.java:1324: method: String com.dmdirc.plugins.PluginInfo.getNiceName()
    //#input(String getNiceName()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(String getNiceName()): __Descendant_Table[others]
    //#input(String getNiceName()): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(String getNiceName()): __Dispatch_Table.getName()Ljava/lang/String;
    //#input(String getNiceName()): this
    //#input(String getNiceName()): this.__Tag
    //#input(String getNiceName()): this.metaData
    //#output(String getNiceName()): return_value
    //#pre[2] (String getNiceName()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[3] (String getNiceName()): init'ed(this.metaData)
    //#post(String getNiceName()): init'ed(return_value)
    //#unanalyzed(String getNiceName()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(String getNiceName()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(String getNiceName()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(String getNiceName()): Effects-of-calling:java.util.Map:get
    //#PluginInfo.java:1324: end of method: String com.dmdirc.plugins.PluginInfo.getNiceName()

	/**
	 * String Representation of this plugin
	 *
	 * @return String Representation of this plugin
	 */
	@Override
	public String toString() { return getNiceName()+" - "+filename; }
    //#PluginInfo.java:1332: method: String com.dmdirc.plugins.PluginInfo.toString()
    //#input(String toString()): " - "._tainted
    //#input(String toString()): ""._tainted
    //#input(String toString()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(String toString()): __Descendant_Table[others]
    //#input(String toString()): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(String toString()): __Dispatch_Table.getName()Ljava/lang/String;
    //#input(String toString()): __Dispatch_Table.getNiceName()Ljava/lang/String;
    //#input(String toString()): this
    //#input(String toString()): this.__Tag
    //#input(String toString()): this.filename
    //#input(String toString()): this.filename._tainted
    //#input(String toString()): this.metaData
    //#output(String toString()): java.lang.StringBuilder:toString(...)._tainted
    //#output(String toString()): return_value
    //#new obj(String toString()): java.lang.StringBuilder:toString(...)
    //#pre[2] (String toString()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[5] (String toString()): init'ed(this.metaData)
    //#post(String toString()): init'ed(java.lang.StringBuilder:toString(...)._tainted)
    //#post(String toString()): return_value == &java.lang.StringBuilder:toString(...)
    //#unanalyzed(String toString()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(String toString()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(String toString()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(String toString()): Effects-of-calling:java.util.Map:get
    //#PluginInfo.java:1332: end of method: String com.dmdirc.plugins.PluginInfo.toString()

	/**
	 * Does this plugin want all its classes loaded?
	 *
	 * @return true/false if loadall=true || loadall=yes
	 */
	public boolean loadAll() {
		final String loadAll = getKeyValue("metadata", "loadall", "no");
    //#PluginInfo.java:1340: method: bool com.dmdirc.plugins.PluginInfo.loadAll()
    //#input(bool loadAll()): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(bool loadAll()): __Descendant_Table[others]
    //#input(bool loadAll()): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(bool loadAll()): this
    //#input(bool loadAll()): this.__Tag
    //#input(bool loadAll()): this.metaData
    //#output(bool loadAll()): return_value
    //#pre[2] (bool loadAll()): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[3] (bool loadAll()): init'ed(this.metaData)
    //#post(bool loadAll()): init'ed(return_value)
    //#unanalyzed(bool loadAll()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(bool loadAll()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(bool loadAll()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(bool loadAll()): Effects-of-calling:java.util.Map:get
		return loadAll.equalsIgnoreCase("true") || loadAll.equalsIgnoreCase("yes");
    //#PluginInfo.java:1341: ?null dereference
    //#    loadAll != null
    //#    severity: MEDIUM
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: bool loadAll()
    //#    basic block: Entry_BB_1
    //#    assertion: loadAll != null
    //#    VN: getKeyValue(...)
    //#    Expected: Inverse{null} or Invalid
    //#    Bad: Addr_Set{null}
    //#    Attribs:  Ptr  null in Bad
    //#PluginInfo.java:1341: end of method: bool com.dmdirc.plugins.PluginInfo.loadAll()
	}

	/**
	 * Get misc meta-information.
	 *
	 * @param metainfo The metainfo to return
	 * @deprecated Use {@link #getKeyValue(String, String, String) instead
	 * @return Misc Meta Info (or "" if not found);
	 */
	@Deprecated
	public String getMetaInfo(final String metainfo) { return getMetaInfo(metainfo,""); }
    //#PluginInfo.java:1352: method: String com.dmdirc.plugins.PluginInfo.getMetaInfo(String)
    //#input(String getMetaInfo(String)): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(String getMetaInfo(String)): __Descendant_Table[others]
    //#input(String getMetaInfo(String)): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(String getMetaInfo(String)): __Dispatch_Table.getMetaInfo(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(String getMetaInfo(String)): metainfo
    //#input(String getMetaInfo(String)): this
    //#input(String getMetaInfo(String)): this.__Tag
    //#input(String getMetaInfo(String)): this.metaData
    //#output(String getMetaInfo(String)): return_value
    //#pre[3] (String getMetaInfo(String)): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[4] (String getMetaInfo(String)): init'ed(this.metaData)
    //#post(String getMetaInfo(String)): init'ed(return_value)
    //#unanalyzed(String getMetaInfo(String)): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(String getMetaInfo(String)): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(String getMetaInfo(String)): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(String getMetaInfo(String)): Effects-of-calling:java.util.Map:get
    //#PluginInfo.java:1352: end of method: String com.dmdirc.plugins.PluginInfo.getMetaInfo(String)

	/**
	 * Get misc meta-information.
	 *
	 * @param metainfo The metainfo to return
	 * @param fallback Fallback value if requested value is not found
	 * @deprecated Use {@link #getKeyValue(String, String, String) instead
	 * @return Misc Meta Info (or fallback if not found);
	 */
	@Deprecated
	public String getMetaInfo(final String metainfo, final String fallback) { return getKeyValue("misc", metainfo, fallback); }
    //#PluginInfo.java:1363: method: String com.dmdirc.plugins.PluginInfo.getMetaInfo(String, String)
    //#input(String getMetaInfo(String, String)): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(String getMetaInfo(String, String)): __Descendant_Table[others]
    //#input(String getMetaInfo(String, String)): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(String getMetaInfo(String, String)): fallback
    //#input(String getMetaInfo(String, String)): metainfo
    //#input(String getMetaInfo(String, String)): this
    //#input(String getMetaInfo(String, String)): this.__Tag
    //#input(String getMetaInfo(String, String)): this.metaData
    //#output(String getMetaInfo(String, String)): return_value
    //#pre[4] (String getMetaInfo(String, String)): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[5] (String getMetaInfo(String, String)): init'ed(this.metaData)
    //#post(String getMetaInfo(String, String)): init'ed(return_value)
    //#unanalyzed(String getMetaInfo(String, String)): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(String getMetaInfo(String, String)): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(String getMetaInfo(String, String)): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(String getMetaInfo(String, String)): Effects-of-calling:java.util.Map:get
    //#PluginInfo.java:1363: end of method: String com.dmdirc.plugins.PluginInfo.getMetaInfo(String, String)
	
	/**
	 * Get misc meta-information.
	 *
	 * @param metainfo The metainfos to look for in order. If the first item in
	 *                 the array is not found, the next will be looked for, and
	 *                 so on until either one is found, or none are found.
	 * @deprecated Use {@link #getKeyValue(String, String, String) instead
	 * @return Misc Meta Info (or "" if none are found);
	 */
	@Deprecated
	public String getMetaInfo(final String[] metainfo) { return getMetaInfo(metainfo,""); }
    //#PluginInfo.java:1375: method: String com.dmdirc.plugins.PluginInfo.getMetaInfo(String[])
    //#input(String getMetaInfo(String[])): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(String getMetaInfo(String[])): __Descendant_Table[others]
    //#input(String getMetaInfo(String[])): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(String getMetaInfo(String[])): __Dispatch_Table.getMetaInfo([Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(String getMetaInfo(String[])): metainfo
    //#input(String getMetaInfo(String[])): metainfo.length
    //#input(String getMetaInfo(String[])): metainfo[0..4_294_967_295]
    //#input(String getMetaInfo(String[])): this
    //#input(String getMetaInfo(String[])): this.__Tag
    //#input(String getMetaInfo(String[])): this.metaData
    //#output(String getMetaInfo(String[])): return_value
    //#pre[1] (String getMetaInfo(String[])): metainfo != null
    //#pre[2] (String getMetaInfo(String[])): metainfo.length <= 4_294_967_295
    //#pre[5] (String getMetaInfo(String[])): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[3] (String getMetaInfo(String[])): (soft) init'ed(metainfo[0..4_294_967_295])
    //#pre[6] (String getMetaInfo(String[])): (soft) init'ed(this.metaData)
    //#post(String getMetaInfo(String[])): init'ed(return_value)
    //#unanalyzed(String getMetaInfo(String[])): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(String getMetaInfo(String[])): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(String getMetaInfo(String[])): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(String getMetaInfo(String[])): Effects-of-calling:java.util.Map:get
    //#PluginInfo.java:1375: end of method: String com.dmdirc.plugins.PluginInfo.getMetaInfo(String[])
	
	/**
	 * Get misc meta-information.
	 *
	 * @param metainfo The metainfos to look for in order. If the first item in
	 *                 the array is not found, the next will be looked for, and
	 *                 so on until either one is found, or none are found.
	 * @param fallback Fallback value if requested values are not found
	 * @deprecated Use {@link #getKeyValue(String, String, String) instead
	 * @return Misc Meta Info (or "" if none are found);
	 */
	@Deprecated
	public String getMetaInfo(final String[] metainfo, final String fallback) {
		for (String meta : metainfo) {
    //#PluginInfo.java:1389: method: String com.dmdirc.plugins.PluginInfo.getMetaInfo(String[], String)
    //#input(String getMetaInfo(String[], String)): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(String getMetaInfo(String[], String)): __Descendant_Table[others]
    //#input(String getMetaInfo(String[], String)): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(String getMetaInfo(String[], String)): fallback
    //#input(String getMetaInfo(String[], String)): metainfo
    //#input(String getMetaInfo(String[], String)): metainfo.length
    //#input(String getMetaInfo(String[], String)): metainfo[0..4_294_967_295]
    //#input(String getMetaInfo(String[], String)): this
    //#input(String getMetaInfo(String[], String)): this.__Tag
    //#input(String getMetaInfo(String[], String)): this.metaData
    //#output(String getMetaInfo(String[], String)): return_value
    //#pre[2] (String getMetaInfo(String[], String)): metainfo != null
    //#pre[3] (String getMetaInfo(String[], String)): metainfo.length <= 4_294_967_295
    //#pre[4] (String getMetaInfo(String[], String)): (soft) init'ed(metainfo[0..4_294_967_295])
    //#pre[6] (String getMetaInfo(String[], String)): (soft) this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[7] (String getMetaInfo(String[], String)): (soft) init'ed(this.metaData)
    //#post(String getMetaInfo(String[], String)): init'ed(return_value)
    //#unanalyzed(String getMetaInfo(String[], String)): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(String getMetaInfo(String[], String)): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(String getMetaInfo(String[], String)): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(String getMetaInfo(String[], String)): Effects-of-calling:java.util.Map:get
			final String result = getKeyValue("misc", meta, null);
			if (result != null) { return result; }
		}
		return fallback;
    //#PluginInfo.java:1393: end of method: String com.dmdirc.plugins.PluginInfo.getMetaInfo(String[], String)
	}


	/**
	 * Compares this object with the specified object for order.
	 * Returns a negative integer, zero, or a positive integer as per String.compareTo();
	 *
	 * @param o Object to compare to
	 * @return a negative integer, zero, or a positive integer.
	 */
	@Override
	public int compareTo(final PluginInfo o) {
		return toString().compareTo(o.toString());
    //#PluginInfo.java:1406: method: int com.dmdirc.plugins.PluginInfo.compareTo(PluginInfo)
    //#PluginInfo.java:1406: Warning: unused assignment in callee
    //#    Unused assignment to (java.lang.StringBuilder:toString(...)._tainted) in toString
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: int compareTo(PluginInfo)
    //#input(int compareTo(PluginInfo)): " - "._tainted
    //#input(int compareTo(PluginInfo)): ""._tainted
    //#input(int compareTo(PluginInfo)): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(int compareTo(PluginInfo)): __Descendant_Table[others]
    //#input(int compareTo(PluginInfo)): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(int compareTo(PluginInfo)): __Dispatch_Table.getName()Ljava/lang/String;
    //#input(int compareTo(PluginInfo)): __Dispatch_Table.getNiceName()Ljava/lang/String;
    //#input(int compareTo(PluginInfo)): __Dispatch_Table.toString()Ljava/lang/String;
    //#input(int compareTo(PluginInfo)): o
    //#input(int compareTo(PluginInfo)): o.__Tag
    //#input(int compareTo(PluginInfo)): o.filename
    //#input(int compareTo(PluginInfo)): o.filename._tainted
    //#input(int compareTo(PluginInfo)): o.metaData
    //#input(int compareTo(PluginInfo)): this
    //#input(int compareTo(PluginInfo)): this.__Tag
    //#input(int compareTo(PluginInfo)): this.filename
    //#input(int compareTo(PluginInfo)): this.filename._tainted
    //#input(int compareTo(PluginInfo)): this.metaData
    //#output(int compareTo(PluginInfo)): return_value
    //#pre[1] (int compareTo(PluginInfo)): o != null
    //#pre[2] (int compareTo(PluginInfo)): o.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[5] (int compareTo(PluginInfo)): init'ed(o.metaData)
    //#pre[7] (int compareTo(PluginInfo)): this.__Tag == com/dmdirc/plugins/PluginInfo
    //#pre[10] (int compareTo(PluginInfo)): init'ed(this.metaData)
    //#post(int compareTo(PluginInfo)): init'ed(return_value)
    //#unanalyzed(int compareTo(PluginInfo)): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(int compareTo(PluginInfo)): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(int compareTo(PluginInfo)): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(int compareTo(PluginInfo)): Effects-of-calling:java.util.Map:get
    //#unanalyzed(int compareTo(PluginInfo)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(int compareTo(PluginInfo)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(int compareTo(PluginInfo)): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(int compareTo(PluginInfo)): Effects-of-calling:getNiceName
    //#PluginInfo.java:1406: end of method: int com.dmdirc.plugins.PluginInfo.compareTo(PluginInfo)
	}
	
	/**
	 * Update exports list.
	 */
	private void updateExports() {
		exports.clear();
    //#PluginInfo.java:1413: method: void com.dmdirc.plugins.PluginInfo.updateExports()
    //#input(void updateExports()): "plugins"._tainted
    //#input(void updateExports()): com/dmdirc/plugins/PluginManager.__Class_Obj.__Lock
    //#input(void updateExports()): com/dmdirc/plugins/PluginManager.__Descendant_Table[com/dmdirc/plugins/PluginManager]
    //#input(void updateExports()): com/dmdirc/plugins/PluginManager.__Descendant_Table[others]
    //#input(void updateExports()): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getPossiblePluginInfos(Z)Ljava/util/List;
    //#input(void updateExports()): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getService(Ljava/lang/String;Ljava/lang/String;Z)Lcom/dmdirc/plugins/Service;
    //#input(void updateExports()): com/dmdirc/plugins/PluginManager.com.dmdirc.actions.CoreActionType.CLIENT_PREFS_CLOSED
    //#input(void updateExports()): com/dmdirc/plugins/PluginManager.com.dmdirc.actions.CoreActionType.CLIENT_PREFS_OPENED
    //#input(void updateExports()): com/dmdirc/plugins/PluginManager.me.__Tag
    //#input(void updateExports()): com/dmdirc/plugins/PluginManager.me.services
    //#input(void updateExports()): com/dmdirc/plugins/Service.__Descendant_Table[com/dmdirc/plugins/Service]
    //#input(void updateExports()): com/dmdirc/plugins/Service.__Descendant_Table[others]
    //#input(void updateExports()): com/dmdirc/plugins/Service.__Dispatch_Table.addProvider(Lcom/dmdirc/plugins/ServiceProvider;)V
    //#input(void updateExports()): this
    //#input(void updateExports()): this.exports
    //#input(void updateExports()): this.metaData
    //#input(void updateExports()): this.provides
    //#output(void updateExports()): com/dmdirc/plugins/PluginManager.me
    //#output(void updateExports()): java.lang.StringBuilder:toString(...)._tainted
    //#output(void updateExports()): new HashMap(PluginManager#2) num objects
    //#output(void updateExports()): new Hashtable(PluginManager#1) num objects
    //#output(void updateExports()): new PluginClassLoader(getSubClassLoader#1) num objects
    //#output(void updateExports()): new PluginClassLoader(getSubClassLoader#1).__Tag
    //#output(void updateExports()): new PluginClassLoader(getSubClassLoader#1).pluginInfo
    //#output(void updateExports()): new PluginManager(getPluginManager#1) num objects
    //#output(void updateExports()): new PluginManager(getPluginManager#1).__Tag
    //#output(void updateExports()): new PluginManager(getPluginManager#1).knownPlugins
    //#output(void updateExports()): new PluginManager(getPluginManager#1).myDir
    //#output(void updateExports()): new PluginManager(getPluginManager#1).services
    //#new obj(void updateExports()): java.lang.StringBuilder:toString(...)
    //#new obj(void updateExports()): new HashMap(PluginManager#2)
    //#new obj(void updateExports()): new Hashtable(PluginManager#1)
    //#new obj(void updateExports()): new PluginClassLoader(getSubClassLoader#1)
    //#new obj(void updateExports()): new PluginManager(getPluginManager#1)
    //#pre[7] (void updateExports()): this.exports != null
    //#pre[8] (void updateExports()): this.metaData != null
    //#presumption(void updateExports()): java.util.Iterator:next(...)@1418 != null
    //#post(void updateExports()): possibly_updated(com/dmdirc/plugins/PluginManager.me)
    //#post(void updateExports()): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(void updateExports()): new HashMap(PluginManager#2) num objects == 0
    //#post(void updateExports()): new Hashtable(PluginManager#1) num objects == 0
    //#post(void updateExports()): new PluginClassLoader(getSubClassLoader#1) num objects == 0
    //#post(void updateExports()): possibly_updated(new PluginClassLoader(getSubClassLoader#1).__Tag)
    //#post(void updateExports()): possibly_updated(new PluginClassLoader(getSubClassLoader#1).pluginInfo)
    //#post(void updateExports()): new PluginManager(getPluginManager#1) num objects == 0
    //#post(void updateExports()): init'ed(new PluginManager(getPluginManager#1).__Tag)
    //#post(void updateExports()): init'ed(new PluginManager(getPluginManager#1).knownPlugins)
    //#post(void updateExports()): init'ed(new PluginManager(getPluginManager#1).myDir)
    //#post(void updateExports()): init'ed(new PluginManager(getPluginManager#1).services)
    //#unanalyzed(void updateExports()): Effects-of-calling:java.lang.String:isEmpty
    //#unanalyzed(void updateExports()): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(void updateExports()): Effects-of-calling:java.net.URL:getPath
    //#unanalyzed(void updateExports()): Effects-of-calling:java.util.List:remove
    //#unanalyzed(void updateExports()): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(void updateExports()): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(void updateExports()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(void updateExports()): Effects-of-calling:java.util.Map:get
    //#unanalyzed(void updateExports()): Effects-of-calling:com.dmdirc.util.ConfigFile:isFlatDomain
    //#unanalyzed(void updateExports()): Effects-of-calling:com.dmdirc.util.ConfigFile:getFlatDomain
    //#unanalyzed(void updateExports()): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(void updateExports()): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(void updateExports()): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(void updateExports()): Effects-of-calling:java.util.List:contains
    //#unanalyzed(void updateExports()): Effects-of-calling:getPluginManager
    //#unanalyzed(void updateExports()): Effects-of-calling:addError
    //#unanalyzed(void updateExports()): Effects-of-calling:com.dmdirc.actions.ActionManager:processEvent
    //#unanalyzed(void updateExports()): Effects-of-calling:getPluginInfoByName
    //#unanalyzed(void updateExports()): Effects-of-calling:java.util.List:iterator
    //#unanalyzed(void updateExports()): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(void updateExports()): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(void updateExports()): Effects-of-calling:java.lang.ClassLoader
    //#unanalyzed(void updateExports()): Effects-of-calling:java.lang.String:equalsIgnoreCase
    //#unanalyzed(void updateExports()): Effects-of-calling:unloadPlugin
    //#unanalyzed(void updateExports()): Effects-of-calling:delProvider
    //#unanalyzed(void updateExports()): Effects-of-calling:java.util.List:clear
    //#unanalyzed(void updateExports()): Effects-of-calling:isUnloadable
    //#unanalyzed(void updateExports()): Effects-of-calling:onUnload
    //#unanalyzed(void updateExports()): Effects-of-calling:java.lang.Exception:getMessage
    //#unanalyzed(void updateExports()): Effects-of-calling:java.lang.Exception:printStackTrace
    //#unanalyzed(void updateExports()): Effects-of-calling:java.lang.Exception
    //#unanalyzed(void updateExports()): Effects-of-calling:com.dmdirc.plugins.PluginInfo
    //#unanalyzed(void updateExports()): Effects-of-calling:java.util.Hashtable
    //#unanalyzed(void updateExports()): Effects-of-calling:java.util.HashMap
    //#unanalyzed(void updateExports()): Effects-of-calling:java.lang.System:getProperty
    //#unanalyzed(void updateExports()): Effects-of-calling:com.dmdirc.Main:getConfigDir
    //#unanalyzed(void updateExports()): Effects-of-calling:com.dmdirc.actions.ActionManager:addListener
    //#unanalyzed(void updateExports()): Effects-of-calling:java.util.Map:values
    //#unanalyzed(void updateExports()): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(void updateExports()): Effects-of-calling:java.util.Collection:iterator
    //#unanalyzed(void updateExports()): Effects-of-calling:java.lang.String:toLowerCase
    //#unanalyzed(void updateExports()): Effects-of-calling:java.util.Map:put
    //#unanalyzed(void updateExports()): Effects-of-calling:java.util.LinkedList
    //#unanalyzed(void updateExports()): Effects-of-calling:java.io.File
    //#unanalyzed(void updateExports()): Effects-of-calling:java.util.LinkedList:add
    //#unanalyzed(void updateExports()): Effects-of-calling:java.util.LinkedList:isEmpty
    //#unanalyzed(void updateExports()): Effects-of-calling:java.util.LinkedList:pop
    //#unanalyzed(void updateExports()): Effects-of-calling:java.io.File:isDirectory
    //#unanalyzed(void updateExports()): Effects-of-calling:java.io.File:listFiles
    //#unanalyzed(void updateExports()): Effects-of-calling:java.io.File:isFile
    //#unanalyzed(void updateExports()): Effects-of-calling:java.io.File:getName
    //#unanalyzed(void updateExports()): Effects-of-calling:java.lang.String:endsWith
    //#unanalyzed(void updateExports()): Effects-of-calling:java.io.File:getPath
    //#unanalyzed(void updateExports()): Effects-of-calling:java.lang.String:length
    //#unanalyzed(void updateExports()): Effects-of-calling:java.lang.String:substring
    //#unanalyzed(void updateExports()): Effects-of-calling:addPlugin
    //#unanalyzed(void updateExports()): Effects-of-calling:java.net.URL
    //#unanalyzed(void updateExports()): Effects-of-calling:java.net.MalformedURLException:getMessage
    //#unanalyzed(void updateExports()): Effects-of-calling:java.io.File:exists
    //#unanalyzed(void updateExports()): Effects-of-calling:delPlugin
    //#unanalyzed(void updateExports()): Effects-of-calling:com.dmdirc.updater.components.PluginComponent
    //#unanalyzed(void updateExports()): Effects-of-calling:com.dmdirc.plugins.PluginException:getMessage
    //#unanalyzed(void updateExports()): Effects-of-calling:java.util.Map:remove
    //#unanalyzed(void updateExports()): Effects-of-calling:getPossiblePluginInfos
    //#unanalyzed(void updateExports()): Effects-of-calling:java.util.List:add
    //#test_vector(void updateExports()): com.dmdirc.util.ConfigFile:getFlatDomain(...)@1416: Addr_Set{null}, Inverse{null}
    //#test_vector(void updateExports()): java.util.Iterator:hasNext(...)@1418: {0}, {1}
		
		// Get exports provided by this plugin
		final List<String> exportsList = metaData.getFlatDomain("exports");
    //#PluginInfo.java:1416: Warning: method not available - call not analyzed
    //#    call on List com.dmdirc.util.ConfigFile:getFlatDomain(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void updateExports()
    //#    unanalyzed callee: List com.dmdirc.util.ConfigFile:getFlatDomain(String)
		if (exportsList != null) {
			for (String item : exportsList) {
				final String[] bits = item.split(" ");
				if (bits.length > 2) {
    //#PluginInfo.java:1420: ?use of default init
    //#    init'ed(bits.length)
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void updateExports()
    //#    basic block: bb_4
    //#    assertion: init'ed(bits.length)
    //#    VN: undefined
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#PluginInfo.java:1420: Warning: test always goes same way
    //#    Test predetermined because bits.length == 0
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void updateExports()
    //#    from bb: bb_4
    //#    live edge: bb_4-->bb_9
    //#    tested vn: undefined - 2
    //#    tested vn values: {-2}
					final String methodName = bits[0];
    //#PluginInfo.java:1421: Warning: dead code
    //#    Dead code here because bits.length == 0
    //#    severity: LOW
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void updateExports()
    //#    dead bb: bb_5
					final String methodClass = bits[2];
					final String serviceName = (bits.length > 4) ? bits[4] : bits[0];
    //#PluginInfo.java:1423: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.plugins.PluginInfo
    //#    method: void updateExports()
    //#    dead bb: bb_8
				
					// Add a provides for this
					final Service service = PluginManager.getPluginManager().getService("export", serviceName, true);
					service.addProvider(this);
					provides.add(service);
					// Add is as an export
					exports.put(serviceName, new ExportInfo(methodName, methodClass, this));
				}
			}
		}
	}
    //#PluginInfo.java:1434: end of method: void com.dmdirc.plugins.PluginInfo.updateExports()
	
	/**
	 * Get an ExportedService object from this provider.
	 *
	 * @param name Service name
	 * @return ExportedService object. If no such service exists, the execute
	 *         method of this ExportedService will always return null.
	 */
	@Override
	public ExportedService getExportedService(final String name) {
		if (exports.containsKey(name)) {
    //#PluginInfo.java:1445: method: ExportedService com.dmdirc.plugins.PluginInfo.getExportedService(String)
    //#input(ExportedService getExportedService(String)): ""._tainted
    //#input(ExportedService getExportedService(String)): "' (wanted by "._tainted
    //#input(ExportedService getExportedService(String)): ") -> "._tainted
    //#input(ExportedService getExportedService(String)): ") does not exist."._tainted
    //#input(ExportedService getExportedService(String)): "-resourcemanagerTimer"._tainted
    //#input(ExportedService getExportedService(String)): ".class"._tainted
    //#input(ExportedService getExportedService(String)): "Could not load "._tainted
    //#input(ExportedService getExportedService(String)): "Error loading '"._tainted
    //#input(ExportedService getExportedService(String)): "Resource '"._tainted
    //#input(ExportedService getExportedService(String)): "jar:.."._tainted
    //#input(ExportedService getExportedService(String)): __Descendant_Table[com/dmdirc/plugins/PluginInfo]
    //#input(ExportedService getExportedService(String)): __Descendant_Table[others]
    //#input(ExportedService getExportedService(String)): __Dispatch_Table.getClassList()Ljava/util/List;
    //#input(ExportedService getExportedService(String)): __Dispatch_Table.getFullFilename()Ljava/lang/String;
    //#input(ExportedService getExportedService(String)): __Dispatch_Table.getKeyValue(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
    //#input(ExportedService getExportedService(String)): __Dispatch_Table.getMainClass()Ljava/lang/String;
    //#input(ExportedService getExportedService(String)): __Dispatch_Table.getName()Ljava/lang/String;
    //#input(ExportedService getExportedService(String)): __Dispatch_Table.getPersistentClasses()Ljava/util/List;
    //#input(ExportedService getExportedService(String)): __Dispatch_Table.getPluginClassLoader()Lcom/dmdirc/plugins/PluginClassLoader;
    //#input(ExportedService getExportedService(String)): __Dispatch_Table.getPluginObject()Lcom/dmdirc/plugins/Plugin;
    //#input(ExportedService getExportedService(String)): __Dispatch_Table.getResourceManager()Lcom/dmdirc/util/resourcemanager/ResourceManager;
    //#input(ExportedService getExportedService(String)): __Dispatch_Table.getResourceManager(Z)Lcom/dmdirc/util/resourcemanager/ResourceManager;
    //#input(ExportedService getExportedService(String)): __Dispatch_Table.isPersistent()Z
    //#input(ExportedService getExportedService(String)): __Dispatch_Table.isPersistent(Ljava/lang/String;)Z
    //#input(ExportedService getExportedService(String)): com/dmdirc/plugins/ExportInfo.__Descendant_Table[com/dmdirc/plugins/ExportInfo]
    //#input(ExportedService getExportedService(String)): com/dmdirc/plugins/ExportInfo.__Descendant_Table[others]
    //#input(ExportedService getExportedService(String)): com/dmdirc/plugins/ExportInfo.__Dispatch_Table.getExportedService()Lcom/dmdirc/plugins/ExportedService;
    //#input(ExportedService getExportedService(String)): com/dmdirc/plugins/GlobalClassLoader.__Class_Obj.__Lock
    //#input(ExportedService getExportedService(String)): com/dmdirc/plugins/GlobalClassLoader.me
    //#input(ExportedService getExportedService(String)): com/dmdirc/plugins/PluginClassLoader.__Descendant_Table[com/dmdirc/plugins/PluginClassLoader]
    //#input(ExportedService getExportedService(String)): com/dmdirc/plugins/PluginClassLoader.__Descendant_Table[others]
    //#input(ExportedService getExportedService(String)): com/dmdirc/plugins/PluginClassLoader.__Dispatch_Table.isClassLoaded(Ljava/lang/String;Z)Z
    //#input(ExportedService getExportedService(String)): com/dmdirc/plugins/PluginClassLoader.__Dispatch_Table.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;
    //#input(ExportedService getExportedService(String)): com/dmdirc/plugins/PluginManager.__Descendant_Table[com/dmdirc/plugins/PluginManager]
    //#input(ExportedService getExportedService(String)): com/dmdirc/plugins/PluginManager.__Descendant_Table[others]
    //#input(ExportedService getExportedService(String)): com/dmdirc/plugins/PluginManager.__Dispatch_Table.getPluginInfos()Ljava/util/Collection;
    //#input(ExportedService getExportedService(String)): name
    //#input(ExportedService getExportedService(String)): this
    //#input(ExportedService getExportedService(String)): this.exports
    //#output(ExportedService getExportedService(String)): com/dmdirc/plugins/GlobalClassLoader.me
    //#output(ExportedService getExportedService(String)): new ExportedService(getExportedService#1) num objects
    //#output(ExportedService getExportedService(String)): new ExportedService(getExportedService#1).__Tag
    //#output(ExportedService getExportedService(String)): new ExportedService(getExportedService#1).myMethod
    //#output(ExportedService getExportedService(String)): new ExportedService(getExportedService#1).myObject
    //#output(ExportedService getExportedService(String)): new ExportedService(getExportedService#1*) num objects
    //#output(ExportedService getExportedService(String)): new ExportedService(getExportedService#1*).__Tag
    //#output(ExportedService getExportedService(String)): new ExportedService(getExportedService#1*).myMethod
    //#output(ExportedService getExportedService(String)): new ExportedService(getExportedService#1*).myObject
    //#output(ExportedService getExportedService(String)): new ExportedService(getExportedService#2*) num objects
    //#output(ExportedService getExportedService(String)): new ExportedService(getExportedService#2*).__Tag
    //#output(ExportedService getExportedService(String)): new ExportedService(getExportedService#2*).myMethod
    //#output(ExportedService getExportedService(String)): new ExportedService(getExportedService#2*).myObject
    //#output(ExportedService getExportedService(String)): new GlobalClassLoader(getGlobalClassLoader#1) num objects
    //#output(ExportedService getExportedService(String)): new GlobalClassLoader(getGlobalClassLoader#1).__Tag
    //#output(ExportedService getExportedService(String)): new GlobalClassLoader(getGlobalClassLoader#1).resourcesList
    //#output(ExportedService getExportedService(String)): new HashMap(GlobalClassLoader#1) num objects
    //#output(ExportedService getExportedService(String)): return_value
    //#new obj(ExportedService getExportedService(String)): new ExportedService(getExportedService#1)
    //#new obj(ExportedService getExportedService(String)): new ExportedService(getExportedService#1*)
    //#new obj(ExportedService getExportedService(String)): new ExportedService(getExportedService#2*)
    //#new obj(ExportedService getExportedService(String)): new GlobalClassLoader(getGlobalClassLoader#1)
    //#new obj(ExportedService getExportedService(String)): new HashMap(GlobalClassLoader#1)
    //#pre[5] (ExportedService getExportedService(String)): this.exports != null
    //#pre[3] (ExportedService getExportedService(String)): (soft) com/dmdirc/plugins/GlobalClassLoader.me != null
    //#presumption(ExportedService getExportedService(String)): com/dmdirc/plugins/GlobalClassLoader.me.resourcesList@1446 != null
    //#presumption(ExportedService getExportedService(String)): java.util.Map:get(...).__Tag@1446 == com/dmdirc/plugins/ExportInfo
    //#presumption(ExportedService getExportedService(String)): java.util.Map:get(...).className@1446 != null
    //#presumption(ExportedService getExportedService(String)): java.util.Map:get(...).pluginInfo...__Tag@1446 == com/dmdirc/plugins/PluginInfo
    //#presumption(ExportedService getExportedService(String)): java.util.Map:get(...).pluginInfo...url@1446 != null
    //#presumption(ExportedService getExportedService(String)): java.util.Map:get(...).pluginInfo.__Tag@1446 == com/dmdirc/plugins/PluginInfo
    //#presumption(ExportedService getExportedService(String)): java.util.Map:get(...).pluginInfo.classloader.__Tag@1446 == com/dmdirc/plugins/PluginClassLoader
    //#presumption(ExportedService getExportedService(String)): java.util.Map:get(...).pluginInfo.classloader.pluginInfo@1446 != null
    //#presumption(ExportedService getExportedService(String)): java.util.Map:get(...).pluginInfo.classloader@1446 != null
    //#presumption(ExportedService getExportedService(String)): java.util.Map:get(...).pluginInfo@1446 != null
    //#presumption(ExportedService getExportedService(String)): java.util.Map:get(...)@1446 != null
    //#post(ExportedService getExportedService(String)): init'ed(com/dmdirc/plugins/GlobalClassLoader.me)
    //#post(ExportedService getExportedService(String)): return_value in Addr_Set{&new ExportedService(getExportedService#1),&new ExportedService(getExportedService#1*),&new ExportedService(getExportedService#2*)}
    //#post(ExportedService getExportedService(String)): new ExportedService(getExportedService#1) num objects <= 1
    //#post(ExportedService getExportedService(String)): new ExportedService(getExportedService#1).__Tag == com/dmdirc/plugins/ExportedService
    //#post(ExportedService getExportedService(String)): init'ed(new ExportedService(getExportedService#1).myMethod)
    //#post(ExportedService getExportedService(String)): new ExportedService(getExportedService#1).myObject == null
    //#post(ExportedService getExportedService(String)): new ExportedService(getExportedService#1*) num objects <= 1
    //#post(ExportedService getExportedService(String)): new ExportedService(getExportedService#1*).__Tag == com/dmdirc/plugins/ExportedService
    //#post(ExportedService getExportedService(String)): init'ed(new ExportedService(getExportedService#1*).myMethod)
    //#post(ExportedService getExportedService(String)): init'ed(new ExportedService(getExportedService#1*).myObject)
    //#post(ExportedService getExportedService(String)): new ExportedService(getExportedService#2*) num objects <= 1
    //#post(ExportedService getExportedService(String)): new ExportedService(getExportedService#2*).__Tag == com/dmdirc/plugins/ExportedService
    //#post(ExportedService getExportedService(String)): init'ed(new ExportedService(getExportedService#2*).myMethod)
    //#post(ExportedService getExportedService(String)): new ExportedService(getExportedService#2*).myObject == null
    //#post(ExportedService getExportedService(String)): new GlobalClassLoader(getGlobalClassLoader#1) num objects == 0
    //#post(ExportedService getExportedService(String)): init'ed(new GlobalClassLoader(getGlobalClassLoader#1).__Tag)
    //#post(ExportedService getExportedService(String)): init'ed(new GlobalClassLoader(getGlobalClassLoader#1).resourcesList)
    //#post(ExportedService getExportedService(String)): new HashMap(GlobalClassLoader#1) num objects == 0
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.net.URL:getPath
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:com.dmdirc.util.ConfigFile:isKeyDomain
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:com.dmdirc.util.ConfigFile:getKeyDomain
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.util.Map:get
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:com.dmdirc.util.ConfigFile:isFlatDomain
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:com.dmdirc.util.ConfigFile:getFlatDomain
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.util.List:add
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.lang.String:matches
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.util.List:contains
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:getPluginManager
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:getFullFilename
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:getName
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:getMainClass
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:getResourceManager
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.util.Timer
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.util.TimerTask
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.util.Timer:schedule
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:getResourceManager
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:getResourcesStartingWith
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.util.List:iterator
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.lang.String:replaceAll
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.lang.String:replace
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:com.dmdirc.plugins.PluginClassLoader:findLoadedClass
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.lang.ClassLoader
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.util.HashMap
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:com.dmdirc.plugins.GlobalClassLoader:findLoadedClass
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:com.dmdirc.plugins.PluginClassLoader:getParent
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:loadClass
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:isPersistent
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:resourceExists
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:com.dmdirc.util.resourcemanager.ResourceManager:getResourceBytes
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:com.dmdirc.plugins.GlobalClassLoader:defineClass
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.lang.ClassLoader:loadClass
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:getPluginInfos
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.util.Collection:iterator
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:getClassList
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:getPluginClassLoader
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:getPersistentClasses
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.util.Map:put
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.lang.NoClassDefFoundError:getMessage
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.lang.ClassNotFoundException
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:com.dmdirc.plugins.PluginClassLoader:defineClass
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:com.dmdirc.plugins.PluginClassLoader:resolveClass
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.lang.String:equals
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:getPluginObject
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.lang.Class:getDeclaredMethods
    //#unanalyzed(ExportedService getExportedService(String)): Effects-of-calling:java.lang.reflect.Method:getName
    //#test_vector(ExportedService getExportedService(String)): java.util.Map:containsKey(...)@1445: {0}, {1}
			return exports.get(name).getExportedService();
		} else {
			return new ExportedService(null, null);
    //#PluginInfo.java:1448: end of method: ExportedService com.dmdirc.plugins.PluginInfo.getExportedService(String)
		}
	}
	
	/**
	 * Get the Plugin object for this plugin.
	 *
	 * @return Plugin object for the plugin
	 */
	protected Plugin getPluginObject() {
		return plugin;
    //#PluginInfo.java:1458: method: Plugin com.dmdirc.plugins.PluginInfo.getPluginObject()
    //#input(Plugin getPluginObject()): this
    //#input(Plugin getPluginObject()): this.plugin
    //#output(Plugin getPluginObject()): return_value
    //#pre[2] (Plugin getPluginObject()): init'ed(this.plugin)
    //#post(Plugin getPluginObject()): return_value == this.plugin
    //#post(Plugin getPluginObject()): init'ed(return_value)
    //#PluginInfo.java:1458: end of method: Plugin com.dmdirc.plugins.PluginInfo.getPluginObject()
	}
}
    //#output(com.dmdirc.plugins.PluginInfo$1__static_init): __Descendant_Table[com/dmdirc/plugins/PluginInfo$1]
    //#output(com.dmdirc.plugins.PluginInfo$1__static_init): __Dispatch_Table.run()V
    //#post(com.dmdirc.plugins.PluginInfo$1__static_init): __Descendant_Table[com/dmdirc/plugins/PluginInfo$1] == &__Dispatch_Table
    //#post(com.dmdirc.plugins.PluginInfo$1__static_init): __Dispatch_Table.run()V == &run
    //#PluginInfo.java:: end of method: com.dmdirc.plugins.PluginInfo$1.com.dmdirc.plugins.PluginInfo$1__static_init
    //#PluginInfo.java:: end of class: com.dmdirc.plugins.PluginInfo$1
    //#PluginInfo.java:: end of class: com.dmdirc.plugins.PluginInfo
