//# 1 errors, 410 messages
//#
/*
    //#Update.java:1:1: class: com.dmdirc.updater.Update$1
    //#Update.java:1:1: method: com.dmdirc.updater.Update$1.com.dmdirc.updater.Update$1__static_init
    //#Update.java:1:1: class: com.dmdirc.updater.Update
    //#Update.java:1:1: method: com.dmdirc.updater.Update.com.dmdirc.updater.Update__static_init
 * 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.updater;

import com.dmdirc.Main;
import com.dmdirc.logger.ErrorLevel;
import com.dmdirc.logger.Logger;
import com.dmdirc.util.DownloadListener;
import com.dmdirc.util.Downloader;
import com.dmdirc.util.WeakList;

import java.io.IOException;
import java.util.List;

/**
 * Represents a single available update for some component.
 *
 * @author chris
 */
public final class Update implements DownloadListener {
    //#Update.java:40: method: UpdateComponent com.dmdirc.updater.Update.access$000(Update)
    //#input(UpdateComponent access$000(Update)): x0
    //#input(UpdateComponent access$000(Update)): x0.component
    //#output(UpdateComponent access$000(Update)): return_value
    //#pre[1] (UpdateComponent access$000(Update)): x0 != null
    //#post(UpdateComponent access$000(Update)): return_value == x0.component
    //#post(UpdateComponent access$000(Update)): init'ed(return_value)
    //#Update.java:40: end of method: UpdateComponent com.dmdirc.updater.Update.access$000(Update)

    /** Update component. */
    private final UpdateComponent component;
    /** Remote version name. */
    private final String versionName;
    /** Update url. */
    private final String url;
    /** The progress of the current stage. */
    private float progress;

    /** A list of registered update listeners. */
    private final List<UpdateListener> listeners
            = new WeakList<UpdateListener>();

    /** Our current status. */
    private UpdateStatus status = UpdateStatus.PENDING;

    /**
     * Creates a new instance of Update, with details from the specified line.
     *
     * @param updateInfo An update information line from the update server
     */
    public Update(final String updateInfo) {
    //#Update.java:63: method: void com.dmdirc.updater.Update.com.dmdirc.updater.Update(String)
    //#input(void com.dmdirc.updater.Update(String)): "line: "._tainted
    //#input(void com.dmdirc.updater.Update(String)): com.dmdirc.logger.ErrorLevel.LOW
    //#input(void com.dmdirc.updater.Update(String)): com/dmdirc/updater/UpdateChecker.components
    //#input(void com.dmdirc.updater.Update(String)): com/dmdirc/updater/UpdateComponent.__Descendant_Table[com/dmdirc/updater/UpdateComponent]
    //#input(void com.dmdirc.updater.Update(String)): com/dmdirc/updater/UpdateComponent.__Descendant_Table[com/dmdirc/updater/components/ActionGroupComponent]
    //#input(void com.dmdirc.updater.Update(String)): com/dmdirc/updater/UpdateComponent.__Descendant_Table[com/dmdirc/updater/components/ClientComponent]
    //#input(void com.dmdirc.updater.Update(String)): com/dmdirc/updater/UpdateComponent.__Descendant_Table[com/dmdirc/updater/components/DefaultsComponent]
    //#input(void com.dmdirc.updater.Update(String)): com/dmdirc/updater/UpdateComponent.__Descendant_Table[com/dmdirc/updater/components/LauncherComponent]
    //#input(void com.dmdirc.updater.Update(String)): com/dmdirc/updater/UpdateComponent.__Descendant_Table[com/dmdirc/updater/components/ModeAliasesComponent]
    //#input(void com.dmdirc.updater.Update(String)): com/dmdirc/updater/UpdateComponent.__Descendant_Table[com/dmdirc/updater/components/PluginComponent]
    //#input(void com.dmdirc.updater.Update(String)): com/dmdirc/updater/UpdateComponent.__Descendant_Table[others]
    //#input(void com.dmdirc.updater.Update(String)): com/dmdirc/updater/UpdateComponent.__Dispatch_Table.getName()Ljava/lang/String;
    //#input(void com.dmdirc.updater.Update(String)): com/dmdirc/updater/UpdateStatus.PENDING
    //#input(void com.dmdirc.updater.Update(String)): com/dmdirc/updater/components/ActionGroupComponent.__Dispatch_Table.getName()Ljava/lang/String;
    //#input(void com.dmdirc.updater.Update(String)): com/dmdirc/updater/components/ClientComponent.__Dispatch_Table.getName()Ljava/lang/String;
    //#input(void com.dmdirc.updater.Update(String)): com/dmdirc/updater/components/DefaultsComponent.__Dispatch_Table.getName()Ljava/lang/String;
    //#input(void com.dmdirc.updater.Update(String)): com/dmdirc/updater/components/LauncherComponent.__Dispatch_Table.getName()Ljava/lang/String;
    //#input(void com.dmdirc.updater.Update(String)): com/dmdirc/updater/components/ModeAliasesComponent.__Dispatch_Table.getName()Ljava/lang/String;
    //#input(void com.dmdirc.updater.Update(String)): com/dmdirc/updater/components/PluginComponent.__Dispatch_Table.getName()Ljava/lang/String;
    //#input(void com.dmdirc.updater.Update(String)): this
    //#input(void com.dmdirc.updater.Update(String)): updateInfo
    //#input(void com.dmdirc.updater.Update(String)): updateInfo._tainted
    //#output(void com.dmdirc.updater.Update(String)): new ArrayList(WeakList#1) num objects
    //#output(void com.dmdirc.updater.Update(String)): new WeakList(Update#1) num objects
    //#output(void com.dmdirc.updater.Update(String)): this.listeners.__Tag
    //#output(void com.dmdirc.updater.Update(String)): this.listeners.list
    //#output(void com.dmdirc.updater.Update(String)): this.component
    //#output(void com.dmdirc.updater.Update(String)): this.listeners
    //#output(void com.dmdirc.updater.Update(String)): this.status
    //#output(void com.dmdirc.updater.Update(String)): this.url
    //#output(void com.dmdirc.updater.Update(String)): this.versionName
    //#new obj(void com.dmdirc.updater.Update(String)): new ArrayList(WeakList#1)
    //#new obj(void com.dmdirc.updater.Update(String)): new WeakList(Update#1)
    //#pre[2] (void com.dmdirc.updater.Update(String)): updateInfo != null
    //#presumption(void com.dmdirc.updater.Update(String)): init'ed(com.dmdirc.logger.ErrorLevel.LOW)
    //#post(void com.dmdirc.updater.Update(String)): this.component == null
    //#post(void com.dmdirc.updater.Update(String)): this.listeners == &new WeakList(Update#1)
    //#post(void com.dmdirc.updater.Update(String)): this.status == &com.dmdirc.updater.UpdateStatus__static_init.new UpdateStatus(UpdateStatus__static_init#1)
    //#post(void com.dmdirc.updater.Update(String)): this.url == null
    //#post(void com.dmdirc.updater.Update(String)): this.versionName == null
    //#post(void com.dmdirc.updater.Update(String)): new ArrayList(WeakList#1) num objects == 1
    //#post(void com.dmdirc.updater.Update(String)): new WeakList(Update#1) num objects == 1
    //#post(void com.dmdirc.updater.Update(String)): this.listeners.__Tag == com/dmdirc/util/WeakList
    //#post(void com.dmdirc.updater.Update(String)): this.listeners.list == &new ArrayList(WeakList#1)
    //#unanalyzed(void com.dmdirc.updater.Update(String)): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(void com.dmdirc.updater.Update(String)): Effects-of-calling:getName
    //#unanalyzed(void com.dmdirc.updater.Update(String)): Effects-of-calling:java.util.List:iterator
    //#unanalyzed(void com.dmdirc.updater.Update(String)): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(void com.dmdirc.updater.Update(String)): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(void com.dmdirc.updater.Update(String)): Effects-of-calling:java.lang.String:equals
        // outofdate client STABLE 20071007 0.5.1 file
        final String[] parts = updateInfo.split(" ");

        if (parts.length == 6) {
    //#Update.java:67: ?use of default init
    //#    init'ed(parts.length)
    //#    severity: LOW
    //#    class: com.dmdirc.updater.Update
    //#    method: void com.dmdirc.updater.Update(String)
    //#    basic block: Entry_BB_1
    //#    assertion: init'ed(parts.length)
    //#    VN: undefined
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#Update.java:67: Warning: test always goes same way
    //#    Test predetermined because parts.length == 0
    //#    severity: LOW
    //#    class: com.dmdirc.updater.Update
    //#    method: void com.dmdirc.updater.Update(String)
    //#    from bb: Entry_BB_1
    //#    live edge: Entry_BB_1-->bb_3
    //#    tested vn: undefined - 6
    //#    tested vn values: {-6}
            component = UpdateChecker.findComponent(parts[1]);
    //#Update.java:68: Warning: dead code
    //#    Dead code here because parts.length == 0
    //#    severity: LOW
    //#    class: com.dmdirc.updater.Update
    //#    method: void com.dmdirc.updater.Update(String)
    //#    dead bb: bb_2
            versionName = parts[4];
            url = parts[5];
        } else {
            component = null;
            versionName = null;
            url = null;

            Logger.appError(ErrorLevel.LOW,
    //#Update.java:76: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.logger.Logger:appError(ErrorLevel, String, Throwable)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.updater.Update
    //#    method: void com.dmdirc.updater.Update(String)
    //#    unanalyzed callee: void com.dmdirc.logger.Logger:appError(ErrorLevel, String, Throwable)
                    "Invalid update line received from server: ",
                    new UnsupportedOperationException("line: " + updateInfo));
        }
    }
    //#Update.java:80: end of method: void com.dmdirc.updater.Update.com.dmdirc.updater.Update(String)

    /**
     * Retrieves the component that this update is for.
     *
     * @return The component of this update
     */
    public UpdateComponent getComponent() {
        return component;
    //#Update.java:88: method: UpdateComponent com.dmdirc.updater.Update.getComponent()
    //#input(UpdateComponent getComponent()): this
    //#input(UpdateComponent getComponent()): this.component
    //#output(UpdateComponent getComponent()): return_value
    //#post(UpdateComponent getComponent()): return_value == this.component
    //#post(UpdateComponent getComponent()): init'ed(return_value)
    //#Update.java:88: end of method: UpdateComponent com.dmdirc.updater.Update.getComponent()
    }

    /**
     * Returns the remote version of the component that's available.
     *
     * @return The remote version number
     */
    public String getRemoteVersion() {
        return versionName;
    //#Update.java:97: method: String com.dmdirc.updater.Update.getRemoteVersion()
    //#input(String getRemoteVersion()): this
    //#input(String getRemoteVersion()): this.versionName
    //#output(String getRemoteVersion()): return_value
    //#post(String getRemoteVersion()): return_value == this.versionName
    //#post(String getRemoteVersion()): init'ed(return_value)
    //#Update.java:97: end of method: String com.dmdirc.updater.Update.getRemoteVersion()
    }

    /**
     * Returns the URL where the new update may be downloaded.
     *
     * @return The URL of the update
     */
    public String getUrl() {
        return url;
    //#Update.java:106: method: String com.dmdirc.updater.Update.getUrl()
    //#input(String getUrl()): this
    //#input(String getUrl()): this.url
    //#output(String getUrl()): return_value
    //#post(String getUrl()): return_value == this.url
    //#post(String getUrl()): init'ed(return_value)
    //#Update.java:106: end of method: String com.dmdirc.updater.Update.getUrl()
    }

    /**
     * Retrieves the status of this update.
     *
     * @return This update's status
     */
    public UpdateStatus getStatus() {
        return status;
    //#Update.java:115: method: UpdateStatus com.dmdirc.updater.Update.getStatus()
    //#input(UpdateStatus getStatus()): this
    //#input(UpdateStatus getStatus()): this.status
    //#output(UpdateStatus getStatus()): return_value
    //#pre[2] (UpdateStatus getStatus()): init'ed(this.status)
    //#post(UpdateStatus getStatus()): return_value == this.status
    //#post(UpdateStatus getStatus()): init'ed(return_value)
    //#Update.java:115: end of method: UpdateStatus com.dmdirc.updater.Update.getStatus()
    }

    /**
     * Sets the status of this update, and notifies all listeners of the change.
     *
     * @param newStatus This update's new status
     */
    protected void setStatus(final UpdateStatus newStatus) {
        status = newStatus;
    //#Update.java:124: method: void com.dmdirc.updater.Update.setStatus(UpdateStatus)
    //#Update.java:124: Warning: suspicious precondition
    //#    The precondition for com.dmdirc.util.ListenerList.new MapList(ListenerList#1).__Tag is not a contiguous range of values
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.updater.Update
    //#    method: void setStatus(UpdateStatus)
    //#    suspicious precondition index: [1]
    //#    Attribs:  Soft
    //#input(void setStatus(UpdateStatus)): __Descendant_Table[com/dmdirc/updater/Update]
    //#input(void setStatus(UpdateStatus)): __Descendant_Table[others]
    //#input(void setStatus(UpdateStatus)): com.dmdirc.updater.UpdateChecker__static_init.new ListenerList(UpdateChecker__static_init#5).__Tag
    //#input(void setStatus(UpdateStatus)): com.dmdirc.updater.UpdateChecker__static_init.new ListenerList(UpdateChecker__static_init#5).listeners
    //#input(void setStatus(UpdateStatus)): com.dmdirc.updater.UpdateChecker__static_init.new ListenerList(UpdateChecker__static_init#5).listeners.__Tag
    //#input(void setStatus(UpdateStatus)): com.dmdirc.updater.UpdateChecker__static_init.new ListenerList(UpdateChecker__static_init#5).listeners.map
    //#input(void setStatus(UpdateStatus)): com.dmdirc.util.ListenerList.new MapList(ListenerList#1).__Tag
    //#input(void setStatus(UpdateStatus)): com.dmdirc.util.ListenerList.new MapList(ListenerList#1).map
    //#input(void setStatus(UpdateStatus)): com/dmdirc/updater/UpdateChecker$1.__Dispatch_Table.updateStatusChange(Lcom/dmdirc/updater/Update;Lcom/dmdirc/updater/UpdateStatus;)V
    //#input(void setStatus(UpdateStatus)): com/dmdirc/updater/UpdateChecker$STATE.IDLE
    //#input(void setStatus(UpdateStatus)): com/dmdirc/updater/UpdateChecker$STATE.RESTART_REQUIRED
    //#input(void setStatus(UpdateStatus)): com/dmdirc/updater/UpdateChecker$STATE.UPDATING
    //#input(void setStatus(UpdateStatus)): com/dmdirc/updater/UpdateChecker.listener
    //#input(void setStatus(UpdateStatus)): com/dmdirc/updater/UpdateChecker.listeners
    //#input(void setStatus(UpdateStatus)): com/dmdirc/updater/UpdateChecker.status
    //#input(void setStatus(UpdateStatus)): com/dmdirc/updater/UpdateChecker.updates
    //#input(void setStatus(UpdateStatus)): com/dmdirc/updater/UpdateCheckerListener.__Descendant_Table[com/dmdirc/updater/UpdateCheckerListener]
    //#input(void setStatus(UpdateStatus)): com/dmdirc/updater/UpdateCheckerListener.__Descendant_Table[others]
    //#input(void setStatus(UpdateStatus)): com/dmdirc/updater/UpdateCheckerListener.__Dispatch_Table.statusChanged(Lcom/dmdirc/updater/UpdateChecker$STATE;)V
    //#input(void setStatus(UpdateStatus)): com/dmdirc/updater/UpdateListener.__Descendant_Table[com/dmdirc/updater/UpdateChecker$1]
    //#input(void setStatus(UpdateStatus)): com/dmdirc/updater/UpdateListener.__Descendant_Table[com/dmdirc/updater/UpdateListener]
    //#input(void setStatus(UpdateStatus)): com/dmdirc/updater/UpdateListener.__Descendant_Table[others]
    //#input(void setStatus(UpdateStatus)): com/dmdirc/updater/UpdateListener.__Dispatch_Table.updateStatusChange(Lcom/dmdirc/updater/Update;Lcom/dmdirc/updater/UpdateStatus;)V
    //#input(void setStatus(UpdateStatus)): com/dmdirc/updater/UpdateStatus.ERROR
    //#input(void setStatus(UpdateStatus)): com/dmdirc/updater/UpdateStatus.INSTALLED
    //#input(void setStatus(UpdateStatus)): com/dmdirc/updater/UpdateStatus.PENDING
    //#input(void setStatus(UpdateStatus)): com/dmdirc/updater/UpdateStatus.RESTART_NEEDED
    //#input(void setStatus(UpdateStatus)): com/dmdirc/util/ListenerList.__Descendant_Table[com/dmdirc/util/ListenerList]
    //#input(void setStatus(UpdateStatus)): com/dmdirc/util/ListenerList.__Dispatch_Table.get(Ljava/lang/Class;)Ljava/util/List;
    //#input(void setStatus(UpdateStatus)): com/dmdirc/util/MapList.__Descendant_Table[com/dmdirc/util/MapList]
    //#input(void setStatus(UpdateStatus)): com/dmdirc/util/MapList.__Descendant_Table[com/dmdirc/util/WeakMapList]
    //#input(void setStatus(UpdateStatus)): com/dmdirc/util/MapList.__Descendant_Table[others]
    //#input(void setStatus(UpdateStatus)): com/dmdirc/util/MapList.__Dispatch_Table.containsKey(Ljava/lang/Object;)Z
    //#input(void setStatus(UpdateStatus)): com/dmdirc/util/MapList.__Dispatch_Table.get(Ljava/lang/Object;)Ljava/util/List;
    //#input(void setStatus(UpdateStatus)): com/dmdirc/util/WeakMapList.__Dispatch_Table.containsKey(Ljava/lang/Object;)Z
    //#input(void setStatus(UpdateStatus)): com/dmdirc/util/WeakMapList.__Dispatch_Table.get(Ljava/lang/Object;)Ljava/util/List;
    //#input(void setStatus(UpdateStatus)): newStatus
    //#input(void setStatus(UpdateStatus)): this
    //#input(void setStatus(UpdateStatus)): this.listeners
    //#output(void setStatus(UpdateStatus)): com/dmdirc/updater/UpdateChecker.status
    //#output(void setStatus(UpdateStatus)): this.progress
    //#output(void setStatus(UpdateStatus)): this.status
    //#pre[6] (void setStatus(UpdateStatus)): this.listeners != null
    //#pre[1] (void setStatus(UpdateStatus)): (soft) com.dmdirc.util.ListenerList.new MapList(ListenerList#1).__Tag in {com/dmdirc/util/MapList, com/dmdirc/util/WeakMapList}
    //#pre[2] (void setStatus(UpdateStatus)): (soft) com.dmdirc.util.ListenerList.new MapList(ListenerList#1).map != null
    //#pre[4] (void setStatus(UpdateStatus)): (soft) init'ed(com/dmdirc/updater/UpdateChecker.status)
    //#presumption(void setStatus(UpdateStatus)): java.util.Iterator:next(...).__Tag@127 in {com/dmdirc/updater/UpdateChecker$1, com/dmdirc/updater/UpdateListener}
    //#presumption(void setStatus(UpdateStatus)): java.util.Iterator:next(...)@127 != null
    //#post(void setStatus(UpdateStatus)): init'ed(com/dmdirc/updater/UpdateChecker.status)
    //#post(void setStatus(UpdateStatus)): this.progress == +0
    //#post(void setStatus(UpdateStatus)): init'ed(this.status)
    //#unanalyzed(void setStatus(UpdateStatus)): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(void setStatus(UpdateStatus)): Effects-of-calling:java.util.List:iterator
    //#unanalyzed(void setStatus(UpdateStatus)): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(void setStatus(UpdateStatus)): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(void setStatus(UpdateStatus)): Effects-of-calling:java.lang.Thread
    //#unanalyzed(void setStatus(UpdateStatus)): Effects-of-calling:java.lang.Thread:start
    //#unanalyzed(void setStatus(UpdateStatus)): Effects-of-calling:java.util.List:remove
    //#unanalyzed(void setStatus(UpdateStatus)): Effects-of-calling:removeUpdate
    //#unanalyzed(void setStatus(UpdateStatus)): Effects-of-calling:access$000
    //#unanalyzed(void setStatus(UpdateStatus)): Effects-of-calling:access$100
    //#unanalyzed(void setStatus(UpdateStatus)): Effects-of-calling:getStatus
    //#unanalyzed(void setStatus(UpdateStatus)): Effects-of-calling:doUpdate
    //#unanalyzed(void setStatus(UpdateStatus)): Effects-of-calling:setStatus
    //#unanalyzed(void setStatus(UpdateStatus)): Effects-of-calling:java.util.List:isEmpty
    //#unanalyzed(void setStatus(UpdateStatus)): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(void setStatus(UpdateStatus)): Effects-of-calling:java.util.Map:get
    //#unanalyzed(void setStatus(UpdateStatus)): Effects-of-calling:statusChanged
    //#unanalyzed(void setStatus(UpdateStatus)): Effects-of-calling:removeUpdateListener
    //#test_vector(void setStatus(UpdateStatus)): java.util.Iterator:hasNext(...)@127: {0}, {1}
        progress = 0;

        for (UpdateListener listener : listeners) {
            listener.updateStatusChange(this, status);
        }
    }
    //#Update.java:130: end of method: void com.dmdirc.updater.Update.setStatus(UpdateStatus)

    /**
     * Removes the specified update listener.
     *
     * @param o The update listener to remove
     */
    public void removeUpdateListener(final Object o) {
        listeners.remove(o);
    //#Update.java:138: method: void com.dmdirc.updater.Update.removeUpdateListener(Object)
    //#input(void removeUpdateListener(Object)): o
    //#input(void removeUpdateListener(Object)): this
    //#input(void removeUpdateListener(Object)): this.listeners
    //#pre[3] (void removeUpdateListener(Object)): this.listeners != null
    }
    //#Update.java:139: end of method: void com.dmdirc.updater.Update.removeUpdateListener(Object)

    /**
     * Adds the specified update listener.
     *
     * @param e The update listener to add
     */
    public void addUpdateListener(final UpdateListener e) {
        listeners.add(e);
    //#Update.java:147: method: void com.dmdirc.updater.Update.addUpdateListener(UpdateListener)
    //#input(void addUpdateListener(UpdateListener)): e
    //#input(void addUpdateListener(UpdateListener)): this
    //#input(void addUpdateListener(UpdateListener)): this.listeners
    //#pre[3] (void addUpdateListener(UpdateListener)): this.listeners != null
    }
    //#Update.java:148: end of method: void com.dmdirc.updater.Update.addUpdateListener(UpdateListener)

    /**
     * Makes this update download and install itself.
     */
    public void doUpdate() {
        new Thread(new Runnable() {
    //#Update.java:154: method: void com.dmdirc.updater.Update$1.com.dmdirc.updater.Update$1(Update)
    //#input(void com.dmdirc.updater.Update$1(Update)): Param_1
    //#input(void com.dmdirc.updater.Update$1(Update)): this
    //#output(void com.dmdirc.updater.Update$1(Update)): this.this$0
    //#post(void com.dmdirc.updater.Update$1(Update)): this.this$0 == Param_1
    //#post(void com.dmdirc.updater.Update$1(Update)): init'ed(this.this$0)
    //#Update.java:154: end of method: void com.dmdirc.updater.Update$1.com.dmdirc.updater.Update$1(Update)
    //#Update.java:154: method: void com.dmdirc.updater.Update.doUpdate()
    //#input(void doUpdate()): this

            /** {@inheritDoc} */
            @Override
            public void run() {
                final String path = Main.getConfigDir() + "update.tmp."
    //#Update.java:159: method: void com.dmdirc.updater.Update$1.run()
    //#Update.java:159: Warning: method not available - call not analyzed
    //#    call on String com.dmdirc.Main:getConfigDir()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.updater.Update$1
    //#    method: void run()
    //#    unanalyzed callee: String com.dmdirc.Main:getConfigDir()
    //#Update.java:159: Warning: suspicious precondition
    //#    The precondition for com.dmdirc.util.ListenerList.new MapList(ListenerList#1).__Tag is not a contiguous range of values
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.updater.Update$1
    //#    method: void run()
    //#    suspicious precondition index: [1]
    //#    Attribs:  Soft
    //#Update.java:159: Warning: suspicious precondition
    //#    The precondition for this.this$0.__Tag is not a contiguous range of values
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.updater.Update$1
    //#    method: void run()
    //#    suspicious precondition index: [6]
    //#    Attribs:  Soft
    //#Update.java:159: Warning: suspicious precondition
    //#    The precondition for this.this$0.component.__Tag is not a contiguous range of values
    //#    severity: SUPPRESSED
    //#    class: com.dmdirc.updater.Update$1
    //#    method: void run()
    //#    suspicious precondition index: [8]
    //#input(void run()): "Error when updating component "._tainted
    //#input(void run()): "I.O error when updating component "._tainted
    //#input(void run()): "update.tmp."._tainted
    //#input(void run()): com.dmdirc.logger.ErrorLevel.MEDIUM
    //#input(void run()): com.dmdirc.updater.UpdateChecker__static_init.new ListenerList(UpdateChecker__static_init#5).__Tag
    //#input(void run()): com.dmdirc.updater.UpdateChecker__static_init.new ListenerList(UpdateChecker__static_init#5).listeners
    //#input(void run()): com.dmdirc.updater.UpdateChecker__static_init.new ListenerList(UpdateChecker__static_init#5).listeners.__Tag
    //#input(void run()): com.dmdirc.updater.UpdateChecker__static_init.new ListenerList(UpdateChecker__static_init#5).listeners.map
    //#input(void run()): com.dmdirc.util.ListenerList.new MapList(ListenerList#1).__Tag
    //#input(void run()): com.dmdirc.util.ListenerList.new MapList(ListenerList#1).map
    //#input(void run()): com/dmdirc/updater/Update.__Descendant_Table[com/dmdirc/updater/Update]
    //#input(void run()): com/dmdirc/updater/Update.__Descendant_Table[others]
    //#input(void run()): com/dmdirc/updater/Update.__Dispatch_Table.downloadProgress(F)V
    //#input(void run()): com/dmdirc/updater/Update.__Dispatch_Table.setIndeterminate(Z)V
    //#input(void run()): com/dmdirc/updater/UpdateChecker$1.__Dispatch_Table.updateProgressChange(Lcom/dmdirc/updater/Update;F)V
    //#input(void run()): com/dmdirc/updater/UpdateChecker$1.__Dispatch_Table.updateStatusChange(Lcom/dmdirc/updater/Update;Lcom/dmdirc/updater/UpdateStatus;)V
    //#input(void run()): com/dmdirc/updater/UpdateChecker$STATE.IDLE
    //#input(void run()): com/dmdirc/updater/UpdateChecker$STATE.RESTART_REQUIRED
    //#input(void run()): com/dmdirc/updater/UpdateChecker$STATE.UPDATING
    //#input(void run()): com/dmdirc/updater/UpdateChecker.components
    //#input(void run()): com/dmdirc/updater/UpdateChecker.listener
    //#input(void run()): com/dmdirc/updater/UpdateChecker.listeners
    //#input(void run()): com/dmdirc/updater/UpdateChecker.status
    //#input(void run()): com/dmdirc/updater/UpdateChecker.updates
    //#input(void run()): com/dmdirc/updater/UpdateCheckerListener.__Descendant_Table[com/dmdirc/updater/UpdateCheckerListener]
    //#input(void run()): com/dmdirc/updater/UpdateCheckerListener.__Descendant_Table[others]
    //#input(void run()): com/dmdirc/updater/UpdateCheckerListener.__Dispatch_Table.statusChanged(Lcom/dmdirc/updater/UpdateChecker$STATE;)V
    //#input(void run()): com/dmdirc/updater/UpdateComponent.__Descendant_Table[com/dmdirc/updater/UpdateComponent]
    //#input(void run()): com/dmdirc/updater/UpdateComponent.__Descendant_Table[com/dmdirc/updater/components/ActionGroupComponent]
    //#input(void run()): com/dmdirc/updater/UpdateComponent.__Descendant_Table[com/dmdirc/updater/components/ClientComponent]
    //#input(void run()): com/dmdirc/updater/UpdateComponent.__Descendant_Table[com/dmdirc/updater/components/DefaultsComponent]
    //#input(void run()): com/dmdirc/updater/UpdateComponent.__Descendant_Table[com/dmdirc/updater/components/LauncherComponent]
    //#input(void run()): com/dmdirc/updater/UpdateComponent.__Descendant_Table[com/dmdirc/updater/components/ModeAliasesComponent]
    //#input(void run()): com/dmdirc/updater/UpdateComponent.__Descendant_Table[com/dmdirc/updater/components/PluginComponent]
    //#input(void run()): com/dmdirc/updater/UpdateComponent.__Descendant_Table[others]
    //#input(void run()): com/dmdirc/updater/UpdateComponent.__Dispatch_Table.doInstall(Ljava/lang/String;)Z
    //#input(void run()): com/dmdirc/updater/UpdateComponent.__Dispatch_Table.getName()Ljava/lang/String;
    //#input(void run()): com/dmdirc/updater/UpdateListener.__Descendant_Table[com/dmdirc/updater/UpdateChecker$1]
    //#input(void run()): com/dmdirc/updater/UpdateListener.__Descendant_Table[com/dmdirc/updater/UpdateListener]
    //#input(void run()): com/dmdirc/updater/UpdateListener.__Descendant_Table[others]
    //#input(void run()): com/dmdirc/updater/UpdateListener.__Dispatch_Table.updateProgressChange(Lcom/dmdirc/updater/Update;F)V
    //#input(void run()): com/dmdirc/updater/UpdateListener.__Dispatch_Table.updateStatusChange(Lcom/dmdirc/updater/Update;Lcom/dmdirc/updater/UpdateStatus;)V
    //#input(void run()): com/dmdirc/updater/UpdateStatus.DOWNLOADING
    //#input(void run()): com/dmdirc/updater/UpdateStatus.ERROR
    //#input(void run()): com/dmdirc/updater/UpdateStatus.INSTALLED
    //#input(void run()): com/dmdirc/updater/UpdateStatus.INSTALLING
    //#input(void run()): com/dmdirc/updater/UpdateStatus.PENDING
    //#input(void run()): com/dmdirc/updater/UpdateStatus.RESTART_NEEDED
    //#input(void run()): com/dmdirc/updater/components/ActionGroupComponent.__Dispatch_Table.doInstall(Ljava/lang/String;)Z
    //#input(void run()): com/dmdirc/updater/components/ActionGroupComponent.__Dispatch_Table.getName()Ljava/lang/String;
    //#input(void run()): com/dmdirc/updater/components/ClientComponent.__Dispatch_Table.doInstall(Ljava/lang/String;)Z
    //#input(void run()): com/dmdirc/updater/components/ClientComponent.__Dispatch_Table.getName()Ljava/lang/String;
    //#input(void run()): com/dmdirc/updater/components/DefaultsComponent.__Dispatch_Table.doInstall(Ljava/lang/String;)Z
    //#input(void run()): com/dmdirc/updater/components/DefaultsComponent.__Dispatch_Table.getName()Ljava/lang/String;
    //#input(void run()): com/dmdirc/updater/components/LauncherComponent.__Dispatch_Table.doInstall(Ljava/lang/String;)Z
    //#input(void run()): com/dmdirc/updater/components/LauncherComponent.__Dispatch_Table.getName()Ljava/lang/String;
    //#input(void run()): com/dmdirc/updater/components/ModeAliasesComponent.__Dispatch_Table.doInstall(Ljava/lang/String;)Z
    //#input(void run()): com/dmdirc/updater/components/ModeAliasesComponent.__Dispatch_Table.getName()Ljava/lang/String;
    //#input(void run()): com/dmdirc/updater/components/PluginComponent.__Dispatch_Table.doInstall(Ljava/lang/String;)Z
    //#input(void run()): com/dmdirc/updater/components/PluginComponent.__Dispatch_Table.getName()Ljava/lang/String;
    //#input(void run()): com/dmdirc/util/DownloadListener.__Descendant_Table[com/dmdirc/updater/Update]
    //#input(void run()): com/dmdirc/util/DownloadListener.__Descendant_Table[com/dmdirc/util/DownloadListener]
    //#input(void run()): com/dmdirc/util/DownloadListener.__Descendant_Table[others]
    //#input(void run()): com/dmdirc/util/DownloadListener.__Dispatch_Table.downloadProgress(F)V
    //#input(void run()): com/dmdirc/util/DownloadListener.__Dispatch_Table.setIndeterminate(Z)V
    //#input(void run()): com/dmdirc/util/ListenerList.__Descendant_Table[com/dmdirc/util/ListenerList]
    //#input(void run()): com/dmdirc/util/ListenerList.__Dispatch_Table.get(Ljava/lang/Class;)Ljava/util/List;
    //#input(void run()): com/dmdirc/util/MapList.__Descendant_Table[com/dmdirc/util/MapList]
    //#input(void run()): com/dmdirc/util/MapList.__Descendant_Table[com/dmdirc/util/WeakMapList]
    //#input(void run()): com/dmdirc/util/MapList.__Descendant_Table[others]
    //#input(void run()): com/dmdirc/util/MapList.__Dispatch_Table.containsKey(Ljava/lang/Object;)Z
    //#input(void run()): com/dmdirc/util/MapList.__Dispatch_Table.get(Ljava/lang/Object;)Ljava/util/List;
    //#input(void run()): com/dmdirc/util/WeakMapList.__Dispatch_Table.containsKey(Ljava/lang/Object;)Z
    //#input(void run()): com/dmdirc/util/WeakMapList.__Dispatch_Table.get(Ljava/lang/Object;)Ljava/util/List;
    //#input(void run()): this
    //#input(void run()): this.this$0
    //#input(void run()): this.this$0.__Tag
    //#input(void run()): this.this$0.component
    //#input(void run()): this.this$0.component.__Tag
    //#input(void run()): this.this$0.listeners
    //#input(void run()): this.this$0.url
    //#output(void run()): com/dmdirc/updater/UpdateChecker.status
    //#output(void run()): this.this$0.progress
    //#output(void run()): this.this$0.status
    //#pre[5] (void run()): this.this$0 != null
    //#pre[7] (void run()): this.component != null
    //#pre[8] (void run()): this.component.__Tag in {com/dmdirc/updater/UpdateComponent, com/dmdirc/updater/components/ActionGroupComponent, com/dmdirc/updater/components/ClientComponent, com/dmdirc/updater/components/DefaultsComponent, com/dmdirc/updater/components/LauncherComponent, com/dmdirc/updater/components/ModeAliasesComponent, com/dmdirc/updater/components/PluginComponent}
    //#pre[9] (void run()): this.listeners != null
    //#pre[1] (void run()): (soft) com.dmdirc.util.ListenerList.new MapList(ListenerList#1).__Tag in {com/dmdirc/util/MapList, com/dmdirc/util/WeakMapList}
    //#pre[2] (void run()): (soft) com.dmdirc.util.ListenerList.new MapList(ListenerList#1).map != null
    //#pre[3] (void run()): (soft) init'ed(com/dmdirc/updater/UpdateChecker.status)
    //#pre[6] (void run()): (soft) this.__Tag in {com/dmdirc/updater/Update, com/dmdirc/util/DownloadListener}
    //#presumption(void run()): init'ed(com.dmdirc.logger.ErrorLevel.MEDIUM)
    //#presumption(void run()): getName(...)@182 != null
    //#post(void run()): init'ed(com/dmdirc/updater/UpdateChecker.status)
    //#post(void run()): this.this$0.progress == +0
    //#post(void run()): this.this$0.status in Addr_Set{&com.dmdirc.updater.UpdateStatus__static_init.new UpdateStatus(UpdateStatus__static_init#4),&com.dmdirc.updater.UpdateStatus__static_init.new UpdateStatus(UpdateStatus__static_init#6),&com.dmdirc.updater.UpdateStatus__static_init.new UpdateStatus(UpdateStatus__static_init#5)}
    //#unanalyzed(void run()): Effects-of-calling:getName
    //#unanalyzed(void run()): Effects-of-calling:java.util.List:iterator
    //#unanalyzed(void run()): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(void run()): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(void run()): Effects-of-calling:removeUpdate
    //#unanalyzed(void run()): Effects-of-calling:access$000
    //#unanalyzed(void run()): Effects-of-calling:access$100
    //#unanalyzed(void run()): Effects-of-calling:updateStatusChange
    //#unanalyzed(void run()): Effects-of-calling:java.net.URL
    //#unanalyzed(void run()): Effects-of-calling:java.net.URL:openConnection
    //#unanalyzed(void run()): Effects-of-calling:java.net.URLConnection:setUseCaches
    //#unanalyzed(void run()): Effects-of-calling:java.net.URLConnection:setDoInput
    //#unanalyzed(void run()): Effects-of-calling:java.lang.String:length
    //#unanalyzed(void run()): Effects-of-calling:java.net.URLConnection:setDoOutput
    //#unanalyzed(void run()): Effects-of-calling:java.net.URLConnection:setConnectTimeout
    //#unanalyzed(void run()): Effects-of-calling:java.net.URLConnection:setRequestProperty
    //#unanalyzed(void run()): Effects-of-calling:java.net.URLConnection:getOutputStream
    //#unanalyzed(void run()): Effects-of-calling:java.io.DataOutputStream
    //#unanalyzed(void run()): Effects-of-calling:java.io.DataOutputStream:writeBytes
    //#unanalyzed(void run()): Effects-of-calling:java.io.DataOutputStream:flush
    //#unanalyzed(void run()): Effects-of-calling:java.io.DataOutputStream:close
    //#unanalyzed(void run()): Effects-of-calling:java.net.URLConnection:getInputStream
    //#unanalyzed(void run()): Effects-of-calling:java.io.File
    //#unanalyzed(void run()): Effects-of-calling:java.io.FileOutputStream
    //#unanalyzed(void run()): Effects-of-calling:java.net.URLConnection:getContentLength
    //#unanalyzed(void run()): Effects-of-calling:setIndeterminate
    //#unanalyzed(void run()): Effects-of-calling:java.io.InputStream:read
    //#unanalyzed(void run()): Effects-of-calling:java.io.FileOutputStream:write
    //#unanalyzed(void run()): Effects-of-calling:downloadProgress
    //#unanalyzed(void run()): Effects-of-calling:java.io.InputStream:close
    //#unanalyzed(void run()): Effects-of-calling:java.io.FileOutputStream:close
    //#unanalyzed(void run()): Effects-of-calling:java.util.List:remove
    //#unanalyzed(void run()): Effects-of-calling:java.lang.String:equals
    //#unanalyzed(void run()): Effects-of-calling:java.util.ArrayList
    //#unanalyzed(void run()): Effects-of-calling:getStatus
    //#unanalyzed(void run()): Effects-of-calling:doUpdate
    //#unanalyzed(void run()): Effects-of-calling:setStatus
    //#unanalyzed(void run()): Effects-of-calling:java.util.List:isEmpty
    //#unanalyzed(void run()): Effects-of-calling:java.util.Map:containsKey
    //#unanalyzed(void run()): Effects-of-calling:java.util.Map:get
    //#unanalyzed(void run()): Effects-of-calling:statusChanged
    //#unanalyzed(void run()): Effects-of-calling:removeUpdateListener
    //#unanalyzed(void run()): Effects-of-calling:updateProgressChange
    //#unanalyzed(void run()): Effects-of-calling:java.lang.Thread
    //#unanalyzed(void run()): Effects-of-calling:java.lang.Thread:start
    //#test_vector(void run()): doInstall(...)@178: {0}, {1}
                        + Math.round(Math.random() * 1000);

                setStatus(UpdateStatus.DOWNLOADING);

                try {
                    Downloader.downloadPage(getUrl(), path, Update.this);
                } catch (IOException ex) {
                    setStatus(UpdateStatus.ERROR);

                    Logger.userError(ErrorLevel.MEDIUM, "Error when updating component "
    //#Update.java:169: Warning: call too complex - analysis skipped
    //#    call on String getName()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.updater.Update$1
    //#    method: void run()
    //#    unanalyzed callee: String getName()
    //#Update.java:169: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.logger.Logger:userError(ErrorLevel, String, Throwable)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.updater.Update$1
    //#    method: void run()
    //#    unanalyzed callee: void com.dmdirc.logger.Logger:userError(ErrorLevel, String, Throwable)
                            + component.getName(), ex);

                    return;
                }

                setStatus(UpdateStatus.INSTALLING);

                try {
                    final boolean restart = getComponent().doInstall(path);
    //#Update.java:178: Warning: call too complex - analysis skipped
    //#    call on bool doInstall(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.updater.Update$1
    //#    method: void run()
    //#    unanalyzed callee: bool doInstall(String)

                    if (restart) {
                        setStatus(UpdateStatus.RESTART_NEEDED);
                        UpdateChecker.removeComponent(getComponent().getName());
    //#Update.java:182: Warning: call too complex - analysis skipped
    //#    call on String getName()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.updater.Update$1
    //#    method: void run()
    //#    unanalyzed callee: String getName()
                    } else {
                        setStatus(UpdateStatus.INSTALLED);
                    }
                } catch (IOException ex) {
                    setStatus(UpdateStatus.ERROR);
                    Logger.userError(ErrorLevel.MEDIUM,
    //#Update.java:188: Warning: call too complex - analysis skipped
    //#    call on String getName()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.updater.Update$1
    //#    method: void run()
    //#    unanalyzed callee: String getName()
    //#Update.java:188: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.logger.Logger:userError(ErrorLevel, String, Throwable)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.updater.Update$1
    //#    method: void run()
    //#    unanalyzed callee: void com.dmdirc.logger.Logger:userError(ErrorLevel, String, Throwable)
                            "I/O error when updating component " + component.getName(), ex);
                } catch (Throwable ex) {
                    setStatus(UpdateStatus.ERROR);
                    Logger.appError(ErrorLevel.MEDIUM,
    //#Update.java:192: Warning: call too complex - analysis skipped
    //#    call on String getName()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.updater.Update$1
    //#    method: void run()
    //#    unanalyzed callee: String getName()
    //#Update.java:192: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.logger.Logger:appError(ErrorLevel, String, Throwable)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.updater.Update$1
    //#    method: void run()
    //#    unanalyzed callee: void com.dmdirc.logger.Logger:appError(ErrorLevel, String, Throwable)
                            "Error when updating component " + component.getName(), ex);
                }
            }
    //#Update.java:195: end of method: void com.dmdirc.updater.Update$1.run()

        }, "Update thread").start();
    }
    //#Update.java:198: end of method: void com.dmdirc.updater.Update.doUpdate()

    /** {@inheritDoc} */
    @Override
    public void downloadProgress(final float percent) {
        progress = percent;
    //#Update.java:203: method: void com.dmdirc.updater.Update.downloadProgress(float)
    //#input(void downloadProgress(float)): com/dmdirc/updater/UpdateChecker$1.__Dispatch_Table.updateProgressChange(Lcom/dmdirc/updater/Update;F)V
    //#input(void downloadProgress(float)): com/dmdirc/updater/UpdateListener.__Descendant_Table[com/dmdirc/updater/UpdateChecker$1]
    //#input(void downloadProgress(float)): com/dmdirc/updater/UpdateListener.__Descendant_Table[com/dmdirc/updater/UpdateListener]
    //#input(void downloadProgress(float)): com/dmdirc/updater/UpdateListener.__Descendant_Table[others]
    //#input(void downloadProgress(float)): com/dmdirc/updater/UpdateListener.__Dispatch_Table.updateProgressChange(Lcom/dmdirc/updater/Update;F)V
    //#input(void downloadProgress(float)): percent
    //#input(void downloadProgress(float)): this
    //#input(void downloadProgress(float)): this.listeners
    //#output(void downloadProgress(float)): this.progress
    //#pre[3] (void downloadProgress(float)): this.listeners != null
    //#presumption(void downloadProgress(float)): java.util.Iterator:next(...).__Tag@205 in {com/dmdirc/updater/UpdateChecker$1, com/dmdirc/updater/UpdateListener}
    //#presumption(void downloadProgress(float)): java.util.Iterator:next(...)@205 != null
    //#post(void downloadProgress(float)): this.progress == percent
    //#post(void downloadProgress(float)): init'ed(this.progress)
    //#test_vector(void downloadProgress(float)): java.util.Iterator:hasNext(...)@205: {0}, {1}
        
        for (UpdateListener listener : listeners) {
            listener.updateProgressChange(this, percent);
        }
    }
    //#Update.java:208: end of method: void com.dmdirc.updater.Update.downloadProgress(float)

    /**
     * Retrieves the current progress of the current state of this update.
     * 
     * @return The percentage of the current stage that has been completed
     */
    public float getProgress() {
        return progress;
    //#Update.java:216: method: float com.dmdirc.updater.Update.getProgress()
    //#input(float getProgress()): this
    //#input(float getProgress()): this.progress
    //#output(float getProgress()): return_value
    //#pre[2] (float getProgress()): init'ed(this.progress)
    //#post(float getProgress()): return_value == this.progress
    //#post(float getProgress()): init'ed(return_value)
    //#Update.java:216: end of method: float com.dmdirc.updater.Update.getProgress()
    }

    /** {@inheritDoc} */
    @Override
    public void setIndeterminate(boolean indeterminate) {
        //TODO
    }
    //#Update.java:223: method: void com.dmdirc.updater.Update.setIndeterminate(bool)
    //#Update.java:223: end of method: void com.dmdirc.updater.Update.setIndeterminate(bool)
    
}
    //#output(com.dmdirc.updater.Update$1__static_init): __Descendant_Table[com/dmdirc/updater/Update$1]
    //#output(com.dmdirc.updater.Update$1__static_init): __Dispatch_Table.run()V
    //#post(com.dmdirc.updater.Update$1__static_init): __Descendant_Table[com/dmdirc/updater/Update$1] == &__Dispatch_Table
    //#post(com.dmdirc.updater.Update$1__static_init): __Dispatch_Table.run()V == &run
    //#Update.java:: end of method: com.dmdirc.updater.Update$1.com.dmdirc.updater.Update$1__static_init
    //#Update.java:: end of class: com.dmdirc.updater.Update$1
    //#output(com.dmdirc.updater.Update__static_init): __Descendant_Table[com/dmdirc/updater/Update]
    //#output(com.dmdirc.updater.Update__static_init): __Dispatch_Table.addUpdateListener(Lcom/dmdirc/updater/UpdateListener;)V
    //#output(com.dmdirc.updater.Update__static_init): __Dispatch_Table.doUpdate()V
    //#output(com.dmdirc.updater.Update__static_init): __Dispatch_Table.downloadProgress(F)V
    //#output(com.dmdirc.updater.Update__static_init): __Dispatch_Table.getComponent()Lcom/dmdirc/updater/UpdateComponent;
    //#output(com.dmdirc.updater.Update__static_init): __Dispatch_Table.getProgress()F
    //#output(com.dmdirc.updater.Update__static_init): __Dispatch_Table.getRemoteVersion()Ljava/lang/String;
    //#output(com.dmdirc.updater.Update__static_init): __Dispatch_Table.getStatus()Lcom/dmdirc/updater/UpdateStatus;
    //#output(com.dmdirc.updater.Update__static_init): __Dispatch_Table.getUrl()Ljava/lang/String;
    //#output(com.dmdirc.updater.Update__static_init): __Dispatch_Table.removeUpdateListener(Ljava/lang/Object;)V
    //#output(com.dmdirc.updater.Update__static_init): __Dispatch_Table.setIndeterminate(Z)V
    //#output(com.dmdirc.updater.Update__static_init): __Dispatch_Table.setStatus(Lcom/dmdirc/updater/UpdateStatus;)V
    //#output(com.dmdirc.updater.Update__static_init): com/dmdirc/util/DownloadListener.__Descendant_Table[com/dmdirc/updater/Update]
    //#post(com.dmdirc.updater.Update__static_init): __Descendant_Table[com/dmdirc/updater/Update] == &__Dispatch_Table
    //#post(com.dmdirc.updater.Update__static_init): com/dmdirc/util/DownloadListener.__Descendant_Table[com/dmdirc/updater/Update] == &__Dispatch_Table
    //#post(com.dmdirc.updater.Update__static_init): __Dispatch_Table.addUpdateListener(Lcom/dmdirc/updater/UpdateListener;)V == &addUpdateListener
    //#post(com.dmdirc.updater.Update__static_init): __Dispatch_Table.doUpdate()V == &doUpdate
    //#post(com.dmdirc.updater.Update__static_init): __Dispatch_Table.downloadProgress(F)V == &downloadProgress
    //#post(com.dmdirc.updater.Update__static_init): __Dispatch_Table.getComponent()Lcom/dmdirc/updater/UpdateComponent; == &getComponent
    //#post(com.dmdirc.updater.Update__static_init): __Dispatch_Table.getProgress()F == &getProgress
    //#post(com.dmdirc.updater.Update__static_init): __Dispatch_Table.getRemoteVersion()Ljava/lang/String; == &getRemoteVersion
    //#post(com.dmdirc.updater.Update__static_init): __Dispatch_Table.getStatus()Lcom/dmdirc/updater/UpdateStatus; == &getStatus
    //#post(com.dmdirc.updater.Update__static_init): __Dispatch_Table.getUrl()Ljava/lang/String; == &getUrl
    //#post(com.dmdirc.updater.Update__static_init): __Dispatch_Table.removeUpdateListener(Ljava/lang/Object;)V == &removeUpdateListener
    //#post(com.dmdirc.updater.Update__static_init): __Dispatch_Table.setIndeterminate(Z)V == &setIndeterminate
    //#post(com.dmdirc.updater.Update__static_init): __Dispatch_Table.setStatus(Lcom/dmdirc/updater/UpdateStatus;)V == &setStatus
    //#Update.java:: end of method: com.dmdirc.updater.Update.com.dmdirc.updater.Update__static_init
    //#Update.java:: end of class: com.dmdirc.updater.Update
