/*
 * The contents of this file are subject to the terms of the Common Development
 * and Distribution License (the License). You may not use this file except in
 * compliance with the License.
 *
 * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
 * or http://www.netbeans.org/cddl.txt.
 * 
 * When distributing Covered Code, include this CDDL Header Notice in each file
 * and include the License file at http://www.netbeans.org/cddl.txt.
 * If applicable, add the following below the CDDL Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * The Original Software is NetBeans. The Initial Developer of the Original
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.autoupdate;

import java.awt.KeyboardFocusManager;
import java.awt.Window;
import java.util.*;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.awt.Component;
import java.awt.Font;
import java.io.File;
import java.io.FileNotFoundException;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;

import org.openide.DialogDisplayer;
import org.openide.ErrorManager;
import org.openide.util.NbBundle;
import org.openide.NotifyDescriptor;
import org.openide.util.Utilities;
import org.openide.windows.WindowManager;

class ResultsPanel extends javax.swing.JPanel {

    private static final String SPACE = " "; //NOI18N

    private static final String BAD_DOWNLOAD = SPACE + getBundle("CTL_BAD_DOWNLOAD") + SPACE;
    private static final String CORRUPTED = SPACE + getBundle("CTL_CORRUPTED") + SPACE;
    private static final String NOT_SIGNED = SPACE + getBundle("CTL_NOT_SIGNED") + SPACE;
    private static final String SIGNED = SPACE + getBundle("CTL_SIGNED") + SPACE;
    private static final String TRUSTED = SPACE + getBundle("CTL_TRUSTED") + SPACE;

    private Wizard.Validator validator;

    private int modulesOK;

    private JTable table;
    private ResultsTableModel model;
    
    //private static String yesToAll = getBundle( "CTL_Yes_All" );
    private static JButton yesToAll;
    private boolean includeAll = false;
    private boolean globalAll = false;

    static final long serialVersionUID =-6053101371836354161L;
    
    /** Stores the last selected directory */
    private static File defaultDir = null;

    /** Creates new form ResultsPanel */
    public ResultsPanel( Wizard.Validator validator ) {
        putClientProperty("WizardPanel_contentSelectedIndex", new Integer(3));  // NOI18N
        setName(getBundle("LBL_View"));
        initComponents();
        
        this.validator = validator;
        
        model = new ResultsTableModel();
        //issue 33790, font size problems in Chinese locale - use a JTable that can
        //self-size
        table = new ServerPanel.AutoResizeTable(model, 2);
        table.getTableHeader().setReorderingAllowed( false );
        table.getColumnModel().getColumn(0).setCellRenderer( new BooleanRenderer() );
        table.getColumnModel().getColumn(1).setCellRenderer( new ResultsCellRenderer() );
        table.getColumnModel().getColumn(2).setCellRenderer( new BooleanRenderer() );
//        table.setRowHeight( 2 * table.getRowHeight() );
        table.setSelectionMode( javax.swing.ListSelectionModel.SINGLE_SELECTION );
        table.getColumnModel().getColumn(0).setPreferredWidth(48);
        table.getColumnModel().getColumn(1).setPreferredWidth(480);
        table.getColumnModel().getColumn(2).setPreferredWidth(48);
        table.setIntercellSpacing( new java.awt.Dimension( 0, 0 ) );
        
        jScrollPane1.setViewportView(table);

        table.getSelectionModel().addListSelectionListener(
            new javax.swing.event.ListSelectionListener() {
                public void valueChanged( javax.swing.event.ListSelectionEvent evt ) {
                    selectionChange();
                }
            }
        );
        
        selectionChange();

        getAccessibleContext().setAccessibleName(getBundle("LBL_View"));
        getAccessibleContext().setAccessibleDescription(getBundle("LBL_41"));
        certificateButton.getAccessibleContext().setAccessibleDescription(getBundle("ACS_View"));
        table.getAccessibleContext().setAccessibleDescription(getBundle("ACS_Module_List"));
        
        jLabel1.setLabelFor( table );
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        buttonGroup1 = new javax.swing.ButtonGroup();
        jTextArea1 = new javax.swing.JTextArea();
        jScrollPane1 = new javax.swing.JScrollPane();
        jLabel1 = new javax.swing.JLabel();
        jPanel1 = new javax.swing.JPanel();
        certificateButton = new javax.swing.JButton();
        saveButton = new javax.swing.JButton();

        setLayout(new java.awt.GridBagLayout());

        jTextArea1.setBackground(getBackground());
        jTextArea1.setFont(new Font("Dialog", Font.PLAIN, jTextArea1.getFont().getSize()));
        jTextArea1.setLineWrap(true);
        jTextArea1.setText(getBundle("LBL_41"));
        jTextArea1.setWrapStyleWord(true);
        jTextArea1.setDisabledTextColor(java.awt.Color.black);
        jTextArea1.setEnabled(false);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 12, 0);
        add(jTextArea1, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        add(jScrollPane1, gridBagConstraints);

        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, getBundle("LAB_ModulesList"));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        add(jLabel1, gridBagConstraints);

        jPanel1.setLayout(new java.awt.GridBagLayout());

        org.openide.awt.Mnemonics.setLocalizedText(certificateButton, getBundle("BTN_View"));
        buttonGroup1.add(certificateButton);
        certificateButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                certificateButtonActionPerformed(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(12, 0, 0, 0);
        jPanel1.add(certificateButton, gridBagConstraints);

        org.openide.awt.Mnemonics.setLocalizedText(saveButton, getBundle("BTN_SaveCopy"));
        buttonGroup1.add(saveButton);
        saveButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveButtonActionPerformed(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(12, 11, 0, 0);
        jPanel1.add(saveButton, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
        gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        add(jPanel1, gridBagConstraints);

    }
    // </editor-fold>//GEN-END:initComponents

    private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveButtonActionPerformed
        try {
            File saveDir = getSaveCopyDir();
            if (saveDir == null) return ;
            ModuleUpdate mu = getListSelection();
            File target = new File ( saveDir, mu.getDistributionFilename());
            if ( target.exists() ) {
                NotifyDescriptor.Confirmation nd =
                        new NotifyDescriptor.Confirmation(
                            getBundle( "MSG_OverwriteConfirmation" ),
                            NotifyDescriptor.YES_NO_OPTION
                        );
                if ( ! DialogDisplayer.getDefault().notify( nd ).equals( NotifyDescriptor.YES_OPTION ) )
                    return;
            }
            Downloader.saveCopy( getListSelection(), target );
        } catch (FileNotFoundException fnfe) {
            ErrorManager.getDefault ().notify (ErrorManager.USER,
                ErrorManager.getDefault ().annotate (fnfe,
                    NbBundle.getMessage (ResultsPanel.class, "CTL_Directory_not_exits", fnfe.getMessage ())));
        }
    }//GEN-LAST:event_saveButtonActionPerformed

    private void certificateButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_certificateButtonActionPerformed
        int accValue = CertificateDialog.showDialog( getListSelection().getCerts(), 
                                      getListSelection().getSecurity() );        
        doCertAction(accValue, getListSelection());        
        table.invalidate();
        table.repaint();
        selectionChange();
    }//GEN-LAST:event_certificateButtonActionPerformed

    private void doInclude(ModuleUpdate mu) {
        if ( mu.isForcedGlobal () && Downloader.bannedWriteToInstall (mu)) {
            NotifyDescriptor.Message nd = 
                new NotifyDescriptor.Message( 
                    NbBundle.getMessage( ResultsPanel.class, "MSG_CannotInstall_2", mu.getName())
                );
            DialogDisplayer.getDefault().notify( nd );
            return;
        }
        if ( mu.getSecurity() == SignVerifier.NOT_SIGNED ) {
            if ( mu.isInstallApproved() ) {
                mu.setInstallApproved( false );
                checkValidity();
            } 
            else {
                Object ret = null;
                if ( !includeAll ) {
                    NotifyDescriptor.Confirmation nd =
                        new NotifyDescriptor.Confirmation( 
                            getBundle( "MSG_NotSignedConfirmation" ),
                            getBundle( "CTL_NotSignedConfirmation" ),
                            NotifyDescriptor.YES_NO_OPTION 
                        );
                    nd.setOptions( new Object[] {
                            NotifyDescriptor.YES_OPTION,
                            NotifyDescriptor.NO_OPTION,
                            getYesToAll () } );
                    ret = DialogDisplayer.getDefault().notify( nd );
                    if (ret.equals (getYesToAll ())) {
                        includeAll = true;
                    }
                }
                if ( includeAll || ret.equals( NotifyDescriptor.YES_OPTION ) ) {
                    mu.setInstallApproved( true );
                    checkValidity();
                }
            }
        }
        else if ( mu.getSecurity() == SignVerifier.SIGNED ||
                  mu.getSecurity() == SignVerifier.TRUSTED ) {
            doCertAction(CertificateDialog.showDialog( 
                                  mu.getCerts(), 
                                  mu.getSecurity()
                            ), 
                         mu
            );
        }
        else if ( mu.getSecurity() == SignVerifier.CORRUPTED ) {
            NotifyDescriptor.Message nd = 
                  new NotifyDescriptor.Message(getBundle( "MSG_CorruptedJAR" ) );
            DialogDisplayer.getDefault().notify( nd );
        }
        else {
            NotifyDescriptor.Message nd = 
                  new NotifyDescriptor.Message(getBundle( "MSG_BadDownload" ) );
            DialogDisplayer.getDefault().notify( nd );
        }
        table.invalidate();
        table.repaint();
        selectionChange();
    }
    
    private void doGlobal(ModuleUpdate mu) throws IllegalArgumentException {
        if ( mu.isForcedGlobal () ) {
            NotifyDescriptor.Message nd = 
                new NotifyDescriptor.Message( 
                    NbBundle.getMessage( ResultsPanel.class, "MSG_InstallDepending",
                        mu.getName()
                    )
                );
            DialogDisplayer.getDefault().notify( nd );
            return;
        }
        
        if (Downloader.bannedWriteToInstall (mu)) {
            NotifyDescriptor.Message nd = 
                    new NotifyDescriptor.Message( getBundle( "MSG_InstallNoWrite" ) );
            DialogDisplayer.getDefault().notify( nd );
            return;
        }
        
        if (mu.isGlobal () != null) {
            if (mu.isGlobal ().booleanValue ()) {
                NotifyDescriptor.Message nd =
                        new NotifyDescriptor.Message ( 
                            NbBundle.getMessage( ResultsPanel.class, "MSG_InstallGloballyForced",
                                mu.getName()
                            ),
                            NotifyDescriptor.INFORMATION_MESSAGE
                        );
                DialogDisplayer.getDefault ().notify (nd);
                return ;
            } else {
                NotifyDescriptor.Message nd =
                        new NotifyDescriptor.Message ( 
                            NbBundle.getMessage( ResultsPanel.class, "MSG_InstallLocallyForced",
                                mu.getName() 
                            ),
                            NotifyDescriptor.INFORMATION_MESSAGE
                        );
                DialogDisplayer.getDefault ().notify (nd);
                return ;
            }
        }

        if ( mu.isToInstallDir() ) {
            Object ret = null;
            if ("".equals (getBundle ("MSG_InstallLocallyConfirmation"))) {
                mu.setToInstallDir (false);
            } else {
                NotifyDescriptor.Confirmation nd =
                        new NotifyDescriptor.Confirmation( 
                            NbBundle.getMessage( ResultsPanel.class, "MSG_InstallLocallyConfirmation",
                                mu.getName()
                            ),
                            NotifyDescriptor.YES_NO_OPTION 
                        );
                nd.setOptions( new Object[] {
                            NotifyDescriptor.YES_OPTION,
                            NotifyDescriptor.NO_OPTION } );
                ret = DialogDisplayer.getDefault().notify( nd );
                if ( ret.equals( NotifyDescriptor.YES_OPTION ) ) {
                    mu.setToInstallDir( false );
                }
            }
        } else {
            Object ret = null;
            if ( !globalAll ) {
                if ("".equals (getBundle( "MSG_InstallGloballyConfirmation" ))) {
                    mu.setToInstallDir (false);
                } else {
                    NotifyDescriptor.Confirmation nd =
                            new NotifyDescriptor.Confirmation( 
                                NbBundle.getMessage( ResultsPanel.class, "MSG_InstallGloballyConfirmation",
                                    mu.getName() 
                                ),
                                NotifyDescriptor.YES_NO_OPTION 
                            );
                    nd.setOptions( new Object[] {
                                NotifyDescriptor.YES_OPTION,
                                NotifyDescriptor.NO_OPTION,
                                getYesToAll () } );
                    ret = DialogDisplayer.getDefault().notify( nd );
                    if (ret.equals ( getYesToAll ())) {
                        globalAll = true;
                    }
                }
            }
            if ( globalAll || ret.equals( NotifyDescriptor.YES_OPTION ) ) {
                mu.setToInstallDir( true );
            }
        }
        table.invalidate();
        table.repaint();
        selectionChange();
    }
    
    void doCertAction(int accValue, ModuleUpdate mu) {
        switch ( accValue ) {
            /*
        case CertificateDialog.FOR_MODULE:
            getListSelection().setInstallApproved( true );
            checkValidity();
            break;
             */
        case CertificateDialog.ACCEPT:
            setApproved4All( mu.getCerts(), true, -1 );
            checkValidity();
            break;
        case CertificateDialog.REJECT:
            setApproved4All( mu.getCerts(), false, -1 );
            checkValidity();
            break;
        case CertificateDialog.NOT_ALWAYS_ACCEPT:
            setApproved4All( mu.getCerts(), false, SignVerifier.SIGNED );
            checkValidity();
            try {
                SignVerifier.removeCertificates( mu.getCerts() );
            }
            catch ( java.security.cert.CertificateException e ) {
                ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
            }
            catch ( java.security.KeyStoreException e ) {
                ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
            }
            catch ( java.io.IOException e ) {
                ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
            }
            catch ( java.security.NoSuchAlgorithmException e ) {
                ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
            }
            break;
        case CertificateDialog.ALWAYS_ACCEPT:
            setApproved4All( mu.getCerts(), true, SignVerifier.TRUSTED );
            checkValidity();
            try {
                SignVerifier.addCertificates( mu.getCerts() );
            }
            catch ( java.security.cert.CertificateException e ) {
                ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
            }
            catch ( java.security.KeyStoreException e ) {
                ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
            }
            catch ( java.io.IOException e ) {
                ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
            }
            catch ( java.security.NoSuchAlgorithmException e ) {
                ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
            }
            break;
        default:
            return;
        }        
    }
    
    /** Utility function approves installing of all modules signed
    * by given Collection of certs 
    */
    private void setApproved4All( Collection certs, boolean approved, int security ) {

        if ( certs == null ) {
            return;
        }
        
        for ( int i=0; i < model.getRowCount(); i++ ) {
            ModuleUpdate mu = (ModuleUpdate)model.getValueAt(i, 1);

            boolean bannedWriteToInstall = Downloader.bannedWriteToInstall(mu);
            if ( approved && mu.isForcedGlobal () && bannedWriteToInstall ) {
                continue;
            }
            
            if ( mu.getCerts() != null && certs.containsAll( mu.getCerts() ) ) {
                mu.setInstallApproved( approved );

                if ( security == SignVerifier.TRUSTED || security == SignVerifier.SIGNED ) {
                    mu.setSecurity( security );
                }
            }

        }
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.JButton certificateButton;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextArea jTextArea1;
    private javax.swing.JButton saveButton;
    // End of variables declaration//GEN-END:variables

    int generateResults() {

        modulesOK = 0;

        List modulelist = new ArrayList();

        Collection modules = Wizard.getAllModules();
        Iterator it = modules.iterator();
        boolean writeConflict = false;
        int selectRow = -1;
        while( it.hasNext() ) {
            ModuleUpdate mu = (ModuleUpdate)it.next();

            if ( mu.isSelected() ) {
                modulelist.add( mu );
                if ( mu.isDownloadOK() ) {
                    modulesOK ++;
                    if ( selectRow == -1 )
                        if (!mu.isInstallApproved())
                            selectRow = modulelist.size()-1;
                }
                if ( mu.isForcedGlobal () ) {
                    boolean bannedWriteToInstall = Downloader.bannedWriteToInstall (mu);
                    if ( bannedWriteToInstall ) {
                        mu.setInstallApproved( false );
                        writeConflict = true;
                    }
                    mu.setToInstallDir( true );
                }
            }
        }
        if ( writeConflict ) {
            NotifyDescriptor.Message nd = 
                    new NotifyDescriptor.Message( getBundle( "MSG_CannotInstall_1" ) );
            DialogDisplayer.getDefault().notify( nd );
        }
        
        model.refreshContent( modulelist );
        
        if ( selectRow == -1 )
            selectRow = 0;
        if ( table.getRowCount() > 0 )
            table.getSelectionModel().setSelectionInterval( selectRow, selectRow );

        checkValidity();
        selectionChange();
        includeAll = false;
        globalAll = false;
        return modulesOK;
    }

    /** Called when the selection in selectedList or explorerView changes */
    private void selectionChange() {
        ModuleUpdate mu = getListSelection();
        
        // Enable/Disable view button
        if ( mu != null &&
                ( mu.getSecurity() == SignVerifier.SIGNED ||
                  mu.getSecurity() == SignVerifier.TRUSTED ) ) {
            certificateButton.setEnabled( true );
        }
        else {
            certificateButton.setEnabled( false );
        }
        
        // Enable/Disable save button
        if ( mu != null &&
                mu.getSecurity() != SignVerifier.BAD_DOWNLOAD ) {
            saveButton.setEnabled( true );
        }
        else {
            saveButton.setEnabled( false );
        }
    }

    /** Gets the ModuleUpdate selected in the list */
    private ModuleUpdate getListSelection() {

        int index = table.getSelectionModel().getMinSelectionIndex();

        if ( index < 0 )
            return null;

        return (ModuleUpdate) model.getValueAt( index, 1 );
    }
    
    /** Checks wther there exists at least one update with approved install
    * if so enables finish button
    */
    private void checkValidity() {

        boolean valid = false;

        Collection modules = Wizard.getAllModules();
        Iterator it = modules.iterator();
        while( it.hasNext() ) {
            ModuleUpdate mu = (ModuleUpdate)it.next();

            if ( mu.isSelected() && mu.isInstallApproved() ) {
                valid = true;
            }

        }

        validator.setValid( valid );

    }
    
    class ResultsTableModel extends AbstractTableModel {
        final String[] columnNames = {getBundle("LBL_42"),
                                      getBundle("LBL_43"),
                                      getBundle("LBL_Global")};
        private List modulelist = new ArrayList();

        public int getColumnCount() {
            return columnNames.length;
        }
        
        public int getRowCount() {
            return modulelist.size();
        }

        public String getColumnName(int col) {
            return columnNames[col];
        }

        public Object getValueAt(int row, int col) {
            if (col == 0)
                return ((ModuleUpdate)modulelist.get(row)).isInstallApproved() ? Boolean.TRUE : Boolean.FALSE;
            else if (col == 1)
                return modulelist.get(row);
            else {
                ModuleUpdate mu = (ModuleUpdate)modulelist.get (row);
                return Boolean.valueOf (mu.isToInstallDir());
            }
        }

        public Class getColumnClass(int c) {
            return getValueAt(0, c).getClass();
        }

        public boolean isCellEditable(int row, int col) {
            if (col == 1) { 
                return false;
            } else {
                return true;
            }
        }

        public void setValueAt(Object value, int row, int col) {
            if (value instanceof Boolean) {
                if ( col == 0 )
                    doInclude( (ModuleUpdate)modulelist.get(row) );
                else {
                    try {
                        doGlobal( (ModuleUpdate)modulelist.get(row) );
                    } catch (IllegalArgumentException iae) {
                        ErrorManager.getDefault ().notify (ErrorManager.INFORMATIONAL, iae);
                    }
                }
            }
        }
        
        void refreshContent( List modulelist ) {
            this.modulelist = modulelist;
        }        
    }
    
    private class ResultsCellRenderer extends JPanel implements TableCellRenderer {

        private JLabel nameLabel;
        private JLabel securityLabel;
        
        public ResultsCellRenderer() {
	    super();
            initComponents();
	}
        
        /** Overrides superclass method. */
        public Component getTableCellRendererComponent(JTable table, Object value,
                boolean isSelected, boolean hasFocus, int row, int column) {

            String sec = ""; // NOI18N
            if ( value == null )
                value = model.getValueAt( row, column );
            switch ( ((ModuleUpdate)value).getSecurity() ) {
            case SignVerifier.BAD_DOWNLOAD:
                sec = BAD_DOWNLOAD;
                break;
            case SignVerifier.CORRUPTED:
                sec = CORRUPTED;
                break;
            case SignVerifier.NOT_SIGNED:
                sec = NOT_SIGNED;
                break;
            case SignVerifier.SIGNED:
                StringBuffer sb = new StringBuffer( SIGNED );
                sb.append( SPACE + getBundle("CTL_By"));
                Collection certs = ((ModuleUpdate)value).getCerts();
                Iterator it = certs.iterator();
                while ( it.hasNext() ) {
                    Certificate cert = (Certificate)it.next();
                    if ( cert instanceof X509Certificate ) {
                        sb.append( " " ).append( ((X509Certificate)cert).getSubjectDN().getName() ); //NOI18N
                    }
                }

                sec = sb.toString();
                break;
            case SignVerifier.TRUSTED:
                sec = TRUSTED;
                break;
            }

            if ( isSelected ) {
                setBackground ((java.awt.Color) javax.swing.UIManager.getDefaults ().get ("Table.selectionBackground")); // NOI18N
                nameLabel.setForeground((java.awt.Color) javax.swing.UIManager.getDefaults ().get ("Table.selectionForeground")); // NOI18N
                securityLabel.setForeground((java.awt.Color) javax.swing.UIManager.getDefaults ().get ("Table.selectionForeground")); // NOI18N
            }
            else {
                setBackground ((java.awt.Color) javax.swing.UIManager.getDefaults ().get ("Table.background")); // NOI18N
                nameLabel.setForeground((java.awt.Color) javax.swing.UIManager.getDefaults ().get ("Table.Foreground")); // NOI18N
                securityLabel.setForeground((java.awt.Color) javax.swing.UIManager.getDefaults ().get ("Table.Foreground")); // NOI18N
            }
            nameLabel.setText( ((ModuleUpdate)value).getName() +
                                        "  " + getBundle( "CTL_Version" ) +
                                        ((ModuleUpdate)value).getRemoteModule().getSpecificationVersion());
            securityLabel.setText( sec );
            
            return this;
        }
        
        private void initComponents() {
            java.awt.GridBagConstraints gridBagConstraints;

            nameLabel = new JLabel();
            securityLabel = new JLabel();
            
            setLayout(new java.awt.GridBagLayout());
            nameLabel.setFont(doDeriveFont(nameLabel.getFont(), Font.BOLD));
            
            gridBagConstraints = new java.awt.GridBagConstraints();
            gridBagConstraints.gridwidth = java.awt.GridBagConstraints.RELATIVE;
            gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
            gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
            gridBagConstraints.weightx = 1.0;
            gridBagConstraints.weighty = 1.0;
            gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 0);
            add(nameLabel, gridBagConstraints);

            gridBagConstraints = new java.awt.GridBagConstraints();
            gridBagConstraints.gridx = 0;
            gridBagConstraints.gridy = 1;
            gridBagConstraints.gridwidth = java.awt.GridBagConstraints.RELATIVE;
            gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
            gridBagConstraints.insets = new java.awt.Insets(0, 6, 0, 0);
            gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
            gridBagConstraints.weightx = 1.0;
            gridBagConstraints.weighty = 1.0;
            add(securityLabel, gridBagConstraints);

        }
    }
    
    static class BooleanRenderer extends JCheckBox implements TableCellRenderer {
	public BooleanRenderer() {
	    super();
	    setHorizontalAlignment(JLabel.CENTER);            
            setBorder(new javax.swing.border.LineBorder((java.awt.Color) javax.swing.UIManager.getDefaults().get("Button.focus")));
	}

        public Component getTableCellRendererComponent(JTable table, Object value,
						       boolean isSelected, boolean hasFocus, int row, int column) {
	    if (isSelected) {
	        setForeground(table.getSelectionForeground());
	        super.setBackground(table.getSelectionBackground());
	    }
	    else {
	        setForeground(table.getForeground());
	        setBackground(table.getBackground());
	    }
            
            setBorderPainted( isSelected && table.getSelectedColumn() == column );
            
            setSelected((value != null && ((Boolean)value).booleanValue()));
            return this;
        }
    }
    
    private File getSaveCopyDir() throws FileNotFoundException {
        JFileChooser chooser = new JFileChooser();
        chooser.setFileSelectionMode( JFileChooser.DIRECTORIES_ONLY );
        chooser.setDialogTitle(
            NbBundle.getMessage( ResultsPanel.class, "CTL_FileChooserSC_Title",
                        getListSelection().getDistributionFilename()
            )
        );
        chooser.setFileFilter( new javax.swing.filechooser.FileFilter() {
            public boolean accept( File f ) {
                return f.canWrite();
            }

            public String getDescription() {
                return getBundle( "CTL_FileFilterSCDescription" );
            }
        });

        if (defaultDir == null)
            defaultDir = SelectModulesPanel.getDefaultDir();

        if ( defaultDir != null) {
            File parent = defaultDir.getParentFile();
            if ( parent != null ) {
                chooser.setCurrentDirectory( parent );
                chooser.setSelectedFile( defaultDir );
            }
            else
                chooser.setCurrentDirectory( defaultDir );
        }
        
        Window focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager ().getActiveWindow ();
        
        File res = null;

        if (chooser.showDialog( WindowManager.getDefault().getMainWindow (),
                               getBundle("CTL_Save"))
                == JFileChooser.APPROVE_OPTION) {

            defaultDir = chooser.getSelectedFile();
            if (defaultDir.exists ()) {
                res = defaultDir;
            } else {
                // bugfix #39006, check if the chosen directory exists otherwise throw a exception
                // notify user the selected directory doesn't exists
                throw new FileNotFoundException (defaultDir.getAbsolutePath ()); // NOI18N
            }
        } else {
            res = null;
        }
        
        // #46353, recover focus after close the JFileChooser
        if (focusOwner != null) {
            focusOwner.toFront ();
        }
        
        return res;
    }
    
    private JButton getYesToAll () {
        if (yesToAll == null) {
            yesToAll = new JButton (getBundle("CTL_Yes_All"));
            yesToAll.getAccessibleContext ().setAccessibleName (getBundle("ACSN_Yes_All"));
            yesToAll.getAccessibleContext ().setAccessibleDescription (getBundle("ACSD_Yes_All"));
            yesToAll.setMnemonic (getBundle("ACS_Yes_All_mnc").charAt (0));
        }
        return yesToAll;
    }
    
    private static String getBundle( String key ) {
        return NbBundle.getMessage( ResultsPanel.class, key );
    }
    
    static Font doDeriveFont(Font original, int style) {
                // don't use deriveFont() - see #49973 for details
       if (Utilities.getOperatingSystem() == Utilities.OS_MAC) {
           return new Font(original.getName(), style, original.getSize());
       }
       return original.deriveFont(style);
    }
}
