//# 3 errors, 224 messages
//#
/*
    //#URLBuilder.java:1:1: class: com.dmdirc.util.URLBuilder
    //#URLBuilder.java:1:1: method: com.dmdirc.util.URLBuilder.com.dmdirc.util.URLBuilder__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.util;

import com.dmdirc.logger.ErrorLevel;
import com.dmdirc.logger.Logger;
import com.dmdirc.plugins.PluginManager;
import com.dmdirc.ui.themes.ThemeManager;

import java.net.MalformedURLException;
import java.net.URL;

/**
 * Provides methods for building URLs to reference DMDirc resources.
 * 
 * @author chris
 */
public final class URLBuilder {
    
    /**
     * Creates a new instance of URLBuilder.
     */
    private URLBuilder() {
    //#URLBuilder.java:43: method: void com.dmdirc.util.URLBuilder.com.dmdirc.util.URLBuilder()
        // Shouldn't be constructed
    }
    //#URLBuilder.java:45: end of method: void com.dmdirc.util.URLBuilder.com.dmdirc.util.URLBuilder()

    /**
     * Constructs an URL pointing to the specified resource on the file system.
     * 
     * @param path The path that the URL is for
     * @return An URL corresponding to the specified path, or null on failure
     */
    public static URL buildFileURL(final String path) {
        final String prefix = path.startsWith("file://") ? "" : "file://";
    //#URLBuilder.java:54: method: URL com.dmdirc.util.URLBuilder.buildFileURL(String)
    //#input(URL buildFileURL(String)): ""._tainted
    //#input(URL buildFileURL(String)): "file:.."._tainted
    //#input(URL buildFileURL(String)): com.dmdirc.logger.ErrorLevel.HIGH
    //#input(URL buildFileURL(String)): path
    //#input(URL buildFileURL(String)): path._tainted
    //#output(URL buildFileURL(String)): new URL(buildFileURL#1) num objects
    //#output(URL buildFileURL(String)): return_value
    //#new obj(URL buildFileURL(String)): new URL(buildFileURL#1)
    //#pre[1] (URL buildFileURL(String)): path != null
    //#presumption(URL buildFileURL(String)): init'ed(com.dmdirc.logger.ErrorLevel.HIGH)
    //#post(URL buildFileURL(String)): return_value in Addr_Set{null,&new URL(buildFileURL#1)}
    //#post(URL buildFileURL(String)): new URL(buildFileURL#1) num objects <= 1
        
        try {
            return new URL(prefix + path);
        } catch (MalformedURLException ex) {
            Logger.appError(ErrorLevel.HIGH, "Unable to build file URL", ex);
    //#URLBuilder.java:59: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.logger.Logger:appError(ErrorLevel, String, Throwable)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.util.URLBuilder
    //#    method: URL buildFileURL(String)
    //#    unanalyzed callee: void com.dmdirc.logger.Logger:appError(ErrorLevel, String, Throwable)
            return null;
    //#URLBuilder.java:60: end of method: URL com.dmdirc.util.URLBuilder.buildFileURL(String)
        }
    }
    
    /**
     * Constructs an URL pointing to the specified resource within a jar file.
     * 
     * @param jarFile Path to the jar file (including scheme)
     * @param path Path to the resource within the jar file
     * @return An URL corresponding to the specified resource, or null on failure
     */
    public static URL buildJarURL(final String jarFile, final String path) {
        try {
            String url = "jar:" + buildURL(jarFile) + "!/" + path;
    //#URLBuilder.java:73: method: URL com.dmdirc.util.URLBuilder.buildJarURL(String, String)
    //#URLBuilder.java:73: ?use of default init
    //#    init'ed(buildURL(...)._tainted)
    //#    severity: LOW
    //#    class: com.dmdirc.util.URLBuilder
    //#    method: URL buildJarURL(String, String)
    //#    basic block: bb_2
    //#    assertion: init'ed(buildURL(...)._tainted)
    //#    VN: buildURL(...)._tainted
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#input(URL buildJarURL(String, String)): "!."._tainted
    //#input(URL buildJarURL(String, String)): ""._tainted
    //#input(URL buildJarURL(String, String)): ".zip"._tainted
    //#input(URL buildJarURL(String, String)): "Invalid URL, must contain ':': "._tainted
    //#input(URL buildJarURL(String, String)): "file:.."._tainted
    //#input(URL buildJarURL(String, String)): "jar:"._tainted
    //#input(URL buildJarURL(String, String)): "jar:file:."._tainted
    //#input(URL buildJarURL(String, String)): com.dmdirc.logger.ErrorLevel.HIGH
    //#input(URL buildJarURL(String, String)): com.dmdirc.logger.ErrorLevel.LOW
    //#input(URL buildJarURL(String, String)): com.dmdirc.logger.ErrorLevel.MEDIUM
    //#input(URL buildJarURL(String, String)): com/dmdirc/ui/themes/ThemeManager.THEME_DIR
    //#input(URL buildJarURL(String, String)): jarFile
    //#input(URL buildJarURL(String, String)): jarFile._tainted
    //#input(URL buildJarURL(String, String)): path
    //#input(URL buildJarURL(String, String)): path._tainted
    //#output(URL buildJarURL(String, String)): new URL(buildJarURL#3) num objects
    //#output(URL buildJarURL(String, String)): return_value
    //#new obj(URL buildJarURL(String, String)): new URL(buildJarURL#3)
    //#pre[1] (URL buildJarURL(String, String)): (soft) jarFile != null
    //#presumption(URL buildJarURL(String, String)): init'ed(com.dmdirc.logger.ErrorLevel.HIGH)
    //#post(URL buildJarURL(String, String)): return_value in Addr_Set{null,&new URL(buildJarURL#3)}
    //#post(URL buildJarURL(String, String)): new URL(buildJarURL#3) num objects <= 1
    //#unanalyzed(URL buildJarURL(String, String)): Effects-of-calling:java.lang.String:startsWith
    //#unanalyzed(URL buildJarURL(String, String)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(URL buildJarURL(String, String)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(URL buildJarURL(String, String)): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(URL buildJarURL(String, String)): Effects-of-calling:java.net.URL
    //#unanalyzed(URL buildJarURL(String, String)): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(URL buildJarURL(String, String)): Effects-of-calling:com.dmdirc.logger.Logger:appError
    //#unanalyzed(URL buildJarURL(String, String)): Effects-of-calling:java.lang.Thread:currentThread
    //#unanalyzed(URL buildJarURL(String, String)): Effects-of-calling:java.lang.Thread:getContextClassLoader
    //#unanalyzed(URL buildJarURL(String, String)): Effects-of-calling:java.lang.ClassLoader:getResource
    //#unanalyzed(URL buildJarURL(String, String)): Effects-of-calling:buildJarURL
    //#unanalyzed(URL buildJarURL(String, String)): Effects-of-calling:com.dmdirc.plugins.PluginManager:getPluginManager
    //#unanalyzed(URL buildJarURL(String, String)): Effects-of-calling:com.dmdirc.plugins.PluginManager:getPluginInfoByName
    //#unanalyzed(URL buildJarURL(String, String)): Effects-of-calling:com.dmdirc.plugins.PluginInfo:getFullFilename
    //#unanalyzed(URL buildJarURL(String, String)): Effects-of-calling:java.lang.String:substring
    //#unanalyzed(URL buildJarURL(String, String)): Effects-of-calling:java.lang.String:indexOf
    //#unanalyzed(URL buildJarURL(String, String)): Effects-of-calling:com.dmdirc.logger.Logger:userError
    //#test_vector(URL buildJarURL(String, String)): java.lang.String:startsWith(...)@74: {0}, {1}
            if (url.startsWith("jar:file://")) {
                url = "jar:file:/" + url.substring(11);
            }
            return new URL(url);
        } catch (MalformedURLException ex) {
            Logger.appError(ErrorLevel.HIGH, "Unable to build jar URL", ex);
    //#URLBuilder.java:79: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.logger.Logger:appError(ErrorLevel, String, Throwable)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.util.URLBuilder
    //#    method: URL buildJarURL(String, String)
    //#    unanalyzed callee: void com.dmdirc.logger.Logger:appError(ErrorLevel, String, Throwable)
            return null;
    //#URLBuilder.java:80: end of method: URL com.dmdirc.util.URLBuilder.buildJarURL(String, String)
        }        
    }
    
    /**
     * Constructs an URL pointing to the specified resource within the DMDirc
     * project.
     * 
     * @param resource The path to the resource
     * @return An URL corresponding to the specified resource
     */
    public static URL buildDMDircURL(final String resource) {
        return Thread.currentThread().getContextClassLoader().getResource(resource);
    //#URLBuilder.java:92: method: URL com.dmdirc.util.URLBuilder.buildDMDircURL(String)
    //#input(URL buildDMDircURL(String)): resource
    //#output(URL buildDMDircURL(String)): return_value
    //#presumption(URL buildDMDircURL(String)): java.lang.Thread:currentThread(...)@92 != null
    //#presumption(URL buildDMDircURL(String)): java.lang.Thread:getContextClassLoader(...)@92 != null
    //#post(URL buildDMDircURL(String)): init'ed(return_value)
    //#URLBuilder.java:92: end of method: URL com.dmdirc.util.URLBuilder.buildDMDircURL(String)
    }
    
    /**
     * Builds an URL pointing to a resource within a DMDirc theme.
     * 
     * @param theme The theme which the resource is located in
     * @param path The path within the theme of the resource
     * @return An URL corresponding to the specified resource, or null on failure
     */
    public static URL buildThemeURL(final String theme, final String path) {
        return buildJarURL(ThemeManager.getThemeDirectory() + theme + ".zip", path);
    //#URLBuilder.java:103: method: URL com.dmdirc.util.URLBuilder.buildThemeURL(String, String)
    //#URLBuilder.java:103: ?use of default init
    //#    init'ed(getThemeDirectory(...)._tainted)
    //#    severity: LOW
    //#    class: com.dmdirc.util.URLBuilder
    //#    method: URL buildThemeURL(String, String)
    //#    basic block: Entry_BB_1
    //#    assertion: init'ed(getThemeDirectory(...)._tainted)
    //#    VN: undefined
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#URLBuilder.java:103: ?use of default init
    //#    init'ed(java/lang/StringBuilder:append(...)._tainted)
    //#    severity: LOW
    //#    class: com.dmdirc.util.URLBuilder
    //#    method: URL buildThemeURL(String, String)
    //#    basic block: Entry_BB_1
    //#    assertion: init'ed(java/lang/StringBuilder:append(...)._tainted)
    //#    VN: undefined
    //#    Expected: {-Inf..+Inf}
    //#    Bad: {Invalid}
    //#    Attribs:  Int  Bad only invalid
    //#input(URL buildThemeURL(String, String)): "!."._tainted
    //#input(URL buildThemeURL(String, String)): ""._tainted
    //#input(URL buildThemeURL(String, String)): ".zip"._tainted
    //#input(URL buildThemeURL(String, String)): "Invalid URL, must contain ':': "._tainted
    //#input(URL buildThemeURL(String, String)): "file:.."._tainted
    //#input(URL buildThemeURL(String, String)): "jar:"._tainted
    //#input(URL buildThemeURL(String, String)): "jar:file:."._tainted
    //#input(URL buildThemeURL(String, String)): com.dmdirc.logger.ErrorLevel.HIGH
    //#input(URL buildThemeURL(String, String)): com.dmdirc.logger.ErrorLevel.LOW
    //#input(URL buildThemeURL(String, String)): com.dmdirc.logger.ErrorLevel.MEDIUM
    //#input(URL buildThemeURL(String, String)): com/dmdirc/ui/themes/ThemeManager.THEME_DIR
    //#input(URL buildThemeURL(String, String)): path
    //#input(URL buildThemeURL(String, String)): path._tainted
    //#input(URL buildThemeURL(String, String)): theme
    //#input(URL buildThemeURL(String, String)): theme._tainted
    //#output(URL buildThemeURL(String, String)): new URL(buildJarURL#3) num objects
    //#output(URL buildThemeURL(String, String)): return_value
    //#new obj(URL buildThemeURL(String, String)): new URL(buildJarURL#3)
    //#post(URL buildThemeURL(String, String)): return_value == One-of{&new URL(buildJarURL#3), null}
    //#post(URL buildThemeURL(String, String)): return_value in Addr_Set{null,&new URL(buildJarURL#3)}
    //#post(URL buildThemeURL(String, String)): new URL(buildJarURL#3) num objects <= 1
    //#unanalyzed(URL buildThemeURL(String, String)): Effects-of-calling:java.lang.String:startsWith
    //#unanalyzed(URL buildThemeURL(String, String)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(URL buildThemeURL(String, String)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(URL buildThemeURL(String, String)): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(URL buildThemeURL(String, String)): Effects-of-calling:java.net.URL
    //#unanalyzed(URL buildThemeURL(String, String)): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(URL buildThemeURL(String, String)): Effects-of-calling:com.dmdirc.logger.Logger:appError
    //#unanalyzed(URL buildThemeURL(String, String)): Effects-of-calling:java.lang.Thread:currentThread
    //#unanalyzed(URL buildThemeURL(String, String)): Effects-of-calling:java.lang.Thread:getContextClassLoader
    //#unanalyzed(URL buildThemeURL(String, String)): Effects-of-calling:java.lang.ClassLoader:getResource
    //#unanalyzed(URL buildThemeURL(String, String)): Effects-of-calling:buildJarURL
    //#unanalyzed(URL buildThemeURL(String, String)): Effects-of-calling:com.dmdirc.plugins.PluginManager:getPluginManager
    //#unanalyzed(URL buildThemeURL(String, String)): Effects-of-calling:com.dmdirc.plugins.PluginManager:getPluginInfoByName
    //#unanalyzed(URL buildThemeURL(String, String)): Effects-of-calling:com.dmdirc.plugins.PluginInfo:getFullFilename
    //#unanalyzed(URL buildThemeURL(String, String)): Effects-of-calling:java.lang.String:substring
    //#unanalyzed(URL buildThemeURL(String, String)): Effects-of-calling:java.lang.String:indexOf
    //#unanalyzed(URL buildThemeURL(String, String)): Effects-of-calling:com.dmdirc.logger.Logger:userError
    //#URLBuilder.java:103: end of method: URL com.dmdirc.util.URLBuilder.buildThemeURL(String, String)
    }
    
    /**
     * Builds an URL pointing to a resource within a DMDirc plugin.
     * 
     * @param plugin The plugin which the resource is located in
     * @param path The path within the theme of the resource
     * @return An URL corresponding to the specified resource, or null on failure
     */
    public static URL buildPluginURL(final String plugin, final String path) {
        return buildJarURL(
    //#URLBuilder.java:114: method: URL com.dmdirc.util.URLBuilder.buildPluginURL(String, String)
    //#URLBuilder.java:114: Warning: method not available - call not analyzed
    //#    call on PluginManager com.dmdirc.plugins.PluginManager:getPluginManager()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.util.URLBuilder
    //#    method: URL buildPluginURL(String, String)
    //#    unanalyzed callee: PluginManager com.dmdirc.plugins.PluginManager:getPluginManager()
    //#URLBuilder.java:114: Warning: method not available - call not analyzed
    //#    call on PluginInfo com.dmdirc.plugins.PluginManager:getPluginInfoByName(String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.util.URLBuilder
    //#    method: URL buildPluginURL(String, String)
    //#    unanalyzed callee: PluginInfo com.dmdirc.plugins.PluginManager:getPluginInfoByName(String)
    //#URLBuilder.java:114: Warning: method not available - call not analyzed
    //#    call on String com.dmdirc.plugins.PluginInfo:getFullFilename()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.util.URLBuilder
    //#    method: URL buildPluginURL(String, String)
    //#    unanalyzed callee: String com.dmdirc.plugins.PluginInfo:getFullFilename()
    //#input(URL buildPluginURL(String, String)): "!."._tainted
    //#input(URL buildPluginURL(String, String)): ""._tainted
    //#input(URL buildPluginURL(String, String)): ".zip"._tainted
    //#input(URL buildPluginURL(String, String)): "Invalid URL, must contain ':': "._tainted
    //#input(URL buildPluginURL(String, String)): "file:.."._tainted
    //#input(URL buildPluginURL(String, String)): "jar:"._tainted
    //#input(URL buildPluginURL(String, String)): "jar:file:."._tainted
    //#input(URL buildPluginURL(String, String)): com.dmdirc.logger.ErrorLevel.HIGH
    //#input(URL buildPluginURL(String, String)): com.dmdirc.logger.ErrorLevel.LOW
    //#input(URL buildPluginURL(String, String)): com.dmdirc.logger.ErrorLevel.MEDIUM
    //#input(URL buildPluginURL(String, String)): com/dmdirc/ui/themes/ThemeManager.THEME_DIR
    //#input(URL buildPluginURL(String, String)): path
    //#input(URL buildPluginURL(String, String)): path._tainted
    //#input(URL buildPluginURL(String, String)): plugin
    //#output(URL buildPluginURL(String, String)): new URL(buildJarURL#3) num objects
    //#output(URL buildPluginURL(String, String)): return_value
    //#new obj(URL buildPluginURL(String, String)): new URL(buildJarURL#3)
    //#presumption(URL buildPluginURL(String, String)): com.dmdirc.plugins.PluginInfo:getFullFilename(...)@114 != null
    //#presumption(URL buildPluginURL(String, String)): com.dmdirc.plugins.PluginManager:getPluginInfoByName(...)@114 != null
    //#presumption(URL buildPluginURL(String, String)): com.dmdirc.plugins.PluginManager:getPluginManager(...)@114 != null
    //#post(URL buildPluginURL(String, String)): return_value == One-of{&new URL(buildJarURL#3), null}
    //#post(URL buildPluginURL(String, String)): return_value in Addr_Set{null,&new URL(buildJarURL#3)}
    //#post(URL buildPluginURL(String, String)): new URL(buildJarURL#3) num objects <= 1
    //#unanalyzed(URL buildPluginURL(String, String)): Effects-of-calling:java.lang.String:startsWith
    //#unanalyzed(URL buildPluginURL(String, String)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(URL buildPluginURL(String, String)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(URL buildPluginURL(String, String)): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(URL buildPluginURL(String, String)): Effects-of-calling:java.net.URL
    //#unanalyzed(URL buildPluginURL(String, String)): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(URL buildPluginURL(String, String)): Effects-of-calling:com.dmdirc.logger.Logger:appError
    //#unanalyzed(URL buildPluginURL(String, String)): Effects-of-calling:java.lang.Thread:currentThread
    //#unanalyzed(URL buildPluginURL(String, String)): Effects-of-calling:java.lang.Thread:getContextClassLoader
    //#unanalyzed(URL buildPluginURL(String, String)): Effects-of-calling:java.lang.ClassLoader:getResource
    //#unanalyzed(URL buildPluginURL(String, String)): Effects-of-calling:buildJarURL
    //#unanalyzed(URL buildPluginURL(String, String)): Effects-of-calling:com.dmdirc.plugins.PluginManager:getPluginManager
    //#unanalyzed(URL buildPluginURL(String, String)): Effects-of-calling:com.dmdirc.plugins.PluginManager:getPluginInfoByName
    //#unanalyzed(URL buildPluginURL(String, String)): Effects-of-calling:com.dmdirc.plugins.PluginInfo:getFullFilename
    //#unanalyzed(URL buildPluginURL(String, String)): Effects-of-calling:java.lang.String:substring
    //#unanalyzed(URL buildPluginURL(String, String)): Effects-of-calling:java.lang.String:indexOf
    //#unanalyzed(URL buildPluginURL(String, String)): Effects-of-calling:com.dmdirc.logger.Logger:userError
    //#URLBuilder.java:114: end of method: URL com.dmdirc.util.URLBuilder.buildPluginURL(String, String)
                PluginManager.getPluginManager().getPluginInfoByName(plugin).getFullFilename(),
                path);
    }
    
    /**
     * Constructs an URL corresponding to the described resource.
     * 
     * @param spec The resource location. May take the form of: <ul>
     * <li>dmdirc://com/dmdirc/etc/
     * <li>jar://path/to/jarfile:path/inside/jarfile
     * <li>zip://path/to/zipfile:path/inside/zipfile
     * <li>theme://theme_name:file/inside/theme
     * <li>plugin://plugin_name:file/inside/plugin
     * <li>http://server/path
     * <li>https://server/path
     * <li>[file://]/path/on/filesystem</ul>
     * 
     * @return An URL corresponding to the specified resource, or null on failure
     */
    public static URL buildURL(final String spec) {
        if (spec.startsWith("dmdirc://")) {
    //#URLBuilder.java:135: method: URL com.dmdirc.util.URLBuilder.buildURL(String)
    //#input(URL buildURL(String)): "!."._tainted
    //#input(URL buildURL(String)): ""._tainted
    //#input(URL buildURL(String)): ".zip"._tainted
    //#input(URL buildURL(String)): "Invalid URL, must contain ':': "._tainted
    //#input(URL buildURL(String)): "file:.."._tainted
    //#input(URL buildURL(String)): "jar:"._tainted
    //#input(URL buildURL(String)): "jar:file:."._tainted
    //#input(URL buildURL(String)): com.dmdirc.logger.ErrorLevel.HIGH
    //#input(URL buildURL(String)): com.dmdirc.logger.ErrorLevel.LOW
    //#input(URL buildURL(String)): com.dmdirc.logger.ErrorLevel.MEDIUM
    //#input(URL buildURL(String)): com/dmdirc/ui/themes/ThemeManager.THEME_DIR
    //#input(URL buildURL(String)): spec
    //#input(URL buildURL(String)): spec._tainted
    //#output(URL buildURL(String)): new URL(buildFileURL#1) num objects
    //#output(URL buildURL(String)): new URL(buildJarURL#3) num objects
    //#output(URL buildURL(String)): new URL(buildURL#4) num objects
    //#output(URL buildURL(String)): return_value
    //#new obj(URL buildURL(String)): new URL(buildFileURL#1)
    //#new obj(URL buildURL(String)): new URL(buildJarURL#3)
    //#new obj(URL buildURL(String)): new URL(buildURL#4)
    //#pre[1] (URL buildURL(String)): spec != null
    //#presumption(URL buildURL(String)): init'ed(com.dmdirc.logger.ErrorLevel.LOW)
    //#presumption(URL buildURL(String)): init'ed(com.dmdirc.logger.ErrorLevel.MEDIUM)
    //#presumption(URL buildURL(String)): java.lang.String:indexOf(...)@138 <= 4_294_967_294
    //#presumption(URL buildURL(String)): java.lang.String:indexOf(...)@147 <= 4_294_967_294
    //#presumption(URL buildURL(String)): java.lang.String:indexOf(...)@156 <= 4_294_967_294
    //#post(URL buildURL(String)): init'ed(return_value)
    //#post(URL buildURL(String)): new URL(buildFileURL#1) num objects <= 1
    //#post(URL buildURL(String)): new URL(buildJarURL#3) num objects <= 1
    //#post(URL buildURL(String)): new URL(buildURL#4) num objects <= 1
    //#unanalyzed(URL buildURL(String)): Effects-of-calling:java.lang.String:startsWith
    //#unanalyzed(URL buildURL(String)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(URL buildURL(String)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(URL buildURL(String)): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(URL buildURL(String)): Effects-of-calling:java.net.URL
    //#unanalyzed(URL buildURL(String)): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(URL buildURL(String)): Effects-of-calling:com.dmdirc.logger.Logger:appError
    //#unanalyzed(URL buildURL(String)): Effects-of-calling:java.lang.Thread:currentThread
    //#unanalyzed(URL buildURL(String)): Effects-of-calling:java.lang.Thread:getContextClassLoader
    //#unanalyzed(URL buildURL(String)): Effects-of-calling:java.lang.ClassLoader:getResource
    //#unanalyzed(URL buildURL(String)): Effects-of-calling:buildJarURL
    //#unanalyzed(URL buildURL(String)): Effects-of-calling:com.dmdirc.plugins.PluginManager:getPluginManager
    //#unanalyzed(URL buildURL(String)): Effects-of-calling:com.dmdirc.plugins.PluginManager:getPluginInfoByName
    //#unanalyzed(URL buildURL(String)): Effects-of-calling:com.dmdirc.plugins.PluginInfo:getFullFilename
    //#unanalyzed(URL buildURL(String)): Effects-of-calling:java.lang.String:substring
    //#unanalyzed(URL buildURL(String)): Effects-of-calling:java.lang.String:indexOf
    //#unanalyzed(URL buildURL(String)): Effects-of-calling:com.dmdirc.logger.Logger:userError
    //#test_vector(URL buildURL(String)): java.lang.String:indexOf(...)@138: {0..4_294_967_294}, {-2_147_483_648..-1}
    //#test_vector(URL buildURL(String)): java.lang.String:indexOf(...)@147: {0..4_294_967_294}, {-2_147_483_648..-1}
    //#test_vector(URL buildURL(String)): java.lang.String:indexOf(...)@156: {0..4_294_967_294}, {-2_147_483_648..-1}
    //#test_vector(URL buildURL(String)): java.lang.String:startsWith(...)@135: {0}, {1}
    //#test_vector(URL buildURL(String)): java.lang.String:startsWith(...)@137: {1}, {0}
    //#test_vector(URL buildURL(String)): java.lang.String:startsWith(...)@137: {0}, {1}
    //#test_vector(URL buildURL(String)): java.lang.String:startsWith(...)@146: {0}, {1}
    //#test_vector(URL buildURL(String)): java.lang.String:startsWith(...)@155: {0}, {1}
    //#test_vector(URL buildURL(String)): java.lang.String:startsWith(...)@164: {1}, {0}
    //#test_vector(URL buildURL(String)): java.lang.String:startsWith(...)@164: {0}, {1}
            return buildDMDircURL(spec.substring(9));
        } else if (spec.startsWith("jar://") || spec.startsWith("zip://")) {
            final int offset = spec.indexOf(':', 6);
            
            if (offset < 0) {
                Logger.userError(ErrorLevel.LOW, "Invalid URL, must contain ':': " + spec);
    //#URLBuilder.java:141: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.logger.Logger:userError(ErrorLevel, String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.util.URLBuilder
    //#    method: URL buildURL(String)
    //#    unanalyzed callee: void com.dmdirc.logger.Logger:userError(ErrorLevel, String)
                return null;
            } else {
                return buildJarURL(spec.substring(6, offset), spec.substring(offset + 1));
            }
        } else if (spec.startsWith("plugin://")) {
            final int offset = spec.indexOf(':', 8);
            
            if (offset < 0) {
                Logger.userError(ErrorLevel.LOW, "Invalid URL, must contain ':': " + spec);
    //#URLBuilder.java:150: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.logger.Logger:userError(ErrorLevel, String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.util.URLBuilder
    //#    method: URL buildURL(String)
    //#    unanalyzed callee: void com.dmdirc.logger.Logger:userError(ErrorLevel, String)
                return null;
            } else {
                return buildPluginURL(spec.substring(9, offset), spec.substring(offset + 1));
            }            
        } else if (spec.startsWith("theme://")) {
            final int offset = spec.indexOf(':', 8);
            
            if (offset < 0) {
                Logger.userError(ErrorLevel.LOW, "Invalid URL, must contain ':': " + spec);
    //#URLBuilder.java:159: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.logger.Logger:userError(ErrorLevel, String)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.util.URLBuilder
    //#    method: URL buildURL(String)
    //#    unanalyzed callee: void com.dmdirc.logger.Logger:userError(ErrorLevel, String)
                return null;
            } else {
                return buildThemeURL(spec.substring(8, offset), spec.substring(offset + 1));
            }
        } else if (spec.startsWith("http://") || spec.startsWith("https://")) {
            try {
                return new URL(spec);
            } catch (MalformedURLException ex) {
                Logger.userError(ErrorLevel.MEDIUM, "Unable to load resource", ex);
    //#URLBuilder.java:168: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.logger.Logger:userError(ErrorLevel, String, Throwable)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.util.URLBuilder
    //#    method: URL buildURL(String)
    //#    unanalyzed callee: void com.dmdirc.logger.Logger:userError(ErrorLevel, String, Throwable)
                return null;
            }
        } else {
            return buildFileURL(spec);
    //#URLBuilder.java:172: end of method: URL com.dmdirc.util.URLBuilder.buildURL(String)
        }
    }
}
    //#output(com.dmdirc.util.URLBuilder__static_init): __Descendant_Table[com/dmdirc/util/URLBuilder]
    //#post(com.dmdirc.util.URLBuilder__static_init): __Descendant_Table[com/dmdirc/util/URLBuilder] == &__Dispatch_Table
    //#URLBuilder.java:: end of method: com.dmdirc.util.URLBuilder.com.dmdirc.util.URLBuilder__static_init
    //#URLBuilder.java:: end of class: com.dmdirc.util.URLBuilder
