alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

HSQLDB example source code file (DatabaseManagerSwing.java)

This example HSQLDB source code file (DatabaseManagerSwing.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - HSQLDB tags/keywords

actionlistener, awt, defaultmutabletreenode, defaultmutabletreenode, failed, file, gui, jcheckboxmenuitem, jdbc, jmenuitem, jmenuitem, object, script, sql, sqlexception, sqlexception, string, string, swing, util

The HSQLDB DatabaseManagerSwing.java source code

/*
 * For work developed by the HSQL Development Group:
 *
 * Copyright (c) 2001-2010, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 *
 * For work originally developed by the Hypersonic SQL Group:
 *
 * Copyright (c) 1995-2000, The Hypersonic SQL Group.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the Hypersonic SQL Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE HYPERSONIC SQL GROUP,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * on behalf of the Hypersonic SQL Group.
 */


package org.hsqldb.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessControlException;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Locale;
import java.util.Properties;
import java.util.Vector;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Font;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.RootPaneContainer;
import javax.swing.SwingUtilities;
import javax.swing.table.TableModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

import org.hsqldb.lib.RCData;
import org.hsqldb.lib.java.JavaSystem;

//dmarshall@users - 20020101 - original swing port of DatabaseManager
//sqlbob@users 20020401 - patch 537501 by ulrivo - commandline arguments
//sqlbob@users 20020407 - patch 1.7.0 - reengineering and enhancements
//nickferguson@users 20021005 - patch 1.7.1 - enhancements
//deccles@users 2004 - 2008 - bug fixes and enhancements
//weconsultants@users 20041109 - version 1.8.0 - reengineering and enhancements:
//              Added: Goodies 'Look and Feel'.
//              Added: a Font Changer(Font Type\Style).
//              Added: a Color Changer (foreground\bckground).
//              Added: RowCounts for each JTree table nodes.
//              Added: OneTouchExpandable attribute to JSplitPanes.
//              Moved: setFramePositon code to a CommonSwing.setFramePositon() Method.
//              Added: call to new method to handle exception processing (CommonSwing.errorMessage());
//              Added: Added a new pane added at the bottom of the Frame. (Status Icon and StatusLine).
//              Added: 2 Methods (setStatusMessage()), one overrides the other. One to change the ruung status
//                              another to allow a message to be posted without changing the Status Icon if needed.
//              Added: Added a customCursor for the current wait cursor
//      Added: Ability to switch the current LAF while runing (Native,Java or Motif)
//unsaved@users 2005xxxx - improvements and bug fixes

/**
 * Swing Tool for managing a JDBC database.<p>
 * <pre>
 *             Usage: java DatabaseManagerSwing [--options]
 *             where options include:
 *              --driver <classname>  jdbc driver class
 *              --url <name>          jdbc url
 *              --user <name>         username used for connection
 *              --password <password> password for this user
 *              --dir <path>          default directory
 *              --script <file>       reads from script file
 *              --urlid <urlid>       get connection info from RC file
 *              --rcfile <file>       use instead of default (with urlid)
 *              --noexit              Don't exit JVM
 * </pre>
 *
 * Note that the sys-table switch will not work for Oracle, because Oracle
 * does not categorize their system tables correctly in the JDBC Metadata.
 *
 * New class based on Hypersonic SQL original
 *
 * @author dmarshall@users
 * @author Bob Preston (sqlbob@users dot sourceforge.net)
 * @version 1.8.0
 * @since 1.7.0
 */
public class DatabaseManagerSwing extends JApplet
implements ActionListener, WindowListener, KeyListener, MouseListener {

    /*
     * This is down here because it is an  implementation note, not a
     * Javadoc comment!
     * Tue Apr 26 16:38:54 EDT 2005
     * Switched default switch method from "-switch" to "--switch" because
     * "-switch" usage is ambiguous as used here.  Single switches should
     * be reserved for single-letter switches which can be mixed like
     * "-u -r -l" = "-url".  -blaine
     */
    private static String homedir  = null;
    private boolean       isOracle = false;    // Need some workarounds for Oracle

    static {
        try {
            Class c = Class.forName("sun.security.action.GetPropertyAction");
            Constructor constructor = c.getConstructor(new Class[]{
                String.class });
            java.security.PrivilegedAction a =
                (java.security.PrivilegedAction) constructor.newInstance(
                    new Object[]{ "user.home" });

            homedir = (String) java.security.AccessController.doPrivileged(a);
        } catch (IllegalAccessException e) {
            System.err.println(
                "Failed to get home directory.\n"
                + "Therefore not retrieving/storing user preferences.\n("
                + e.getMessage() + ')');
        } catch (NoSuchMethodException e) {
            System.err.println(
                "Failed to get home directory.\n"
                + "Therefore not retrieving/storing user preferences.\n("
                + e.getMessage() + ')');
        } catch (ClassNotFoundException e) {
            System.err.println(
                "Failed to get home directory.\n"
                + "Therefore not retrieving/storing user preferences.\n("
                + e.getMessage() + ')');
        } catch (InstantiationException e) {
            System.err.println(
                "Failed to get home directory.\n"
                + "Therefore not retrieving/storing user preferences.\n("
                + e.getMessage() + ')');
        } catch (InvocationTargetException e) {
            System.err.println(
                "Failed to get home directory.\n"
                + "Therefore not retrieving/storing user preferences.\n("
                + e.getMessage() + ')');
        } catch (AccessControlException e) {
            System.err.println(
                "Failed to get home directory.\n"
                + "Therefore not retrieving/storing user preferences.\n("
                + e.getMessage() + ')');
        }
    }

    ArrayList                   localActionList = new ArrayList();
    private JFrame              jframe          = null;
    private static final String DEFAULT_RCFILE  = homedir + "/dbmanager.rc";
    private static boolean      TT_AVAILABLE    = false;

    static {
        try {
            Class.forName(DatabaseManagerSwing.class.getPackage().getName()
                          + ".Transfer");

            TT_AVAILABLE = true;
        } catch (Throwable t) {

            //System.err.println("Failed to get "
            //+ DatabaseManagerSwing.class.getPackage().getName()
            //+ ".Transfer: " + t);
            // Enable this print statement for debugging class access problems.
        }
    }

    private static final String HELP_TEXT =
        "See the HSQLDB Utilities Guide, forums and mailing lists \n"
        + "at http://hsqldb.org.\n\n"
        + "Please paste the following version identifier with any\n"
        + "problem reports or help requests:  $Revision: 3496 $"
        + (TT_AVAILABLE ? ""
                        : ("\n\nTransferTool classes are not in CLASSPATH.\n"
                           + "To enable the Tools menu, add 'transfer.jar' "
                           + "to your class path."));
    ;
    private static final String ABOUT_TEXT =
        "$Revision: 3496 $ of DatabaseManagerSwing\n\n"
        + "Copyright (c) 1995-2000, The Hypersonic SQL Group.\n"
        + "Copyright (c) 2001-2010, The HSQL Development Group.\n"
        + "http://hsqldb.org  (Utilities Guide available at this site).\n\n\n"
        + "You may use and redistribute according to the HSQLDB\n"
        + "license documented in the source code and at the web\n"
        + "site above."
        + (TT_AVAILABLE ? "\n\nTransferTool options are available."
                        : "");
    static final String    NL         = System.getProperty("line.separator");
    static final String    NULL_STR   = "[null]";
    static int             iMaxRecent = 24;
    Connection             cConn;
    Connection             rowConn;    // holds the connetion for getting table row counts
    DatabaseMetaData       dMeta;
    Statement              sStatement;
    JMenu                  mRecent;
    String[]               sRecent;
    int                    iRecent;
    JTextArea              txtCommand;
    JScrollPane            txtCommandScroll;
    JButton                butExecute;
    JTree                  tTree;
    JScrollPane            tScrollPane;
    DefaultTreeModel       treeModel;
    TableModel             tableModel;
    DefaultMutableTreeNode rootNode;
    JPanel                 pResult;
    long                   lTime;
    GridSwing              gResult;

    /**
     * I think this is used to store model info whether we're using Grid
     *  output or not (this object is queried for data to display for
     *  text output mode).
     *  If so, the presentation-independent model part should be moved
     *  to an appropriately-named class instead of storing pure data in
     *  a Swing-specific class.
     */
    JTable            gResultTable;
    JScrollPane       gScrollPane;
    JTextArea         txtResult;
    JScrollPane       txtResultScroll;
    JSplitPane        nsSplitPane;     // Contains query over results
    JSplitPane        ewSplitPane;     // Contains tree beside nsSplitPane
    boolean           bHelp;
    RootPaneContainer fMain;
    static boolean    bMustExit;

    /** Value of this variable only retained if huge input script read in. */
    String          sqlScriptBuffer = null;
    JToolBar        jtoolbar;
    private boolean showSchemas  = true;
    private boolean showTooltips = true;
    private boolean autoRefresh  = true;
    private boolean gridFormat   = true;

    // Added: (weconsultants@users)
    static DatabaseManagerSwing refForFontDialogSwing;
    boolean                     displayRowCounts = false;
    boolean                     showSys          = false;
    boolean                     showIndexDetails = true;
    String                      currentLAF       = null;
    JPanel                      pStatus;
    static JButton              iReadyStatus;
    JRadioButtonMenuItem        rbAllSchemas = new JRadioButtonMenuItem("*");
    JMenuItem                   mitemAbout   = new JMenuItem("About", 'A');
    JMenuItem                   mitemHelp    = new JMenuItem("Help", 'H');
    JMenuItem mitemUpdateSchemas             = new JMenuItem("Update Schemas");
    JCheckBoxMenuItem boxAutoCommit =
        new JCheckBoxMenuItem(AUTOCOMMIT_BOX_TEXT);
    JCheckBoxMenuItem boxLogging = new JCheckBoxMenuItem(LOGGING_BOX_TEXT);
    JCheckBoxMenuItem boxShowSchemas =
        new JCheckBoxMenuItem(SHOWSCHEMAS_BOX_TEXT);
    JCheckBoxMenuItem boxAutoRefresh =
        new JCheckBoxMenuItem(AUTOREFRESH_BOX_TEXT);
    JCheckBoxMenuItem boxTooltips  = new JCheckBoxMenuItem(SHOWTIPS_BOX_TEXT);
    JCheckBoxMenuItem boxRowCounts = new JCheckBoxMenuItem(ROWCOUNTS_BOX_TEXT);
    JCheckBoxMenuItem boxShowGrid  = new JCheckBoxMenuItem(GRID_BOX_TEXT);
    JCheckBoxMenuItem boxShowSys   = new JCheckBoxMenuItem(SHOWSYS_BOX_TEXT);

    // Consider adding GTK and Plaf L&Fs.
    JRadioButtonMenuItem rbNativeLF =
        new JRadioButtonMenuItem("Native Look & Feel");
    JRadioButtonMenuItem rbJavaLF =
        new JRadioButtonMenuItem("Java Look & Feel");
    JRadioButtonMenuItem rbMotifLF =
        new JRadioButtonMenuItem("Motif Look & Feel");
    JLabel                      jStatusLine;
    static String               READY_STATUS         = "Ready";
    private static final String AUTOCOMMIT_BOX_TEXT  = "Autocommit mode";
    private static final String LOGGING_BOX_TEXT     = "Logging mode";
    private static final String SHOWSCHEMAS_BOX_TEXT = "Show schemas";
    private static final String AUTOREFRESH_BOX_TEXT = "Auto-refresh tree";
    private static final String SHOWTIPS_BOX_TEXT    = "Show Tooltips";
    private static final String ROWCOUNTS_BOX_TEXT   = "Show row counts";
    private static final String SHOWSYS_BOX_TEXT     = "Show system tables";
    private static final String GRID_BOX_TEXT =
        "Show results in Grid (a.o.t. Text)";

    // variables to hold the default cursors for these top level swing objects
    // so we can restore them when we exit our thread
    Cursor        fMainCursor;
    Cursor        txtCommandCursor;
    Cursor        txtResultCursor;
    HashMap       tipMap     = new HashMap();
    private JMenu mnuSchemas = new JMenu("Schemas");

    /**
     * Wait Cursor
     */

    // Changed: (weconsultants@users): commonted out the, out of the box, cursor to use a custom cursor
    private final Cursor waitCursor = new Cursor(Cursor.WAIT_CURSOR);

    //getToolkit().createCustomCursor(CommonSwing.getIcon("SystemCursor"),
    //                                new Point(4, 4), "HourGlass cursor");
    // (ulrivo): variables set by arguments from the commandline
    static String  defDriver   = "org.hsqldb.jdbcDriver";
    static String  defURL      = "jdbc:hsqldb:mem:.";
    static String  defUser     = "SA";
    static String  defPassword = "";
    static String  defScript;
    static String  defDirectory;
    private String schemaFilter = null;

    public DatabaseManagerSwing() {
        jframe = new JFrame("HSQLDB DatabaseManager");
        fMain  = jframe;
    }
    ;

    public DatabaseManagerSwing(JFrame frameIn) {
        jframe = frameIn;
        fMain  = jframe;
    }
    ;

    public void init() {

        javax.swing.AbstractButton btn;

        fMain = this;

        main();

        for (int i = 0; i < localActionList.size(); i++) {
            btn = (javax.swing.AbstractButton) localActionList.get(i);

            btn.setEnabled(false);
        }

        Connection c    = null;
        boolean    auto = false;

        if (getParameter("jdbcDriver") != null) {
            auto      = true;
            defDriver = getParameter("jdbcDriver");
        }

        if (getParameter("jdbcUrl") != null) {
            auto   = true;
            defURL = getParameter("jdbcUrl");
        }

        if (getParameter("jdbcUser") != null) {
            auto    = true;
            defUser = getParameter("jdbcUser");
        }

        if (getParameter("jdbcPassword") != null) {
            auto        = true;
            defPassword = getParameter("jdbcPassword");
        }

        try {
            setWaiting("Initializing");

            //insertTestData();
            //updateAutoCommitBox();
            c = (auto
                 ? ConnectionDialogSwing.createConnection(defDriver, defURL,
                     defUser, defPassword)
                 : ConnectionDialogSwing.createConnection(jframe, "Connect"));
        } catch (Exception e) {

            //  Added: (weconsultants@users)
            CommonSwing.errorMessage(e);
        } finally {
            setWaiting(null);
        }

        if (c != null) {
            connect(c);
        }

        if (getParameter("loadSampleData") != null
                && getParameter("loadSampleData").equals("true")) {
            insertTestData();

            try {
                Thread.sleep(1000);
            } catch (InterruptedException ie) {}
            ;

            // I don't know why, but the tree refresh below sometimes
            // doesn't show all tables unless I put this delay here.
            refreshTree();
        }

        if (getParameter("schemaFilter") != null) {
            schemaFilter = getParameter("schemaFilter");
        }
    }

    /**
     * Run with --help switch for usage instructions.
     *
     * @throws IllegalArgumentException for the obvious reason
     */
    public static void main(String[] arg) {

        System.getProperties().put("sun.java2d.noddraw", "true");

        // (ulrivo): read all arguments from the command line
        String  lowerArg;
        String  urlid        = null;
        String  rcFile       = null;
        boolean autoConnect  = false;
        boolean urlidConnect = false;

        bMustExit = true;

        for (int i = 0; i < arg.length; i++) {
            lowerArg = arg[i].toLowerCase();

            if (lowerArg.startsWith("--")) {
                lowerArg = lowerArg.substring(1);
            }

            i++;

            if (lowerArg.equals("-driver")) {
                defDriver   = arg[i];
                autoConnect = true;
            } else if (lowerArg.equals("-url")) {
                defURL      = arg[i];
                autoConnect = true;
            } else if (lowerArg.equals("-user")) {
                defUser     = arg[i];
                autoConnect = true;
            } else if (lowerArg.equals("-password")) {
                defPassword = arg[i];
                autoConnect = true;
            } else if (lowerArg.equals("-urlid")) {
                urlid        = arg[i];
                urlidConnect = true;
            } else if (lowerArg.equals("-rcfile")) {
                rcFile       = arg[i];
                urlidConnect = true;
            } else if (lowerArg.equals("-dir")) {
                defDirectory = arg[i];
            } else if (lowerArg.equals("-script")) {
                defScript = arg[i];
            } else if (lowerArg.equals("-noexit")) {
                bMustExit = false;

                i--;
            } else if (lowerArg.equals("-help")) {
                showUsage();

                return;
            } else {
                /* Syntax ERRORS should either throw or exit with non-0 status.
                 * In our case, it may be unsafe to exit, so we throw.
                 * (I.e. should provide easy way for caller to programmatically
                 * determine that there was an invocation problem).
                 */
                throw new IllegalArgumentException(
                    "Try:  java... " + DatabaseManagerSwing.class.getName()
                    + " --help");

                // No reason to localize, since the main syntax message is
                // not localized.
            }
        }

        DatabaseManagerSwing m =
            new DatabaseManagerSwing(new JFrame("HSQL Database Manager"));

        // Added: (weconsultants@users): Need databaseManagerSwing for later Reference
        refForFontDialogSwing = m;

        m.main();

        Connection c = null;

        m.setWaiting("Initializing");

        try {
            if (autoConnect && urlidConnect) {
                throw new IllegalArgumentException(
                    "You may not specify both (urlid) AND (url/user/password).");
            }

            if (autoConnect) {
                c = ConnectionDialogSwing.createConnection(defDriver, defURL,
                        defUser, defPassword);
            } else if (urlidConnect) {
                if (urlid == null) {
                    throw new IllegalArgumentException(
                        "You must specify an 'urlid' to use an RC file");
                }

                autoConnect = true;

                String rcfilepath = (rcFile == null) ? DEFAULT_RCFILE
                                                     : rcFile;
                RCData rcdata     = new RCData(new File(rcfilepath), urlid);

                c = rcdata.getConnection(
                    null, System.getProperty("sqlfile.charset"),
                    System.getProperty("javax.net.ssl.trustStore"));
            } else {
                c = ConnectionDialogSwing.createConnection(m.jframe,
                        "Connect");
            }
        } catch (Exception e) {

            //  Added: (weconsultants@users)
            CommonSwing.errorMessage(e);
        } finally {
            m.setWaiting(null);
        }

        if (c != null) {
            m.connect(c);
        }

        // Added: (weconsultants@users): For preloadng FontDialogSwing
        FontDialogSwing.creatFontDialog(refForFontDialogSwing);
        m.start();
    }

    /**
     * This stuff is all quick, except for the refreshTree().
     * This unit can be kicked off in main Gui thread.  The refreshTree
     * will be backgrounded and this method will return.
     */
    public void connect(Connection c) {

        schemaFilter = null;

        if (c == null) {
            return;
        }

        if (cConn != null) {
            try {
                cConn.close();
            } catch (SQLException e) {

                //  Added: (weconsultants@users)
                CommonSwing.errorMessage(e);
            }
        }

        cConn = c;

        // Added: (weconsultants@users) Need to barrow to get the table rowcounts
        rowConn = c;

        try {
            dMeta      = cConn.getMetaData();
            isOracle = (dMeta.getDatabaseProductName().indexOf("Oracle") >= 0);
            sStatement = cConn.createStatement();

            updateAutoCommitBox();

            // Workaround for EXTREME SLOWNESS getting this info from O.
            showIndexDetails = !isOracle;

            Driver driver = DriverManager.getDriver(dMeta.getURL());
            ConnectionSetting newSetting = new ConnectionSetting(
                dMeta.getDatabaseProductName(), driver.getClass().getName(),
                dMeta.getURL(),
                dMeta.getUserName().replaceAll("@localhost", ""), "");
            Hashtable settings =
                ConnectionDialogCommon.loadRecentConnectionSettings();

            ConnectionDialogCommon.addToRecentConnectionSettings(settings,
                    newSetting);
            ConnectionDialogSwing.setConnectionSetting(newSetting);
            refreshTree();
            clearResultPanel();

            if (fMain instanceof JApplet) {
                getAppletContext().showStatus(
                    "JDBC Connection established to a "
                    + dMeta.getDatabaseProductName() + " v. "
                    + dMeta.getDatabaseProductVersion() + " database as '"
                    + dMeta.getUserName() + "'.");
            }
        } catch (SQLException e) {

            //  Added: (weconsultants@users)
            CommonSwing.errorMessage(e);
        } catch (IOException e) {

            //  Added: (weconsultants@users)
            CommonSwing.errorMessage(e);
        } catch (Exception e) {
            CommonSwing.errorMessage(e);
        }
    }

    private static void showUsage() {

        System.out.println(
            "Usage: java DatabaseManagerSwing [--options]\n"
            + "where options include:\n"
            + "    --help                show this message\n"
            + "    --driver <classname>  jdbc driver class\n"
            + "    --url <name>          jdbc url\n"
            + "    --user <name>         username used for connection\n"
            + "    --password <password> password for this user\n"
            + "    --urlid <urlid>       use url/user/password/driver in rc file\n"
            + "    --rcfile <file>       (defaults to 'dbmanager.rc' in home dir)\n"
            + "    --dir <path>          default directory\n"
            + "    --script <file>       reads from script file\n"
            + "    --noexit              do not call system.exit()");
    }

    private void insertTestData() {

        try {
            DatabaseManagerCommon.createTestTables(sStatement);
            txtCommand.setText(
                DatabaseManagerCommon.createTestData(sStatement));

            for (int i = 0; i < DatabaseManagerCommon.testDataSql.length;
                    i++) {
                addToRecent(DatabaseManagerCommon.testDataSql[i]);
            }

            executeCurrentSQL();
        } catch (SQLException e) {

            //  Added: (weconsultants@users)
            CommonSwing.errorMessage(e);
        }
    }

    public void setMustExit(boolean b) {
        this.bMustExit = b;
    }

    private DBMPrefs prefs = null;

    public void main() {

        JMenu     jmenu;
        JMenuItem mitem;

        try {
            prefs = new DBMPrefs(fMain instanceof JApplet);
        } catch (Exception e) {
            System.err.println(
                "Failed to load preferences.  Proceeding with defaults:\n");
        }

        if (prefs == null) {
            setLF(CommonSwing.Native);
        } else {
            autoRefresh      = prefs.autoRefresh;
            displayRowCounts = prefs.showRowCounts;
            showSys          = prefs.showSysTables;
            showSchemas      = prefs.showSchemas;
            gridFormat       = prefs.resultGrid;
            showTooltips     = prefs.showTooltips;

            setLF(prefs.laf);
        }

        // (ulrivo): An actual icon.  N.b., this adds some tips to the tip map
        fMain.getContentPane().add(createToolBar(), "North");

        if (fMain instanceof java.awt.Frame) {
            ((java.awt.Frame) fMain).setIconImage(
                CommonSwing.getIcon("Frame"));
        }

        if (fMain instanceof java.awt.Window) {
            ((java.awt.Window) fMain).addWindowListener(this);
        }

        JMenuBar bar = new JMenuBar();

        // used shortcuts: CERGTSIUDOLM
        String[] fitems = {
            "-Connect...", "--", "OOpen Script...", "-Save Script...",
            "-Save Result...", "--", "-Exit"
        };

        jmenu = addMenu(bar, "File", fitems);

        // All actions after Connect and the divider are local.
        for (int i = 2; i < jmenu.getItemCount(); i++) {
            mitem = jmenu.getItem(i);

            if (mitem != null) {
                localActionList.add(mitem);
            }
        }

        Object[] vitems = {
            "RRefresh Tree", boxAutoRefresh, "--", boxRowCounts, boxShowSys,
            boxShowSchemas, boxShowGrid
        };

        addMenu(bar, "View", vitems);

        String[] sitems = {
            "SSELECT", "IINSERT", "UUPDATE", "DDELETE", "EEXECUTE", "---",
            "-CREATE TABLE", "-DROP TABLE", "-CREATE INDEX", "-DROP INDEX",
            "--", "CCOMMIT*", "LROLLBACK*", "-CHECKPOINT*", "-SCRIPT", "-SET",
            "-SHUTDOWN", "--", "-Test Script"
        };

        addMenu(bar, "Command", sitems);

        mRecent = new JMenu("Recent");

        mRecent.setMnemonic(KeyEvent.VK_R);
        bar.add(mRecent);

        ButtonGroup lfGroup = new ButtonGroup();

        lfGroup.add(rbNativeLF);
        lfGroup.add(rbJavaLF);
        lfGroup.add(rbMotifLF);
        boxShowSchemas.setSelected(showSchemas);
        boxShowGrid.setSelected(gridFormat);
        boxTooltips.setSelected(showTooltips);
        boxShowGrid.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_G,
                Event.CTRL_MASK));
        boxAutoRefresh.setSelected(autoRefresh);
        boxRowCounts.setSelected(displayRowCounts);
        boxShowSys.setSelected(showSys);
        rbNativeLF.setActionCommand("LFMODE:" + CommonSwing.Native);
        rbJavaLF.setActionCommand("LFMODE:" + CommonSwing.Java);
        rbMotifLF.setActionCommand("LFMODE:" + CommonSwing.Motif);
        tipMap.put(mitemUpdateSchemas, "Refresh the schema list in this menu");
        tipMap.put(rbAllSchemas, "Display items in all schemas");
        tipMap.put(mitemAbout, "Display product information");
        tipMap.put(mitemHelp, "Display advice for obtaining help");
        tipMap.put(boxAutoRefresh,
                   "Refresh tree (and schema list) automatically"
                   + "when YOU modify database objects");
        tipMap.put(boxShowSchemas,
                   "Display object names in tree-like schemaname.basename");
        tipMap.put(rbNativeLF,
                   "Set Look and Feel to Native for your platform");
        tipMap.put(rbJavaLF, "Set Look and Feel to Java");
        tipMap.put(rbMotifLF, "Set Look and Feel to Motif");
        boxTooltips.setToolTipText("Display tooltips (hover text), like this");
        tipMap.put(boxAutoCommit,
                   "Shows current Auto-commit mode.  Click to change");
        tipMap.put(
            boxLogging,
            "Shows current JDBC DriverManager logging mode.  Click to change");
        tipMap.put(boxShowSys, "Show system tables in table tree to the left");
        tipMap.put(boxShowGrid, "Show query results in grid (in text if off)");
        tipMap.put(boxRowCounts, "Show row counts with table names in tree");
        boxAutoRefresh.setMnemonic(KeyEvent.VK_C);
        boxShowSchemas.setMnemonic(KeyEvent.VK_Y);
        boxAutoCommit.setMnemonic(KeyEvent.VK_A);
        boxShowSys.setMnemonic(KeyEvent.VK_Y);
        boxShowGrid.setMnemonic(KeyEvent.VK_G);
        boxRowCounts.setMnemonic(KeyEvent.VK_C);
        boxLogging.setMnemonic(KeyEvent.VK_L);
        rbAllSchemas.setMnemonic(KeyEvent.VK_ASTERISK);
        rbNativeLF.setMnemonic(KeyEvent.VK_N);
        rbJavaLF.setMnemonic(KeyEvent.VK_J);
        rbMotifLF.setMnemonic(KeyEvent.VK_M);
        mitemUpdateSchemas.setMnemonic(KeyEvent.VK_U);

        Object[] soptions = {

            // Added: (weconsultants@users) New menu options
            rbNativeLF, rbJavaLF, rbMotifLF, "--", "-Set Fonts", "--",
            boxAutoCommit, "--", "-Disable MaxRows", "-Set MaxRows to 100",
            "--", boxLogging, "--", "-Insert test data"
        };

        addMenu(bar, "Options", soptions);

        String[] stools = {
            "-Dump", "-Restore", "-Transfer"
        };

        jmenu = addMenu(bar, "Tools", stools);

        jmenu.setEnabled(TT_AVAILABLE);
        localActionList.add(jmenu);

        for (int i = 0; i < jmenu.getItemCount(); i++) {
            mitem = jmenu.getItem(i);

            if (mitem != null) {
                localActionList.add(mitem);
            }
        }

        mnuSchemas.setMnemonic(KeyEvent.VK_S);
        bar.add(mnuSchemas);

        JMenu mnuHelp = new JMenu("Help");

        mnuHelp.setMnemonic(KeyEvent.VK_H);
        mnuHelp.add(mitemAbout);
        mnuHelp.add(mitemHelp);
        mnuHelp.add(boxTooltips);
        rbAllSchemas.addActionListener(schemaListListener);

        // May be illegal:
        mitemUpdateSchemas.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent actionevent) {
                updateSchemaList();
            }
        });
        mitemHelp.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent actionevent) {

                JOptionPane.showMessageDialog(fMain.getContentPane(),
                                              HELP_TEXT, "HELP",
                                              JOptionPane.INFORMATION_MESSAGE);
            }
        });
        mitemAbout.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent actionevent) {

                JOptionPane.showMessageDialog(fMain.getContentPane(),
                                              ABOUT_TEXT, "About",
                                              JOptionPane.INFORMATION_MESSAGE);
            }
        });
        boxTooltips.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent actionevent) {

                showTooltips = boxTooltips.isSelected();

                resetTooltips();
            }
        });
        bar.add(mnuHelp);

        if (fMain instanceof JApplet) {
            ((JApplet) fMain).setJMenuBar(bar);
        } else if (fMain instanceof JFrame) {
            ((JFrame) fMain).setJMenuBar(bar);
        }

        initGUI();

        sRecent = new String[iMaxRecent];

        // Modified: (weconsultants@users)Mode code to CommonSwing for general use
        if (!(fMain instanceof JApplet)) {
            CommonSwing.setFramePositon((JFrame) fMain);
        }

        // Modified: (weconsultants@users) Changed from deprecated show()
        ((Component) fMain).setVisible(true);

        // (ulrivo): load query from command line
        if (defScript != null) {
            if (defDirectory != null) {
                defScript = defDirectory + File.separator + defScript;
            }

            // if insert stmet is thousands of records...skip showing it
            // as text.  Too huge.
            sqlScriptBuffer = DatabaseManagerCommon.readFile(defScript);

            if (4096 <= sqlScriptBuffer.length()) {
                int eoThirdLine = sqlScriptBuffer.indexOf('\n');

                if (eoThirdLine > 0) {
                    eoThirdLine = sqlScriptBuffer.indexOf('\n',
                                                          eoThirdLine + 1);
                }

                if (eoThirdLine > 0) {
                    eoThirdLine = sqlScriptBuffer.indexOf('\n',
                                                          eoThirdLine + 1);
                }

                if (eoThirdLine < 1) {
                    eoThirdLine = 100;
                }

                txtCommand.setText(
                    "............... Script File loaded: " + defScript
                    + " ..................... \n"
                    + "............... Click Execute or Clear "
                    + "...................\n"
                    + sqlScriptBuffer.substring(0, eoThirdLine + 1)
                    + "..........................................."
                    + "..............................\n"
                    + "............................................."
                    + "............................\n");
                txtCommand.setEnabled(false);
            } else {
                txtCommand.setText(sqlScriptBuffer);

                sqlScriptBuffer = null;

                txtCommand.setEnabled(true);
            }
        }

        // This must be done AFTER all tip texts are put into the map
        resetTooltips();
        txtCommand.requestFocus();
    }

    private JMenu addMenu(JMenuBar b, String name, Object[] items) {

        JMenu menu = new JMenu(name);

        menu.setMnemonic(name.charAt(0));
        addMenuItems(menu, items);
        b.add(menu);

        return menu;
    }

    private void addMenuItems(JMenu f, Object[] m) {

        /*
         * This method needs to be completely written or just
         * obliterated and we'll use the Menu objects directly.
         * Problem is, passing in Strings for menu elements makes it
         * extremely difficult to use non-text menu items (an important
         * part of a good Gui), hot-keys, mnemonic keys, tooltips.
         * Note the "trick" required here to set hot-keys.
         */
        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();

        for (int i = 0; i < m.length; i++) {
            if (m[i].equals("--")) {
                f.addSeparator();
            } else if (m[i].equals("---")) {

                // (ulrivo): full size on screen with less than 640 width
                if (d.width >= 640) {
                    f.addSeparator();
                } else {
                    return;
                }
            } else {
                JMenuItem item;

                if (m[i] instanceof JMenuItem) {
                    item = (JMenuItem) m[i];
                } else if (m[i] instanceof String) {
                    item = new JMenuItem(((String) m[i]).substring(1));

                    char c = ((String) m[i]).charAt(0);

                    if (c != '-') {
                        KeyStroke key =
                            KeyStroke.getKeyStroke(c, Event.CTRL_MASK);

                        item.setAccelerator(key);
                    }
                } else {
                    throw new RuntimeException(
                        "Unexpected element for menu item creation: "
                        + m[i].getClass().getName());
                }

                item.addActionListener(this);
                f.add(item);
            }
        }
    }

    public void keyPressed(KeyEvent k) {}

    public void keyReleased(KeyEvent k) {}

    public void keyTyped(KeyEvent k) {

        if (k.getKeyChar() == '\n' && k.isControlDown()) {
            k.consume();
            executeCurrentSQL();
        }
    }

    Thread dummyThread = new Thread("dummy");

    public void actionPerformed(ActionEvent ev) {

        String s = ev.getActionCommand();

        if (s == null) {
            if (ev.getSource() instanceof JMenuItem) {
                s = ((JMenuItem) ev.getSource()).getText();
            }
        }

        if (s == null) {}
        else if (s.equals("Exit")) {
            windowClosing(null);
        } else if (s.equals("Transfer")) {
            Transfer.work(null);
        } else if (s.equals("Dump")) {
            Transfer.work(new String[]{ "-d" });
        } else if (s.equals("Restore")) {
            JOptionPane.showMessageDialog(
                fMain.getContentPane(),
                "Use Ctrl-R or the View menu to\n"
                + "update nav. tree after Restoration", "Suggestion",
                    JOptionPane.INFORMATION_MESSAGE);

            // Regardless of whether autoRefresh is on, half of
            // Restore runs asynchronously, so we could only
            // update the tree from within the Transfer class.
            Transfer.work(new String[]{ "-r" });

            // Would be better to put the modal suggestion here, after the
            // user selects the import file, but that messes up the z
            // layering of the 3 windows already displayed.
        } else if (s.equals(LOGGING_BOX_TEXT)) {
            JavaSystem.setLogToSystem(boxLogging.isSelected());
        } else if (s.equals(AUTOREFRESH_BOX_TEXT)) {
            autoRefresh = boxAutoRefresh.isSelected();

            refreshTree();
        } else if (s.equals("Refresh Tree")) {
            refreshTree();
        } else if (s.startsWith("#")) {
            int i = Integer.parseInt(s.substring(1));

            txtCommand.setText(sRecent[i]);
        } else if (s.equals("Connect...")) {
            Connection newCon = null;

            try {
                setWaiting("Connecting");

                newCon = ConnectionDialogSwing.createConnection(jframe,
                        "Connect");
            } finally {
                setWaiting(null);
            }

            connect(newCon);
        } else if (s.equals(GRID_BOX_TEXT)) {
            gridFormat = boxShowGrid.isSelected();

            displayResults();
        } else if (s.equals("Open Script...")) {
            JFileChooser f = new JFileChooser(".");

            f.setDialogTitle("Open Script...");

            // (ulrivo): set default directory if set from command line
            if (defDirectory != null) {
                f.setCurrentDirectory(new File(defDirectory));
            }

            int option = f.showOpenDialog((Component) fMain);

            if (option == JFileChooser.APPROVE_OPTION) {
                File file = f.getSelectedFile();

                if (file != null) {
                    sqlScriptBuffer =
                        DatabaseManagerCommon.readFile(file.getAbsolutePath());

                    if (4096 <= sqlScriptBuffer.length()) {
                        int eoThirdLine = sqlScriptBuffer.indexOf('\n');

                        if (eoThirdLine > 0) {
                            eoThirdLine = sqlScriptBuffer.indexOf('\n',
                                                                  eoThirdLine
                                                                  + 1);
                        }

                        if (eoThirdLine > 0) {
                            eoThirdLine = sqlScriptBuffer.indexOf('\n',
                                                                  eoThirdLine
                                                                  + 1);
                        }

                        if (eoThirdLine < 1) {
                            eoThirdLine = 100;
                        }

                        txtCommand.setText(
                            "............... Script File loaded: " + file
                            + " ..................... \n"
                            + "............... Click Execute or Clear "
                            + "...................\n"
                            + sqlScriptBuffer.substring(0, eoThirdLine + 1)
                            + "........................................."
                            + "................................\n"
                            + "..........................................."
                            + "..............................\n");
                        txtCommand.setEnabled(false);
                    } else {
                        txtCommand.setText(sqlScriptBuffer);

                        sqlScriptBuffer = null;

                        txtCommand.setEnabled(true);
                    }
                }
            }
        } else if (s.equals("Save Script...")) {
            JFileChooser f = new JFileChooser(".");

            f.setDialogTitle("Save Script");

            // (ulrivo): set default directory if set from command line
            if (defDirectory != null) {
                f.setCurrentDirectory(new File(defDirectory));
            }

            int option = f.showSaveDialog((Component) fMain);

            if (option == JFileChooser.APPROVE_OPTION) {
                File file = f.getSelectedFile();

                if (file != null) {
                    DatabaseManagerCommon.writeFile(file.getAbsolutePath(),
                                                    txtCommand.getText());
                }
            }
        } else if (s.equals("Save Result...")) {
            JFileChooser f = new JFileChooser(".");

            f.setDialogTitle("Save Result...");

            // (ulrivo): set default directory if set from command line
            if (defDirectory != null) {
                f.setCurrentDirectory(new File(defDirectory));
            }

            int option = f.showSaveDialog((Component) fMain);

            if (option == JFileChooser.APPROVE_OPTION) {
                File file = f.getSelectedFile();

                if (file != null) {
                    showResultInText();
                    DatabaseManagerCommon.writeFile(file.getAbsolutePath(),
                                                    txtResult.getText());
                }
            }
        } else if (s.equals(SHOWSYS_BOX_TEXT)) {
            showSys = boxShowSys.isSelected();

            refreshTree();
        } else if (s.equals(ROWCOUNTS_BOX_TEXT)) {
            displayRowCounts = boxRowCounts.isSelected();

            refreshTree();
        } else if (s.startsWith("LFMODE:")) {
            setLF(s.substring("LFMODE:".length()));
        } else if (s.equals("Set Fonts")) {

            // Added: (weconsultants@users)
            FontDialogSwing.creatFontDialog(refForFontDialogSwing);
        } else if (s.equals(AUTOCOMMIT_BOX_TEXT)) {
            try {
                cConn.setAutoCommit(boxAutoCommit.isSelected());
            } catch (SQLException e) {
                boxAutoCommit.setSelected(!boxAutoCommit.isSelected());

                //  Added: (weconsultants@users)
                CommonSwing.errorMessage(e);
            }
        } else if (s.equals("COMMIT*")) {
            try {
                cConn.commit();
                showHelp(new String[] {
                    "", "COMMIT executed"
                });
            } catch (SQLException e) {

                //  Added: (weconsultants@users)
                CommonSwing.errorMessage(e);
            }
        } else if (s.equals("Insert test data")) {
            insertTestData();
            refreshTree();
        } else if (s.equals("ROLLBACK*")) {
            try {
                cConn.rollback();
                showHelp(new String[] {
                    "", "ROLLBACK executed"
                });
            } catch (SQLException e) {

                //  Added: (weconsultants@users)
                CommonSwing.errorMessage(e);
            }
        } else if (s.equals("Disable MaxRows")) {
            try {
                sStatement.setMaxRows(0);
            } catch (SQLException e) {

                //  Added: (weconsultants@users)
                CommonSwing.errorMessage(e);
            }
        } else if (s.equals("Set MaxRows to 100")) {
            try {
                sStatement.setMaxRows(100);
            } catch (SQLException e) {
                CommonSwing.errorMessage(e);
            }
        } else if (s.equals("SELECT")) {
            showHelp(DatabaseManagerCommon.selectHelp);
        } else if (s.equals("INSERT")) {
            showHelp(DatabaseManagerCommon.insertHelp);
        } else if (s.equals("UPDATE")) {
            showHelp(DatabaseManagerCommon.updateHelp);
        } else if (s.equals("DELETE")) {
            showHelp(DatabaseManagerCommon.deleteHelp);
        } else if (s.equals("EXECUTE")) {
            executeCurrentSQL();
        } else if (s.equals("CREATE TABLE")) {
            showHelp(DatabaseManagerCommon.createTableHelp);
        } else if (s.equals("DROP TABLE")) {
            showHelp(DatabaseManagerCommon.dropTableHelp);
        } else if (s.equals("CREATE INDEX")) {
            showHelp(DatabaseManagerCommon.createIndexHelp);
        } else if (s.equals("DROP INDEX")) {
            showHelp(DatabaseManagerCommon.dropIndexHelp);
        } else if (s.equals("CHECKPOINT*")) {
            try {
                cConn.createStatement().executeUpdate("CHECKPOINT");
                showHelp(new String[] {
                    "", "CHECKPOINT executed"
                });
            } catch (SQLException e) {
                CommonSwing.errorMessage(e);
            }
        } else if (s.equals("SCRIPT")) {
            showHelp(DatabaseManagerCommon.scriptHelp);
        } else if (s.equals("SHUTDOWN")) {
            showHelp(DatabaseManagerCommon.shutdownHelp);
        } else if (s.equals("SET")) {
            showHelp(DatabaseManagerCommon.setHelp);
        } else if (s.equals("Test Script")) {
            showHelp(DatabaseManagerCommon.testHelp);
        } else if (s.equals(SHOWSCHEMAS_BOX_TEXT)) {
            showSchemas = boxShowSchemas.isSelected();

            refreshTree();
        } else {
            throw new RuntimeException("Unexpected action triggered: " + s);
        }
    }

    private void displayResults() {

        if (gridFormat) {
            setResultsInGrid();
        } else {
            setResultsInText();
        }
    }

    private void setResultsInGrid() {

        pResult.removeAll();
        pResult.add(gScrollPane, BorderLayout.CENTER);
        pResult.doLayout();
        gResult.fireTableChanged(null);
        pResult.repaint();
    }

    private void setResultsInText() {

        pResult.removeAll();
        pResult.add(txtResultScroll, BorderLayout.CENTER);
        pResult.doLayout();
        showResultInText();
        pResult.repaint();
    }

    private void showHelp(String[] help) {

        txtCommand.setText(help[0]);

        bHelp = true;

        pResult.removeAll();
        pResult.add(txtResultScroll, BorderLayout.CENTER);
        pResult.doLayout();
        txtResult.setText(help[1]);
        pResult.repaint();
        txtCommand.requestFocus();
        txtCommand.setCaretPosition(help[0].length());
    }

    public void windowActivated(WindowEvent e) {}

    public void windowDeactivated(WindowEvent e) {}

    public void windowClosed(WindowEvent e) {}

    public void windowDeiconified(WindowEvent e) {}

    public void windowIconified(WindowEvent e) {}

    public void windowOpened(WindowEvent e) {}

    public void windowClosing(WindowEvent ev) {

        stop();

        try {
            if (cConn != null) {
                cConn.close();
            }

            if (prefs != null) {
                prefs.autoRefresh   = autoRefresh;
                prefs.showRowCounts = displayRowCounts;
                prefs.showSysTables = showSys;
                prefs.showSchemas   = showSchemas;
                prefs.resultGrid    = gridFormat;
                prefs.showTooltips  = showTooltips;
                prefs.laf           = currentLAF;

                prefs.store();
            }
        } catch (Exception e) {

            //  Added: (weconsultants@users)
            CommonSwing.errorMessage(e);
        }

        if (fMain instanceof java.awt.Window) {
            ((java.awt.Window) fMain).dispose();
        }

        if (bMustExit) {
            System.exit(0);
        }
    }

    private void clear() {

        sqlScriptBuffer = null;

        txtCommand.setText("");
        txtCommand.setEnabled(true);
    }

    private String busyText = null;

    private void backgroundIt(Runnable r, String description) {

        if (busyText != null) {
            Toolkit.getDefaultToolkit().beep();

            return;
        }

        // set Waiting mode here.  Inverse op must be called by final()
        // in the Thread.run() of every background thread.
        setWaiting(description);
        SwingUtilities.invokeLater(r);
    }

    private void clearResultPanel() {

        gResult.setHead(new Object[0]);
        gResult.clear();

        if (gridFormat) {
            gResult.fireTableChanged(null);
        } else {
            showResultInText();
        }
    }

    public void setWaiting(String description) {

        busyText = description;

        if (busyText == null) {

            // restore the cursors we saved
            if (fMain instanceof java.awt.Frame) {
                ((java.awt.Frame) fMain).setCursor(fMainCursor);
            } else {
                ((Component) fMain).setCursor(fMainCursor);
            }

            txtCommand.setCursor(txtCommandCursor);
            txtResult.setCursor(txtResultCursor);

            /** @todo: Enable actionButtons */
        } else {

            // save the old cursors
            if (fMainCursor == null) {
                fMainCursor = ((fMain instanceof java.awt.Frame)
                               ? (((java.awt.Frame) fMain).getCursor())
                               : (((Component) fMain).getCursor()));
                txtCommandCursor = txtCommand.getCursor();
                txtResultCursor  = txtResult.getCursor();
            }

            // set the cursors to the wait cursor
            if (fMain instanceof java.awt.Frame) {
                ((java.awt.Frame) fMain).setCursor(waitCursor);
            } else {
                ((Component) fMain).setCursor(waitCursor);
            }

            txtCommand.setCursor(waitCursor);
            txtResult.setCursor(waitCursor);

            /** @todo: Disable actionButtons */
        }

        setStatusLine(busyText, ((busyText == null) ? gResult.getRowCount()
                                                    : 0));
    }

    private Runnable enableButtonRunnable = new Runnable() {

        public void run() {
            jbuttonClear.setEnabled(true);
            jbuttonExecute.setEnabled(true);
        }
    };
    private Runnable disableButtonRunnable = new Runnable() {

        public void run() {
            jbuttonClear.setEnabled(false);
            jbuttonExecute.setEnabled(false);
        }
    };
    private Thread           buttonUpdaterThread = null;
    private static final int BUTTON_CHECK_PERIOD = 500;
    private Runnable         buttonUpdater       = new Runnable() {

        public void run() {

            boolean havesql;

            while (true) {
                try {
                    Thread.sleep(BUTTON_CHECK_PERIOD);
                } catch (InterruptedException ie) {}

                if (buttonUpdaterThread == null) {    // Pointer to me
                    return;
                }

                havesql = (txtCommand.getText().length() > 0);

                if (jbuttonClear.isEnabled() != havesql) {
                    SwingUtilities.invokeLater(havesql ? enableButtonRunnable
                                                       : disableButtonRunnable);
                }
            }
        }
    };
    private JButton jbuttonClear;
    private JButton jbuttonExecute;

    public void start() {

        if (buttonUpdaterThread == null) {
            buttonUpdaterThread = new Thread(buttonUpdater);
        }

        buttonUpdaterThread.start();
    }

    public void stop() {

        System.err.println("Stopping");

        buttonUpdaterThread = null;
    }

    private Runnable treeRefreshRunnable = new Runnable() {

        public void run() {

            try {
                directRefreshTree();
            } catch (RuntimeException re) {
                CommonSwing.errorMessage(re);

                throw re;
            } finally {
                setWaiting(null);
            }
        }
    };

    /**
     * Schedules to run in a Gui-safe thread
     */
    protected void executeCurrentSQL() {

        if (txtCommand.getText().length() < 1) {
            CommonSwing.errorMessage("No SQL to execute");

            return;
        }

        backgroundIt(new StatementExecRunnable(), "Executing SQL");
    }

    protected class StatementExecRunnable implements Runnable {

        public void run() {

            gResult.clear();

            try {
                if (txtCommand.getText().startsWith("-->>>TEST<<<--")) {
                    testPerformance();
                } else {
                    executeSQL();
                }

                updateResult();
                displayResults();
                updateAutoCommitBox();

                // System.gc();
            } catch (RuntimeException re) {
                CommonSwing.errorMessage(re);

                throw re;
            } finally {
                setWaiting(null);
            }
        }
    }
    ;

    private void executeSQL() {

        String[] g   = new String[1];
        String   sql = null;

        try {
            lTime = System.currentTimeMillis();
            sql   = ((sqlScriptBuffer == null ? txtCommand.getText()
                                              : sqlScriptBuffer));

            sStatement.execute(sql);

            int r = sStatement.getUpdateCount();

            if (r == -1) {
                ResultSet rs = sStatement.getResultSet();

                try {
                    formatResultSet(rs);
                } catch (Throwable t) {
                    g[0] = "Error displaying the ResultSet";

                    gResult.setHead(g);

                    String s = t.getMessage();

                    g[0] = s;

                    gResult.addRow(g);
                }
            } else {
                g[0] = "update count";

                gResult.setHead(g);

                g[0] = "" + r;

                gResult.addRow(g);
            }

            lTime = System.currentTimeMillis() - lTime;

            if (sqlScriptBuffer == null) {
                addToRecent(sql);
                txtCommand.setEnabled(true);    // clear() does this otherwise
            } else {
                clear();
            }
        } catch (SQLException e) {
            lTime = System.currentTimeMillis() - lTime;
            g[0]  = "SQL Error";

            gResult.setHead(g);

            String s = e.getMessage();

            s    += " / Error Code: " + e.getErrorCode();
            s    += " / State: " + e.getSQLState();
            g[0] = s;

            gResult.addRow(g);

            //  Added: (weconsultants@users)
            CommonSwing.errorMessage(e);

            return;
        }

        if (autoRefresh) {

            // We're already running in a "busy" thread.  Just update the
            // status text.
            setStatusLine("Refreshing object tree", 0);

            String upper = sql.toUpperCase(Locale.ENGLISH);

            // This test can be very liberal.  Too liberal will just do
            // some extra refreshes.  Too conservative will display
            // obsolete info.
            if (upper.indexOf("ALTER") > -1 || upper.indexOf("DROP") > -1
                    || upper.indexOf("CREATE") > -1) {
                directRefreshTree();
            }
        }
    }

    /**
     * Could somebody explain what the purpose of this method is?
     * Contrary to the method name, it looks like it displays
     * results only if gridFormat is off (seems like it  does
     * nothing otherwise, except for clearing help text and moving focus).
     */
    private void updateResult() {

        if (gridFormat) {

            // in case 'help' has removed the grid
            if (bHelp) {
                pResult.removeAll();
                pResult.add(gScrollPane, BorderLayout.CENTER);
                pResult.doLayout();
                gResult.fireTableChanged(null);
                pResult.repaint();

                bHelp = false;
            }
        } else {
            showResultInText();
        }

        txtCommand.selectAll();
        txtCommand.requestFocus();
    }

    /**
     * We let Swing handle displaying nulls (which it generally does by
     * printing nothing for them), except for the case of database
     * VARCHARs, because this is the only class where there is any
     * ambiguity about whether there is a null stored or not.
     */
    private void formatResultSet(ResultSet r) {

        if (r == null) {
            String[] g = new String[1];

            g[0] = "Result";

            gResult.setHead(g);

            g[0] = "(empty)";

            gResult.addRow(g);

            return;
        }

        try {
            ResultSetMetaData m         = r.getMetaData();
            int               col       = m.getColumnCount();
            Object[]          h         = new Object[col];
            boolean[]         isVarChar = new boolean[col];

            for (int i = 1; i <= col; i++) {
                h[i - 1] = m.getColumnLabel(i);
                isVarChar[i - 1] = (m.getColumnType(i)
                                    == java.sql.Types.VARCHAR);
            }

            gResult.setHead(h);

            while (r.next()) {
                for (int i = 1; i <= col; i++) {
                    try {
                        h[i - 1] = r.getObject(i);

                        if (r.wasNull()) {
                            h[i - 1] = (isVarChar[i - 1] ? NULL_STR
                                                         : null);
                        }
                    } catch (SQLException e) {}
                }

                gResult.addRow(h);
            }

            r.close();
        } catch (SQLException e) {

            //  Added: (weconsultants@users)
            CommonSwing.errorMessage(e);
        }
    }

    private void testPerformance() {

        String       all   = txtCommand.getText();
        StringBuffer b     = new StringBuffer();
        long         total = 0;

        for (int i = 0; i < all.length(); i++) {
            char c = all.charAt(i);

            if (c != '\n') {
                b.append(c);
            }
        }

        all = b.toString();

        String[] g = new String[4];

        g[0] = "ms";
        g[1] = "count";
        g[2] = "sql";
        g[3] = "error";

        gResult.setHead(g);

        int max = 1;

        lTime = System.currentTimeMillis() - lTime;

        while (!all.equals("")) {
            int    i = all.indexOf(';');
            String sql;

            if (i != -1) {
                sql = all.substring(0, i);
                all = all.substring(i + 1);
            } else {
                sql = all;
                all = "";
            }

            if (sql.startsWith("--#")) {
                max = Integer.parseInt(sql.substring(3));

                continue;
            } else if (sql.startsWith("--")) {
                continue;
            }

            g[2] = sql;

            long l = 0;

            try {
                l = DatabaseManagerCommon.testStatement(sStatement, sql, max);
                total += l;
                g[0]  = "" + l;
                g[1]  = "" + max;
                g[3]  = "";
            } catch (SQLException e) {
                g[0] = g[1] = "n/a";
                g[3] = e.toString();

                //  Added: (weconsultants@users)
                CommonSwing.errorMessage(e);
            }

            gResult.addRow(g);
            System.out.println(l + " ms : " + sql);
        }

        g[0] = "" + total;
        g[1] = "total";
        g[2] = "";

        gResult.addRow(g);

        lTime = System.currentTimeMillis() - lTime;
    }

    private void showResultInText() {

        Object[] col   = gResult.getHead();
        int      width = col.length;
        int[]    size  = new int[width];
        Vector   data  = gResult.getData();
        Object[] row;
        int      height = data.size();

        for (int i = 0; i < width; i++) {
            size[i] = col[i].toString().length();
        }

        for (int i = 0; i < height; i++) {
            row = (Object[]) data.elementAt(i);

            for (int j = 0; j < width; j++) {
                String item = ((row[j] == null) ? ""
                                                : row[j].toString());
                int    l    = item.length();

                if (l > size[j]) {
                    size[j] = l;
                }
            }
        }

        StringBuffer b = new StringBuffer();

        for (int i = 0; i < width; i++) {
            b.append(col[i]);

            for (int l = col[i].toString().length(); l <= size[i]; l++) {
                b.append(' ');
            }
        }

        b.append(NL);

        for (int i = 0; i < width; i++) {
            for (int l = 0; l < size[i]; l++) {
                b.append('-');
            }

            b.append(' ');
        }

        b.append(NL);

        for (int i = 0; i < height; i++) {
            row = (Object[]) data.elementAt(i);

            for (int j = 0; j < width; j++) {
                String item = ((row[j] == null) ? ""
                                                : row[j].toString());

                b.append(item);

                for (int l = item.length(); l <= size[j]; l++) {
                    b.append(' ');
                }
            }

            b.append(NL);
        }

        // b.append(NL + height + " row(s) in " + lTime + " ms");
        // There is no reason why this report should be text-output-specific.
        // Moving it to bottom of the setWaiting method (where the report
        // gets written to the status line).
        // I'm only doing the rowcount now.  Add the time report there if
        // you are so inclined.
        txtResult.setText(b.toString());
    }

    private void addToRecent(String s) {

        for (int i = 0; i < iMaxRecent; i++) {
            if (s.equals(sRecent[i])) {
                return;
            }
        }

        if (sRecent[iRecent] != null) {
            mRecent.remove(iRecent);
        }

        sRecent[iRecent] = s;

        if (s.length() > 43) {
            s = s.substring(0, 40) + "...";
        }

        JMenuItem item = new JMenuItem(s);

        item.setActionCommand("#" + iRecent);
        item.addActionListener(this);
        mRecent.insert(item, iRecent);

        iRecent = (iRecent + 1) % iMaxRecent;
    }

    // empty implementations for mouse listener.  We're only using
    // mouseReleased
    public final void mouseClicked(final MouseEvent mouseEvent) {}

    public final void mouseEntered(final MouseEvent mouseEvent) {}

    public final void mouseExited(final MouseEvent mouseEvent) {}

    // Check for handlePopup in both mousePressed and mouseReleased.  According to
    // MouseEvent javadocs it's necessary for cross platform compatibility.
    // We keep a record of the last alreadyHandled mouseEvent so we don't do it twice.
    private MouseEvent alreadyHandled = null;

    // mousePressed calls handlePopup, which creates the context-sensitive
    // helper menu.
    public final void mousePressed(final MouseEvent e) {

        if (alreadyHandled == e) {
            return;
        }

        handlePopup(e);

        alreadyHandled = e;
    }

    // mouseReleased calls handlePopup, which creates the context-sensitive
    // helper menu.
    public final void mouseReleased(final MouseEvent e) {

        if (alreadyHandled == e) {
            return;
        }

        handlePopup(e);

        alreadyHandled = e;
    }

    // based on the table or column right-clicked on, create some helper
    // actions for common sql statements
    public final void handlePopup(MouseEvent e) {

        //System.out.println("Handle popup");
        // if this is not a mouse action for popups then do nothing and return
        if (!e.isPopupTrigger()) {
            return;
        }

        // make sure the source of this mouse event was from the tree
        Object source = e.getSource();

        if (!(source instanceof JTree)) {
            return;
        }

        JTree    tree     = (JTree) source;
        TreePath treePath = tree.getPathForLocation(e.getX(), e.getY());

        // if we couldn't find a tree path that corresponds to the
        // right-click, then return
        if (treePath == null) {
            return;
        }

        // create the popup and menus
        JPopupMenu popup = new JPopupMenu();
        JMenuItem  menuItem;
        String     menus[] = new String[] {
            "Select", "Delete", "Update", "Insert"
        };

        // loop throught the menus we want to create, making a PopupListener
        // for each one
        for (int i = 0; i < menus.length; i++) {
            PopupListener popupListener = new PopupListener(menus[i],
                treePath);
            String title = popupListener.toString();

            if (title == null) {
                return;
            }

            // Some of the menu names can be quite long (especially insert).
            // If it's too long, abbreviate it
            if (title.length() > 40) {
                title = title.substring(0, 40) + "...";
            }

            menuItem = new JMenuItem(title);

            menuItem.addActionListener(popupListener);
            popup.add(menuItem);
        }

        popup.show(e.getComponent(), e.getX(), e.getY());
    }

    // handles the creation of the command when a popup is triggered
    private class PopupListener implements ActionListener {

        // used to identify depth while right clicking in tree.
        public static final int DEPTH_URL    = 1;
        public static final int DEPTH_TABLE  = 2;
        public static final int DEPTH_COLUMN = 3;
        String                  command;
        TreePath                treePath;
        TreePath                tablePath;
        TreePath                columnPath;
        String                  table  = null;
        String                  column = null;

        PopupListener(String command, TreePath treePath) {

            super();

            this.command  = command;
            this.treePath = treePath;
        }

        // when the popup is triggered, create a command string and set it in
        // the txtCommand buffer
        public void actionPerformed(ActionEvent ae) {
            txtCommand.setText(getCommandString());
        }

        // text to display when added to a menu
        public String toString() {
            return getCommandString();
        }

        //
        public String getCommandString() {

            // if we are at TABLE depth, set tablePath and table for use later
            if (treePath.getPathCount() == DEPTH_TABLE) {
                tablePath = treePath;
                table = treePath.getPathComponent(DEPTH_TABLE - 1).toString();
            }

            // if we are at TABLE depth, set columnPath, column, tablePath and
            // table for use later
            if (treePath.getPathCount() == DEPTH_COLUMN) {
                tablePath  = treePath.getParentPath();
                table = treePath.getPathComponent(DEPTH_TABLE - 1).toString();
                columnPath = treePath;
                column = treePath.getPathComponent(DEPTH_COLUMN
                                                   - 1).toString();
            }

            // handle command "SELECT".  Use table and column if set.
            if (command.toUpperCase().equals("SELECT")) {
                String result = "SELECT * FROM " + quoteTableName(table);

                if (column != null) {
                    DefaultMutableTreeNode childNode =
                        (DefaultMutableTreeNode) treePath
                            .getLastPathComponent();
                    String  childName = null;
                    boolean isChar;

                    if (childNode.getChildCount() > 0) {
                        childName = childNode.getFirstChild().toString();
                        isChar    = childName.indexOf("CHAR") >= 0;
                        result    += " WHERE " + quoteObjectName(column);

                        if (isChar) {
                            result += " LIKE \'%%\'";
                        } else {
                            result += " = ";
                        }
                    }
                }

                return result;
            }

            // handle command "UPDATE".  Use table and column if set.
            else if (command.toUpperCase().equals("UPDATE")) {
                String result = "UPDATE " + quoteTableName(table) + " SET ";

                if (column != null) {
                    result += quoteObjectName(column) + " = ";
                }

                return result;
            }

            // handle command "DELETE".  Use table and column if set.
            else if (command.toUpperCase().equals("DELETE")) {
                String result = "DELETE FROM " + quoteTableName(table);

                if (column != null) {
                    DefaultMutableTreeNode childNode =
                        (DefaultMutableTreeNode) treePath
                            .getLastPathComponent();
                    String  childName = null;
                    boolean isChar;

                    if (childNode.getChildCount() > 0) {
                        childName = childNode.getFirstChild().toString();
                        isChar    = childName.indexOf("CHAR") >= 0;
                        result    += " WHERE " + quoteObjectName(column);

                        if (isChar) {
                            result += " LIKE \'%%\'";
                        } else {
                            result += " = ";
                        }
                    }
                }

                return result;
            }

            // handle command "INSERT".  Use table and column if set.
            else if (command.toUpperCase().equals("INSERT")) {
                TreeNode    tableNode;
                Enumeration enumer;
                String      columns = "";
                String      values  = " ";
                String      comma   = "";
                String      quote   = "";

                // build a string that includes all the columns that need to
                // be added, with a parenthesied list of commas, suitable for
                // inserting values into.
                if (tablePath == null) {
                    return null;
                }

                tableNode = (TreeNode) tablePath.getLastPathComponent();
                enumer    = tableNode.children();

                while (enumer.hasMoreElements()) {
                    Object o = enumer.nextElement();

                    if (o.toString().equals("Indices")) {
                        continue;
                    }

                    DefaultMutableTreeNode childNode =
                        (DefaultMutableTreeNode) o;
                    String childName = null;

                    if (childNode.getChildCount() == 0) {
                        continue;
                    } else {
                        childName = childNode.getFirstChild().toString();
                    }

                    // If our first child (type) is some sort of char, use ''
                    // in the string.  Makes is more obvious to the user when
                    // they need to use a string
                    if (childName.indexOf("CHAR") >= 0) {
                        quote = "\'\'";
                    } else {
                        quote = "";
                    }

                    columns += comma + quoteObjectName(o.toString());
                    values  += comma + quote;
                    comma   = ", ";
                }

                return "INSERT INTO " + quoteTableName(table) + "\n( "
                       + columns + " )\nVALUES (" + values + ")";
            } else {
                return "Got here in error " + command
                       + ".  Should never happen";
            }
        }
    }

    /**
     * Perform a limited check (inconclusive) and quote object name if required.
     * Gives wrong result if a quoted name contains a dot.
     */
    private String quoteTableName(String name) {

        int dot = name.indexOf(".");

        if (dot < 0) {
            return quoteObjectName(name);
        }

        String partOne = name.substring(0, dot);
        String partTwo = name.substring(dot + 1);

        return quoteObjectName(partOne) + '.' + quoteObjectName(partTwo);
    }

    /**
     * perform a limited check (inconclusive) and quote object name if required
     */
    private String quoteObjectName(String name) {

        if (name.toUpperCase().equals(name) && name.indexOf(' ') < 0) {
            return name;
        }

        return "\"" + name + "\"";
    }

    private void initGUI() {

        JPanel pCommand = new JPanel();

        pResult = new JPanel();
        nsSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, pCommand,
                                     pResult);

        // Added: (weconsultants@users)
        nsSplitPane.setOneTouchExpandable(true);
        pCommand.setLayout(new BorderLayout());
        pResult.setLayout(new BorderLayout());

        Font fFont = new Font("Dialog", Font.PLAIN, 12);

        txtCommand = new JTextArea(5, 40);

        txtCommand.setMargin(new Insets(5, 5, 5, 5));
        txtCommand.addKeyListener(this);

        txtCommandScroll = new JScrollPane(txtCommand);
        txtResult        = new JTextArea(20, 40);

        txtResult.setMargin(new Insets(5, 5, 5, 5));

        txtResultScroll = new JScrollPane(txtResult);

        txtCommand.setFont(fFont);
        txtResult.setFont(new Font("Courier", Font.PLAIN, 12));
        pCommand.add(txtCommandScroll, BorderLayout.CENTER);

        gResult = new GridSwing();

        TableSorter sorter = new TableSorter(gResult);

        tableModel   = sorter;
        gResultTable = new JTable(sorter);

        sorter.setTableHeader(gResultTable.getTableHeader());

        gScrollPane = new JScrollPane(gResultTable);

        gResultTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        gResult.setJTable(gResultTable);

        //getContentPane().setLayout(new BorderLayout());
        pResult.add(gScrollPane, BorderLayout.CENTER);

        // Set up the tree
        rootNode    = new DefaultMutableTreeNode("Connection");
        treeModel   = new DefaultTreeModel(rootNode);
        tTree       = new JTree(treeModel);
        tScrollPane = new JScrollPane(tTree);

        // System.out.println("Adding mouse listener");
        tTree.addMouseListener(this);
        tScrollPane.setPreferredSize(new Dimension(120, 400));
        tScrollPane.setMinimumSize(new Dimension(70, 100));
        txtCommandScroll.setPreferredSize(new Dimension(360, 100));
        txtCommandScroll.setMinimumSize(new Dimension(180, 100));
        gScrollPane.setPreferredSize(new Dimension(460, 300));

        ewSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, tScrollPane,
                                     nsSplitPane);

        // Added: (weconsultants@users)
        ewSplitPane.setOneTouchExpandable(true);
        fMain.getContentPane().add(ewSplitPane, BorderLayout.CENTER);

        // Added: (weconsultants@users)
        jStatusLine = new JLabel();
        iReadyStatus =
            new JButton(new ImageIcon(CommonSwing.getIcon("StatusReady")));

        iReadyStatus.setSelectedIcon(
            new ImageIcon(CommonSwing.getIcon("StatusRunning")));

        pStatus = new JPanel();

        pStatus.setLayout(new BorderLayout());
        pStatus.add(iReadyStatus, BorderLayout.WEST);
        pStatus.add(jStatusLine, BorderLayout.CENTER);
        fMain.getContentPane().add(pStatus, "South");
        doLayout();

        if (fMain instanceof java.awt.Window) {
            ((java.awt.Window) fMain).pack();
        } else {
            ((Container) fMain).validate();
        }
    }

    /* Simple tree node factory method - set's parent and user object.
     */
    private DefaultMutableTreeNode makeNode(Object userObject,
            MutableTreeNode parent) {

        DefaultMutableTreeNode node = new DefaultMutableTreeNode(userObject);

        if (parent != null) {
            treeModel.insertNodeInto(node, parent, parent.getChildCount());
        }

        return node;
    }

    private static final String[] usertables       = {
        "TABLE", "GLOBAL TEMPORARY", "VIEW", "SYSTEM TABLE"
    };
    private static final String[] nonSystables     = {
        "TABLE", "GLOBAL TEMPORARY", "VIEW"
    };
    private static final HashSet  oracleSysUsers   = new HashSet();
    private static final String[] oracleSysSchemas = {
        "SYS", "SYSTEM", "OUTLN", "DBSNMP", "OUTLN", "MDSYS", "ORDSYS",
        "ORDPLUGINS", "CTXSYS", "DSSYS", "PERFSTAT", "WKPROXY", "WKSYS",
        "WMSYS", "XDB", "ANONYMOUS", "ODM", "ODM_MTR", "OLAPSYS", "TRACESVR",
        "REPADMIN"
    };

    static {
        for (int i = 0; i < oracleSysSchemas.length; i++) {
            oracleSysUsers.add(oracleSysSchemas[i]);
        }
    }

    /**
     * Schedules to run in a Gui-safe thread
     */
    protected void refreshTree() {
        backgroundIt(treeRefreshRunnable, "Refreshing object tree");
    }

    /**
     * Clear all existing nodes from the tree model and rebuild from scratch.
     *
     * This method executes in current thread
     */
    protected void directRefreshTree() {

        int[]                  rowCounts;
        DefaultMutableTreeNode propertiesNode;

        // Added: (weconsultants@users) Moved tableNode here for visibiity nd new DECFM
        DefaultMutableTreeNode tableNode;
        DecimalFormat DECFMT = new DecimalFormat(" ( ####,###,####,##0 )");

        // First clear the existing tree by simply enumerating
        // over the root node's children and removing them one by one.
        while (treeModel.getChildCount(rootNode) > 0) {
            DefaultMutableTreeNode child =
                (DefaultMutableTreeNode) treeModel.getChild(rootNode, 0);

            treeModel.removeNodeFromParent(child);
            child.removeAllChildren();
            child.removeFromParent();
        }

        treeModel.nodeStructureChanged(rootNode);
        treeModel.reload();
        tScrollPane.repaint();

        ResultSet result = null;

        // Now rebuild the tree below its root
        try {

            // Start by naming the root node from its URL:
            rootNode.setUserObject(dMeta.getURL());

            // get metadata about user tables by building a vector of table names
            result = dMeta.getTables(null, null, null, (showSys ? usertables
                                                                : nonSystables));

            Vector tables  = new Vector();
            Vector schemas = new Vector();

            // sqlbob@users Added remarks.
            Vector remarks = new Vector();
            String schema;

            while (result.next()) {
                schema = result.getString(2);

                if ((!showSys) && isOracle
                        && oracleSysUsers.contains(schema)) {
                    continue;
                }

                if (schemaFilter == null || schema.equals(schemaFilter)) {
                    schemas.addElement(schema);
                    tables.addElement(result.getString(3));
                    remarks.addElement(result.getString(5));

                    continue;
                }
            }

            result.close();

            result = null;

            // Added: (weconsultants@users)
            // Sort not to go into production. Have to sync with 'remarks Vector' for DBMS that has it
            //   Collections.sort(tables);
            // Added: (weconsultants@users) - Add rowCounts if needed.
            rowCounts = new int[tables.size()];

            try {
                rowCounts = getRowCounts(tables, schemas);
            } catch (Exception e) {

                //  Added: (weconsultants@users)
                CommonSwing.errorMessage(e);
            }

            ResultSet col;

            // For each table, build a tree node with interesting info
            for (int i = 0; i < tables.size(); i++) {
                col = null;

                String name;

                try {
                    name = (String) tables.elementAt(i);

                    if (isOracle && name.startsWith("BIN$")) {
                        continue;

                        // Oracle Recyle Bin tables.
                        // Contains metacharacters which screw up metadata
                        // queries below.
                    }

                    schema = (String) schemas.elementAt(i);

                    String schemaname = "";

                    if (schema != null && showSchemas) {
                        schemaname = schema + '.';
                    }

                    String rowcount = displayRowCounts
                                      ? (" " + DECFMT.format(rowCounts[i]))
                                      : "";
                    String displayedName = schemaname + name + rowcount;

                    // weconsul@ptd.net Add rowCounts if needed.
                    tableNode = makeNode(displayedName, rootNode);
                    col       = dMeta.getColumns(null, schema, name, null);

                    if ((schema != null) && !schema.trim().equals("")) {
                        makeNode(schema, tableNode);
                    }

                    // sqlbob@users Added remarks.
                    String remark = (String) remarks.elementAt(i);

                    if ((remark != null) && !remark.trim().equals("")) {
                        makeNode(remark, tableNode);
                    }

                    // This block is very slow for some Oracle tables.
                    // With a child for each column containing pertinent attributes
                    while (col.next()) {
                        String c = col.getString(4);
                        DefaultMutableTreeNode columnNode = makeNode(c,
                            tableNode);
                        String type = col.getString(6);

                        makeNode("Type: " + type, columnNode);

                        boolean nullable = col.getInt(11)
                                           != DatabaseMetaData.columnNoNulls;

                        makeNode("Nullable: " + nullable, columnNode);
                    }
                } finally {
                    if (col != null) {
                        try {
                            col.close();
                        } catch (SQLException se) {}
                    }
                }

                DefaultMutableTreeNode indexesNode = makeNode("Indices",
                    tableNode);

                if (showIndexDetails) {
                    ResultSet ind = null;

                    try {
                        ind = dMeta.getIndexInfo(null, schema, name, false,
                                                 false);

                        String                 oldiname  = null;
                        DefaultMutableTreeNode indexNode = null;

                        // A child node to contain each index - and its attributes
                        while (ind.next()) {
                            boolean nonunique = ind.getBoolean(4);
                            String  iname     = ind.getString(6);

                            if ((oldiname == null
                                    || !oldiname.equals(iname))) {
                                indexNode = makeNode(iname, indexesNode);

                                makeNode("Unique: " + !nonunique, indexNode);

                                oldiname = iname;
                            }

                            // And the ordered column list for index components
                            makeNode(ind.getString(9), indexNode);
                        }
                    } catch (SQLException se) {

                        // Workaround for Oracle
                        if (se.getMessage() == null || ((!se.getMessage()
                                .startsWith("ORA-25191:")) && (!se.getMessage()
                                .startsWith("ORA-01702:")) && !se.getMessage()
                                    .startsWith("ORA-01031:"))) {
                            throw se;
                        }
                    } finally {
                        if (ind != null) {
                            ind.close();

                            ind = null;
                        }
                    }
                }
            }

            // Finally - a little additional metadata on this connection
            propertiesNode = makeNode("Properties", rootNode);

            makeNode("User: " + dMeta.getUserName(), propertiesNode);
            makeNode("ReadOnly: " + cConn.isReadOnly(), propertiesNode);
            makeNode("AutoCommit: " + cConn.getAutoCommit(), propertiesNode);
            makeNode("Driver: " + dMeta.getDriverName(), propertiesNode);
            makeNode("Product: " + dMeta.getDatabaseProductName(),
                     propertiesNode);
            makeNode("Version: " + dMeta.getDatabaseProductVersion(),
                     propertiesNode);
        } catch (SQLException se) {
            propertiesNode = makeNode("Error getting metadata:", rootNode);

            makeNode(se.getMessage(), propertiesNode);
            makeNode(se.getSQLState(), propertiesNode);
            CommonSwing.errorMessage(se);
        } finally {
            if (result != null) {
                try {
                    result.close();
                } catch (SQLException se) {}
            }
        }

        treeModel.nodeStructureChanged(rootNode);
        treeModel.reload();
        tScrollPane.repaint();

        // We want the Schema List to always be in sync with the displayed tree
        updateSchemaList();
    }

    // Added: (weconsultants@users) Sets up\changes the running status icon
    void setStatusLine(String busyBaseString, int rowCount) {

        iReadyStatus.setSelected(busyBaseString != null);

        if (busyBaseString == null) {
            String additionalMsg = "";

            if (schemaFilter != null) {
                additionalMsg = " /  Tree showing objects in schema '"
                                + schemaFilter + "'";
            }

            if (rowCount > 1) {
                additionalMsg += " / " + rowCount + " rows retrieved";
            }

            jStatusLine.setText("  " + READY_STATUS + additionalMsg);
        } else {
            jStatusLine.setText("  " + busyBaseString + "...");
        }
    }

    // Added: (weconsultants@users) Needed to aggragate counts per table in jTree
    protected int[] getRowCounts(Vector inTable,
                                 Vector inSchema) throws Exception {

        if (!displayRowCounts) {
            return (null);
        }

        String rowCountSelect = "SELECT COUNT(*) FROM ";
        int[]  counts;
        String name;

        counts = new int[inTable.size()];

        try {
            Statement select = rowConn.createStatement();

            for (int i = 0; i < inTable.size(); i++) {
                try {
                    String schemaPart = (String) inSchema.elementAt(i);

                    schemaPart = schemaPart == null ? ""
                                                    : (schemaPart + '.');
                    name       = schemaPart + (String) inTable.elementAt(i);

                    ResultSet resultSet = select.executeQuery(rowCountSelect
                        + name);

                    while (resultSet.next()) {
                        counts[i] = resultSet.getInt(1);
                    }
                } catch (Exception e) {
                    System.err.println("Unable to get row count for table "
                                       + inSchema.elementAt(i) + '.'
                                       + inTable.elementAt(i)
                                       + ".  Using value '0': " + e);
                }
            }
        } catch (Exception e) {
            CommonSwing.errorMessage(e);
        }

        return (counts);
    }

    protected JToolBar createToolBar() {

        // Build jtoolbar and jtoolbar Buttons
        JToolBar jtoolbar = new JToolBar();

        jtoolbar.putClientProperty("JToolBar.isRollover", Boolean.TRUE);

        // I'm dropping "Statement" from  "Execute SQL Statement", etc.,
        // because it may or may not be "one statement", but it is SQL.
        // Build jbuttonClear Buttons - blaine
        jbuttonClear =
            new JButton("Clear SQL",
                        new ImageIcon(CommonSwing.getIcon("Clear")));

        jbuttonClear.putClientProperty("is3DEnabled", Boolean.TRUE);
        tipMap.put(jbuttonClear, "Clear SQL");
        jbuttonClear.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent actionevent) {

                if (sqlScriptBuffer == null
                        && txtCommand.getText().length() < 1) {
                    CommonSwing.errorMessage("No SQL to clear");

                    return;
                }

                clear();
            }
        });

        jbuttonExecute =
            new JButton("Execute SQL",
                        new ImageIcon(CommonSwing.getIcon("Execute")));

        tipMap.put(jbuttonExecute, "Execute SQL");
        jbuttonExecute.putClientProperty("is3DEnabled", Boolean.TRUE);
        jbuttonExecute.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent actionevent) {
                executeCurrentSQL();
            }
        });
        jtoolbar.addSeparator();
        jtoolbar.add(jbuttonClear);
        jtoolbar.addSeparator();
        jtoolbar.add(jbuttonExecute);
        jtoolbar.addSeparator();
        jbuttonClear.setAlignmentY(0.5F);
        jbuttonClear.setAlignmentX(0.5F);
        jbuttonExecute.setAlignmentY(0.5F);
        jbuttonExecute.setAlignmentX(0.5F);

        return jtoolbar;
    }

    void updateAutoCommitBox() {

        try {
            boxAutoCommit.setSelected(cConn.getAutoCommit());
        } catch (SQLException se) {
            CommonSwing.errorMessage(se);
        }
    }

    private void setLF(String newLAF) {

        if (currentLAF != null && currentLAF == newLAF) {    // No change
            return;
        }

        if (pResult != null && gridFormat) {
            pResult.removeAll();
        }

        CommonSwing.setSwingLAF((Component) fMain, newLAF);

        if (pResult != null && gridFormat) {
            setResultsInGrid();
        }

        currentLAF = newLAF;

        if (currentLAF.equals(CommonSwing.Native)) {
            rbNativeLF.setSelected(true);
        } else if (currentLAF.equals(CommonSwing.Java)) {
            rbJavaLF.setSelected(true);
        } else if (currentLAF.equals(CommonSwing.Motif)) {
            rbMotifLF.setSelected(true);
        }
    }

    void resetTooltips() {

        Iterator   it = tipMap.keySet().iterator();
        JComponent component;

        while (it.hasNext()) {
            component = (JComponent) it.next();

            component.setToolTipText(showTooltips
                                     ? ((String) tipMap.get(component))
                                     : (String) null);
        }
    }

    private void updateSchemaList() {

        ButtonGroup group  = new ButtonGroup();
        ArrayList   list   = new ArrayList();
        ResultSet   result = null;

        try {
            result = dMeta.getSchemas();

            if (result == null) {
                throw new SQLException("Failed to get metadata from database");
            }

            while (result.next()) {
                list.add(result.getString(1));
            }
        } catch (SQLException se) {
            CommonSwing.errorMessage(se);
        } finally {
            if (result != null) {
                try {
                    result.close();
                } catch (SQLException se) {}
            }
        }

        mnuSchemas.removeAll();
        rbAllSchemas.setSelected(schemaFilter == null);
        group.add(rbAllSchemas);
        mnuSchemas.add(rbAllSchemas);

        String               s;
        JRadioButtonMenuItem radioButton;

        for (int i = 0; i < list.size(); i++) {
            s           = (String) list.get(i);
            radioButton = new JRadioButtonMenuItem(s);

            group.add(radioButton);
            mnuSchemas.add(radioButton);
            radioButton.setSelected(schemaFilter != null
                                    && schemaFilter.equals(s));
            radioButton.addActionListener(schemaListListener);
            radioButton.setEnabled(list.size() > 1);
        }

        mnuSchemas.addSeparator();
        mnuSchemas.add(mitemUpdateSchemas);
    }

    ActionListener schemaListListener = (new ActionListener() {

        public void actionPerformed(ActionEvent actionevent) {

            schemaFilter = actionevent.getActionCommand();

            if (schemaFilter.equals("*")) {
                schemaFilter = null;
            }

            refreshTree();
        }
    });

    /**
     * Persisted User Preferences for DatabaseManagerSwing.
     *
     * These are settings for items in the View and Options pulldown menus,
     * plus Help/Show Tooltips.
     */
    public class DBMPrefs {

        public File prefsFile = null;

        /**
         * The constructor guarantees that this will be null for Applet,
         *  non-null if using a local preferences file
         */

        // Set defaults from Data
        boolean autoRefresh   = true;
        boolean showRowCounts = false;
        boolean showSysTables = false;
        boolean showSchemas   = true;
        boolean resultGrid    = true;
        String  laf           = CommonSwing.Native;

        // Somebody with more time can store the font settings.  IMO, that
        // menu item shouldn't even be there if the settings aren't persisted.
        boolean showTooltips = true;

        public DBMPrefs(boolean isApplet) throws IOException {

            if (isApplet) {}
            else {
                if (homedir == null) {
                    throw new IOException(
                        "Skipping preferences since do not know home dir");
                }

                prefsFile = new File(homedir, "dbmprefs.properties");
            }

            load();
        }

        public void load() throws IOException {

            String tmpString;

            if (prefsFile == null) {

                // LOAD PREFERENCES FROM APPLET PARAMS
                tmpString = getParameter("autoRefresh");

                if (tmpString != null) {
                    autoRefresh = Boolean.valueOf(tmpString).booleanValue();
                }

                tmpString = getParameter("showRowCounts");

                if (tmpString != null) {
                    showRowCounts = Boolean.valueOf(tmpString).booleanValue();
                }

                tmpString = getParameter("showSysTables");

                if (tmpString != null) {
                    showSysTables = Boolean.valueOf(tmpString).booleanValue();
                }

                tmpString = getParameter("showSchemas");

                if (tmpString != null) {
                    showSchemas = Boolean.valueOf(tmpString).booleanValue();
                }

                tmpString = getParameter("resultGrid");

                if (tmpString != null) {
                    resultGrid = Boolean.valueOf(tmpString).booleanValue();
                }

                tmpString = getParameter("laf");
                laf       = ((tmpString == null) ? CommonSwing.Native
                                                 : tmpString);
                tmpString = getParameter("showTooltips");

                if (tmpString != null) {
                    showTooltips = Boolean.valueOf(tmpString).booleanValue();
                }
            } else {

                // LOAD PREFERENCES FROM LOCAL PREFERENCES FILE
                if (!prefsFile.exists()) {
                    throw new IOException("No such file: " + prefsFile);
                }

                Properties props = new Properties();

                try {
                    FileInputStream fis = new FileInputStream(prefsFile);

                    props.load(fis);
                    fis.close();
                } catch (IOException ioe) {
                    throw new IOException("Failed to read preferences file '"
                                          + prefsFile + "':  "
                                          + ioe.getMessage());
                }

                tmpString = props.getProperty("autoRefresh");

                if (tmpString != null) {
                    autoRefresh = Boolean.valueOf(tmpString).booleanValue();
                }

                tmpString = props.getProperty("showRowCounts");

                if (tmpString != null) {
                    showRowCounts = Boolean.valueOf(tmpString).booleanValue();
                }

                tmpString = props.getProperty("showSysTables");

                if (tmpString != null) {
                    showSysTables = Boolean.valueOf(tmpString).booleanValue();
                }

                tmpString = props.getProperty("showSchemas");

                if (tmpString != null) {
                    showSchemas = Boolean.valueOf(tmpString).booleanValue();
                }

                tmpString = props.getProperty("resultGrid");

                if (tmpString != null) {
                    resultGrid = Boolean.valueOf(tmpString).booleanValue();
                }

                tmpString = props.getProperty("laf");
                laf       = ((tmpString == null) ? CommonSwing.Native
                                                 : tmpString);
                tmpString = props.getProperty("showTooltips");

                if (tmpString != null) {
                    showTooltips = Boolean.valueOf(tmpString).booleanValue();
                }
            }
        }

        public void store() {

            if (prefsFile == null) {

                // Can't persist Applet settings.
                return;
            }

            Properties props = new Properties();

            // Boolean.toString(boolean) was new with Java 1.4, so don't use that.
            props.setProperty("autoRefresh", (autoRefresh ? tString
                                                          : fString));
            props.setProperty("showRowCounts", (showRowCounts ? tString
                                                              : fString));
            props.setProperty("showSysTables", (showSysTables ? tString
                                                              : fString));
            props.setProperty("showSchemas", (showSchemas ? tString
                                                          : fString));
            props.setProperty("resultGrid", (resultGrid ? tString
                                                        : fString));
            props.setProperty("laf", laf);
            props.setProperty("showTooltips", (showTooltips ? tString
                                                            : fString));

            try {
                FileOutputStream fos = new FileOutputStream(prefsFile);

                props.store(fos, "DatabaseManagerSwing user preferences");
                fos.flush();
                fos.close();
            } catch (IOException ioe) {
                throw new RuntimeException(
                    "Failed to prepare preferences file '" + prefsFile
                    + "':  " + ioe.getMessage());
            }
        }
    }

    private static final String tString = Boolean.TRUE.toString();
    private static final String fString = Boolean.FALSE.toString();
}

Other HSQLDB examples (source code examples)

Here is a short list of links related to this HSQLDB DatabaseManagerSwing.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.