1 /* Copyright (c) 2001-2011, The HSQL Development Group
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of the HSQL Development Group nor the names of its
15  * contributors may be used to endorse or promote products derived from this
16  * software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
22  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 
32 package org.hsqldb.util;
33 
34 import java.io.File;
35 import java.io.FileInputStream;
36 import java.io.FileOutputStream;
37 import java.io.IOException;
38 import java.lang.reflect.Constructor;
39 import java.lang.reflect.InvocationTargetException;
40 import java.security.AccessControlException;
41 import java.sql.Connection;
42 import java.sql.DatabaseMetaData;
43 import java.sql.Driver;
44 import java.sql.DriverManager;
45 import java.sql.ResultSet;
46 import java.sql.ResultSetMetaData;
47 import java.sql.SQLException;
48 import java.sql.Statement;
49 import java.text.DecimalFormat;
50 import java.util.ArrayList;
51 import java.util.Enumeration;
52 import java.util.HashMap;
53 import java.util.HashSet;
54 import java.util.Hashtable;
55 import java.util.Iterator;
56 import java.util.Locale;
57 import java.util.Properties;
58 import java.util.Vector;
59 
60 import java.awt.BorderLayout;
61 import java.awt.Component;
62 import java.awt.Container;
63 import java.awt.Cursor;
64 import java.awt.Dimension;
65 import java.awt.Event;
66 import java.awt.Font;
67 import java.awt.Insets;
68 import java.awt.Toolkit;
69 import java.awt.event.ActionEvent;
70 import java.awt.event.ActionListener;
71 import java.awt.event.KeyEvent;
72 import java.awt.event.KeyListener;
73 import java.awt.event.MouseEvent;
74 import java.awt.event.MouseListener;
75 import java.awt.event.WindowEvent;
76 import java.awt.event.WindowListener;
77 import javax.swing.ButtonGroup;
78 import javax.swing.ImageIcon;
79 import javax.swing.JApplet;
80 import javax.swing.JButton;
81 import javax.swing.JCheckBoxMenuItem;
82 import javax.swing.JComponent;
83 import javax.swing.JFileChooser;
84 import javax.swing.JFrame;
85 import javax.swing.JLabel;
86 import javax.swing.JMenu;
87 import javax.swing.JMenuBar;
88 import javax.swing.JMenuItem;
89 import javax.swing.JOptionPane;
90 import javax.swing.JPanel;
91 import javax.swing.JPopupMenu;
92 import javax.swing.JRadioButtonMenuItem;
93 import javax.swing.JScrollPane;
94 import javax.swing.JSplitPane;
95 import javax.swing.JTable;
96 import javax.swing.JTextArea;
97 import javax.swing.JToolBar;
98 import javax.swing.JTree;
99 import javax.swing.KeyStroke;
100 import javax.swing.RootPaneContainer;
101 import javax.swing.SwingUtilities;
102 import javax.swing.table.TableModel;
103 import javax.swing.tree.DefaultMutableTreeNode;
104 import javax.swing.tree.DefaultTreeModel;
105 import javax.swing.tree.MutableTreeNode;
106 import javax.swing.tree.TreeNode;
107 import javax.swing.tree.TreePath;
108 
109 import org.hsqldb.lib.RCData;
110 import org.hsqldb.lib.java.JavaSystem;
111 
112 //dmarshall@users - 20020101 - original swing port of DatabaseManager
113 //sqlbob@users 20020401 - patch 537501 by ulrivo - commandline arguments
114 //sqlbob@users 20020407 - patch 1.7.0 - reengineering and enhancements
115 //nickferguson@users 20021005 - patch 1.7.1 - enhancements
116 //deccles@users 2004 - 2008 - bug fixes and enhancements
117 //weconsultants@users 20041109 - version 1.8.0 - reengineering and enhancements:
118 //              Added: Goodies 'Look and Feel'.
119 //              Added: a Font Changer(Font Type\Style).
120 //              Added: a Color Changer (foreground\bckground).
121 //              Added: RowCounts for each JTree table nodes.
122 //              Added: OneTouchExpandable attribute to JSplitPanes.
123 //              Moved: setFramePositon code to a CommonSwing.setFramePositon() Method.
124 //              Added: call to new method to handle exception processing (CommonSwing.errorMessage());
125 //              Added: Added a new pane added at the bottom of the Frame. (Status Icon and StatusLine).
126 //              Added: 2 Methods (setStatusMessage()), one overrides the other. One to change the ruung status
127 //                              another to allow a message to be posted without changing the Status Icon if needed.
128 //              Added: Added a customCursor for the current wait cursor
129 //      Added: Ability to switch the current LAF while runing (Native,Java or Motif)
130 //unsaved@users 2005xxxx - improvements and bug fixes
131 
132 /**
133  * Swing Tool for managing a JDBC database.<p>
134  * <pre>
135  *             Usage: java DatabaseManagerSwing [--options]
136  *             where options include:
137  *              --driver <classname>  jdbc driver class
138  *              --url <name>          jdbc url
139  *              --user <name>         username used for connection
140  *              --password <password> password for this user
141  *              --dir <path>          default directory
142  *              --script <file>       reads from script file
143  *              --urlid <urlid>       get connection info from RC file
144  *              --rcfile <file>       use instead of default (with urlid)
145  *              --noexit              Don't exit JVM
146  * </pre>
147  *
148  * Note that the sys-table switch will not work for Oracle, because Oracle
149  * does not categorize their system tables correctly in the JDBC Metadata.
150  *
151  * @author dmarshall@users
152  * @author Bob Preston (sqlbob@users dot sourceforge.net)
153  * @version 2.3.0
154  * @since 1.7.0
155  */
156 public class DatabaseManagerSwing extends JApplet
157 implements ActionListener, WindowListener, KeyListener, MouseListener {
158 
159     /*
160      * This is down here because it is an  implementation note, not a
161      * Javadoc comment!
162      * Tue Apr 26 16:38:54 EDT 2005
163      * Switched default switch method from "-switch" to "--switch" because
164      * "-switch" usage is ambiguous as used here.  Single switches should
165      * be reserved for single-letter switches which can be mixed like
166      * "-u -r -l" = "-url".  -blaine
167      */
168     private static String homedir  = null;
169     private boolean       isOracle = false;    // Need some workarounds for Oracle
170 
171     static {
172         try {
173             Class c = Class.forName("sun.security.action.GetPropertyAction");
174             Constructor constructor = c.getConstructor(new Class[]{
175                 String.class });
176             java.security.PrivilegedAction a =
177                 (java.security.PrivilegedAction) constructor.newInstance(
178                     new Object[]{ "user.home" });
179 
180             homedir = (String) java.security.AccessController.doPrivileged(a);
181         } catch (IllegalAccessException e) {
182             System.err.println(
183                 "Failed to get home directory.\n"
184                 + "Therefore not retrieving/storing user preferences.\n("
185                 + e.getMessage() + ')');
186         } catch (NoSuchMethodException e) {
187             System.err.println(
188                 "Failed to get home directory.\n"
189                 + "Therefore not retrieving/storing user preferences.\n("
190                 + e.getMessage() + ')');
191         } catch (ClassNotFoundException e) {
192             System.err.println(
193                 "Failed to get home directory.\n"
194                 + "Therefore not retrieving/storing user preferences.\n("
195                 + e.getMessage() + ')');
196         } catch (InstantiationException e) {
197             System.err.println(
198                 "Failed to get home directory.\n"
199                 + "Therefore not retrieving/storing user preferences.\n("
200                 + e.getMessage() + ')');
201         } catch (InvocationTargetException e) {
202             System.err.println(
203                 "Failed to get home directory.\n"
204                 + "Therefore not retrieving/storing user preferences.\n("
205                 + e.getMessage() + ')');
206         } catch (AccessControlException e) {
207             System.err.println(
208                 "Failed to get home directory.\n"
209                 + "Therefore not retrieving/storing user preferences.\n("
210                 + e.getMessage() + ')');
211         }
212     }
213 
214     ArrayList                   localActionList = new ArrayList();
215     private JFrame              jframe          = null;
216     private static final String DEFAULT_RCFILE  = homedir + "/dbmanager.rc";
217     private static boolean      TT_AVAILABLE    = false;
218 
219     static {
220         try {
221             Class.forName(DatabaseManagerSwing.class.getPackage().getName()
222                           + ".Transfer");
223 
224             TT_AVAILABLE = true;
225         } catch (Throwable t) {
226 
227             //System.err.println("Failed to get "
228             //+ DatabaseManagerSwing.class.getPackage().getName()
229             //+ ".Transfer: " + t);
230             // Enable this print statement for debugging class access problems.
231         }
232     }
233 
234     private static final String HELP_TEXT =
235         "See the HSQLDB Utilities Guide, forums and mailing lists \n"
236         + "at http://hsqldb.org.\n\n"
237         + "Please paste the following version identifier with any\n"
238         + "problem reports or help requests:  $Revision: 5221 $"
239         + (TT_AVAILABLE ? ""
240                         : ("\n\nTransferTool classes are not in CLASSPATH.\n"
241                            + "To enable the Tools menu, add 'transfer.jar' "
242                            + "to your class path."));
243     ;
244     private static final String ABOUT_TEXT =
245         "$Revision: 5221 $ of DatabaseManagerSwing\n\n"
246         + "Copyright (c) 2001-2010, The HSQL Development Group.\n"
247         + "http://hsqldb.org  (Utilities Guide available at this site).\n\n\n"
248         + "You may use and redistribute according to the HSQLDB\n"
249         + "license documented in the source code and at the web\n"
250         + "site above."
251         + (TT_AVAILABLE ? "\n\nTransferTool options are available."
252                         : "");
253     static final String    NL         = System.getProperty("line.separator");
254     static final String    NULL_STR   = "[null]";
255     static int             iMaxRecent = 24;
256     Connection             cConn;
257     Connection             rowConn;    // holds the connetion for getting table row counts
258     DatabaseMetaData       dMeta;
259     Statement              sStatement;
260     JMenu                  mRecent;
261     String[]               sRecent;
262     int                    iRecent;
263     JTextArea              txtCommand;
264     JScrollPane            txtCommandScroll;
265     JButton                butExecute;
266     JTree                  tTree;
267     JScrollPane            tScrollPane;
268     DefaultTreeModel       treeModel;
269     TableModel             tableModel;
270     DefaultMutableTreeNode rootNode;
271     JPanel                 pResult;
272     long                   lTime;
273     GridSwing              gResult;
274 
275     /**
276      * I think this is used to store model info whether we're using Grid
277      *  output or not (this object is queried for data to display for
278      *  text output mode).
279      *  If so, the presentation-independent model part should be moved
280      *  to an appropriately-named class instead of storing pure data in
281      *  a Swing-specific class.
282      */
283     JTable            gResultTable;
284     JScrollPane       gScrollPane;
285     JTextArea         txtResult;
286     JScrollPane       txtResultScroll;
287     JSplitPane        nsSplitPane;     // Contains query over results
288     JSplitPane        ewSplitPane;     // Contains tree beside nsSplitPane
289     boolean           bHelp;
290     RootPaneContainer fMain;
291     static boolean    bMustExit;
292 
293     /** Value of this variable only retained if huge input script read in. */
294     String          sqlScriptBuffer = null;
295     JToolBar        jtoolbar;
296     private boolean showSchemas  = true;
297     private boolean showTooltips = true;
298     private boolean autoRefresh  = true;
299     private boolean gridFormat   = true;
300 
301     // Added: (weconsultants@users)
302     static DatabaseManagerSwing refForFontDialogSwing;
303     boolean                     displayRowCounts = false;
304     boolean                     showSys          = false;
305     boolean                     showIndexDetails = true;
306     String                      currentLAF       = null;
307     JPanel                      pStatus;
308     static JButton              iReadyStatus;
309     JRadioButtonMenuItem        rbAllSchemas = new JRadioButtonMenuItem("*");
310     JMenuItem                   mitemAbout   = new JMenuItem("About", 'A');
311     JMenuItem                   mitemHelp    = new JMenuItem("Help", 'H');
312     JMenuItem mitemUpdateSchemas             = new JMenuItem("Update Schemas");
313     JCheckBoxMenuItem boxAutoCommit =
314         new JCheckBoxMenuItem(AUTOCOMMIT_BOX_TEXT);
315     JCheckBoxMenuItem boxLogging = new JCheckBoxMenuItem(LOGGING_BOX_TEXT);
316     JCheckBoxMenuItem boxShowSchemas =
317         new JCheckBoxMenuItem(SHOWSCHEMAS_BOX_TEXT);
318     JCheckBoxMenuItem boxAutoRefresh =
319         new JCheckBoxMenuItem(AUTOREFRESH_BOX_TEXT);
320     JCheckBoxMenuItem boxTooltips  = new JCheckBoxMenuItem(SHOWTIPS_BOX_TEXT);
321     JCheckBoxMenuItem boxRowCounts = new JCheckBoxMenuItem(ROWCOUNTS_BOX_TEXT);
322     JCheckBoxMenuItem boxShowGrid  = new JCheckBoxMenuItem(GRID_BOX_TEXT);
323     JCheckBoxMenuItem boxShowSys   = new JCheckBoxMenuItem(SHOWSYS_BOX_TEXT);
324 
325     // Consider adding GTK and Plaf L&Fs.
326     JRadioButtonMenuItem rbNativeLF =
327         new JRadioButtonMenuItem("Native Look & Feel");
328     JRadioButtonMenuItem rbJavaLF =
329         new JRadioButtonMenuItem("Java Look & Feel");
330     JRadioButtonMenuItem rbMotifLF =
331         new JRadioButtonMenuItem("Motif Look & Feel");
332     JLabel                      jStatusLine;
333     static String               READY_STATUS         = "Ready";
334     private static final String AUTOCOMMIT_BOX_TEXT  = "Autocommit mode";
335     private static final String LOGGING_BOX_TEXT     = "Logging mode";
336     private static final String SHOWSCHEMAS_BOX_TEXT = "Show schemas";
337     private static final String AUTOREFRESH_BOX_TEXT = "Auto-refresh tree";
338     private static final String SHOWTIPS_BOX_TEXT    = "Show Tooltips";
339     private static final String ROWCOUNTS_BOX_TEXT   = "Show row counts";
340     private static final String SHOWSYS_BOX_TEXT     = "Show system tables";
341     private static final String GRID_BOX_TEXT =
342         "Show results in Grid (a.o.t. Text)";
343 
344     // variables to hold the default cursors for these top level swing objects
345     // so we can restore them when we exit our thread
346     Cursor        fMainCursor;
347     Cursor        txtCommandCursor;
348     Cursor        txtResultCursor;
349     HashMap       tipMap     = new HashMap();
350     private JMenu mnuSchemas = new JMenu("Schemas");
351 
352     /**
353      * Wait Cursor
354      */
355 
356     // Changed: (weconsultants@users): commonted out the, out of the box, cursor to use a custom cursor
357     private final Cursor waitCursor = new Cursor(Cursor.WAIT_CURSOR);
358 
359     //getToolkit().createCustomCursor(CommonSwing.getIcon("SystemCursor"),
360     //                                new Point(4, 4), "HourGlass cursor");
361     // (ulrivo): variables set by arguments from the commandline
362     static String  defDriver   = "org.hsqldb.jdbcDriver";
363     static String  defURL      = "jdbc:hsqldb:mem:.";
364     static String  defUser     = "SA";
365     static String  defPassword = "";
366     static String  defScript;
367     static String  defDirectory;
368     private String schemaFilter = null;
369 
DatabaseManagerSwing()370     public DatabaseManagerSwing() {
371         jframe = new JFrame("HSQLDB DatabaseManager");
372         fMain  = jframe;
373     }
374     ;
375 
DatabaseManagerSwing(JFrame frameIn)376     public DatabaseManagerSwing(JFrame frameIn) {
377         jframe = frameIn;
378         fMain  = jframe;
379     }
380     ;
381 
init()382     public void init() {
383 
384         javax.swing.AbstractButton btn;
385 
386         fMain = this;
387 
388         main();
389 
390         for (int i = 0; i < localActionList.size(); i++) {
391             btn = (javax.swing.AbstractButton) localActionList.get(i);
392 
393             btn.setEnabled(false);
394         }
395 
396         Connection c    = null;
397         boolean    auto = false;
398 
399         if (getParameter("jdbcDriver") != null) {
400             auto      = true;
401             defDriver = getParameter("jdbcDriver");
402         }
403 
404         if (getParameter("jdbcUrl") != null) {
405             auto   = true;
406             defURL = getParameter("jdbcUrl");
407         }
408 
409         if (getParameter("jdbcUser") != null) {
410             auto    = true;
411             defUser = getParameter("jdbcUser");
412         }
413 
414         if (getParameter("jdbcPassword") != null) {
415             auto        = true;
416             defPassword = getParameter("jdbcPassword");
417         }
418 
419         try {
420             setWaiting("Initializing");
421 
422             //insertTestData();
423             //updateAutoCommitBox();
424             c = (auto
425                  ? ConnectionDialogSwing.createConnection(defDriver, defURL,
426                      defUser, defPassword)
427                  : ConnectionDialogSwing.createConnection(jframe, "Connect"));
428         } catch (Exception e) {
429 
430             //  Added: (weconsultants@users)
431             CommonSwing.errorMessage(e);
432         } finally {
433             setWaiting(null);
434         }
435 
436         if (c != null) {
437             connect(c);
438         }
439 
440         if (getParameter("loadSampleData") != null
441                 && getParameter("loadSampleData").equals("true")) {
442             insertTestData();
443 
444             try {
445                 Thread.sleep(1000);
446             } catch (InterruptedException ie) {}
447             ;
448 
449             // I don't know why, but the tree refresh below sometimes
450             // doesn't show all tables unless I put this delay here.
451             refreshTree();
452         }
453 
454         if (getParameter("schemaFilter") != null) {
455             schemaFilter = getParameter("schemaFilter");
456         }
457     }
458 
459     /**
460      * Run with --help switch for usage instructions.
461      *
462      * @throws IllegalArgumentException for the obvious reason
463      */
main(String[] arg)464     public static void main(String[] arg) {
465 
466         System.getProperties().put("sun.java2d.noddraw", "true");
467 
468         // (ulrivo): read all arguments from the command line
469         String  currentArg;
470         String  lowerArg;
471         String  urlid        = null;
472         String  rcFile       = null;
473         boolean autoConnect  = false;
474         boolean urlidConnect = false;
475 
476         bMustExit = true;
477 
478         for (int i = 0; i < arg.length; i++) {
479             currentArg = arg[i];
480             lowerArg = arg[i].toLowerCase();
481 
482             if (lowerArg.startsWith("--")) {
483                 lowerArg = lowerArg.substring(1);
484             }
485 
486             if (lowerArg.equals("-noexit") || lowerArg.equals("-help")) {
487 
488                 //
489             } else if (i == arg.length - 1) {
490                 throw new IllegalArgumentException("No value for argument "
491                                                    + currentArg);
492             }
493 
494             i++;
495 
496             if (lowerArg.equals("-driver")) {
497                 defDriver   = arg[i];
498                 autoConnect = true;
499             } else if (lowerArg.equals("-url")) {
500                 defURL      = arg[i];
501                 autoConnect = true;
502             } else if (lowerArg.equals("-user")) {
503                 defUser     = arg[i];
504                 autoConnect = true;
505             } else if (lowerArg.equals("-password")) {
506                 defPassword = arg[i];
507                 autoConnect = true;
508             } else if (lowerArg.equals("-urlid")) {
509                 urlid        = arg[i];
510                 urlidConnect = true;
511             } else if (lowerArg.equals("-rcfile")) {
512                 rcFile       = arg[i];
513                 urlidConnect = true;
514             } else if (lowerArg.equals("-dir")) {
515                 defDirectory = arg[i];
516             } else if (lowerArg.equals("-script")) {
517                 defScript = arg[i];
518             } else if (lowerArg.equals("-noexit")) {
519                 bMustExit = false;
520 
521                 i--;
522             } else if (lowerArg.equals("-help")) {
523                 showUsage();
524 
525                 return;
526             } else {
527                 /* Syntax ERRORS should either throw or exit with non-0 status.
528                  * In our case, it may be unsafe to exit, so we throw.
529                  * (I.e. should provide easy way for caller to programmatically
530                  * determine that there was an invocation problem).
531                  */
532                 throw new IllegalArgumentException(
533                     "invalid argrument " + currentArg + " try:  java... "
534                     + DatabaseManagerSwing.class.getName() + " --help");
535 
536                 // No reason to localize, since the main syntax message is
537                 // not localized.
538             }
539         }
540 
541         DatabaseManagerSwing m =
542             new DatabaseManagerSwing(new JFrame("HSQL Database Manager"));
543 
544         // Added: (weconsultants@users): Need databaseManagerSwing for later Reference
545         refForFontDialogSwing = m;
546 
547         m.main();
548 
549         Connection c = null;
550 
551         m.setWaiting("Initializing");
552 
553         try {
554             if (autoConnect && urlidConnect) {
555                 throw new IllegalArgumentException(
556                     "You may not specify both (urlid) AND (url/user/password).");
557             }
558 
559             if (autoConnect) {
560                 c = ConnectionDialogSwing.createConnection(defDriver, defURL,
561                         defUser, defPassword);
562             } else if (urlidConnect) {
563                 if (urlid == null) {
564                     throw new IllegalArgumentException(
565                         "You must specify an 'urlid' to use an RC file");
566                 }
567 
568                 autoConnect = true;
569 
570                 String rcfilepath = (rcFile == null) ? DEFAULT_RCFILE
571                                                      : rcFile;
572                 RCData rcdata     = new RCData(new File(rcfilepath), urlid);
573 
574                 c = rcdata.getConnection(
575                     null, System.getProperty("javax.net.ssl.trustStore"));
576             } else {
577                 c = ConnectionDialogSwing.createConnection(m.jframe,
578                         "Connect");
579             }
580         } catch (Exception e) {
581 
582             //  Added: (weconsultants@users)
583             CommonSwing.errorMessage(e);
584         } finally {
585             m.setWaiting(null);
586         }
587 
588         if (c != null) {
589             m.connect(c);
590         }
591 
592         // Added: (weconsultants@users): For preloadng FontDialogSwing
593         FontDialogSwing.creatFontDialog(refForFontDialogSwing);
594         m.start();
595     }
596 
597     /**
598      * This stuff is all quick, except for the refreshTree().
599      * This unit can be kicked off in main Gui thread.  The refreshTree
600      * will be backgrounded and this method will return.
601      */
connect(Connection c)602     public void connect(Connection c) {
603 
604         schemaFilter = null;
605 
606         if (c == null) {
607             return;
608         }
609 
610         if (cConn != null) {
611             try {
612                 cConn.close();
613             } catch (SQLException e) {
614 
615                 //  Added: (weconsultants@users)
616                 CommonSwing.errorMessage(e);
617             }
618         }
619 
620         cConn = c;
621 
622         // Added: (weconsultants@users) Need to barrow to get the table rowcounts
623         rowConn = c;
624 
625         try {
626             dMeta      = cConn.getMetaData();
627             isOracle = (dMeta.getDatabaseProductName().indexOf("Oracle") >= 0);
628             sStatement = cConn.createStatement();
629 
630             updateAutoCommitBox();
631 
632             // Workaround for EXTREME SLOWNESS getting this info from O.
633             showIndexDetails = !isOracle;
634 
635             Driver driver = DriverManager.getDriver(dMeta.getURL());
636             ConnectionSetting newSetting = new ConnectionSetting(
637                 dMeta.getDatabaseProductName(), driver.getClass().getName(),
638                 dMeta.getURL(),
639                 dMeta.getUserName().replaceAll("@localhost", ""), "");
640             Hashtable settings =
641                 ConnectionDialogCommon.loadRecentConnectionSettings();
642 
643             ConnectionDialogCommon.addToRecentConnectionSettings(settings,
644                     newSetting);
645             ConnectionDialogSwing.setConnectionSetting(newSetting);
646             refreshTree();
647             clearResultPanel();
648 
649             if (fMain instanceof JApplet) {
650                 getAppletContext().showStatus(
651                     "JDBC Connection established to a "
652                     + dMeta.getDatabaseProductName() + " v. "
653                     + dMeta.getDatabaseProductVersion() + " database as '"
654                     + dMeta.getUserName() + "'.");
655             }
656         } catch (SQLException e) {
657 
658             //  Added: (weconsultants@users)
659             CommonSwing.errorMessage(e);
660         } catch (IOException e) {
661 
662             //  Added: (weconsultants@users)
663             CommonSwing.errorMessage(e);
664         } catch (Exception e) {
665             CommonSwing.errorMessage(e);
666         }
667     }
668 
showUsage()669     private static void showUsage() {
670 
671         System.out.println(
672             "Usage: java DatabaseManagerSwing [--options]\n"
673             + "where options include:\n"
674             + "    --help                show this message\n"
675             + "    --driver <classname>  jdbc driver class\n"
676             + "    --url <name>          jdbc url\n"
677             + "    --user <name>         username used for connection\n"
678             + "    --password <password> password for this user\n"
679             + "    --urlid <urlid>       use url/user/password/driver in rc file\n"
680             + "    --rcfile <file>       (defaults to 'dbmanager.rc' in home dir)\n"
681             + "    --dir <path>          default directory\n"
682             + "    --script <file>       reads from script file\n"
683             + "    --noexit              do not call system.exit()");
684     }
685 
insertTestData()686     private void insertTestData() {
687 
688         try {
689             DatabaseManagerCommon.createTestTables(sStatement);
690             txtCommand.setText(
691                 DatabaseManagerCommon.createTestData(sStatement));
692 
693             for (int i = 0; i < DatabaseManagerCommon.testDataSql.length;
694                     i++) {
695                 addToRecent(DatabaseManagerCommon.testDataSql[i]);
696             }
697 
698             executeCurrentSQL();
699         } catch (SQLException e) {
700 
701             //  Added: (weconsultants@users)
702             CommonSwing.errorMessage(e);
703         }
704     }
705 
setMustExit(boolean b)706     public void setMustExit(boolean b) {
707         this.bMustExit = b;
708     }
709 
710     private DBMPrefs prefs = null;
711 
main()712     public void main() {
713 
714         JMenu     jmenu;
715         JMenuItem mitem;
716 
717         try {
718             prefs = new DBMPrefs(fMain instanceof JApplet);
719         } catch (Exception e) {
720 /*
721             System.err.println(
722                 "Failed to load preferences.  Proceeding with defaults:\n");
723 */
724         }
725 
726         if (prefs == null) {
727             setLF(CommonSwing.Native);
728         } else {
729             autoRefresh      = prefs.autoRefresh;
730             displayRowCounts = prefs.showRowCounts;
731             showSys          = prefs.showSysTables;
732             showSchemas      = prefs.showSchemas;
733             gridFormat       = prefs.resultGrid;
734             showTooltips     = prefs.showTooltips;
735 
736             setLF(prefs.laf);
737         }
738 
739         // (ulrivo): An actual icon.  N.b., this adds some tips to the tip map
740         fMain.getContentPane().add(createToolBar(), "North");
741 
742         if (fMain instanceof java.awt.Frame) {
743             ((java.awt.Frame) fMain).setIconImage(
744                 CommonSwing.getIcon("Frame"));
745         }
746 
747         if (fMain instanceof java.awt.Window) {
748             ((java.awt.Window) fMain).addWindowListener(this);
749         }
750 
751         JMenuBar bar = new JMenuBar();
752 
753         // used shortcuts: CERGTSIUDOLM
754         String[] fitems = {
755             "-Connect...", "--", "OOpen Script...", "-Save Script...",
756             "-Save Result...", "--", "-Exit"
757         };
758 
759         jmenu = addMenu(bar, "File", fitems);
760 
761         // All actions after Connect and the divider are local.
762         for (int i = 2; i < jmenu.getItemCount(); i++) {
763             mitem = jmenu.getItem(i);
764 
765             if (mitem != null) {
766                 localActionList.add(mitem);
767             }
768         }
769 
770         Object[] vitems = {
771             "RRefresh Tree", boxAutoRefresh, "--", boxRowCounts, boxShowSys,
772             boxShowSchemas, boxShowGrid
773         };
774 
775         addMenu(bar, "View", vitems);
776 
777         String[] sitems = {
778             "SSELECT", "IINSERT", "UUPDATE", "DDELETE", "EEXECUTE", "---",
779             "-CREATE TABLE", "-DROP TABLE", "-CREATE INDEX", "-DROP INDEX",
780             "--", "CCOMMIT*", "LROLLBACK*", "-CHECKPOINT*", "-SCRIPT", "-SET",
781             "-SHUTDOWN", "--", "-Test Script"
782         };
783 
784         addMenu(bar, "Command", sitems);
785 
786         mRecent = new JMenu("Recent");
787 
788         mRecent.setMnemonic(KeyEvent.VK_R);
789         bar.add(mRecent);
790 
791         ButtonGroup lfGroup = new ButtonGroup();
792 
793         lfGroup.add(rbNativeLF);
794         lfGroup.add(rbJavaLF);
795         lfGroup.add(rbMotifLF);
796         boxShowSchemas.setSelected(showSchemas);
797         boxShowGrid.setSelected(gridFormat);
798         boxTooltips.setSelected(showTooltips);
799         boxShowGrid.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_G,
800                 Event.CTRL_MASK));
801         boxAutoRefresh.setSelected(autoRefresh);
802         boxRowCounts.setSelected(displayRowCounts);
803         boxShowSys.setSelected(showSys);
804         rbNativeLF.setActionCommand("LFMODE:" + CommonSwing.Native);
805         rbJavaLF.setActionCommand("LFMODE:" + CommonSwing.Java);
806         rbMotifLF.setActionCommand("LFMODE:" + CommonSwing.Motif);
807         tipMap.put(mitemUpdateSchemas, "Refresh the schema list in this menu");
808         tipMap.put(rbAllSchemas, "Display items in all schemas");
809         tipMap.put(mitemAbout, "Display product information");
810         tipMap.put(mitemHelp, "Display advice for obtaining help");
811         tipMap.put(boxAutoRefresh,
812                    "Refresh tree (and schema list) automatically"
813                    + "when YOU modify database objects");
814         tipMap.put(boxShowSchemas,
815                    "Display object names in tree-like schemaname.basename");
816         tipMap.put(rbNativeLF,
817                    "Set Look and Feel to Native for your platform");
818         tipMap.put(rbJavaLF, "Set Look and Feel to Java");
819         tipMap.put(rbMotifLF, "Set Look and Feel to Motif");
820         boxTooltips.setToolTipText("Display tooltips (hover text), like this");
821         tipMap.put(boxAutoCommit,
822                    "Shows current Auto-commit mode.  Click to change");
823         tipMap.put(
824             boxLogging,
825             "Shows current JDBC DriverManager logging mode.  Click to change");
826         tipMap.put(boxShowSys, "Show system tables in table tree to the left");
827         tipMap.put(boxShowGrid, "Show query results in grid (in text if off)");
828         tipMap.put(boxRowCounts, "Show row counts with table names in tree");
829         boxAutoRefresh.setMnemonic(KeyEvent.VK_C);
830         boxShowSchemas.setMnemonic(KeyEvent.VK_Y);
831         boxAutoCommit.setMnemonic(KeyEvent.VK_A);
832         boxShowSys.setMnemonic(KeyEvent.VK_Y);
833         boxShowGrid.setMnemonic(KeyEvent.VK_G);
834         boxRowCounts.setMnemonic(KeyEvent.VK_C);
835         boxLogging.setMnemonic(KeyEvent.VK_L);
836         rbAllSchemas.setMnemonic(KeyEvent.VK_ASTERISK);
837         rbNativeLF.setMnemonic(KeyEvent.VK_N);
838         rbJavaLF.setMnemonic(KeyEvent.VK_J);
839         rbMotifLF.setMnemonic(KeyEvent.VK_M);
840         mitemUpdateSchemas.setMnemonic(KeyEvent.VK_U);
841 
842         Object[] soptions = {
843 
844             // Added: (weconsultants@users) New menu options
845             rbNativeLF, rbJavaLF, rbMotifLF, "--", "-Set Fonts", "--",
846             boxAutoCommit, "--", "-Disable MaxRows", "-Set MaxRows to 100",
847             "--", boxLogging, "--", "-Insert test data"
848         };
849 
850         addMenu(bar, "Options", soptions);
851 
852         String[] stools = {
853             "-Dump", "-Restore", "-Transfer"
854         };
855 
856         jmenu = addMenu(bar, "Tools", stools);
857 
858         jmenu.setEnabled(TT_AVAILABLE);
859         localActionList.add(jmenu);
860 
861         for (int i = 0; i < jmenu.getItemCount(); i++) {
862             mitem = jmenu.getItem(i);
863 
864             if (mitem != null) {
865                 localActionList.add(mitem);
866             }
867         }
868 
869         mnuSchemas.setMnemonic(KeyEvent.VK_S);
870         bar.add(mnuSchemas);
871 
872         JMenu mnuHelp = new JMenu("Help");
873 
874         mnuHelp.setMnemonic(KeyEvent.VK_H);
875         mnuHelp.add(mitemAbout);
876         mnuHelp.add(mitemHelp);
877         mnuHelp.add(boxTooltips);
878         rbAllSchemas.addActionListener(schemaListListener);
879 
880         // May be illegal:
881         mitemUpdateSchemas.addActionListener(new ActionListener() {
882 
883             public void actionPerformed(ActionEvent actionevent) {
884                 updateSchemaList();
885             }
886         });
887         mitemHelp.addActionListener(new ActionListener() {
888 
889             public void actionPerformed(ActionEvent actionevent) {
890 
891                 JOptionPane.showMessageDialog(fMain.getContentPane(),
892                                               HELP_TEXT, "HELP",
893                                               JOptionPane.INFORMATION_MESSAGE);
894             }
895         });
896         mitemAbout.addActionListener(new ActionListener() {
897 
898             public void actionPerformed(ActionEvent actionevent) {
899 
900                 JOptionPane.showMessageDialog(fMain.getContentPane(),
901                                               ABOUT_TEXT, "About",
902                                               JOptionPane.INFORMATION_MESSAGE);
903             }
904         });
905         boxTooltips.addActionListener(new ActionListener() {
906 
907             public void actionPerformed(ActionEvent actionevent) {
908 
909                 showTooltips = boxTooltips.isSelected();
910 
911                 resetTooltips();
912             }
913         });
914         bar.add(mnuHelp);
915 
916         if (fMain instanceof JApplet) {
917             ((JApplet) fMain).setJMenuBar(bar);
918         } else if (fMain instanceof JFrame) {
919             ((JFrame) fMain).setJMenuBar(bar);
920         }
921 
922         initGUI();
923 
924         sRecent = new String[iMaxRecent];
925 
926         // Modified: (weconsultants@users)Mode code to CommonSwing for general use
927         if (!(fMain instanceof JApplet)) {
928             CommonSwing.setFramePositon((JFrame) fMain);
929         }
930 
931         // Modified: (weconsultants@users) Changed from deprecated show()
932         ((Component) fMain).setVisible(true);
933 
934         // (ulrivo): load query from command line
935         if (defScript != null) {
936             if (defDirectory != null) {
937                 defScript = defDirectory + File.separator + defScript;
938             }
939 
940             // if insert stmet is thousands of records...skip showing it
941             // as text.  Too huge.
942             sqlScriptBuffer = DatabaseManagerCommon.readFile(defScript);
943 
944             if (4096 <= sqlScriptBuffer.length()) {
945                 int eoThirdLine = sqlScriptBuffer.indexOf('\n');
946 
947                 if (eoThirdLine > 0) {
948                     eoThirdLine = sqlScriptBuffer.indexOf('\n',
949                                                           eoThirdLine + 1);
950                 }
951 
952                 if (eoThirdLine > 0) {
953                     eoThirdLine = sqlScriptBuffer.indexOf('\n',
954                                                           eoThirdLine + 1);
955                 }
956 
957                 if (eoThirdLine < 1) {
958                     eoThirdLine = 100;
959                 }
960 
961                 txtCommand.setText(
962                     "............... Script File loaded: " + defScript
963                     + " ..................... \n"
964                     + "............... Click Execute or Clear "
965                     + "...................\n"
966                     + sqlScriptBuffer.substring(0, eoThirdLine + 1)
967                     + "..........................................."
968                     + "..............................\n"
969                     + "............................................."
970                     + "............................\n");
971                 txtCommand.setEnabled(false);
972             } else {
973                 txtCommand.setText(sqlScriptBuffer);
974 
975                 sqlScriptBuffer = null;
976 
977                 txtCommand.setEnabled(true);
978             }
979         }
980 
981         // This must be done AFTER all tip texts are put into the map
982         resetTooltips();
983         txtCommand.requestFocus();
984     }
985 
addMenu(JMenuBar b, String name, Object[] items)986     private JMenu addMenu(JMenuBar b, String name, Object[] items) {
987 
988         JMenu menu = new JMenu(name);
989 
990         menu.setMnemonic(name.charAt(0));
991         addMenuItems(menu, items);
992         b.add(menu);
993 
994         return menu;
995     }
996 
addMenuItems(JMenu f, Object[] m)997     private void addMenuItems(JMenu f, Object[] m) {
998 
999         /*
1000          * This method needs to be completely written or just
1001          * obliterated and we'll use the Menu objects directly.
1002          * Problem is, passing in Strings for menu elements makes it
1003          * extremely difficult to use non-text menu items (an important
1004          * part of a good Gui), hot-keys, mnemonic keys, tooltips.
1005          * Note the "trick" required here to set hot-keys.
1006          */
1007         Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
1008 
1009         for (int i = 0; i < m.length; i++) {
1010             if (m[i].equals("--")) {
1011                 f.addSeparator();
1012             } else if (m[i].equals("---")) {
1013 
1014                 // (ulrivo): full size on screen with less than 640 width
1015                 if (d.width >= 640) {
1016                     f.addSeparator();
1017                 } else {
1018                     return;
1019                 }
1020             } else {
1021                 JMenuItem item;
1022 
1023                 if (m[i] instanceof JMenuItem) {
1024                     item = (JMenuItem) m[i];
1025                 } else if (m[i] instanceof String) {
1026                     item = new JMenuItem(((String) m[i]).substring(1));
1027 
1028                     char c = ((String) m[i]).charAt(0);
1029 
1030                     if (c != '-') {
1031                         KeyStroke key =
1032                             KeyStroke.getKeyStroke(c, Event.CTRL_MASK);
1033 
1034                         item.setAccelerator(key);
1035                     }
1036                 } else {
1037                     throw new RuntimeException(
1038                         "Unexpected element for menu item creation: "
1039                         + m[i].getClass().getName());
1040                 }
1041 
1042                 item.addActionListener(this);
1043                 f.add(item);
1044             }
1045         }
1046     }
1047 
keyPressed(KeyEvent k)1048     public void keyPressed(KeyEvent k) {}
1049 
keyReleased(KeyEvent k)1050     public void keyReleased(KeyEvent k) {}
1051 
keyTyped(KeyEvent k)1052     public void keyTyped(KeyEvent k) {
1053 
1054         if (k.getKeyChar() == '\n' && k.isControlDown()) {
1055             k.consume();
1056             executeCurrentSQL();
1057         }
1058     }
1059 
1060     Thread dummyThread = new Thread("dummy");
1061 
actionPerformed(ActionEvent ev)1062     public void actionPerformed(ActionEvent ev) {
1063 
1064         String s = ev.getActionCommand();
1065 
1066         if (s == null) {
1067             if (ev.getSource() instanceof JMenuItem) {
1068                 s = ((JMenuItem) ev.getSource()).getText();
1069             }
1070         }
1071 
1072         if (s == null) {}
1073         else if (s.equals("Exit")) {
1074             windowClosing(null);
1075         } else if (s.equals("Transfer")) {
1076             Transfer.work(null);
1077         } else if (s.equals("Dump")) {
1078             Transfer.work(new String[]{ "-d" });
1079         } else if (s.equals("Restore")) {
1080             JOptionPane.showMessageDialog(
1081                 fMain.getContentPane(),
1082                 "Use Ctrl-R or the View menu to\n"
1083                 + "update nav. tree after Restoration", "Suggestion",
1084                     JOptionPane.INFORMATION_MESSAGE);
1085 
1086             // Regardless of whether autoRefresh is on, half of
1087             // Restore runs asynchronously, so we could only
1088             // update the tree from within the Transfer class.
1089             Transfer.work(new String[]{ "-r" });
1090 
1091             // Would be better to put the modal suggestion here, after the
1092             // user selects the import file, but that messes up the z
1093             // layering of the 3 windows already displayed.
1094         } else if (s.equals(LOGGING_BOX_TEXT)) {
1095             JavaSystem.setLogToSystem(boxLogging.isSelected());
1096         } else if (s.equals(AUTOREFRESH_BOX_TEXT)) {
1097             autoRefresh = boxAutoRefresh.isSelected();
1098 
1099             refreshTree();
1100         } else if (s.equals("Refresh Tree")) {
1101             refreshTree();
1102         } else if (s.startsWith("#")) {
1103             int i = Integer.parseInt(s.substring(1));
1104 
1105             txtCommand.setText(sRecent[i]);
1106         } else if (s.equals("Connect...")) {
1107             Connection newCon = null;
1108 
1109             try {
1110                 setWaiting("Connecting");
1111 
1112                 newCon = ConnectionDialogSwing.createConnection(jframe,
1113                         "Connect");
1114             } finally {
1115                 setWaiting(null);
1116             }
1117 
1118             connect(newCon);
1119         } else if (s.equals(GRID_BOX_TEXT)) {
1120             gridFormat = boxShowGrid.isSelected();
1121 
1122             displayResults();
1123         } else if (s.equals("Open Script...")) {
1124             JFileChooser f = new JFileChooser(".");
1125 
1126             f.setDialogTitle("Open Script...");
1127 
1128             // (ulrivo): set default directory if set from command line
1129             if (defDirectory != null) {
1130                 f.setCurrentDirectory(new File(defDirectory));
1131             }
1132 
1133             int option = f.showOpenDialog((Component) fMain);
1134 
1135             if (option == JFileChooser.APPROVE_OPTION) {
1136                 File file = f.getSelectedFile();
1137 
1138                 if (file != null) {
1139                     sqlScriptBuffer =
1140                         DatabaseManagerCommon.readFile(file.getAbsolutePath());
1141 
1142                     if (4096 <= sqlScriptBuffer.length()) {
1143                         int eoThirdLine = sqlScriptBuffer.indexOf('\n');
1144 
1145                         if (eoThirdLine > 0) {
1146                             eoThirdLine = sqlScriptBuffer.indexOf('\n',
1147                                                                   eoThirdLine
1148                                                                   + 1);
1149                         }
1150 
1151                         if (eoThirdLine > 0) {
1152                             eoThirdLine = sqlScriptBuffer.indexOf('\n',
1153                                                                   eoThirdLine
1154                                                                   + 1);
1155                         }
1156 
1157                         if (eoThirdLine < 1) {
1158                             eoThirdLine = 100;
1159                         }
1160 
1161                         txtCommand.setText(
1162                             "............... Script File loaded: " + file
1163                             + " ..................... \n"
1164                             + "............... Click Execute or Clear "
1165                             + "...................\n"
1166                             + sqlScriptBuffer.substring(0, eoThirdLine + 1)
1167                             + "........................................."
1168                             + "................................\n"
1169                             + "..........................................."
1170                             + "..............................\n");
1171                         txtCommand.setEnabled(false);
1172                     } else {
1173                         txtCommand.setText(sqlScriptBuffer);
1174 
1175                         sqlScriptBuffer = null;
1176 
1177                         txtCommand.setEnabled(true);
1178                     }
1179                 }
1180             }
1181         } else if (s.equals("Save Script...")) {
1182             JFileChooser f = new JFileChooser(".");
1183 
1184             f.setDialogTitle("Save Script");
1185 
1186             // (ulrivo): set default directory if set from command line
1187             if (defDirectory != null) {
1188                 f.setCurrentDirectory(new File(defDirectory));
1189             }
1190 
1191             int option = f.showSaveDialog((Component) fMain);
1192 
1193             if (option == JFileChooser.APPROVE_OPTION) {
1194                 File file = f.getSelectedFile();
1195 
1196                 if (file != null) {
1197                     DatabaseManagerCommon.writeFile(file.getAbsolutePath(),
1198                                                     txtCommand.getText());
1199                 }
1200             }
1201         } else if (s.equals("Save Result...")) {
1202             JFileChooser f = new JFileChooser(".");
1203 
1204             f.setDialogTitle("Save Result...");
1205 
1206             // (ulrivo): set default directory if set from command line
1207             if (defDirectory != null) {
1208                 f.setCurrentDirectory(new File(defDirectory));
1209             }
1210 
1211             int option = f.showSaveDialog((Component) fMain);
1212 
1213             if (option == JFileChooser.APPROVE_OPTION) {
1214                 File file = f.getSelectedFile();
1215 
1216                 if (file != null) {
1217                     showResultInText();
1218                     DatabaseManagerCommon.writeFile(file.getAbsolutePath(),
1219                                                     txtResult.getText());
1220                 }
1221             }
1222         } else if (s.equals(SHOWSYS_BOX_TEXT)) {
1223             showSys = boxShowSys.isSelected();
1224 
1225             refreshTree();
1226         } else if (s.equals(ROWCOUNTS_BOX_TEXT)) {
1227             displayRowCounts = boxRowCounts.isSelected();
1228 
1229             refreshTree();
1230         } else if (s.startsWith("LFMODE:")) {
1231             setLF(s.substring("LFMODE:".length()));
1232         } else if (s.equals("Set Fonts")) {
1233 
1234             // Added: (weconsultants@users)
1235             FontDialogSwing.creatFontDialog(refForFontDialogSwing);
1236         } else if (s.equals(AUTOCOMMIT_BOX_TEXT)) {
1237             try {
1238                 cConn.setAutoCommit(boxAutoCommit.isSelected());
1239             } catch (SQLException e) {
1240                 boxAutoCommit.setSelected(!boxAutoCommit.isSelected());
1241 
1242                 //  Added: (weconsultants@users)
1243                 CommonSwing.errorMessage(e);
1244             }
1245         } else if (s.equals("COMMIT*")) {
1246             try {
1247                 cConn.commit();
1248                 showHelp(new String[] {
1249                     "", "COMMIT executed"
1250                 });
1251             } catch (SQLException e) {
1252 
1253                 //  Added: (weconsultants@users)
1254                 CommonSwing.errorMessage(e);
1255             }
1256         } else if (s.equals("Insert test data")) {
1257             insertTestData();
1258             refreshTree();
1259         } else if (s.equals("ROLLBACK*")) {
1260             try {
1261                 cConn.rollback();
1262                 showHelp(new String[] {
1263                     "", "ROLLBACK executed"
1264                 });
1265             } catch (SQLException e) {
1266 
1267                 //  Added: (weconsultants@users)
1268                 CommonSwing.errorMessage(e);
1269             }
1270         } else if (s.equals("Disable MaxRows")) {
1271             try {
1272                 sStatement.setMaxRows(0);
1273             } catch (SQLException e) {
1274 
1275                 //  Added: (weconsultants@users)
1276                 CommonSwing.errorMessage(e);
1277             }
1278         } else if (s.equals("Set MaxRows to 100")) {
1279             try {
1280                 sStatement.setMaxRows(100);
1281             } catch (SQLException e) {
1282                 CommonSwing.errorMessage(e);
1283             }
1284         } else if (s.equals("SELECT")) {
1285             showHelp(DatabaseManagerCommon.selectHelp);
1286         } else if (s.equals("INSERT")) {
1287             showHelp(DatabaseManagerCommon.insertHelp);
1288         } else if (s.equals("UPDATE")) {
1289             showHelp(DatabaseManagerCommon.updateHelp);
1290         } else if (s.equals("DELETE")) {
1291             showHelp(DatabaseManagerCommon.deleteHelp);
1292         } else if (s.equals("EXECUTE")) {
1293             executeCurrentSQL();
1294         } else if (s.equals("CREATE TABLE")) {
1295             showHelp(DatabaseManagerCommon.createTableHelp);
1296         } else if (s.equals("DROP TABLE")) {
1297             showHelp(DatabaseManagerCommon.dropTableHelp);
1298         } else if (s.equals("CREATE INDEX")) {
1299             showHelp(DatabaseManagerCommon.createIndexHelp);
1300         } else if (s.equals("DROP INDEX")) {
1301             showHelp(DatabaseManagerCommon.dropIndexHelp);
1302         } else if (s.equals("CHECKPOINT*")) {
1303             try {
1304                 cConn.createStatement().executeUpdate("CHECKPOINT");
1305                 showHelp(new String[] {
1306                     "", "CHECKPOINT executed"
1307                 });
1308             } catch (SQLException e) {
1309                 CommonSwing.errorMessage(e);
1310             }
1311         } else if (s.equals("SCRIPT")) {
1312             showHelp(DatabaseManagerCommon.scriptHelp);
1313         } else if (s.equals("SHUTDOWN")) {
1314             showHelp(DatabaseManagerCommon.shutdownHelp);
1315         } else if (s.equals("SET")) {
1316             showHelp(DatabaseManagerCommon.setHelp);
1317         } else if (s.equals("Test Script")) {
1318             showHelp(DatabaseManagerCommon.testHelp);
1319         } else if (s.equals(SHOWSCHEMAS_BOX_TEXT)) {
1320             showSchemas = boxShowSchemas.isSelected();
1321 
1322             refreshTree();
1323         } else {
1324             throw new RuntimeException("Unexpected action triggered: " + s);
1325         }
1326     }
1327 
displayResults()1328     private void displayResults() {
1329 
1330         if (gridFormat) {
1331             setResultsInGrid();
1332         } else {
1333             setResultsInText();
1334         }
1335     }
1336 
setResultsInGrid()1337     private void setResultsInGrid() {
1338 
1339         pResult.removeAll();
1340         pResult.add(gScrollPane, BorderLayout.CENTER);
1341         pResult.doLayout();
1342         gResult.fireTableChanged(null);
1343         pResult.repaint();
1344     }
1345 
setResultsInText()1346     private void setResultsInText() {
1347 
1348         pResult.removeAll();
1349         pResult.add(txtResultScroll, BorderLayout.CENTER);
1350         pResult.doLayout();
1351         showResultInText();
1352         pResult.repaint();
1353     }
1354 
showHelp(String[] help)1355     private void showHelp(String[] help) {
1356 
1357         txtCommand.setText(help[0]);
1358 
1359         bHelp = true;
1360 
1361         pResult.removeAll();
1362         pResult.add(txtResultScroll, BorderLayout.CENTER);
1363         pResult.doLayout();
1364         txtResult.setText(help[1]);
1365         pResult.repaint();
1366         txtCommand.requestFocus();
1367         txtCommand.setCaretPosition(help[0].length());
1368     }
1369 
windowActivated(WindowEvent e)1370     public void windowActivated(WindowEvent e) {}
1371 
windowDeactivated(WindowEvent e)1372     public void windowDeactivated(WindowEvent e) {}
1373 
windowClosed(WindowEvent e)1374     public void windowClosed(WindowEvent e) {}
1375 
windowDeiconified(WindowEvent e)1376     public void windowDeiconified(WindowEvent e) {}
1377 
windowIconified(WindowEvent e)1378     public void windowIconified(WindowEvent e) {}
1379 
windowOpened(WindowEvent e)1380     public void windowOpened(WindowEvent e) {}
1381 
windowClosing(WindowEvent ev)1382     public void windowClosing(WindowEvent ev) {
1383 
1384         stop();
1385 
1386         try {
1387             if (cConn != null) {
1388                 cConn.close();
1389             }
1390 
1391             if (prefs != null) {
1392                 prefs.autoRefresh   = autoRefresh;
1393                 prefs.showRowCounts = displayRowCounts;
1394                 prefs.showSysTables = showSys;
1395                 prefs.showSchemas   = showSchemas;
1396                 prefs.resultGrid    = gridFormat;
1397                 prefs.showTooltips  = showTooltips;
1398                 prefs.laf           = currentLAF;
1399 
1400                 prefs.store();
1401             }
1402         } catch (Exception e) {
1403 
1404             //  Added: (weconsultants@users)
1405             CommonSwing.errorMessage(e);
1406         }
1407 
1408         if (fMain instanceof java.awt.Window) {
1409             ((java.awt.Window) fMain).dispose();
1410         }
1411 
1412         if (bMustExit) {
1413             System.exit(0);
1414         }
1415     }
1416 
clear()1417     private void clear() {
1418 
1419         sqlScriptBuffer = null;
1420 
1421         txtCommand.setText("");
1422         txtCommand.setEnabled(true);
1423     }
1424 
1425     private String busyText = null;
1426 
backgroundIt(Runnable r, String description)1427     private void backgroundIt(Runnable r, String description) {
1428 
1429         if (busyText != null) {
1430             Toolkit.getDefaultToolkit().beep();
1431 
1432             return;
1433         }
1434 
1435         // set Waiting mode here.  Inverse op must be called by final()
1436         // in the Thread.run() of every background thread.
1437         setWaiting(description);
1438         SwingUtilities.invokeLater(r);
1439     }
1440 
clearResultPanel()1441     private void clearResultPanel() {
1442 
1443         gResult.setHead(new Object[0]);
1444         gResult.clear();
1445 
1446         if (gridFormat) {
1447             gResult.fireTableChanged(null);
1448         } else {
1449             showResultInText();
1450         }
1451     }
1452 
setWaiting(String description)1453     public void setWaiting(String description) {
1454 
1455         busyText = description;
1456 
1457         if (busyText == null) {
1458 
1459             // restore the cursors we saved
1460             if (fMain instanceof java.awt.Frame) {
1461                 ((java.awt.Frame) fMain).setCursor(fMainCursor);
1462             } else {
1463                 ((Component) fMain).setCursor(fMainCursor);
1464             }
1465 
1466             txtCommand.setCursor(txtCommandCursor);
1467             txtResult.setCursor(txtResultCursor);
1468 
1469             /** @todo: Enable actionButtons */
1470         } else {
1471 
1472             // save the old cursors
1473             if (fMainCursor == null) {
1474                 fMainCursor = ((fMain instanceof java.awt.Frame)
1475                                ? (((java.awt.Frame) fMain).getCursor())
1476                                : (((Component) fMain).getCursor()));
1477                 txtCommandCursor = txtCommand.getCursor();
1478                 txtResultCursor  = txtResult.getCursor();
1479             }
1480 
1481             // set the cursors to the wait cursor
1482             if (fMain instanceof java.awt.Frame) {
1483                 ((java.awt.Frame) fMain).setCursor(waitCursor);
1484             } else {
1485                 ((Component) fMain).setCursor(waitCursor);
1486             }
1487 
1488             txtCommand.setCursor(waitCursor);
1489             txtResult.setCursor(waitCursor);
1490 
1491             /** @todo: Disable actionButtons */
1492         }
1493 
1494         setStatusLine(busyText, ((busyText == null) ? gResult.getRowCount()
1495                                                     : 0));
1496     }
1497 
1498     private Runnable enableButtonRunnable = new Runnable() {
1499 
1500         public void run() {
1501             jbuttonClear.setEnabled(true);
1502             jbuttonExecute.setEnabled(true);
1503         }
1504     };
1505     private Runnable disableButtonRunnable = new Runnable() {
1506 
1507         public void run() {
1508             jbuttonClear.setEnabled(false);
1509             jbuttonExecute.setEnabled(false);
1510         }
1511     };
1512     private Thread           buttonUpdaterThread = null;
1513     private static final int BUTTON_CHECK_PERIOD = 500;
1514     private Runnable         buttonUpdater       = new Runnable() {
1515 
1516         public void run() {
1517 
1518             boolean havesql;
1519 
1520             while (true) {
1521                 try {
1522                     Thread.sleep(BUTTON_CHECK_PERIOD);
1523                 } catch (InterruptedException ie) {}
1524 
1525                 if (buttonUpdaterThread == null) {    // Pointer to me
1526                     return;
1527                 }
1528 
1529                 havesql = (txtCommand.getText().length() > 0);
1530 
1531                 if (jbuttonClear.isEnabled() != havesql) {
1532                     SwingUtilities.invokeLater(havesql ? enableButtonRunnable
1533                                                        : disableButtonRunnable);
1534                 }
1535             }
1536         }
1537     };
1538     private JButton jbuttonClear;
1539     private JButton jbuttonExecute;
1540 
start()1541     public void start() {
1542 
1543         if (buttonUpdaterThread == null) {
1544             buttonUpdaterThread = new Thread(buttonUpdater);
1545         }
1546 
1547         buttonUpdaterThread.start();
1548     }
1549 
stop()1550     public void stop() {
1551 
1552         System.err.println("Stopping");
1553 
1554         Thread t = buttonUpdaterThread;
1555 
1556         if (t != null) {
1557             t.setContextClassLoader(null);
1558         }
1559 
1560         buttonUpdaterThread = null;
1561     }
1562 
1563     private Runnable treeRefreshRunnable = new Runnable() {
1564 
1565         public void run() {
1566 
1567             try {
1568                 directRefreshTree();
1569             } catch (RuntimeException re) {
1570                 CommonSwing.errorMessage(re);
1571 
1572                 throw re;
1573             } finally {
1574                 setWaiting(null);
1575             }
1576         }
1577     };
1578 
1579     /**
1580      * Schedules to run in a Gui-safe thread
1581      */
executeCurrentSQL()1582     protected void executeCurrentSQL() {
1583 
1584         if (txtCommand.getText().length() < 1) {
1585             CommonSwing.errorMessage("No SQL to execute");
1586 
1587             return;
1588         }
1589 
1590         backgroundIt(new StatementExecRunnable(), "Executing SQL");
1591     }
1592 
1593     protected class StatementExecRunnable implements Runnable {
1594 
run()1595         public void run() {
1596 
1597             gResult.clear();
1598 
1599             try {
1600                 if (txtCommand.getText().startsWith("-->>>TEST<<<--")) {
1601                     testPerformance();
1602                 } else {
1603                     executeSQL();
1604                 }
1605 
1606                 updateResult();
1607                 displayResults();
1608                 updateAutoCommitBox();
1609 
1610                 // System.gc();
1611             } catch (RuntimeException re) {
1612                 CommonSwing.errorMessage(re);
1613 
1614                 throw re;
1615             } finally {
1616                 setWaiting(null);
1617             }
1618         }
1619     }
1620     ;
1621 
executeSQL()1622     private void executeSQL() {
1623 
1624         String[] g   = new String[1];
1625         String   sql = null;
1626 
1627         try {
1628             lTime = System.currentTimeMillis();
1629             sql   = ((sqlScriptBuffer == null ? txtCommand.getText()
1630                                               : sqlScriptBuffer));
1631 
1632             sStatement.execute(sql);
1633 
1634             int r = sStatement.getUpdateCount();
1635 
1636             if (r == -1) {
1637                 ResultSet rs = sStatement.getResultSet();
1638 
1639                 try {
1640                     formatResultSet(rs);
1641                 } catch (Throwable t) {
1642                     g[0] = "Error displaying the ResultSet";
1643 
1644                     gResult.setHead(g);
1645 
1646                     String s = t.getMessage();
1647 
1648                     g[0] = s;
1649 
1650                     gResult.addRow(g);
1651                 }
1652             } else {
1653                 g[0] = "update count";
1654 
1655                 gResult.setHead(g);
1656 
1657                 g[0] = "" + r;
1658 
1659                 gResult.addRow(g);
1660             }
1661 
1662             lTime = System.currentTimeMillis() - lTime;
1663 
1664             if (sqlScriptBuffer == null) {
1665                 addToRecent(sql);
1666                 txtCommand.setEnabled(true);    // clear() does this otherwise
1667             } else {
1668                 clear();
1669             }
1670         } catch (SQLException e) {
1671             lTime = System.currentTimeMillis() - lTime;
1672             g[0]  = "SQL Error";
1673 
1674             gResult.setHead(g);
1675 
1676             String s = e.getMessage();
1677 
1678             s    += " / Error Code: " + e.getErrorCode();
1679             s    += " / State: " + e.getSQLState();
1680             g[0] = s;
1681 
1682             gResult.addRow(g);
1683 
1684             //  Added: (weconsultants@users)
1685             CommonSwing.errorMessage(e);
1686 
1687             return;
1688         }
1689 
1690         if (autoRefresh) {
1691 
1692             // We're already running in a "busy" thread.  Just update the
1693             // status text.
1694             setStatusLine("Refreshing object tree", 0);
1695 
1696             String upper = sql.toUpperCase(Locale.ENGLISH);
1697 
1698             // This test can be very liberal.  Too liberal will just do
1699             // some extra refreshes.  Too conservative will display
1700             // obsolete info.
1701             if (upper.indexOf("ALTER") > -1 || upper.indexOf("DROP") > -1
1702                     || upper.indexOf("CREATE") > -1) {
1703                 directRefreshTree();
1704             }
1705         }
1706     }
1707 
1708     /**
1709      * Could somebody explain what the purpose of this method is?
1710      * Contrary to the method name, it looks like it displays
1711      * results only if gridFormat is off (seems like it  does
1712      * nothing otherwise, except for clearing help text and moving focus).
1713      */
updateResult()1714     private void updateResult() {
1715 
1716         if (gridFormat) {
1717 
1718             // in case 'help' has removed the grid
1719             if (bHelp) {
1720                 pResult.removeAll();
1721                 pResult.add(gScrollPane, BorderLayout.CENTER);
1722                 pResult.doLayout();
1723                 gResult.fireTableChanged(null);
1724                 pResult.repaint();
1725 
1726                 bHelp = false;
1727             }
1728         } else {
1729             showResultInText();
1730         }
1731 
1732         txtCommand.selectAll();
1733         txtCommand.requestFocus();
1734     }
1735 
1736     /**
1737      * We let Swing handle displaying nulls (which it generally does by
1738      * printing nothing for them), except for the case of database
1739      * VARCHARs, because this is the only class where there is any
1740      * ambiguity about whether there is a null stored or not.
1741      */
formatResultSet(ResultSet r)1742     private void formatResultSet(ResultSet r) {
1743 
1744         if (r == null) {
1745             String[] g = new String[1];
1746 
1747             g[0] = "Result";
1748 
1749             gResult.setHead(g);
1750 
1751             g[0] = "(empty)";
1752 
1753             gResult.addRow(g);
1754 
1755             return;
1756         }
1757 
1758         try {
1759             ResultSetMetaData m         = r.getMetaData();
1760             int               col       = m.getColumnCount();
1761             Object[]          h         = new Object[col];
1762             boolean[]         isVarChar = new boolean[col];
1763 
1764             for (int i = 1; i <= col; i++) {
1765                 h[i - 1] = m.getColumnLabel(i);
1766                 isVarChar[i - 1] = (m.getColumnType(i)
1767                                     == java.sql.Types.VARCHAR);
1768             }
1769 
1770             gResult.setHead(h);
1771 
1772             while (r.next()) {
1773                 for (int i = 1; i <= col; i++) {
1774                     try {
1775                         h[i - 1] = r.getObject(i);
1776 
1777                         if (r.wasNull()) {
1778                             h[i - 1] = (isVarChar[i - 1] ? NULL_STR
1779                                                          : null);
1780                         }
1781                     } catch (SQLException e) {}
1782                 }
1783 
1784                 gResult.addRow(h);
1785             }
1786 
1787             r.close();
1788         } catch (SQLException e) {
1789 
1790             //  Added: (weconsultants@users)
1791             CommonSwing.errorMessage(e);
1792         }
1793     }
1794 
testPerformance()1795     private void testPerformance() {
1796 
1797         String       all   = txtCommand.getText();
1798         StringBuffer b     = new StringBuffer();
1799         long         total = 0;
1800 
1801         for (int i = 0; i < all.length(); i++) {
1802             char c = all.charAt(i);
1803 
1804             if (c != '\n') {
1805                 b.append(c);
1806             }
1807         }
1808 
1809         all = b.toString();
1810 
1811         String[] g = new String[4];
1812 
1813         g[0] = "ms";
1814         g[1] = "count";
1815         g[2] = "sql";
1816         g[3] = "error";
1817 
1818         gResult.setHead(g);
1819 
1820         int max = 1;
1821 
1822         lTime = System.currentTimeMillis() - lTime;
1823 
1824         while (!all.equals("")) {
1825             int    i = all.indexOf(';');
1826             String sql;
1827 
1828             if (i != -1) {
1829                 sql = all.substring(0, i);
1830                 all = all.substring(i + 1);
1831             } else {
1832                 sql = all;
1833                 all = "";
1834             }
1835 
1836             if (sql.startsWith("--#")) {
1837                 max = Integer.parseInt(sql.substring(3));
1838 
1839                 continue;
1840             } else if (sql.startsWith("--")) {
1841                 continue;
1842             }
1843 
1844             g[2] = sql;
1845 
1846             long l = 0;
1847 
1848             try {
1849                 l = DatabaseManagerCommon.testStatement(sStatement, sql, max);
1850                 total += l;
1851                 g[0]  = "" + l;
1852                 g[1]  = "" + max;
1853                 g[3]  = "";
1854             } catch (SQLException e) {
1855                 g[0] = g[1] = "n/a";
1856                 g[3] = e.toString();
1857 
1858                 //  Added: (weconsultants@users)
1859                 CommonSwing.errorMessage(e);
1860             }
1861 
1862             gResult.addRow(g);
1863             System.out.println(l + " ms : " + sql);
1864         }
1865 
1866         g[0] = "" + total;
1867         g[1] = "total";
1868         g[2] = "";
1869 
1870         gResult.addRow(g);
1871 
1872         lTime = System.currentTimeMillis() - lTime;
1873     }
1874 
showResultInText()1875     private void showResultInText() {
1876 
1877         Object[] col   = gResult.getHead();
1878         int      width = col.length;
1879         int[]    size  = new int[width];
1880         Vector   data  = gResult.getData();
1881         Object[] row;
1882         int      height = data.size();
1883 
1884         for (int i = 0; i < width; i++) {
1885             size[i] = col[i].toString().length();
1886         }
1887 
1888         for (int i = 0; i < height; i++) {
1889             row = (Object[]) data.elementAt(i);
1890 
1891             for (int j = 0; j < width; j++) {
1892                 String item = ((row[j] == null) ? ""
1893                                                 : row[j].toString());
1894                 int    l    = item.length();
1895 
1896                 if (l > size[j]) {
1897                     size[j] = l;
1898                 }
1899             }
1900         }
1901 
1902         StringBuffer b = new StringBuffer();
1903 
1904         for (int i = 0; i < width; i++) {
1905             b.append(col[i]);
1906 
1907             for (int l = col[i].toString().length(); l <= size[i]; l++) {
1908                 b.append(' ');
1909             }
1910         }
1911 
1912         b.append(NL);
1913 
1914         for (int i = 0; i < width; i++) {
1915             for (int l = 0; l < size[i]; l++) {
1916                 b.append('-');
1917             }
1918 
1919             b.append(' ');
1920         }
1921 
1922         b.append(NL);
1923 
1924         for (int i = 0; i < height; i++) {
1925             row = (Object[]) data.elementAt(i);
1926 
1927             for (int j = 0; j < width; j++) {
1928                 String item = ((row[j] == null) ? ""
1929                                                 : row[j].toString());
1930 
1931                 b.append(item);
1932 
1933                 for (int l = item.length(); l <= size[j]; l++) {
1934                     b.append(' ');
1935                 }
1936             }
1937 
1938             b.append(NL);
1939         }
1940 
1941         // b.append(NL + height + " row(s) in " + lTime + " ms");
1942         // There is no reason why this report should be text-output-specific.
1943         // Moving it to bottom of the setWaiting method (where the report
1944         // gets written to the status line).
1945         // I'm only doing the rowcount now.  Add the time report there if
1946         // you are so inclined.
1947         txtResult.setText(b.toString());
1948     }
1949 
addToRecent(String s)1950     private void addToRecent(String s) {
1951 
1952         for (int i = 0; i < iMaxRecent; i++) {
1953             if (s.equals(sRecent[i])) {
1954                 return;
1955             }
1956         }
1957 
1958         if (sRecent[iRecent] != null) {
1959             mRecent.remove(iRecent);
1960         }
1961 
1962         sRecent[iRecent] = s;
1963 
1964         if (s.length() > 43) {
1965             s = s.substring(0, 40) + "...";
1966         }
1967 
1968         JMenuItem item = new JMenuItem(s);
1969 
1970         item.setActionCommand("#" + iRecent);
1971         item.addActionListener(this);
1972         mRecent.insert(item, iRecent);
1973 
1974         iRecent = (iRecent + 1) % iMaxRecent;
1975     }
1976 
1977     // empty implementations for mouse listener.  We're only using
1978     // mouseReleased
mouseClicked(final MouseEvent mouseEvent)1979     public final void mouseClicked(final MouseEvent mouseEvent) {}
1980 
mouseEntered(final MouseEvent mouseEvent)1981     public final void mouseEntered(final MouseEvent mouseEvent) {}
1982 
mouseExited(final MouseEvent mouseEvent)1983     public final void mouseExited(final MouseEvent mouseEvent) {}
1984 
1985     // Check for handlePopup in both mousePressed and mouseReleased.  According to
1986     // MouseEvent javadocs it's necessary for cross platform compatibility.
1987     // We keep a record of the last alreadyHandled mouseEvent so we don't do it twice.
1988     private MouseEvent alreadyHandled = null;
1989 
1990     // mousePressed calls handlePopup, which creates the context-sensitive
1991     // helper menu.
mousePressed(final MouseEvent e)1992     public final void mousePressed(final MouseEvent e) {
1993 
1994         if (alreadyHandled == e) {
1995             return;
1996         }
1997 
1998         handlePopup(e);
1999 
2000         alreadyHandled = e;
2001     }
2002 
2003     // mouseReleased calls handlePopup, which creates the context-sensitive
2004     // helper menu.
mouseReleased(final MouseEvent e)2005     public final void mouseReleased(final MouseEvent e) {
2006 
2007         if (alreadyHandled == e) {
2008             return;
2009         }
2010 
2011         handlePopup(e);
2012 
2013         alreadyHandled = e;
2014     }
2015 
2016     // based on the table or column right-clicked on, create some helper
2017     // actions for common sql statements
handlePopup(MouseEvent e)2018     public final void handlePopup(MouseEvent e) {
2019 
2020         //System.out.println("Handle popup");
2021         // if this is not a mouse action for popups then do nothing and return
2022         if (!e.isPopupTrigger()) {
2023             return;
2024         }
2025 
2026         // make sure the source of this mouse event was from the tree
2027         Object source = e.getSource();
2028 
2029         if (!(source instanceof JTree)) {
2030             return;
2031         }
2032 
2033         JTree    tree     = (JTree) source;
2034         TreePath treePath = tree.getPathForLocation(e.getX(), e.getY());
2035 
2036         // if we couldn't find a tree path that corresponds to the
2037         // right-click, then return
2038         if (treePath == null) {
2039             return;
2040         }
2041 
2042         // create the popup and menus
2043         JPopupMenu popup = new JPopupMenu();
2044         JMenuItem  menuItem;
2045         String     menus[] = new String[] {
2046             "Select", "Delete", "Update", "Insert"
2047         };
2048 
2049         // loop throught the menus we want to create, making a PopupListener
2050         // for each one
2051         for (int i = 0; i < menus.length; i++) {
2052             PopupListener popupListener = new PopupListener(menus[i],
2053                 treePath);
2054             String title = popupListener.toString();
2055 
2056             if (title == null) {
2057                 return;
2058             }
2059 
2060             // Some of the menu names can be quite long (especially insert).
2061             // If it's too long, abbreviate it
2062             if (title.length() > 40) {
2063                 title = title.substring(0, 40) + "...";
2064             }
2065 
2066             menuItem = new JMenuItem(title);
2067 
2068             menuItem.addActionListener(popupListener);
2069             popup.add(menuItem);
2070         }
2071 
2072         popup.show(e.getComponent(), e.getX(), e.getY());
2073     }
2074 
2075     // handles the creation of the command when a popup is triggered
2076     private class PopupListener implements ActionListener {
2077 
2078         // used to identify depth while right clicking in tree.
2079         public static final int DEPTH_URL    = 1;
2080         public static final int DEPTH_TABLE  = 2;
2081         public static final int DEPTH_COLUMN = 3;
2082         String                  command;
2083         TreePath                treePath;
2084         TreePath                tablePath;
2085         TreePath                columnPath;
2086         String                  table  = null;
2087         String                  column = null;
2088 
PopupListener(String command, TreePath treePath)2089         PopupListener(String command, TreePath treePath) {
2090 
2091             super();
2092 
2093             this.command  = command;
2094             this.treePath = treePath;
2095         }
2096 
2097         // when the popup is triggered, create a command string and set it in
2098         // the txtCommand buffer
actionPerformed(ActionEvent ae)2099         public void actionPerformed(ActionEvent ae) {
2100             txtCommand.setText(getCommandString());
2101         }
2102 
2103         // text to display when added to a menu
toString()2104         public String toString() {
2105             return getCommandString();
2106         }
2107 
2108         //
getCommandString()2109         public String getCommandString() {
2110 
2111             int treeDepth = treePath.getPathCount();
2112 
2113             // if we are at TABLE depth, set tablePath and table for use later
2114             if (treeDepth == DEPTH_URL) {
2115                 return "";
2116             }
2117 
2118             if (treeDepth == DEPTH_TABLE) {
2119                 tablePath = treePath;
2120                 table = treePath.getPathComponent(DEPTH_TABLE - 1).toString();
2121             }
2122 
2123             // if we are at TABLE depth, set columnPath, column, tablePath and
2124             // table for use later
2125             if (treeDepth == DEPTH_COLUMN) {
2126                 tablePath  = treePath.getParentPath();
2127                 table = treePath.getPathComponent(DEPTH_TABLE - 1).toString();
2128                 columnPath = treePath;
2129                 column = treePath.getPathComponent(DEPTH_COLUMN
2130                                                    - 1).toString();
2131             }
2132 
2133             // handle command "SELECT".  Use table and column if set.
2134             if (command.toUpperCase().equals("SELECT")) {
2135                 String result = "SELECT * FROM " + quoteTableName(table);
2136 
2137                 if (column != null) {
2138                     DefaultMutableTreeNode childNode =
2139                         (DefaultMutableTreeNode) treePath
2140                             .getLastPathComponent();
2141                     String  childName = null;
2142                     boolean isChar;
2143 
2144                     if (childNode.getChildCount() > 0) {
2145                         childName = childNode.getFirstChild().toString();
2146                         isChar    = childName.indexOf("CHAR") >= 0;
2147                         result    += " WHERE " + quoteObjectName(column);
2148 
2149                         if (isChar) {
2150                             result += " LIKE \'%%\'";
2151                         } else {
2152                             result += " = ";
2153                         }
2154                     }
2155                 }
2156 
2157                 return result;
2158             }
2159 
2160             // handle command "UPDATE".  Use table and column if set.
2161             else if (command.toUpperCase().equals("UPDATE")) {
2162                 String result = "UPDATE " + quoteTableName(table) + " SET ";
2163 
2164                 if (column != null) {
2165                     result += quoteObjectName(column) + " = ";
2166                 }
2167 
2168                 return result;
2169             }
2170 
2171             // handle command "DELETE".  Use table and column if set.
2172             else if (command.toUpperCase().equals("DELETE")) {
2173                 String result = "DELETE FROM " + quoteTableName(table);
2174 
2175                 if (column != null) {
2176                     DefaultMutableTreeNode childNode =
2177                         (DefaultMutableTreeNode) treePath
2178                             .getLastPathComponent();
2179                     String  childName = null;
2180                     boolean isChar;
2181 
2182                     if (childNode.getChildCount() > 0) {
2183                         childName = childNode.getFirstChild().toString();
2184                         isChar    = childName.indexOf("CHAR") >= 0;
2185                         result    += " WHERE " + quoteObjectName(column);
2186 
2187                         if (isChar) {
2188                             result += " LIKE \'%%\'";
2189                         } else {
2190                             result += " = ";
2191                         }
2192                     }
2193                 }
2194 
2195                 return result;
2196             }
2197 
2198             // handle command "INSERT".  Use table and column if set.
2199             else if (command.toUpperCase().equals("INSERT")) {
2200                 TreeNode    tableNode;
2201                 Enumeration enumer;
2202                 String      columns = "";
2203                 String      values  = " ";
2204                 String      comma   = "";
2205                 String      quote   = "";
2206 
2207                 // build a string that includes all the columns that need to
2208                 // be added, with a parenthesied list of commas, suitable for
2209                 // inserting values into.
2210                 if (tablePath == null) {
2211                     return null;
2212                 }
2213 
2214                 tableNode = (TreeNode) tablePath.getLastPathComponent();
2215                 enumer    = tableNode.children();
2216 
2217                 while (enumer.hasMoreElements()) {
2218                     Object o = enumer.nextElement();
2219 
2220                     if (o.toString().equals("Indices")) {
2221                         continue;
2222                     }
2223 
2224                     DefaultMutableTreeNode childNode =
2225                         (DefaultMutableTreeNode) o;
2226                     String childName = null;
2227 
2228                     if (childNode.getChildCount() == 0) {
2229                         continue;
2230                     } else {
2231                         childName = childNode.getFirstChild().toString();
2232                     }
2233 
2234                     // If our first child (type) is some sort of char, use ''
2235                     // in the string.  Makes is more obvious to the user when
2236                     // they need to use a string
2237                     if (childName.indexOf("CHAR") >= 0) {
2238                         quote = "\'\'";
2239                     } else {
2240                         quote = "";
2241                     }
2242 
2243                     columns += comma + quoteObjectName(o.toString());
2244                     values  += comma + quote;
2245                     comma   = ", ";
2246                 }
2247 
2248                 return "INSERT INTO " + quoteTableName(table) + "\n( "
2249                        + columns + " )\nVALUES (" + values + ")";
2250             } else {
2251                 return "Got here in error " + command
2252                        + ".  Should never happen";
2253             }
2254         }
2255     }
2256 
2257     /**
2258      * Perform a limited check (inconclusive) and quote object name if required.
2259      * Gives wrong result if a quoted name contains a dot.
2260      */
quoteTableName(String name)2261     private String quoteTableName(String name) {
2262 
2263         int dot = name.indexOf(".");
2264 
2265         if (dot < 0) {
2266             int bracket = name.indexOf(" (");
2267 
2268             if (bracket >= 0) {
2269                 name = name.substring(0, bracket);
2270             }
2271 
2272             return quoteObjectName(name);
2273         }
2274 
2275         String partOne = name.substring(0, dot);
2276         String partTwo = name.substring(dot + 1);
2277         int    bracket = partTwo.indexOf(" (");
2278 
2279         if (bracket >= 0) {
2280             partTwo = partTwo.substring(0, bracket);
2281         }
2282 
2283         return quoteObjectName(partOne) + '.' + quoteObjectName(partTwo);
2284     }
2285 
2286     /**
2287      * perform a limited check (inconclusive) and quote object name if required
2288      */
quoteObjectName(String name)2289     private String quoteObjectName(String name) {
2290 
2291 /*
2292         if (name.toUpperCase().equals(name) && name.indexOf(' ') < 0) {
2293             return name;
2294         }
2295 */
2296         return "\"" + name + "\"";
2297     }
2298 
initGUI()2299     private void initGUI() {
2300 
2301         JPanel pCommand = new JPanel();
2302 
2303         pResult = new JPanel();
2304         nsSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, pCommand,
2305                                      pResult);
2306 
2307         // Added: (weconsultants@users)
2308         nsSplitPane.setOneTouchExpandable(true);
2309         pCommand.setLayout(new BorderLayout());
2310         pResult.setLayout(new BorderLayout());
2311 
2312         Font fFont = new Font("Dialog", Font.PLAIN, 12);
2313 
2314         txtCommand = new JTextArea(7, 40);
2315 
2316         txtCommand.setMargin(new Insets(5, 5, 5, 5));
2317         txtCommand.addKeyListener(this);
2318 
2319         txtCommandScroll = new JScrollPane(txtCommand);
2320         txtResult        = new JTextArea(25, 40);
2321 
2322         txtResult.setMargin(new Insets(5, 5, 5, 5));
2323 
2324         txtResultScroll = new JScrollPane(txtResult);
2325 
2326         txtCommand.setFont(fFont);
2327         txtResult.setFont(new Font("Courier", Font.PLAIN, 12));
2328         pCommand.add(txtCommandScroll, BorderLayout.CENTER);
2329 
2330         gResult = new GridSwing();
2331 
2332         TableSorter sorter = new TableSorter(gResult);
2333 
2334         tableModel   = sorter;
2335         gResultTable = new JTable(sorter);
2336 
2337         sorter.setTableHeader(gResultTable.getTableHeader());
2338 
2339         gScrollPane = new JScrollPane(gResultTable);
2340 
2341         gResultTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
2342         gResult.setJTable(gResultTable);
2343 
2344         //getContentPane().setLayout(new BorderLayout());
2345         pResult.add(gScrollPane, BorderLayout.CENTER);
2346 
2347         // Set up the tree
2348         rootNode    = new DefaultMutableTreeNode("Connection");
2349         treeModel   = new DefaultTreeModel(rootNode);
2350         tTree       = new JTree(treeModel);
2351         tScrollPane = new JScrollPane(tTree);
2352 
2353         // System.out.println("Adding mouse listener");
2354         tTree.addMouseListener(this);
2355         tScrollPane.setPreferredSize(new Dimension(200, 400));
2356         tScrollPane.setMinimumSize(new Dimension(70, 100));
2357         txtCommandScroll.setPreferredSize(new Dimension(560, 100));
2358         txtCommandScroll.setMinimumSize(new Dimension(180, 100));
2359         gScrollPane.setPreferredSize(new Dimension(460, 300));
2360 
2361         ewSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, tScrollPane,
2362                                      nsSplitPane);
2363 
2364         // Added: (weconsultants@users)
2365         ewSplitPane.setOneTouchExpandable(true);
2366         fMain.getContentPane().add(ewSplitPane, BorderLayout.CENTER);
2367 
2368         // Added: (weconsultants@users)
2369         jStatusLine = new JLabel();
2370         iReadyStatus =
2371             new JButton(new ImageIcon(CommonSwing.getIcon("StatusReady")));
2372 
2373         iReadyStatus.setSelectedIcon(
2374             new ImageIcon(CommonSwing.getIcon("StatusRunning")));
2375 
2376         pStatus = new JPanel();
2377 
2378         pStatus.setLayout(new BorderLayout());
2379         pStatus.add(iReadyStatus, BorderLayout.WEST);
2380         pStatus.add(jStatusLine, BorderLayout.CENTER);
2381         fMain.getContentPane().add(pStatus, "South");
2382         doLayout();
2383 
2384         if (fMain instanceof java.awt.Window) {
2385             ((java.awt.Window) fMain).pack();
2386         } else {
2387             ((Container) fMain).validate();
2388         }
2389     }
2390 
2391     /* Simple tree node factory method - set's parent and user object.
2392      */
makeNode(Object userObject, MutableTreeNode parent)2393     private DefaultMutableTreeNode makeNode(Object userObject,
2394             MutableTreeNode parent) {
2395 
2396         DefaultMutableTreeNode node = new DefaultMutableTreeNode(userObject);
2397 
2398         if (parent != null) {
2399             treeModel.insertNodeInto(node, parent, parent.getChildCount());
2400         }
2401 
2402         return node;
2403     }
2404 
2405     private static final String[] usertables       = {
2406         "TABLE", "GLOBAL TEMPORARY", "VIEW", "SYSTEM TABLE"
2407     };
2408     private static final String[] nonSystables     = {
2409         "TABLE", "GLOBAL TEMPORARY", "VIEW"
2410     };
2411     private static final HashSet  oracleSysUsers   = new HashSet();
2412     private static final String[] oracleSysSchemas = {
2413         "SYS", "SYSTEM", "OUTLN", "DBSNMP", "OUTLN", "MDSYS", "ORDSYS",
2414         "ORDPLUGINS", "CTXSYS", "DSSYS", "PERFSTAT", "WKPROXY", "WKSYS",
2415         "WMSYS", "XDB", "ANONYMOUS", "ODM", "ODM_MTR", "OLAPSYS", "TRACESVR",
2416         "REPADMIN"
2417     };
2418 
2419     static {
2420         for (int i = 0; i < oracleSysSchemas.length; i++) {
2421             oracleSysUsers.add(oracleSysSchemas[i]);
2422         }
2423     }
2424 
2425     /**
2426      * Schedules to run in a Gui-safe thread
2427      */
refreshTree()2428     protected void refreshTree() {
2429         backgroundIt(treeRefreshRunnable, "Refreshing object tree");
2430     }
2431 
2432     /**
2433      * Clear all existing nodes from the tree model and rebuild from scratch.
2434      *
2435      * This method executes in current thread
2436      */
directRefreshTree()2437     protected void directRefreshTree() {
2438 
2439         int[]                  rowCounts;
2440         DefaultMutableTreeNode propertiesNode;
2441 
2442         // Added: (weconsultants@users) Moved tableNode here for visibiity nd new DECFM
2443         DefaultMutableTreeNode tableNode;
2444         DecimalFormat DECFMT = new DecimalFormat(" ( ####,###,####,##0 )");
2445 
2446         // First clear the existing tree by simply enumerating
2447         // over the root node's children and removing them one by one.
2448         while (treeModel.getChildCount(rootNode) > 0) {
2449             DefaultMutableTreeNode child =
2450                 (DefaultMutableTreeNode) treeModel.getChild(rootNode, 0);
2451 
2452             treeModel.removeNodeFromParent(child);
2453             child.removeAllChildren();
2454             child.removeFromParent();
2455         }
2456 
2457         treeModel.nodeStructureChanged(rootNode);
2458         treeModel.reload();
2459         tScrollPane.repaint();
2460 
2461         ResultSet result = null;
2462 
2463         // Now rebuild the tree below its root
2464         try {
2465 
2466             // Start by naming the root node from its URL:
2467             rootNode.setUserObject(dMeta.getURL());
2468 
2469             // get metadata about user tables by building a vector of table names
2470             result = dMeta.getTables(null, null, null, (showSys ? usertables
2471                                                                 : nonSystables));
2472 
2473             Vector tables  = new Vector();
2474             Vector schemas = new Vector();
2475 
2476             // sqlbob@users Added remarks.
2477             Vector remarks = new Vector();
2478             String schema;
2479 
2480             while (result.next()) {
2481                 schema = result.getString(2);
2482 
2483                 if ((!showSys) && isOracle
2484                         && oracleSysUsers.contains(schema)) {
2485                     continue;
2486                 }
2487 
2488                 if (schemaFilter == null || schema.equals(schemaFilter)) {
2489                     schemas.addElement(schema);
2490                     tables.addElement(result.getString(3));
2491                     remarks.addElement(result.getString(5));
2492 
2493                     continue;
2494                 }
2495             }
2496 
2497             result.close();
2498 
2499             result = null;
2500 
2501             // Added: (weconsultants@users)
2502             // Sort not to go into production. Have to sync with 'remarks Vector' for DBMS that has it
2503             //   Collections.sort(tables);
2504             // Added: (weconsultants@users) - Add rowCounts if needed.
2505             rowCounts = new int[tables.size()];
2506 
2507             try {
2508                 rowCounts = getRowCounts(tables, schemas);
2509             } catch (Exception e) {
2510 
2511                 //  Added: (weconsultants@users)
2512                 CommonSwing.errorMessage(e);
2513             }
2514 
2515             ResultSet col;
2516 
2517             // For each table, build a tree node with interesting info
2518             for (int i = 0; i < tables.size(); i++) {
2519                 col = null;
2520 
2521                 String name;
2522 
2523                 try {
2524                     name = (String) tables.elementAt(i);
2525 
2526                     if (isOracle && name.startsWith("BIN$")) {
2527                         continue;
2528 
2529                         // Oracle Recyle Bin tables.
2530                         // Contains metacharacters which screw up metadata
2531                         // queries below.
2532                     }
2533 
2534                     schema = (String) schemas.elementAt(i);
2535 
2536                     String schemaname = "";
2537 
2538                     if (schema != null && showSchemas) {
2539                         schemaname = schema + '.';
2540                     }
2541 
2542                     String rowcount = displayRowCounts
2543                                       ? (DECFMT.format(rowCounts[i]))
2544                                       : "";
2545                     String displayedName = schemaname + name + rowcount;
2546 
2547                     // weconsul@ptd.net Add rowCounts if needed.
2548                     tableNode = makeNode(displayedName, rootNode);
2549                     col       = dMeta.getColumns(null, schema, name, null);
2550 
2551                     if ((schema != null) && !schema.trim().equals("")) {
2552                         makeNode(schema, tableNode);
2553                     }
2554 
2555                     // sqlbob@users Added remarks.
2556                     String remark = (String) remarks.elementAt(i);
2557 
2558                     if ((remark != null) && !remark.trim().equals("")) {
2559                         makeNode(remark, tableNode);
2560                     }
2561 
2562                     // This block is very slow for some Oracle tables.
2563                     // With a child for each column containing pertinent attributes
2564                     while (col.next()) {
2565                         String c = col.getString(4);
2566                         DefaultMutableTreeNode columnNode = makeNode(c,
2567                             tableNode);
2568                         String type = col.getString(6);
2569 
2570                         makeNode("Type: " + type, columnNode);
2571 
2572                         boolean nullable = col.getInt(11)
2573                                            != DatabaseMetaData.columnNoNulls;
2574 
2575                         makeNode("Nullable: " + nullable, columnNode);
2576                     }
2577                 } finally {
2578                     if (col != null) {
2579                         try {
2580                             col.close();
2581                         } catch (SQLException se) {}
2582                     }
2583                 }
2584 
2585                 DefaultMutableTreeNode indexesNode = makeNode("Indices",
2586                     tableNode);
2587 
2588                 if (showIndexDetails) {
2589                     ResultSet ind = null;
2590 
2591                     try {
2592                         ind = dMeta.getIndexInfo(null, schema, name, false,
2593                                                  false);
2594 
2595                         String                 oldiname  = null;
2596                         DefaultMutableTreeNode indexNode = null;
2597 
2598                         // A child node to contain each index - and its attributes
2599                         while (ind.next()) {
2600                             boolean nonunique = ind.getBoolean(4);
2601                             String  iname     = ind.getString(6);
2602 
2603                             if ((oldiname == null
2604                                     || !oldiname.equals(iname))) {
2605                                 indexNode = makeNode(iname, indexesNode);
2606 
2607                                 makeNode("Unique: " + !nonunique, indexNode);
2608 
2609                                 oldiname = iname;
2610                             }
2611 
2612                             // And the ordered column list for index components
2613                             makeNode(ind.getString(9), indexNode);
2614                         }
2615                     } catch (SQLException se) {
2616 
2617                         // Workaround for Oracle
2618                         if (se.getMessage() == null || ((!se.getMessage()
2619                                 .startsWith("ORA-25191:")) && (!se.getMessage()
2620                                 .startsWith("ORA-01702:")) && !se.getMessage()
2621                                     .startsWith("ORA-01031:"))) {
2622                             throw se;
2623                         }
2624                     } finally {
2625                         if (ind != null) {
2626                             ind.close();
2627 
2628                             ind = null;
2629                         }
2630                     }
2631                 }
2632             }
2633 
2634             // Finally - a little additional metadata on this connection
2635             propertiesNode = makeNode("Properties", rootNode);
2636 
2637             makeNode("User: " + dMeta.getUserName(), propertiesNode);
2638             makeNode("ReadOnly: " + cConn.isReadOnly(), propertiesNode);
2639             makeNode("AutoCommit: " + cConn.getAutoCommit(), propertiesNode);
2640             makeNode("Driver: " + dMeta.getDriverName(), propertiesNode);
2641             makeNode("Product: " + dMeta.getDatabaseProductName(),
2642                      propertiesNode);
2643             makeNode("Version: " + dMeta.getDatabaseProductVersion(),
2644                      propertiesNode);
2645         } catch (SQLException se) {
2646             propertiesNode = makeNode("Error getting metadata:", rootNode);
2647 
2648             makeNode(se.getMessage(), propertiesNode);
2649             makeNode(se.getSQLState(), propertiesNode);
2650             CommonSwing.errorMessage(se);
2651         } finally {
2652             if (result != null) {
2653                 try {
2654                     result.close();
2655                 } catch (SQLException se) {}
2656             }
2657         }
2658 
2659         treeModel.nodeStructureChanged(rootNode);
2660         treeModel.reload();
2661         tScrollPane.repaint();
2662 
2663         // We want the Schema List to always be in sync with the displayed tree
2664         updateSchemaList();
2665     }
2666 
2667     // Added: (weconsultants@users) Sets up\changes the running status icon
setStatusLine(String busyBaseString, int rowCount)2668     void setStatusLine(String busyBaseString, int rowCount) {
2669 
2670         iReadyStatus.setSelected(busyBaseString != null);
2671 
2672         if (busyBaseString == null) {
2673             String additionalMsg = "";
2674 
2675             if (schemaFilter != null) {
2676                 additionalMsg = " /  Tree showing objects in schema '"
2677                                 + schemaFilter + "'";
2678             }
2679 
2680             if (rowCount > 1) {
2681                 additionalMsg += " / " + rowCount + " rows retrieved";
2682             }
2683 
2684             jStatusLine.setText("  " + READY_STATUS + additionalMsg);
2685         } else {
2686             jStatusLine.setText("  " + busyBaseString + "...");
2687         }
2688     }
2689 
2690     // Added: (weconsultants@users) Needed to aggragate counts per table in jTree
getRowCounts(Vector inTable, Vector inSchema)2691     protected int[] getRowCounts(Vector inTable,
2692                                  Vector inSchema) throws Exception {
2693 
2694         if (!displayRowCounts) {
2695             return (null);
2696         }
2697 
2698         String rowCountSelect = "SELECT COUNT(*) FROM ";
2699         int[]  counts;
2700         String name;
2701 
2702         counts = new int[inTable.size()];
2703 
2704         try {
2705             Statement select = rowConn.createStatement();
2706 
2707             for (int i = 0; i < inTable.size(); i++) {
2708                 try {
2709                     String schemaPart = (String) inSchema.elementAt(i);
2710 
2711                     schemaPart = schemaPart == null ? ""
2712                                                     : ("\"" + schemaPart
2713                                                        + "\".\"");
2714                     name = schemaPart + (String) inTable.elementAt(i) + "\"";
2715 
2716                     ResultSet resultSet = select.executeQuery(rowCountSelect
2717                         + name);
2718 
2719                     while (resultSet.next()) {
2720                         counts[i] = resultSet.getInt(1);
2721                     }
2722                 } catch (Exception e) {
2723                     System.err.println("Unable to get row count for table "
2724                                        + inSchema.elementAt(i) + '.'
2725                                        + inTable.elementAt(i)
2726                                        + ".  Using value '0': " + e);
2727                 }
2728             }
2729         } catch (Exception e) {
2730             CommonSwing.errorMessage(e);
2731         }
2732 
2733         return (counts);
2734     }
2735 
createToolBar()2736     protected JToolBar createToolBar() {
2737 
2738         // Build jtoolbar and jtoolbar Buttons
2739         JToolBar jtoolbar = new JToolBar();
2740 
2741         jtoolbar.putClientProperty("JToolBar.isRollover", Boolean.TRUE);
2742 
2743         // I'm dropping "Statement" from  "Execute SQL Statement", etc.,
2744         // because it may or may not be "one statement", but it is SQL.
2745         // Build jbuttonClear Buttons - blaine
2746         jbuttonClear =
2747             new JButton("Clear SQL",
2748                         new ImageIcon(CommonSwing.getIcon("Clear")));
2749 
2750         jbuttonClear.putClientProperty("is3DEnabled", Boolean.TRUE);
2751         tipMap.put(jbuttonClear, "Clear SQL");
2752         jbuttonClear.addActionListener(new ActionListener() {
2753 
2754             public void actionPerformed(ActionEvent actionevent) {
2755 
2756                 if (sqlScriptBuffer == null
2757                         && txtCommand.getText().length() < 1) {
2758                     CommonSwing.errorMessage("No SQL to clear");
2759 
2760                     return;
2761                 }
2762 
2763                 clear();
2764             }
2765         });
2766 
2767         jbuttonExecute =
2768             new JButton("Execute SQL",
2769                         new ImageIcon(CommonSwing.getIcon("Execute")));
2770 
2771         tipMap.put(jbuttonExecute, "Execute SQL");
2772         jbuttonExecute.putClientProperty("is3DEnabled", Boolean.TRUE);
2773         jbuttonExecute.addActionListener(new ActionListener() {
2774 
2775             public void actionPerformed(ActionEvent actionevent) {
2776                 executeCurrentSQL();
2777             }
2778         });
2779         jtoolbar.addSeparator();
2780         jtoolbar.add(jbuttonClear);
2781         jtoolbar.addSeparator();
2782         jtoolbar.add(jbuttonExecute);
2783         jtoolbar.addSeparator();
2784         jbuttonClear.setAlignmentY(0.5F);
2785         jbuttonClear.setAlignmentX(0.5F);
2786         jbuttonExecute.setAlignmentY(0.5F);
2787         jbuttonExecute.setAlignmentX(0.5F);
2788 
2789         return jtoolbar;
2790     }
2791 
updateAutoCommitBox()2792     void updateAutoCommitBox() {
2793 
2794         try {
2795             boxAutoCommit.setSelected(cConn.getAutoCommit());
2796         } catch (SQLException se) {
2797             CommonSwing.errorMessage(se);
2798         }
2799     }
2800 
setLF(String newLAF)2801     private void setLF(String newLAF) {
2802 
2803         if (currentLAF != null && currentLAF == newLAF) {    // No change
2804             return;
2805         }
2806 
2807         if (pResult != null && gridFormat) {
2808             pResult.removeAll();
2809         }
2810 
2811         CommonSwing.setSwingLAF((Component) fMain, newLAF);
2812 
2813         if (pResult != null && gridFormat) {
2814             setResultsInGrid();
2815         }
2816 
2817         currentLAF = newLAF;
2818 
2819         if (currentLAF.equals(CommonSwing.Native)) {
2820             rbNativeLF.setSelected(true);
2821         } else if (currentLAF.equals(CommonSwing.Java)) {
2822             rbJavaLF.setSelected(true);
2823         } else if (currentLAF.equals(CommonSwing.Motif)) {
2824             rbMotifLF.setSelected(true);
2825         }
2826     }
2827 
resetTooltips()2828     void resetTooltips() {
2829 
2830         Iterator   it = tipMap.keySet().iterator();
2831         JComponent component;
2832 
2833         while (it.hasNext()) {
2834             component = (JComponent) it.next();
2835 
2836             component.setToolTipText(showTooltips
2837                                      ? ((String) tipMap.get(component))
2838                                      : (String) null);
2839         }
2840     }
2841 
updateSchemaList()2842     private void updateSchemaList() {
2843 
2844         ButtonGroup group  = new ButtonGroup();
2845         ArrayList   list   = new ArrayList();
2846         ResultSet   result = null;
2847 
2848         try {
2849             result = dMeta.getSchemas();
2850 
2851             if (result == null) {
2852                 throw new SQLException("Failed to get metadata from database");
2853             }
2854 
2855             while (result.next()) {
2856                 list.add(result.getString(1));
2857             }
2858         } catch (SQLException se) {
2859             CommonSwing.errorMessage(se);
2860         } finally {
2861             if (result != null) {
2862                 try {
2863                     result.close();
2864                 } catch (SQLException se) {}
2865             }
2866         }
2867 
2868         mnuSchemas.removeAll();
2869         rbAllSchemas.setSelected(schemaFilter == null);
2870         group.add(rbAllSchemas);
2871         mnuSchemas.add(rbAllSchemas);
2872 
2873         String               s;
2874         JRadioButtonMenuItem radioButton;
2875 
2876         for (int i = 0; i < list.size(); i++) {
2877             s           = (String) list.get(i);
2878             radioButton = new JRadioButtonMenuItem(s);
2879 
2880             group.add(radioButton);
2881             mnuSchemas.add(radioButton);
2882             radioButton.setSelected(schemaFilter != null
2883                                     && schemaFilter.equals(s));
2884             radioButton.addActionListener(schemaListListener);
2885             radioButton.setEnabled(list.size() > 1);
2886         }
2887 
2888         mnuSchemas.addSeparator();
2889         mnuSchemas.add(mitemUpdateSchemas);
2890     }
2891 
2892     ActionListener schemaListListener = (new ActionListener() {
2893 
2894         public void actionPerformed(ActionEvent actionevent) {
2895 
2896             schemaFilter = actionevent.getActionCommand();
2897 
2898             if (schemaFilter.equals("*")) {
2899                 schemaFilter = null;
2900             }
2901 
2902             refreshTree();
2903         }
2904     });
2905 
2906     /**
2907      * Persisted User Preferences for DatabaseManagerSwing.
2908      *
2909      * These are settings for items in the View and Options pulldown menus,
2910      * plus Help/Show Tooltips.
2911      */
2912     public class DBMPrefs {
2913 
2914         public File prefsFile = null;
2915 
2916         /**
2917          * The constructor guarantees that this will be null for Applet,
2918          *  non-null if using a local preferences file
2919          */
2920 
2921         // Set defaults from Data
2922         boolean autoRefresh   = true;
2923         boolean showRowCounts = false;
2924         boolean showSysTables = false;
2925         boolean showSchemas   = true;
2926         boolean resultGrid    = true;
2927         String  laf           = CommonSwing.Native;
2928 
2929         // Somebody with more time can store the font settings.  IMO, that
2930         // menu item shouldn't even be there if the settings aren't persisted.
2931         boolean showTooltips = true;
2932 
DBMPrefs(boolean isApplet)2933         public DBMPrefs(boolean isApplet) throws IOException {
2934 
2935             if (isApplet) {}
2936             else {
2937                 if (homedir == null) {
2938                     throw new IOException(
2939                         "Skipping preferences since do not know home dir");
2940                 }
2941 
2942                 prefsFile = new File(homedir, "dbmprefs.properties");
2943             }
2944 
2945             load();
2946         }
2947 
load()2948         public void load() throws IOException {
2949 
2950             String tmpString;
2951 
2952             if (prefsFile == null) {
2953 
2954                 // LOAD PREFERENCES FROM APPLET PARAMS
2955                 tmpString = getParameter("autoRefresh");
2956 
2957                 if (tmpString != null) {
2958                     autoRefresh = Boolean.valueOf(tmpString).booleanValue();
2959                 }
2960 
2961                 tmpString = getParameter("showRowCounts");
2962 
2963                 if (tmpString != null) {
2964                     showRowCounts = Boolean.valueOf(tmpString).booleanValue();
2965                 }
2966 
2967                 tmpString = getParameter("showSysTables");
2968 
2969                 if (tmpString != null) {
2970                     showSysTables = Boolean.valueOf(tmpString).booleanValue();
2971                 }
2972 
2973                 tmpString = getParameter("showSchemas");
2974 
2975                 if (tmpString != null) {
2976                     showSchemas = Boolean.valueOf(tmpString).booleanValue();
2977                 }
2978 
2979                 tmpString = getParameter("resultGrid");
2980 
2981                 if (tmpString != null) {
2982                     resultGrid = Boolean.valueOf(tmpString).booleanValue();
2983                 }
2984 
2985                 tmpString = getParameter("laf");
2986                 laf       = ((tmpString == null) ? CommonSwing.Native
2987                                                  : tmpString);
2988                 tmpString = getParameter("showTooltips");
2989 
2990                 if (tmpString != null) {
2991                     showTooltips = Boolean.valueOf(tmpString).booleanValue();
2992                 }
2993             } else {
2994 
2995                 // LOAD PREFERENCES FROM LOCAL PREFERENCES FILE
2996                 if (!prefsFile.exists()) {
2997                     throw new IOException("No such file: " + prefsFile);
2998                 }
2999 
3000                 Properties props = new Properties();
3001 
3002                 try {
3003                     FileInputStream fis = new FileInputStream(prefsFile);
3004 
3005                     props.load(fis);
3006                     fis.close();
3007                 } catch (IOException ioe) {
3008                     throw new IOException("Failed to read preferences file '"
3009                                           + prefsFile + "':  "
3010                                           + ioe.getMessage());
3011                 }
3012 
3013                 tmpString = props.getProperty("autoRefresh");
3014 
3015                 if (tmpString != null) {
3016                     autoRefresh = Boolean.valueOf(tmpString).booleanValue();
3017                 }
3018 
3019                 tmpString = props.getProperty("showRowCounts");
3020 
3021                 if (tmpString != null) {
3022                     showRowCounts = Boolean.valueOf(tmpString).booleanValue();
3023                 }
3024 
3025                 tmpString = props.getProperty("showSysTables");
3026 
3027                 if (tmpString != null) {
3028                     showSysTables = Boolean.valueOf(tmpString).booleanValue();
3029                 }
3030 
3031                 tmpString = props.getProperty("showSchemas");
3032 
3033                 if (tmpString != null) {
3034                     showSchemas = Boolean.valueOf(tmpString).booleanValue();
3035                 }
3036 
3037                 tmpString = props.getProperty("resultGrid");
3038 
3039                 if (tmpString != null) {
3040                     resultGrid = Boolean.valueOf(tmpString).booleanValue();
3041                 }
3042 
3043                 tmpString = props.getProperty("laf");
3044                 laf       = ((tmpString == null) ? CommonSwing.Native
3045                                                  : tmpString);
3046                 tmpString = props.getProperty("showTooltips");
3047 
3048                 if (tmpString != null) {
3049                     showTooltips = Boolean.valueOf(tmpString).booleanValue();
3050                 }
3051             }
3052         }
3053 
store()3054         public void store() {
3055 
3056             if (prefsFile == null) {
3057 
3058                 // Can't persist Applet settings.
3059                 return;
3060             }
3061 
3062             Properties props = new Properties();
3063 
3064             // Boolean.toString(boolean) was new with Java 1.4, so don't use that.
3065             props.setProperty("autoRefresh", (autoRefresh ? tString
3066                                                           : fString));
3067             props.setProperty("showRowCounts", (showRowCounts ? tString
3068                                                               : fString));
3069             props.setProperty("showSysTables", (showSysTables ? tString
3070                                                               : fString));
3071             props.setProperty("showSchemas", (showSchemas ? tString
3072                                                           : fString));
3073             props.setProperty("resultGrid", (resultGrid ? tString
3074                                                         : fString));
3075             props.setProperty("laf", laf);
3076             props.setProperty("showTooltips", (showTooltips ? tString
3077                                                             : fString));
3078 
3079             try {
3080                 FileOutputStream fos = new FileOutputStream(prefsFile);
3081 
3082                 props.store(fos, "DatabaseManagerSwing user preferences");
3083                 fos.flush();
3084                 fos.close();
3085             } catch (IOException ioe) {
3086                 throw new RuntimeException(
3087                     "Failed to prepare preferences file '" + prefsFile
3088                     + "':  " + ioe.getMessage());
3089             }
3090         }
3091     }
3092 
3093     private static final String tString = Boolean.TRUE.toString();
3094     private static final String fString = Boolean.FALSE.toString();
3095 }
3096