//# 0 errors, 307 messages
//#
/*
    //#Installer.java:1:1: class: com.dmdirc.installer.Installer$ShortcutType
    //#Installer.java:1:1: class: com.dmdirc.installer.Installer$1
    //#Installer.java:1:1: method: com.dmdirc.installer.Installer$1.com.dmdirc.installer.Installer$1__static_init
    //#Installer.java:1:1: class: com.dmdirc.installer.Installer
    //#Installer.java:1:1: method: com.dmdirc.installer.Installer.com.dmdirc.installer.Installer__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.installer;

import com.dmdirc.installer.cliparser.CLIParser;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.channels.FileChannel;

/**
 * Installs DMDirc.
 */
public abstract class Installer extends Thread {

    /** Types of shortcut. */
    public static enum ShortcutType {
    //#Installer.java:40: method: Installer$ShortcutType[] com.dmdirc.installer.Installer$ShortcutType.values()
    //#input(Installer$ShortcutType[] values()): $VALUES
    //#input(Installer$ShortcutType[] values()): $VALUES.length
    //#input(Installer$ShortcutType[] values()): $VALUES[0..5]
    //#output(Installer$ShortcutType[] values()): new Installer$ShortcutType[](values#1) num objects
    //#output(Installer$ShortcutType[] values()): return_value.length
    //#output(Installer$ShortcutType[] values()): return_value[0..5]
    //#output(Installer$ShortcutType[] values()): return_value
    //#new obj(Installer$ShortcutType[] values()): new Installer$ShortcutType[](values#1)
    //#pre[1] (Installer$ShortcutType[] values()): (soft) init'ed($VALUES[0..5])
    //#post(Installer$ShortcutType[] values()): return_value == &new Installer$ShortcutType[](values#1)
    //#post(Installer$ShortcutType[] values()): new Installer$ShortcutType[](values#1) num objects == 1
    //#post(Installer$ShortcutType[] values()): return_value.length == 5
    //#post(Installer$ShortcutType[] values()): return_value[0..5] == One-of{$VALUES[0..5], undefined}
    //#Installer.java:40: end of method: Installer$ShortcutType[] com.dmdirc.installer.Installer$ShortcutType.values()
    //#Installer.java:40: method: Installer$ShortcutType com.dmdirc.installer.Installer$ShortcutType.valueOf(String)
    //#input(Installer$ShortcutType valueOf(String)): __Descendant_Table[com/dmdirc/installer/Installer$ShortcutType]
    //#input(Installer$ShortcutType valueOf(String)): __Descendant_Table[others]
    //#input(Installer$ShortcutType valueOf(String)): name
    //#output(Installer$ShortcutType valueOf(String)): return_value
    //#presumption(Installer$ShortcutType valueOf(String)): java.lang.Enum:valueOf(...).__Tag@40 == com/dmdirc/installer/Installer$ShortcutType
    //#post(Installer$ShortcutType valueOf(String)): init'ed(return_value)
    //#Installer.java:40: end of method: Installer$ShortcutType com.dmdirc.installer.Installer$ShortcutType.valueOf(String)
    //#Installer.java:40: method: void com.dmdirc.installer.Installer$ShortcutType.com.dmdirc.installer.Installer$ShortcutType(String, int)
    //#input(void com.dmdirc.installer.Installer$ShortcutType(String, int)): Param_1
    //#input(void com.dmdirc.installer.Installer$ShortcutType(String, int)): Param_2
    //#input(void com.dmdirc.installer.Installer$ShortcutType(String, int)): this
    //#Installer.java:40: end of method: void com.dmdirc.installer.Installer$ShortcutType.com.dmdirc.installer.Installer$ShortcutType(String, int)

        /** Desktop shortcut. */
        DESKTOP,
    //#Installer.java:43: method: com.dmdirc.installer.Installer$ShortcutType.com.dmdirc.installer.Installer$ShortcutType__static_init
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): $VALUES
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): DESKTOP
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): MENU
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): PROTOCOL
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): QUICKLAUNCH
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): UNINSTALLER
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): __Descendant_Table[com/dmdirc/installer/Installer$ShortcutType]
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): new Installer$ShortcutType(Installer$ShortcutType__static_init#1) num objects
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): DESKTOP.__Tag
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): new Installer$ShortcutType(Installer$ShortcutType__static_init#2) num objects
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): MENU.__Tag
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): new Installer$ShortcutType(Installer$ShortcutType__static_init#3) num objects
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): QUICKLAUNCH.__Tag
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): new Installer$ShortcutType(Installer$ShortcutType__static_init#4) num objects
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): UNINSTALLER.__Tag
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): new Installer$ShortcutType(Installer$ShortcutType__static_init#5) num objects
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): PROTOCOL.__Tag
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): new Installer$ShortcutType[](Installer$ShortcutType__static_init#6) num objects
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): $VALUES.length
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): $VALUES[0]
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): $VALUES[1]
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): $VALUES[2]
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): $VALUES[3]
    //#output(com.dmdirc.installer.Installer$ShortcutType__static_init): $VALUES[4]
    //#new obj(com.dmdirc.installer.Installer$ShortcutType__static_init): new Installer$ShortcutType(Installer$ShortcutType__static_init#1)
    //#new obj(com.dmdirc.installer.Installer$ShortcutType__static_init): new Installer$ShortcutType(Installer$ShortcutType__static_init#2)
    //#new obj(com.dmdirc.installer.Installer$ShortcutType__static_init): new Installer$ShortcutType(Installer$ShortcutType__static_init#3)
    //#new obj(com.dmdirc.installer.Installer$ShortcutType__static_init): new Installer$ShortcutType(Installer$ShortcutType__static_init#4)
    //#new obj(com.dmdirc.installer.Installer$ShortcutType__static_init): new Installer$ShortcutType(Installer$ShortcutType__static_init#5)
    //#new obj(com.dmdirc.installer.Installer$ShortcutType__static_init): new Installer$ShortcutType[](Installer$ShortcutType__static_init#6)
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): $VALUES == &new Installer$ShortcutType[](Installer$ShortcutType__static_init#6)
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): DESKTOP == &new Installer$ShortcutType(Installer$ShortcutType__static_init#1)
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): $VALUES[0] == &new Installer$ShortcutType(Installer$ShortcutType__static_init#1)
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): MENU == &new Installer$ShortcutType(Installer$ShortcutType__static_init#2)
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): $VALUES[1] == &new Installer$ShortcutType(Installer$ShortcutType__static_init#2)
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): PROTOCOL == &new Installer$ShortcutType(Installer$ShortcutType__static_init#5)
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): $VALUES[4] == &new Installer$ShortcutType(Installer$ShortcutType__static_init#5)
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): QUICKLAUNCH == &new Installer$ShortcutType(Installer$ShortcutType__static_init#3)
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): $VALUES[2] == &new Installer$ShortcutType(Installer$ShortcutType__static_init#3)
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): UNINSTALLER == &new Installer$ShortcutType(Installer$ShortcutType__static_init#4)
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): $VALUES[3] == &new Installer$ShortcutType(Installer$ShortcutType__static_init#4)
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): __Descendant_Table[com/dmdirc/installer/Installer$ShortcutType] == &__Dispatch_Table
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): new Installer$ShortcutType(Installer$ShortcutType__static_init#1) num objects == 1
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): new Installer$ShortcutType(Installer$ShortcutType__static_init#2) num objects == 1
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): new Installer$ShortcutType(Installer$ShortcutType__static_init#3) num objects == 1
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): new Installer$ShortcutType(Installer$ShortcutType__static_init#4) num objects == 1
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): new Installer$ShortcutType(Installer$ShortcutType__static_init#5) num objects == 1
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): new Installer$ShortcutType[](Installer$ShortcutType__static_init#6) num objects == 1
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): DESKTOP.__Tag == com/dmdirc/installer/Installer$ShortcutType
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): MENU.__Tag == com/dmdirc/installer/Installer$ShortcutType
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): QUICKLAUNCH.__Tag == com/dmdirc/installer/Installer$ShortcutType
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): UNINSTALLER.__Tag == com/dmdirc/installer/Installer$ShortcutType
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): PROTOCOL.__Tag == com/dmdirc/installer/Installer$ShortcutType
    //#post(com.dmdirc.installer.Installer$ShortcutType__static_init): $VALUES.length == 5
    //#unanalyzed(com.dmdirc.installer.Installer$ShortcutType__static_init): Effects-of-calling:java.lang.Enum
        /** Menu (start/k/etc) shortcut. */
        MENU,
        /** Quick launch shortcut. */
        QUICKLAUNCH,
        /** The actual uninstaller (not a shortcut, as far as I can tell). */
        UNINSTALLER,
        /** Associate DMDirc with the irc:// protocol (not a shortcut). */
        PROTOCOL;
    //#Installer.java:51: end of method: com.dmdirc.installer.Installer$ShortcutType.com.dmdirc.installer.Installer$ShortcutType__static_init
    }

    /** Step where the installation output should be. */
    protected TextStep step;

    /**
     * Create a new Installer.
     */
    public Installer() {
        super("Installer-Thread");
    //#Installer.java:61: method: void com.dmdirc.installer.Installer.com.dmdirc.installer.Installer()
    //#input(void com.dmdirc.installer.Installer()): this
    }
    //#Installer.java:62: end of method: void com.dmdirc.installer.Installer.com.dmdirc.installer.Installer()

    /**
     * Get the default install location.
     *
     * @return The default install location
     */
    public abstract String defaultInstallLocation();

    /**
     * This is what helps actually perform the installation in run().
     * This is a hack to keep the installing and the GUI separate.
     *
     * @param step The step that called this
     */
    public final void setInstallStep(final TextStep step) {
        this.step = step;
    //#Installer.java:78: method: void com.dmdirc.installer.Installer.setInstallStep(TextStep)
    //#input(void setInstallStep(TextStep)): step
    //#input(void setInstallStep(TextStep)): this
    //#output(void setInstallStep(TextStep)): this.step
    //#post(void setInstallStep(TextStep)): this.step == step
    //#post(void setInstallStep(TextStep)): init'ed(this.step)
    }
    //#Installer.java:79: end of method: void com.dmdirc.installer.Installer.setInstallStep(TextStep)

    /** {@inheritDoc} */
    @Override
    public final void run() {
        step.setText("Beginning Install..\n");
    //#Installer.java:84: method: void com.dmdirc.installer.Installer.run()
    //#Installer.java:84: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.installer.TextStep:setText(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    unanalyzed callee: void com.dmdirc.installer.TextStep:setText(String)
    //#input(void run()): " does not exist."._tainted
    //#input(void run()): " shortcut"._tainted
    //#input(void run()): "Copying "._tainted
    //#input(void run()): "Error copying files: "._tainted
    //#input(void run()): "Installing files to: "._tainted
    //#input(void run()): "Not setting up "._tainted
    //#input(void run()): "Setting up "._tainted
    //#input(void run()): "menu"._tainted
    //#input(void run()): __Descendant_Table[com/dmdirc/installer/Installer]
    //#input(void run()): __Descendant_Table[others]
    //#input(void run()): __Dispatch_Table.doSetup(Ljava/lang/String;)Z
    //#input(void run()): __Dispatch_Table.getMenuName()Ljava/lang/String;
    //#input(void run()): __Dispatch_Table.postInstall(Ljava/lang/String;)V
    //#input(void run()): __Dispatch_Table.setupShortcut(Ljava/lang/String;Lcom/dmdirc/installer/Installer$ShortcutType;)V
    //#input(void run()): __Dispatch_Table.supportsShortcut(Lcom/dmdirc/installer/Installer$ShortcutType;)Z
    //#input(void run()): com/dmdirc/installer/Installer$ShortcutType.DESKTOP
    //#input(void run()): com/dmdirc/installer/Installer$ShortcutType.MENU
    //#input(void run()): com/dmdirc/installer/Installer$ShortcutType.PROTOCOL
    //#input(void run()): com/dmdirc/installer/Installer$ShortcutType.QUICKLAUNCH
    //#input(void run()): com/dmdirc/installer/Installer$ShortcutType.UNINSTALLER
    //#input(void run()): java.io.File.separator
    //#input(void run()): java.io.File.separator._tainted
    //#input(void run()): this
    //#input(void run()): this.__Tag
    //#input(void run()): this.step
    //#pre[2] (void run()): this.__Tag == com/dmdirc/installer/Installer
    //#pre[3] (void run()): this.step != null
    //#presumption(void run()): com.dmdirc.installer.Main:getInstaller(...).__Tag@100 == com/dmdirc/installer/Installer
    //#presumption(void run()): com.dmdirc.installer.Main:getInstaller(...).__Tag@111 == com/dmdirc/installer/Installer
    //#presumption(void run()): com.dmdirc.installer.Main:getInstaller(...).__Tag@120 == com/dmdirc/installer/Installer
    //#presumption(void run()): com.dmdirc.installer.Main:getInstaller(...).__Tag@129 == com/dmdirc/installer/Installer
    //#presumption(void run()): com.dmdirc.installer.Main:getInstaller(...).__Tag@134 == com/dmdirc/installer/Installer
    //#presumption(void run()): com.dmdirc.installer.Main:getInstaller(...)@100 != null
    //#presumption(void run()): com.dmdirc.installer.Main:getInstaller(...)@111 != null
    //#presumption(void run()): com.dmdirc.installer.Main:getInstaller(...)@120 != null
    //#presumption(void run()): com.dmdirc.installer.Main:getInstaller(...)@129 != null
    //#presumption(void run()): com.dmdirc.installer.Main:getInstaller(...)@134 != null
    //#presumption(void run()): com.dmdirc.installer.Main:getWizardFrame(...)@147 != null
    //#presumption(void run()): com.dmdirc.installer.Main:getWizardFrame(...)@88 != null
    //#presumption(void run()): com.dmdirc.installer.Main:getWizardFrame(...)@96 != null
    //#presumption(void run()): com.dmdirc.installer.cliparser.CLIParser:getCLIParser(...)@86 != null
    //#presumption(void run()): com.dmdirc.installer.ui.InstallerDialog:getStep(...)@88 != null
    //#unanalyzed(void run()): Effects-of-calling:java.io.File
    //#unanalyzed(void run()): Effects-of-calling:java.io.File:exists
    //#unanalyzed(void run()): Effects-of-calling:java.io.FileInputStream
    //#unanalyzed(void run()): Effects-of-calling:java.io.FileInputStream:getChannel
    //#unanalyzed(void run()): Effects-of-calling:java.io.FileOutputStream
    //#unanalyzed(void run()): Effects-of-calling:java.io.FileOutputStream:getChannel
    //#unanalyzed(void run()): Effects-of-calling:java.nio.channels.FileChannel:size
    //#unanalyzed(void run()): Effects-of-calling:java.nio.channels.FileChannel:transferFrom
    //#unanalyzed(void run()): Effects-of-calling:java.nio.channels.FileChannel:close
    //#unanalyzed(void run()): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(void run()): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(void run()): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(void run()): Effects-of-calling:java.io.IOException
    //#unanalyzed(void run()): Effects-of-calling:java.io.File:mkdir
    //#unanalyzed(void run()): Effects-of-calling:java.io.File:list
    //#unanalyzed(void run()): Effects-of-calling:com.dmdirc.installer.TextStep:addText
    //#unanalyzed(void run()): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(void run()): Effects-of-calling:java.io.IOException:getMessage
    //#test_vector(void run()): com.dmdirc.installer.cliparser.CLIParser:getParamNumber(...)@86: {0}, {-2_147_483_648..-1, 1..4_294_967_295}

        final boolean isUnattended = (CLIParser.getCLIParser().getParamNumber(
    //#Installer.java:86: Warning: method not available - call not analyzed
    //#    call on CLIParser com.dmdirc.installer.cliparser.CLIParser:getCLIParser()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    unanalyzed callee: CLIParser com.dmdirc.installer.cliparser.CLIParser:getCLIParser()
    //#Installer.java:86: Warning: method not available - call not analyzed
    //#    call on int com.dmdirc.installer.cliparser.CLIParser:getParamNumber(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    unanalyzed callee: int com.dmdirc.installer.cliparser.CLIParser:getParamNumber(String)
                "-unattended") != 0);
        final Settings settings = (isUnattended) ? new DefaultSettings() : ((Settings) Main.getWizardFrame().
    //#Installer.java:88: Warning: method not available - call not analyzed
    //#    call on InstallerDialog com.dmdirc.installer.Main:getWizardFrame()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    unanalyzed callee: InstallerDialog com.dmdirc.installer.Main:getWizardFrame()
    //#Installer.java:88: Warning: method not available - call not analyzed
    //#    call on Step com.dmdirc.installer.ui.InstallerDialog:getStep(int)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    unanalyzed callee: Step com.dmdirc.installer.ui.InstallerDialog:getStep(int)
                getStep(1));

        final String location = settings.getInstallLocation();
    //#Installer.java:91: Warning: method not available - call not analyzed
    //#    call on String com.dmdirc.installer.Settings:getInstallLocation()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    unanalyzed callee: String com.dmdirc.installer.Settings:getInstallLocation()
        step.addText("Installing files to: " + location);
    //#Installer.java:92: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.installer.TextStep:addText(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    unanalyzed callee: void com.dmdirc.installer.TextStep:addText(String)
        if (!doSetup(location)) {
            step.addText("");
    //#Installer.java:94: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.installer.TextStep:addText(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    unanalyzed callee: void com.dmdirc.installer.TextStep:addText(String)
            step.addText("Installation failed\n");
    //#Installer.java:95: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.installer.TextStep:addText(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    unanalyzed callee: void com.dmdirc.installer.TextStep:addText(String)
            Main.getWizardFrame().enableNextStep(true);
    //#Installer.java:96: Warning: method not available - call not analyzed
    //#    call on InstallerDialog com.dmdirc.installer.Main:getWizardFrame()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    unanalyzed callee: InstallerDialog com.dmdirc.installer.Main:getWizardFrame()
    //#Installer.java:96: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.installer.ui.InstallerDialog:enableNextStep(bool)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    unanalyzed callee: void com.dmdirc.installer.ui.InstallerDialog:enableNextStep(bool)
            return;
        }

        if (Main.getInstaller().supportsShortcut(ShortcutType.MENU)) {
    //#Installer.java:100: Warning: method not available - call not analyzed
    //#    call on Installer com.dmdirc.installer.Main:getInstaller()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    unanalyzed callee: Installer com.dmdirc.installer.Main:getInstaller()
    //#Installer.java:100: Warning: test always goes same way
    //#    Test predetermined because supportsShortcut(...) == 0
    //#    severity: LOW
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    from bb: bb_9
    //#    live edge: bb_9-->bb_13
    //#    tested vn: 0
    //#    tested vn values: {0}
            if (settings.getShortcutMenuState()) {
    //#Installer.java:101: Warning: dead code
    //#    Dead code here because supportsShortcut(...) == 0
    //#    severity: LOW
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    dead bb: bb_10
                step.addText("Setting up " + Main.getInstaller().getMenuName() +
    //#Installer.java:102: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    dead bb: bb_11
                             " shortcut");
                setupShortcut(location, ShortcutType.MENU);
            } else {
                step.addText("Not setting up " +
    //#Installer.java:106: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    dead bb: bb_12
                             Main.getInstaller().getMenuName() + " shortcut");
            }
        }

        if (Main.getInstaller().supportsShortcut(ShortcutType.DESKTOP)) {
    //#Installer.java:111: Warning: method not available - call not analyzed
    //#    call on Installer com.dmdirc.installer.Main:getInstaller()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    unanalyzed callee: Installer com.dmdirc.installer.Main:getInstaller()
    //#Installer.java:111: Warning: test always goes same way
    //#    Test predetermined because supportsShortcut(...) == 0
    //#    severity: LOW
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    from bb: bb_13
    //#    live edge: bb_13-->bb_17
    //#    tested vn: 0
    //#    tested vn values: {0}
            if (settings.getShortcutDesktopState()) {
    //#Installer.java:112: Warning: dead code
    //#    Dead code here because supportsShortcut(...) == 0
    //#    severity: LOW
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    dead bb: bb_14
                step.addText("Setting up Desktop shortcut");
    //#Installer.java:113: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    dead bb: bb_15
                setupShortcut(location, ShortcutType.DESKTOP);
            } else {
                step.addText("Not setting up Desktop shortcut");
    //#Installer.java:116: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    dead bb: bb_16
            }
        }

        if (Main.getInstaller().supportsShortcut(ShortcutType.QUICKLAUNCH)) {
    //#Installer.java:120: Warning: method not available - call not analyzed
    //#    call on Installer com.dmdirc.installer.Main:getInstaller()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    unanalyzed callee: Installer com.dmdirc.installer.Main:getInstaller()
    //#Installer.java:120: Warning: test always goes same way
    //#    Test predetermined because supportsShortcut(...) == 0
    //#    severity: LOW
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    from bb: bb_17
    //#    live edge: bb_17-->bb_21
    //#    tested vn: 0
    //#    tested vn values: {0}
            if (settings.getShortcutQuickState()) {
    //#Installer.java:121: Warning: dead code
    //#    Dead code here because supportsShortcut(...) == 0
    //#    severity: LOW
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    dead bb: bb_18
                step.addText("Setting up Quick Launch shortcut");
    //#Installer.java:122: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    dead bb: bb_19
                setupShortcut(location, ShortcutType.QUICKLAUNCH);
            } else {
                step.addText("Not setting up Quick Launch shortcut");
    //#Installer.java:125: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    dead bb: bb_20
            }
        }

        if (Main.getInstaller().supportsShortcut(ShortcutType.UNINSTALLER)) {
    //#Installer.java:129: Warning: method not available - call not analyzed
    //#    call on Installer com.dmdirc.installer.Main:getInstaller()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    unanalyzed callee: Installer com.dmdirc.installer.Main:getInstaller()
    //#Installer.java:129: Warning: test always goes same way
    //#    Test predetermined because supportsShortcut(...) == 0
    //#    severity: LOW
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    from bb: bb_21
    //#    live edge: bb_21-->bb_23
    //#    tested vn: 0
    //#    tested vn values: {0}
            step.addText("Creating uninstaller");
    //#Installer.java:130: Warning: dead code
    //#    Dead code here because supportsShortcut(...) == 0
    //#    severity: LOW
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    dead bb: bb_22
            setupShortcut(location, ShortcutType.UNINSTALLER);
        }

        if (Main.getInstaller().supportsShortcut(ShortcutType.PROTOCOL)) {
    //#Installer.java:134: Warning: method not available - call not analyzed
    //#    call on Installer com.dmdirc.installer.Main:getInstaller()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    unanalyzed callee: Installer com.dmdirc.installer.Main:getInstaller()
    //#Installer.java:134: Warning: test always goes same way
    //#    Test predetermined because supportsShortcut(...) == 0
    //#    severity: LOW
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    from bb: bb_23
    //#    live edge: bb_23-->bb_27
    //#    tested vn: 0
    //#    tested vn values: {0}
            if (settings.getShortcutProtocolState()) {
    //#Installer.java:135: Warning: dead code
    //#    Dead code here because supportsShortcut(...) == 0
    //#    severity: LOW
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    dead bb: bb_24
                step.addText("Setting up irc:// handler");
    //#Installer.java:136: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    dead bb: bb_25
                setupShortcut(location, ShortcutType.PROTOCOL);
            } else {
                step.addText("Not setting up irc:// handler");
    //#Installer.java:139: Warning: dead code continues
    //#    Dead code continues
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    dead bb: bb_26
            }
        }

        postInstall(location);

        step.addText("");
    //#Installer.java:145: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.installer.TextStep:addText(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    unanalyzed callee: void com.dmdirc.installer.TextStep:addText(String)
        step.addText("Installation finished\n");
    //#Installer.java:146: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.installer.TextStep:addText(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    unanalyzed callee: void com.dmdirc.installer.TextStep:addText(String)
        Main.getWizardFrame().enableNextStep(true);
    //#Installer.java:147: Warning: method not available - call not analyzed
    //#    call on InstallerDialog com.dmdirc.installer.Main:getWizardFrame()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    unanalyzed callee: InstallerDialog com.dmdirc.installer.Main:getWizardFrame()
    //#Installer.java:147: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.installer.ui.InstallerDialog:enableNextStep(bool)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: void run()
    //#    unanalyzed callee: void com.dmdirc.installer.ui.InstallerDialog:enableNextStep(bool)
    }
    //#Installer.java:148: end of method: void com.dmdirc.installer.Installer.run()

    /**
     * Is the given file name vaild to copy to the installation directory?
     *
     * @param filename File to check
     * @return true If the file should be copied, else false.
     */
    public abstract boolean validFile(final String filename);

    /**
     * Main Setup stuff.
     *
     * @param location Location where app will be installed to.
     * @return True if installation passed, else false
     */
    public boolean doSetup(final String location) {
        // Create the directory
        final File directory = new File(location);
    //#Installer.java:166: method: bool com.dmdirc.installer.Installer.doSetup(String)
    //#input(bool doSetup(String)): " does not exist."._tainted
    //#input(bool doSetup(String)): "Copying "._tainted
    //#input(bool doSetup(String)): "Error copying files: "._tainted
    //#input(bool doSetup(String)): java.io.File.separator
    //#input(bool doSetup(String)): java.io.File.separator._tainted
    //#input(bool doSetup(String)): location
    //#input(bool doSetup(String)): location._tainted
    //#input(bool doSetup(String)): this
    //#input(bool doSetup(String)): this.step
    //#output(bool doSetup(String)): return_value
    //#pre[4] (bool doSetup(String)): this.step != null
    //#presumption(bool doSetup(String)): arr$.length@181 <= 4_294_967_295
    //#presumption(bool doSetup(String)): init'ed(java.io.File.separator)
    //#post(bool doSetup(String)): init'ed(return_value)
    //#unanalyzed(bool doSetup(String)): Effects-of-calling:java.io.File
    //#unanalyzed(bool doSetup(String)): Effects-of-calling:java.io.File:exists
    //#unanalyzed(bool doSetup(String)): Effects-of-calling:java.io.FileInputStream
    //#unanalyzed(bool doSetup(String)): Effects-of-calling:java.io.FileInputStream:getChannel
    //#unanalyzed(bool doSetup(String)): Effects-of-calling:java.io.FileOutputStream
    //#unanalyzed(bool doSetup(String)): Effects-of-calling:java.io.FileOutputStream:getChannel
    //#unanalyzed(bool doSetup(String)): Effects-of-calling:java.nio.channels.FileChannel:size
    //#unanalyzed(bool doSetup(String)): Effects-of-calling:java.nio.channels.FileChannel:transferFrom
    //#unanalyzed(bool doSetup(String)): Effects-of-calling:java.nio.channels.FileChannel:close
    //#unanalyzed(bool doSetup(String)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(bool doSetup(String)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(bool doSetup(String)): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(bool doSetup(String)): Effects-of-calling:java.io.IOException
    //#test_vector(bool doSetup(String)): java.io.File:exists(...)@167: {1}, {0}
    //#test_vector(bool doSetup(String)): java.io.File:list(...)@181: Addr_Set{null}, Inverse{null}
        if (!directory.exists()) {
            directory.mkdir();
        }

        try {
            final File dir = new File(".");
            final FilenameFilter filter = new FilenameFilter() {
    //#Installer.java:173: method: void com.dmdirc.installer.Installer$1.com.dmdirc.installer.Installer$1(Installer)
    //#input(void com.dmdirc.installer.Installer$1(Installer)): Param_1
    //#input(void com.dmdirc.installer.Installer$1(Installer)): this
    //#output(void com.dmdirc.installer.Installer$1(Installer)): this.this$0
    //#post(void com.dmdirc.installer.Installer$1(Installer)): this.this$0 == Param_1
    //#post(void com.dmdirc.installer.Installer$1(Installer)): init'ed(this.this$0)
    //#Installer.java:173: end of method: void com.dmdirc.installer.Installer$1.com.dmdirc.installer.Installer$1(Installer)

                /** {@inheritDoc} */
                @Override
                public boolean accept(final File dir, final String name) {
                    return name.charAt(0) != '.' && validFile(name);
    //#Installer.java:178: method: bool com.dmdirc.installer.Installer$1.accept(File, String)
    //#Installer.java:178: Warning: method not available - call not analyzed
    //#    call on bool validFile(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer$1
    //#    method: bool accept(File, String)
    //#    unanalyzed callee: bool validFile(String)
    //#input(bool accept(File, String)): com/dmdirc/installer/Installer.__Descendant_Table[com/dmdirc/installer/Installer]
    //#input(bool accept(File, String)): com/dmdirc/installer/Installer.__Descendant_Table[others]
    //#input(bool accept(File, String)): com/dmdirc/installer/Installer.__Dispatch_Table.validFile(Ljava/lang/String;)Z
    //#input(bool accept(File, String)): name
    //#input(bool accept(File, String)): this
    //#input(bool accept(File, String)): this.this$0
    //#input(bool accept(File, String)): this.this$0.__Tag
    //#output(bool accept(File, String)): return_value
    //#pre[1] (bool accept(File, String)): name != null
    //#pre[3] (bool accept(File, String)): (soft) this.this$0 != null
    //#pre[4] (bool accept(File, String)): (soft) this.__Tag == com/dmdirc/installer/Installer
    //#post(bool accept(File, String)): init'ed(return_value)
    //#Installer.java:178: end of method: bool com.dmdirc.installer.Installer$1.accept(File, String)
                }
            };
            final String[] children = dir.list(filter);
            if (children != null) {
                for (String filename : children) {
                    step.addText("Copying " + filename);
    //#Installer.java:184: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.installer.TextStep:addText(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: bool doSetup(String)
    //#    unanalyzed callee: void com.dmdirc.installer.TextStep:addText(String)
                    copyFile(filename, location + File.separator + filename);
                }
            }
        } catch (IOException e) {
            step.addText("Error copying files: " + e.getMessage());
    //#Installer.java:189: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.installer.TextStep:addText(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: bool doSetup(String)
    //#    unanalyzed callee: void com.dmdirc.installer.TextStep:addText(String)
            return false;
        }
        step.addText("File Copying Complete.");
    //#Installer.java:192: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.installer.TextStep:addText(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.installer.Installer
    //#    method: bool doSetup(String)
    //#    unanalyzed callee: void com.dmdirc.installer.TextStep:addText(String)
        return true;
    //#Installer.java:193: end of method: bool com.dmdirc.installer.Installer.doSetup(String)
    }

    /**
     * Check if this OS supports a given shortcut Type.
     *
     * @param shortcutType Type of shortcut to check
     * @return True if this OS supports a given shortcut Type
     */
    public boolean supportsShortcut(final ShortcutType shortcutType) {
        return false;
    //#Installer.java:203: method: bool com.dmdirc.installer.Installer.supportsShortcut(Installer$ShortcutType)
    //#output(bool supportsShortcut(Installer$ShortcutType)): return_value
    //#post(bool supportsShortcut(Installer$ShortcutType)): return_value == 0
    //#Installer.java:203: end of method: bool com.dmdirc.installer.Installer.supportsShortcut(Installer$ShortcutType)
    }

    /**
     * Check what name to show for the menu shortcut
     *
     * @return Name for menu shortcutType
     */
    public String getMenuName() {
        return "menu";
    //#Installer.java:212: method: String com.dmdirc.installer.Installer.getMenuName()
    //#output(String getMenuName()): return_value
    //#post(String getMenuName()): return_value == &"menu"
    //#Installer.java:212: end of method: String com.dmdirc.installer.Installer.getMenuName()
    }

    /**
     * Setup shortcut.
     *
     * @param location Location where app will be installed to.
     * @param shortcutType Type of shortcut to add.
     */
    protected abstract void setupShortcut(final String location,
                                          final ShortcutType shortcutType);

    /**
     * Copy a file from one location to another.
     * Based on http://www.exampledepot.com/egs/java.io/CopyFile.html
     *
     * @param srcFile Original file
     * @param dstFile New file
     * @throws java.io.IOException If an exception occurs while copying
     */
    protected final void copyFile(final String srcFile, final String dstFile)
            throws IOException {
        if (new File(srcFile).exists()) {
    //#Installer.java:234: method: void com.dmdirc.installer.Installer.copyFile(String, String)
    //#input(void copyFile(String, String)): " does not exist."._tainted
    //#input(void copyFile(String, String)): dstFile
    //#input(void copyFile(String, String)): srcFile
    //#input(void copyFile(String, String)): srcFile._tainted
    //#presumption(void copyFile(String, String)): java.io.File:exists(...)@234 == 1
    //#presumption(void copyFile(String, String)): java.io.FileInputStream:getChannel(...)@235 != null
    //#presumption(void copyFile(String, String)): java.io.FileOutputStream:getChannel(...)@237 != null
            final FileChannel srcChannel = new FileInputStream(srcFile).
                    getChannel();
            final FileChannel dstChannel = new FileOutputStream(dstFile).
                    getChannel();

            dstChannel.transferFrom(srcChannel, 0, srcChannel.size());

            srcChannel.close();
            dstChannel.close();
        } else {
            throw new IOException(srcFile + " does not exist.");
        }
    }
    //#Installer.java:247: end of method: void com.dmdirc.installer.Installer.copyFile(String, String)

    /**
     * Any post-install tasks should be done here.
     *
     * @param location Location where app was installed to.
     */
    public void postInstall(final String location) {
        // Nothing to do by default, installers may override
    }
    //#Installer.java:256: method: void com.dmdirc.installer.Installer.postInstall(String)
    //#Installer.java:256: end of method: void com.dmdirc.installer.Installer.postInstall(String)
}    //#Installer.java:: end of class: com.dmdirc.installer.Installer$ShortcutType
    //#output(com.dmdirc.installer.Installer$1__static_init): __Descendant_Table[com/dmdirc/installer/Installer$1]
    //#output(com.dmdirc.installer.Installer$1__static_init): __Dispatch_Table.accept(Ljava/io/File;Ljava/lang/String;)Z
    //#post(com.dmdirc.installer.Installer$1__static_init): __Descendant_Table[com/dmdirc/installer/Installer$1] == &__Dispatch_Table
    //#post(com.dmdirc.installer.Installer$1__static_init): __Dispatch_Table.accept(Ljava/io/File;Ljava/lang/String;)Z == &accept
    //#Installer.java:: end of method: com.dmdirc.installer.Installer$1.com.dmdirc.installer.Installer$1__static_init
    //#Installer.java:: end of class: com.dmdirc.installer.Installer$1
    //#output(com.dmdirc.installer.Installer__static_init): __Descendant_Table[com/dmdirc/installer/Installer]
    //#output(com.dmdirc.installer.Installer__static_init): __Dispatch_Table.copyFile(Ljava/lang/String;Ljava/lang/String;)V
    //#output(com.dmdirc.installer.Installer__static_init): __Dispatch_Table.defaultInstallLocation()Ljava/lang/String;
    //#output(com.dmdirc.installer.Installer__static_init): __Dispatch_Table.doSetup(Ljava/lang/String;)Z
    //#output(com.dmdirc.installer.Installer__static_init): __Dispatch_Table.getMenuName()Ljava/lang/String;
    //#output(com.dmdirc.installer.Installer__static_init): __Dispatch_Table.postInstall(Ljava/lang/String;)V
    //#output(com.dmdirc.installer.Installer__static_init): __Dispatch_Table.run()V
    //#output(com.dmdirc.installer.Installer__static_init): __Dispatch_Table.setInstallStep(Lcom/dmdirc/installer/TextStep;)V
    //#output(com.dmdirc.installer.Installer__static_init): __Dispatch_Table.setupShortcut(Ljava/lang/String;Lcom/dmdirc/installer/Installer$ShortcutType;)V
    //#output(com.dmdirc.installer.Installer__static_init): __Dispatch_Table.supportsShortcut(Lcom/dmdirc/installer/Installer$ShortcutType;)Z
    //#output(com.dmdirc.installer.Installer__static_init): __Dispatch_Table.validFile(Ljava/lang/String;)Z
    //#post(com.dmdirc.installer.Installer__static_init): __Descendant_Table[com/dmdirc/installer/Installer] == &__Dispatch_Table
    //#post(com.dmdirc.installer.Installer__static_init): __Dispatch_Table.copyFile(Ljava/lang/String;Ljava/lang/String;)V == &copyFile
    //#post(com.dmdirc.installer.Installer__static_init): __Dispatch_Table.defaultInstallLocation()Ljava/lang/String; == &defaultInstallLocation
    //#post(com.dmdirc.installer.Installer__static_init): __Dispatch_Table.doSetup(Ljava/lang/String;)Z == &doSetup
    //#post(com.dmdirc.installer.Installer__static_init): __Dispatch_Table.getMenuName()Ljava/lang/String; == &getMenuName
    //#post(com.dmdirc.installer.Installer__static_init): __Dispatch_Table.postInstall(Ljava/lang/String;)V == &postInstall
    //#post(com.dmdirc.installer.Installer__static_init): __Dispatch_Table.run()V == &run
    //#post(com.dmdirc.installer.Installer__static_init): __Dispatch_Table.setInstallStep(Lcom/dmdirc/installer/TextStep;)V == &setInstallStep
    //#post(com.dmdirc.installer.Installer__static_init): __Dispatch_Table.setupShortcut(Ljava/lang/String;Lcom/dmdirc/installer/Installer$ShortcutType;)V == &setupShortcut
    //#post(com.dmdirc.installer.Installer__static_init): __Dispatch_Table.supportsShortcut(Lcom/dmdirc/installer/Installer$ShortcutType;)Z == &supportsShortcut
    //#post(com.dmdirc.installer.Installer__static_init): __Dispatch_Table.validFile(Ljava/lang/String;)Z == &validFile
    //#Installer.java:: end of method: com.dmdirc.installer.Installer.com.dmdirc.installer.Installer__static_init
    //#Installer.java:: end of class: com.dmdirc.installer.Installer
