//# 0 errors, 170 messages
//#
/*
    //#SSLCertificateDialogModel.java:1:1: class: com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel
    //#SSLCertificateDialogModel.java:1:1: method: com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel.com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel__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.ui.core.dialogs.sslcertificate;

import com.dmdirc.CertificateManager;
import com.dmdirc.CertificateManager.CertificateDoesntMatchHostException;
import com.dmdirc.CertificateManager.CertificateNotTrustedException;

import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Model for SSL certificate dialogs.
 *
 * @since 0.6.3m1
 * @author chris
 */
public class SSLCertificateDialogModel {

    /** The certificate chain that we're displaying information about. */
    private final X509Certificate[] chain;

    /** The certificate manager for the connection attempt. */
    private final CertificateManager manager;

    /** The list of problems found with the certs, if any. */
    private final List<CertificateException> problems;

    /** The text to use if a field isn't present on the certificate. */
    private static final String NOTPRESENT = "(not present on certificate)";

    /**
     * Creates a new SSLCertificateDialogModel for the specified chain.
     *
     * @param chain The chain of certificates to display info on
     * @param problems A list of problems with the certificates, if any
     * @param manager The certificate manager responsible for the certs
     */
    public SSLCertificateDialogModel(final X509Certificate[] chain,
            final List<CertificateException> problems,
            final CertificateManager manager) {
    //#SSLCertificateDialogModel.java:67: method: void com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel.com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel(X509Certificate[], List, CertificateManager)
    //#input(void com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel(X509Certificate[], List, CertificateManager)): chain
    //#input(void com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel(X509Certificate[], List, CertificateManager)): manager
    //#input(void com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel(X509Certificate[], List, CertificateManager)): problems
    //#input(void com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel(X509Certificate[], List, CertificateManager)): this
    //#output(void com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel(X509Certificate[], List, CertificateManager)): this.chain
    //#output(void com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel(X509Certificate[], List, CertificateManager)): this.manager
    //#output(void com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel(X509Certificate[], List, CertificateManager)): this.problems
    //#post(void com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel(X509Certificate[], List, CertificateManager)): this.chain == chain
    //#post(void com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel(X509Certificate[], List, CertificateManager)): init'ed(this.chain)
    //#post(void com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel(X509Certificate[], List, CertificateManager)): this.manager == manager
    //#post(void com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel(X509Certificate[], List, CertificateManager)): init'ed(this.manager)
    //#post(void com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel(X509Certificate[], List, CertificateManager)): this.problems == problems
    //#post(void com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel(X509Certificate[], List, CertificateManager)): init'ed(this.problems)
        this.chain = chain;
        this.problems = problems;
        this.manager = manager;
    }
    //#SSLCertificateDialogModel.java:71: end of method: void com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel.com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel(X509Certificate[], List, CertificateManager)

    /**
     * Retrieves the certificate chain that's under question.
     *
     * @return A list of {@link CertificateChainEntry}s corresponding to the
     * certificate chain being questioned.
     */
    public List<CertificateChainEntry> getCertificateChain() {
        final List<CertificateChainEntry> res = new ArrayList<CertificateChainEntry>();
    //#SSLCertificateDialogModel.java:80: method: List com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel.getCertificateChain()
    //#input(List getCertificateChain()): this
    //#input(List getCertificateChain()): this.chain
    //#input(List getCertificateChain()): this.chain.length
    //#input(List getCertificateChain()): this.chain[0..4_294_967_295]
    //#input(List getCertificateChain()): this.manager
    //#output(List getCertificateChain()): new ArrayList(getCertificateChain#1) num objects
    //#output(List getCertificateChain()): return_value
    //#new obj(List getCertificateChain()): new ArrayList(getCertificateChain#1)
    //#pre[2] (List getCertificateChain()): this.chain != null
    //#pre[3] (List getCertificateChain()): this.chain.length <= 4_294_967_295
    //#pre[4] (List getCertificateChain()): (soft) this.chain[0..4_294_967_295] != null
    //#pre[5] (List getCertificateChain()): (soft) this.manager != null
    //#presumption(List getCertificateChain()): com.dmdirc.CertificateManager:getDNFieldsFromCert(...)@94 != null
    //#post(List getCertificateChain()): return_value == &new ArrayList(getCertificateChain#1)
    //#post(List getCertificateChain()): new ArrayList(getCertificateChain#1) num objects == 1

        boolean first = true;

        for (X509Certificate cert : chain) {
            boolean invalid = first && !manager.isValidHost(cert);
    //#SSLCertificateDialogModel.java:85: Warning: method not available - call not analyzed
    //#    call on bool com.dmdirc.CertificateManager:isValidHost(X509Certificate)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel
    //#    method: List getCertificateChain()
    //#    unanalyzed callee: bool com.dmdirc.CertificateManager:isValidHost(X509Certificate)
            first = false;

            try {
                cert.checkValidity();
            } catch (CertificateException ex) {
                invalid |= true;
            }

            res.add(new CertificateChainEntry(CertificateManager
    //#SSLCertificateDialogModel.java:94: Warning: method not available - call not analyzed
    //#    call on Map com.dmdirc.CertificateManager:getDNFieldsFromCert(X509Certificate)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel
    //#    method: List getCertificateChain()
    //#    unanalyzed callee: Map com.dmdirc.CertificateManager:getDNFieldsFromCert(X509Certificate)
    //#SSLCertificateDialogModel.java:94: Warning: method not available - call not analyzed
    //#    call on bool com.dmdirc.CertificateManager:isTrusted(X509Certificate)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel
    //#    method: List getCertificateChain()
    //#    unanalyzed callee: bool com.dmdirc.CertificateManager:isTrusted(X509Certificate)
                    .getDNFieldsFromCert(cert).get("CN"),
                    manager.isTrusted(cert), invalid));
        }

        return res;
    //#SSLCertificateDialogModel.java:99: end of method: List com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel.getCertificateChain()
    }

    /**
     * Retrieves displayable information about the certificate with the
     * specified index in the chain.
     *
     * @param index The index of the certificate to request information on
     * @return A list of lists of {@link CertificateInformationEntry}s.
     */
    public List<List<CertificateInformationEntry>> getCertificateInfo(final int index) {
        final List<List<CertificateInformationEntry>> res
    //#SSLCertificateDialogModel.java:110: method: List com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel.getCertificateInfo(int)
    //#input(List getCertificateInfo(int)): ", "._tainted
    //#input(List getCertificateInfo(int)): __Descendant_Table[com/dmdirc/ui/core/dialogs/sslcertificate/SSLCertificateDialogModel]
    //#input(List getCertificateInfo(int)): __Descendant_Table[others]
    //#input(List getCertificateInfo(int)): __Dispatch_Table.addCertField(Ljava/util/Map;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Z)V
    //#input(List getCertificateInfo(int)): __Dispatch_Table.getAlternateNames(Ljava/security/cert/X509Certificate;)Ljava/lang/String;
    //#input(List getCertificateInfo(int)): index
    //#input(List getCertificateInfo(int)): this
    //#input(List getCertificateInfo(int)): this.__Tag
    //#input(List getCertificateInfo(int)): this.chain
    //#input(List getCertificateInfo(int)): this.chain.length
    //#input(List getCertificateInfo(int)): this.chain[0..4_294_967_295]
    //#input(List getCertificateInfo(int)): this.manager
    //#output(List getCertificateInfo(int)): new ArrayList(getCertificateInfo#1) num objects
    //#output(List getCertificateInfo(int)): return_value
    //#new obj(List getCertificateInfo(int)): new ArrayList(getCertificateInfo#1)
    //#pre[1] (List getCertificateInfo(int)): index >= 0
    //#pre[3] (List getCertificateInfo(int)): this.__Tag == com/dmdirc/ui/core/dialogs/sslcertificate/SSLCertificateDialogModel
    //#pre[4] (List getCertificateInfo(int)): this.chain != null
    //#pre[5] (List getCertificateInfo(int)): this.chain.length >= 1
    //#pre[6] (List getCertificateInfo(int)): index < this.chain.length
    //#pre[7] (List getCertificateInfo(int)): (soft) this.chain[0..4_294_967_295] != null
    //#pre[8] (List getCertificateInfo(int)): (soft) this.manager != null
    //#presumption(List getCertificateInfo(int)): com.dmdirc.CertificateManager:getDNFieldsFromCert(...)@134 != null
    //#presumption(List getCertificateInfo(int)): java.security.cert.X509Certificate:getNotAfter(...)@128 != null
    //#presumption(List getCertificateInfo(int)): java.security.cert.X509Certificate:getNotBefore(...)@126 != null
    //#presumption(List getCertificateInfo(int)): java.security.cert.X509Certificate:getSerialNumber(...)@150 != null
    //#post(List getCertificateInfo(int)): return_value == &new ArrayList(getCertificateInfo#1)
    //#post(List getCertificateInfo(int)): new ArrayList(getCertificateInfo#1) num objects == 1
    //#unanalyzed(List getCertificateInfo(int)): Effects-of-calling:java.lang.Throwable:__curr_excep_obj
    //#unanalyzed(List getCertificateInfo(int)): Effects-of-calling:java.util.Map:get
    //#unanalyzed(List getCertificateInfo(int)): Effects-of-calling:java.util.List:add
    //#unanalyzed(List getCertificateInfo(int)): Effects-of-calling:java.lang.StringBuilder
    //#unanalyzed(List getCertificateInfo(int)): Effects-of-calling:java.security.cert.X509Certificate:getSubjectAlternativeNames
    //#unanalyzed(List getCertificateInfo(int)): Effects-of-calling:java.util.Collection:iterator
    //#unanalyzed(List getCertificateInfo(int)): Effects-of-calling:java.util.Iterator:hasNext
    //#unanalyzed(List getCertificateInfo(int)): Effects-of-calling:java.util.Iterator:next
    //#unanalyzed(List getCertificateInfo(int)): Effects-of-calling:java.util.List:get
    //#unanalyzed(List getCertificateInfo(int)): Effects-of-calling:java.lang.Integer:intValue
    //#unanalyzed(List getCertificateInfo(int)): Effects-of-calling:java.lang.StringBuilder:length
    //#unanalyzed(List getCertificateInfo(int)): Effects-of-calling:java.lang.StringBuilder:append
    //#unanalyzed(List getCertificateInfo(int)): Effects-of-calling:java.lang.StringBuilder:toString
    //#unanalyzed(List getCertificateInfo(int)): Effects-of-calling:java.util.Map:containsKey
                = new ArrayList<List<CertificateInformationEntry>>();
        final X509Certificate cert = chain[index];
        List<CertificateInformationEntry> group;

        boolean tooOld = false, tooNew = false;

        try {
            cert.checkValidity();
        } catch (CertificateExpiredException ex) {
            tooOld = true;
        } catch (CertificateNotYetValidException ex) {
            tooNew = true;
        }

        group = new ArrayList<CertificateInformationEntry>();
        group.add(new CertificateInformationEntry("Valid from",
                cert.getNotBefore().toString(), tooNew, false));
        group.add(new CertificateInformationEntry("Valid to",
                cert.getNotAfter().toString(), tooOld, false));
        res.add(group);

        final boolean wrongName = index == 0 && !manager.isValidHost(cert);
    //#SSLCertificateDialogModel.java:132: Warning: method not available - call not analyzed
    //#    call on bool com.dmdirc.CertificateManager:isValidHost(X509Certificate)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel
    //#    method: List getCertificateInfo(int)
    //#    unanalyzed callee: bool com.dmdirc.CertificateManager:isValidHost(X509Certificate)
        final String names = getAlternateNames(cert);
        final Map<String, String> fields = CertificateManager.getDNFieldsFromCert(cert);
    //#SSLCertificateDialogModel.java:134: Warning: method not available - call not analyzed
    //#    call on Map com.dmdirc.CertificateManager:getDNFieldsFromCert(X509Certificate)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel
    //#    method: List getCertificateInfo(int)
    //#    unanalyzed callee: Map com.dmdirc.CertificateManager:getDNFieldsFromCert(X509Certificate)

        group = new ArrayList<CertificateInformationEntry>();
        addCertField(fields, group, "Common name", "CN", wrongName);

        group.add(new CertificateInformationEntry("Alternate names", 
                names == null ? NOTPRESENT : names, wrongName, names == null));

        addCertField(fields, group, "Organisation", "O", false);
        addCertField(fields, group, "Unit", "OU", false);
        addCertField(fields, group, "Locality", "L", false);
        addCertField(fields, group, "State", "ST", false);
        addCertField(fields, group, "Country", "C", false);
        res.add(group);

        group = new ArrayList<CertificateInformationEntry>();
        group.add(new CertificateInformationEntry("Serial number",
                cert.getSerialNumber().toString(), false, false));
        group.add(new CertificateInformationEntry("Algorithm",
                cert.getSigAlgName(), false, false));
        group.add(new CertificateInformationEntry("SSL version",
                String.valueOf(cert.getVersion()), false, false));
        res.add(group);

        return res;
    //#SSLCertificateDialogModel.java:158: end of method: List com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel.getCertificateInfo(int)
    }

    protected String getAlternateNames(final X509Certificate cert) {
        final StringBuilder res = new StringBuilder();
    //#SSLCertificateDialogModel.java:162: method: String com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel.getAlternateNames(X509Certificate)
    //#input(String getAlternateNames(X509Certificate)): ", "._tainted
    //#input(String getAlternateNames(X509Certificate)): cert
    //#output(String getAlternateNames(X509Certificate)): java.lang.StringBuilder:toString(...)._tainted
    //#output(String getAlternateNames(X509Certificate)): return_value
    //#new obj(String getAlternateNames(X509Certificate)): java.lang.StringBuilder:toString(...)
    //#pre[1] (String getAlternateNames(X509Certificate)): (soft) cert != null
    //#presumption(String getAlternateNames(X509Certificate)): java.security.cert.X509Certificate:getSubjectAlternativeNames(...)@169 != null
    //#presumption(String getAlternateNames(X509Certificate)): java.util.Iterator:next(...)@169 != null
    //#presumption(String getAlternateNames(X509Certificate)): java.util.List:get(...)@170 != null
    //#post(String getAlternateNames(X509Certificate)): java.lang.StringBuilder:toString(...)._tainted == 0
    //#post(String getAlternateNames(X509Certificate)): return_value in Addr_Set{null,&java.lang.StringBuilder:toString(...)}
    //#test_vector(String getAlternateNames(X509Certificate)): java.lang.Integer:intValue(...)@170: {-2_147_483_648..1, 3..6, 8..4_294_967_295}, {7}
    //#test_vector(String getAlternateNames(X509Certificate)): java.lang.StringBuilder:length(...)@174: {-2_147_483_648..0}, {1..4_294_967_295}
    //#test_vector(String getAlternateNames(X509Certificate)): java.security.cert.X509Certificate:getSubjectAlternativeNames(...)@165: Inverse{null}, Addr_Set{null}

        try {
            if (cert.getSubjectAlternativeNames() == null) {
                return null;
            }

            for (List<?> entry : cert.getSubjectAlternativeNames()) {
                final int type = ((Integer) entry.get(0)).intValue();

                // DNS or IP
                if (type == 2 || type == 7) {
                    if (res.length() > 0) {
                        res.append(", ");
                    }

                    res.append(entry.get(1));
                }
            }
        } catch (CertificateParsingException ex) {
            // Do nothing
        }

        return res.toString();
    //#SSLCertificateDialogModel.java:185: end of method: String com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel.getAlternateNames(X509Certificate)
    }

    /**
     * Adds a field to the specified group.
     *
     * @param fields The fields extracted from the certiciate
     * @param group The group to add an entry to
     * @param title The user-friendly title of the field
     * @param field The name of the field to look for
     * @param invalid Whether or not the field is a cause for concern
     */
    protected void addCertField(final Map<String, String> fields,
            final List<CertificateInformationEntry> group, final String title,
            final String field, final boolean invalid) {
        group.add(new CertificateInformationEntry(title,
    //#SSLCertificateDialogModel.java:200: method: void com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel.addCertField(Map, List, String, String, bool)
    //#input(void addCertField(Map, List, String, String, bool)): field
    //#input(void addCertField(Map, List, String, String, bool)): fields
    //#input(void addCertField(Map, List, String, String, bool)): group
    //#input(void addCertField(Map, List, String, String, bool)): invalid
    //#input(void addCertField(Map, List, String, String, bool)): title
    //#pre[2] (void addCertField(Map, List, String, String, bool)): fields != null
    //#pre[3] (void addCertField(Map, List, String, String, bool)): group != null
                fields.containsKey(field) ? fields.get(field) : NOTPRESENT, invalid,
                !fields.containsKey(field)));
    }
    //#SSLCertificateDialogModel.java:203: end of method: void com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel.addCertField(Map, List, String, String, bool)

    /**
     * Retrieves a list of summary elements to describe the overall status
     * of the certificate chain.
     *
     * @return A list of summary entries
     */
    public List<CertificateSummaryEntry> getSummary() {
        final List<CertificateSummaryEntry> res = new ArrayList<CertificateSummaryEntry>();
    //#SSLCertificateDialogModel.java:212: method: List com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel.getSummary()
    //#input(List getSummary()): this
    //#input(List getSummary()): this.problems
    //#output(List getSummary()): new ArrayList(getSummary#1) num objects
    //#output(List getSummary()): return_value
    //#new obj(List getSummary()): new ArrayList(getSummary#1)
    //#pre[2] (List getSummary()): this.problems != null
    //#post(List getSummary()): return_value == &new ArrayList(getSummary#1)
    //#post(List getSummary()): new ArrayList(getSummary#1) num objects == 1
    //#test_vector(List getSummary()): java.util.Iterator:hasNext(...)@216: {0}, {1}

        boolean outofdate = false, wronghost = false, nottrusted = false;

        for (CertificateException ex : problems) {
            if (ex instanceof CertificateExpiredException
                    || ex instanceof CertificateNotYetValidException) {
                outofdate = true;
            } else if (ex instanceof CertificateDoesntMatchHostException) {
                wronghost = true;
            } else if (ex instanceof CertificateNotTrustedException) {
                nottrusted = true;
            }
        }

        if (outofdate) {
            res.add(new CertificateSummaryEntry("One or more certificates are " +
                    "not within their validity period", false));
        } else {
            res.add(new CertificateSummaryEntry("All certificates are " +
                    "within their validity period", true));
        }

        if (nottrusted) {
            res.add(new CertificateSummaryEntry("The certificate is not issued "
                    + "by a trusted authority", false));
        } else {
            res.add(new CertificateSummaryEntry("The certificate chain is "
                    + "trusted", true));
        }

        if (wronghost) {
            res.add(new CertificateSummaryEntry("The certificate is not issued "
                    + "to the host you are connecting to", false));
        } else {
            res.add(new CertificateSummaryEntry("The certificate is issued "
                    + "to the host you are connecting to", true));
        }

        return res;
    //#SSLCertificateDialogModel.java:251: end of method: List com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel.getSummary()
    }
    
    /**
     * Determines whether or not a response is required from the user about
     * this certificate chain.
     *
     * @return True if a response is required, false otherwise
     */
    public boolean needsResponse() {
        return !problems.isEmpty();
    //#SSLCertificateDialogModel.java:261: method: bool com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel.needsResponse()
    //#input(bool needsResponse()): this
    //#input(bool needsResponse()): this.problems
    //#output(bool needsResponse()): return_value
    //#pre[2] (bool needsResponse()): this.problems != null
    //#post(bool needsResponse()): init'ed(return_value)
    //#SSLCertificateDialogModel.java:261: end of method: bool com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel.needsResponse()
    }

    /**
     * Retrieves the name of the server to which the user is trying to connect.
     *
     * @return The name of the server that the user is trying to connect to
     */
    public String getServerName() {
        return manager.getServerName();
    //#SSLCertificateDialogModel.java:270: method: String com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel.getServerName()
    //#SSLCertificateDialogModel.java:270: Warning: method not available - call not analyzed
    //#    call on String com.dmdirc.CertificateManager:getServerName()
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel
    //#    method: String getServerName()
    //#    unanalyzed callee: String com.dmdirc.CertificateManager:getServerName()
    //#input(String getServerName()): this
    //#input(String getServerName()): this.manager
    //#output(String getServerName()): return_value
    //#pre[2] (String getServerName()): this.manager != null
    //#post(String getServerName()): init'ed(return_value)
    //#SSLCertificateDialogModel.java:270: end of method: String com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel.getServerName()
    }

    /**
     * Performs the specified action on the certificate chain/connection.
     * Should only be called once per instance, and only if
     * {@link #needsResponse()} returns true.
     * 
     * @param action The action to be performed
     */
    public void performAction(final CertificateAction action) {
        if (!needsResponse()) {
    //#SSLCertificateDialogModel.java:281: method: void com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel.performAction(CertificateAction)
    //#input(void performAction(CertificateAction)): __Descendant_Table[com/dmdirc/ui/core/dialogs/sslcertificate/SSLCertificateDialogModel]
    //#input(void performAction(CertificateAction)): __Descendant_Table[others]
    //#input(void performAction(CertificateAction)): __Dispatch_Table.needsResponse()Z
    //#input(void performAction(CertificateAction)): action
    //#input(void performAction(CertificateAction)): this
    //#input(void performAction(CertificateAction)): this.__Tag
    //#input(void performAction(CertificateAction)): this.manager
    //#input(void performAction(CertificateAction)): this.problems
    //#pre[3] (void performAction(CertificateAction)): this.__Tag == com/dmdirc/ui/core/dialogs/sslcertificate/SSLCertificateDialogModel
    //#pre[4] (void performAction(CertificateAction)): this.manager != null
    //#pre[5] (void performAction(CertificateAction)): this.problems != null
    //#presumption(void performAction(CertificateAction)): java.util.List:isEmpty(...)@261 == 0
    //#unanalyzed(void performAction(CertificateAction)): Effects-of-calling:java.util.List:isEmpty
            throw new IllegalStateException("Can't perform action when "
                    + "no action is needed");
        }
        
        manager.setAction(action);
    //#SSLCertificateDialogModel.java:286: Warning: method not available - call not analyzed
    //#    call on void com.dmdirc.CertificateManager:setAction(CertificateAction)
    //#    severity: INFORMATIONAL
    //#    class: com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel
    //#    method: void performAction(CertificateAction)
    //#    unanalyzed callee: void com.dmdirc.CertificateManager:setAction(CertificateAction)
    }
    //#SSLCertificateDialogModel.java:287: end of method: void com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel.performAction(CertificateAction)

}
    //#output(com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel__static_init): __Descendant_Table[com/dmdirc/ui/core/dialogs/sslcertificate/SSLCertificateDialogModel]
    //#output(com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel__static_init): __Dispatch_Table.addCertField(Ljava/util/Map;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Z)V
    //#output(com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel__static_init): __Dispatch_Table.getAlternateNames(Ljava/security/cert/X509Certificate;)Ljava/lang/String;
    //#output(com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel__static_init): __Dispatch_Table.getCertificateChain()Ljava/util/List;
    //#output(com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel__static_init): __Dispatch_Table.getCertificateInfo(I)Ljava/util/List;
    //#output(com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel__static_init): __Dispatch_Table.getServerName()Ljava/lang/String;
    //#output(com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel__static_init): __Dispatch_Table.getSummary()Ljava/util/List;
    //#output(com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel__static_init): __Dispatch_Table.needsResponse()Z
    //#output(com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel__static_init): __Dispatch_Table.performAction(Lcom/dmdirc/ui/core/dialogs/sslcertificate/CertificateAction;)V
    //#post(com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel__static_init): __Descendant_Table[com/dmdirc/ui/core/dialogs/sslcertificate/SSLCertificateDialogModel] == &__Dispatch_Table
    //#post(com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel__static_init): __Dispatch_Table.addCertField(Ljava/util/Map;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Z)V == &addCertField
    //#post(com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel__static_init): __Dispatch_Table.getAlternateNames(Ljava/security/cert/X509Certificate;)Ljava/lang/String; == &getAlternateNames
    //#post(com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel__static_init): __Dispatch_Table.getCertificateChain()Ljava/util/List; == &getCertificateChain
    //#post(com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel__static_init): __Dispatch_Table.getCertificateInfo(I)Ljava/util/List; == &getCertificateInfo
    //#post(com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel__static_init): __Dispatch_Table.getServerName()Ljava/lang/String; == &getServerName
    //#post(com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel__static_init): __Dispatch_Table.getSummary()Ljava/util/List; == &getSummary
    //#post(com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel__static_init): __Dispatch_Table.needsResponse()Z == &needsResponse
    //#post(com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel__static_init): __Dispatch_Table.performAction(Lcom/dmdirc/ui/core/dialogs/sslcertificate/CertificateAction;)V == &performAction
    //#SSLCertificateDialogModel.java:: end of method: com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel.com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel__static_init
    //#SSLCertificateDialogModel.java:: end of class: com.dmdirc.ui.core.dialogs.sslcertificate.SSLCertificateDialogModel
