All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hsqldb.util.DatabaseManagerSwing Maven / Gradle / Ivy

There is a newer version: 2.7.2
Show newest version
/* Copyright (c) 2001-2019, 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.
 */


package org.hsqldb.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
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.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
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.InputEvent;
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.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
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;

// 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
// fredt@users - version 2.50 - removed deprecated

/**
 * Swing Tool for managing a JDBC database.
 * 
 * {@code
 *             Usage: java DatabaseManagerSwing [--options]
 *             where options include:
 *              --driver   jdbc driver class
 *              --url           jdbc url
 *              --user          username used for connection
 *              --password  password for this user
 *              --dir           default directory
 *              --script        reads from script file
 *              --urlid        get connection info from RC file
 *              --rcfile        use instead of default (with urlid)
 *              --noexit              Don't exit JVM
 * }
 * 
* * Note that the sys-table switch will not work for Oracle, because Oracle * does not categorize their system tables correctly in the JDBC Metadata. * * @author dmarshall@users * @author Bob Preston (sqlbob@users dot sourceforge.net) * @version 2.5.0 * @since 1.7.0 */ public class DatabaseManagerSwing extends JFrame 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 { homedir = System.getProperty("user.home"); } 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: 5987 $" + (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: 5987 $ of DatabaseManagerSwing\n\n" + "Copyright (c) 2001-2019, 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 = localActionList.get(i); btn.setEnabled(false); } Connection c = null; boolean auto = false; 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); } } /** * 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 currentArg; String lowerArg; String urlid = null; String rcFile = null; boolean autoConnect = false; boolean urlidConnect = false; bMustExit = true; for (int i = 0; i < arg.length; i++) { currentArg = arg[i]; lowerArg = arg[i].toLowerCase(); if (lowerArg.startsWith("--")) { lowerArg = lowerArg.substring(1); } if (lowerArg.equals("-noexit") || lowerArg.equals("-help")) { // } else if (i == arg.length - 1) { throw new IllegalArgumentException("No value for argument " + currentArg); } 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( "invalid argrument " + currentArg + " 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("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(); } 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 jdbc driver class\n" + " --url jdbc url\n" + " --user username used for connection\n" + " --password password for this user\n" + " --urlid use url/user/password/driver in rc file\n" + " --rcfile (defaults to 'dbmanager.rc' in home dir)\n" + " --dir default directory\n" + " --script 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) { bMustExit = b; } private DBMPrefs prefs = null; public void main() { JMenu jmenu; JMenuItem mitem; try { prefs = new DBMPrefs(false); } 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, InputEvent.CTRL_DOWN_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 JFrame) { ((JFrame) fMain).setJMenuBar(bar); } initGUI(); sRecent = new String[iMaxRecent]; // Modified: (weconsultants@users)Mode code to CommonSwing for general use 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, InputEvent.CTRL_DOWN_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)) { 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"); Thread t = buttonUpdaterThread; if (t != null) { t.setContextClassLoader(null); } 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.nanoTime(); sql = ((sqlScriptBuffer == null ? txtCommand.getText() : sqlScriptBuffer)); if (sStatement == null) { g[0] = "no connection"; gResult.setHead(g); return; } sStatement.execute(sql); lTime = System.nanoTime() - lTime; 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); } if (sqlScriptBuffer == null) { addToRecent(sql); txtCommand.setEnabled(true); // clear() does this otherwise } else { clear(); } } catch (SQLException e) { lTime = System.nanoTime() - 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(); StringBuilder b = new StringBuilder(); long total = 0; lTime = 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.nanoTime() - 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.nanoTime() - lTime; } private void showResultInText() { Object[] col = gResult.getHead(); int width = col.length; int[] size = new int[width]; ArrayList 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 = data.get(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; } } } StringBuilder b = new StringBuilder(); 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 = data.get(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() { int treeDepth = treePath.getPathCount(); // if we are at TABLE depth, set tablePath and table for use later if (treeDepth == DEPTH_URL) { return ""; } if (treeDepth == 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 (treeDepth == 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) { int bracket = name.indexOf(" ("); if (bracket >= 0) { name = name.substring(0, bracket); } return quoteObjectName(name); } String partOne = name.substring(0, dot); String partTwo = name.substring(dot + 1); int bracket = partTwo.indexOf(" ("); if (bracket >= 0) { partTwo = partTwo.substring(0, bracket); } 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(7, 40); txtCommand.setMargin(new Insets(5, 5, 5, 5)); txtCommand.addKeyListener(this); txtCommandScroll = new JScrollPane(txtCommand); txtResult = new JTextArea(25, 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(200, 400)); tScrollPane.setMinimumSize(new Dimension(70, 100)); txtCommandScroll.setPreferredSize(new Dimension(560, 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)); ArrayList tables = new ArrayList(); ArrayList schemas = new ArrayList(); // sqlbob@users Added remarks. ArrayList remarks = new ArrayList(); String schema; while (result.next()) { schema = result.getString(2); if ((!showSys) && isOracle && oracleSysUsers.contains(schema)) { continue; } if (schemaFilter == null || schema.equals(schemaFilter)) { schemas.add(schema); tables.add(result.getString(3)); remarks.add(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 = tables.get(i); if (isOracle && name.startsWith("BIN$")) { continue; // Oracle Recyle Bin tables. // Contains metacharacters which screw up metadata // queries below. } schema = schemas.get(i); String schemaname = ""; if (schema != null && showSchemas) { schemaname = schema + '.'; } String rowcount = displayRowCounts ? (DECFMT.format(rowCounts[i])) : ""; String displayedName = schemaname + name + rowcount; // [email protected] 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 = remarks.get(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) { long millis = lTime / 1000000; long fraction = (lTime % 1000000) / 100000; additionalMsg += " / " + rowCount + " rows retrieved in " + millis + '.' + fraction + " ms"; } jStatusLine.setText(" " + READY_STATUS + additionalMsg); } else { jStatusLine.setText(" " + busyBaseString + "..."); } } // Added: (weconsultants@users) Needed to aggragate counts per table in jTree protected int[] getRowCounts(ArrayList inTable, ArrayList 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.get(i); schemaPart = schemaPart == null ? "" : ("\"" + schemaPart + "\".\""); name = schemaPart + inTable.get(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.get(i) + '.' + inTable.get(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 { if (cConn != null) { 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 ? tipMap.get(component) : 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 = 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) { } 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 void setLogToSystem(boolean value) { try { PrintWriter newPrintWriter = (value) ? new PrintWriter(System.out) : null; DriverManager.setLogWriter(newPrintWriter); } catch (Exception e) {} } private static final String tString = Boolean.TRUE.toString(); private static final String fString = Boolean.FALSE.toString(); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy