| /* |
| * 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: 3529 $" |
| + (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: 3529 $ 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("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(); |
| } |