0001: /* Copyright (c) 1995-2000, The Hypersonic SQL Group.
0002: * All rights reserved.
0003: *
0004: * Redistribution and use in source and binary forms, with or without
0005: * modification, are permitted provided that the following conditions are met:
0006: *
0007: * Redistributions of source code must retain the above copyright notice, this
0008: * list of conditions and the following disclaimer.
0009: *
0010: * Redistributions in binary form must reproduce the above copyright notice,
0011: * this list of conditions and the following disclaimer in the documentation
0012: * and/or other materials provided with the distribution.
0013: *
0014: * Neither the name of the Hypersonic SQL Group nor the names of its
0015: * contributors may be used to endorse or promote products derived from this
0016: * software without specific prior written permission.
0017: *
0018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0021: * ARE DISCLAIMED. IN NO EVENT SHALL THE HYPERSONIC SQL GROUP,
0022: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0025: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0026: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0027: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0028: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0029: *
0030: * This software consists of voluntary contributions made by many individuals
0031: * on behalf of the Hypersonic SQL Group.
0032: *
0033: *
0034: * For work added by the HSQL Development Group:
0035: *
0036: * Copyright (c) 2001-2005, The HSQL Development Group
0037: * All rights reserved.
0038: *
0039: * Redistribution and use in source and binary forms, with or without
0040: * modification, are permitted provided that the following conditions are met:
0041: *
0042: * Redistributions of source code must retain the above copyright notice, this
0043: * list of conditions and the following disclaimer.
0044: *
0045: * Redistributions in binary form must reproduce the above copyright notice,
0046: * this list of conditions and the following disclaimer in the documentation
0047: * and/or other materials provided with the distribution.
0048: *
0049: * Neither the name of the HSQL Development Group nor the names of its
0050: * contributors may be used to endorse or promote products derived from this
0051: * software without specific prior written permission.
0052: *
0053: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0054: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0055: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0056: * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
0057: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0058: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0059: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0060: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0061: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0062: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0063: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0064: */
0065:
0066: package org.hsqldb.util;
0067:
0068: import java.io.File;
0069: import java.io.FileInputStream;
0070: import java.io.FileOutputStream;
0071: import java.io.IOException;
0072: import java.lang.reflect.Constructor;
0073: import java.lang.reflect.InvocationTargetException;
0074: import java.sql.Connection;
0075: import java.sql.DatabaseMetaData;
0076: import java.sql.Driver;
0077: import java.sql.DriverManager;
0078: import java.sql.ResultSet;
0079: import java.sql.ResultSetMetaData;
0080: import java.sql.SQLException;
0081: import java.sql.Statement;
0082: import java.text.DecimalFormat;
0083: import java.util.ArrayList;
0084: import java.util.HashMap;
0085: import java.util.HashSet;
0086: import java.util.Hashtable;
0087: import java.util.Iterator;
0088: import java.util.Locale;
0089: import java.util.Properties;
0090: import java.util.Vector;
0091: import java.awt.BorderLayout;
0092: import java.awt.Cursor;
0093: import java.awt.Dimension;
0094: import java.awt.Event;
0095: import java.awt.Font;
0096: import java.awt.Insets;
0097: import java.awt.Toolkit;
0098: import java.awt.event.ActionEvent;
0099: import java.awt.event.ActionListener;
0100: import java.awt.event.KeyEvent;
0101: import java.awt.event.KeyListener;
0102: import java.awt.event.WindowEvent;
0103: import java.awt.event.WindowListener;
0104: import java.awt.Component;
0105: import java.awt.Container;
0106:
0107: import javax.swing.ButtonGroup;
0108: import javax.swing.ImageIcon;
0109: import javax.swing.JApplet;
0110: import javax.swing.JButton;
0111: import javax.swing.JCheckBoxMenuItem;
0112: import javax.swing.JComponent;
0113: import javax.swing.JFileChooser;
0114: import javax.swing.JFrame;
0115: import javax.swing.JLabel;
0116: import javax.swing.JMenu;
0117: import javax.swing.JMenuBar;
0118: import javax.swing.JMenuItem;
0119: import javax.swing.JOptionPane;
0120: import javax.swing.JPanel;
0121: import javax.swing.JRadioButtonMenuItem;
0122: import javax.swing.JScrollPane;
0123: import javax.swing.JSplitPane;
0124: import javax.swing.JTable;
0125: import javax.swing.JTextArea;
0126: import javax.swing.JToolBar;
0127: import javax.swing.JTree;
0128: import javax.swing.KeyStroke;
0129: import javax.swing.SwingUtilities;
0130: import javax.swing.table.TableModel;
0131: import javax.swing.tree.DefaultMutableTreeNode;
0132: import javax.swing.tree.DefaultTreeModel;
0133: import javax.swing.tree.MutableTreeNode;
0134: import javax.swing.RootPaneContainer;
0135:
0136: import java.security.AccessControlException;
0137:
0138: import org.hsqldb.lib.java.JavaSystem;
0139:
0140: //dmarshall@users - 20020101 - original swing port of DatabaseManager
0141: //sqlbob@users 20020401 - patch 537501 by ulrivo - commandline arguments
0142: //sqlbob@users 20020407 - patch 1.7.0 - reengineering and enhancements
0143: //nickferguson@users 20021005 - patch 1.7.1 - enhancements
0144: //deccles@users 20040412 - patch 933671 - various bug fixes
0145: //deccles@users 2004xxxx - enhancements
0146: //weconsultants@users 20041109 - version 1.8.0 - reengineering and enhancements:
0147: // Added: Goodies 'Look and Feel'.
0148: // Added: a Font Changer(Font Type\Style).
0149: // Added: a Color Changer (foreground\bckground).
0150: // Added: RowCounts for each JTree table nodes.
0151: // Added: OneTouchExpandable attribute to JSplitPanes.
0152: // Moved: setFramePositon code to a CommonSwing.setFramePositon() Method.
0153: // Added: call to new method to handle exception processing (CommonSwing.errorMessage());
0154: // Added: Added a new pane added at the bottom of the Frame. (Status Icon and StatusLine).
0155: // Added: 2 Methods (setStatusMessage()), one overrides the other. One to change the ruung status
0156: // another to allow a message to be posted without changing the Status Icon if needed.
0157: // Added: Added a customCursor for the current wait cursor
0158: // Added: Ability to switch the current LAF while runing (Native,Java or Motif)
0159: //unsaved@users 2005xxxx - improvements and bug fixes
0160:
0161: /**
0162: * Swing Tool for managing a JDBC database.<p>
0163: * <pre>
0164: * Usage: java DatabaseManagerSwing [--options]
0165: * where options include:
0166: * --driver <classname> jdbc driver class
0167: * --url <name> jdbc url
0168: * --user <name> username used for connection
0169: * --password <password> password for this user
0170: * --dir <path> default directory
0171: * --script <file> reads from script file
0172: * --urlid <urlid> get connection info from RC file
0173: * --rcfile <file> use instead of default (with urlid)
0174: * --noexit Don't exit JVM
0175: * </pre>
0176: *
0177: * Note that the sys-table switch will not work for Oracle, because Oracle
0178: * does not categorize their system tables correctly in the JDBC Metadata.
0179: *
0180: * New class based on Hypersonic SQL original
0181: *
0182: * @author dmarshall@users
0183: * @version 1.8.0
0184: * @since 1.7.0
0185: */
0186: public class DatabaseManagerSwing extends JApplet implements
0187: ActionListener, WindowListener, KeyListener {
0188:
0189: /*
0190: * This is down here because it is an implementation note, not a
0191: * Javadoc comment!
0192: * Tue Apr 26 16:38:54 EDT 2005
0193: * Switched default switch method from "-switch" to "--switch" because
0194: * "-switch" usage is ambiguous as used here. Single switches should
0195: * be reserved for single-letter switches which can be mixed like
0196: * "-u -r -l" = "-url". -blaine
0197: */
0198: private static String homedir = null;
0199: private boolean isOracle = false; // Need some workarounds for Oracle
0200:
0201: static {
0202: try {
0203: Class c = Class
0204: .forName("sun.security.action.GetPropertyAction");
0205: Constructor constructor = c
0206: .getConstructor(new Class[] { String.class });
0207: java.security.PrivilegedAction a = (java.security.PrivilegedAction) constructor
0208: .newInstance(new Object[] { "user.home" });
0209:
0210: homedir = (String) java.security.AccessController
0211: .doPrivileged(a);
0212: } catch (IllegalAccessException e) {
0213: System.err
0214: .println("Failed to get home directory.\n"
0215: + "Therefore not retrieving/storing user preferences.\n("
0216: + e.getMessage() + ')');
0217: } catch (NoSuchMethodException e) {
0218: System.err
0219: .println("Failed to get home directory.\n"
0220: + "Therefore not retrieving/storing user preferences.\n("
0221: + e.getMessage() + ')');
0222: } catch (ClassNotFoundException e) {
0223: System.err
0224: .println("Failed to get home directory.\n"
0225: + "Therefore not retrieving/storing user preferences.\n("
0226: + e.getMessage() + ')');
0227: } catch (InstantiationException e) {
0228: System.err
0229: .println("Failed to get home directory.\n"
0230: + "Therefore not retrieving/storing user preferences.\n("
0231: + e.getMessage() + ')');
0232: } catch (InvocationTargetException e) {
0233: System.err
0234: .println("Failed to get home directory.\n"
0235: + "Therefore not retrieving/storing user preferences.\n("
0236: + e.getMessage() + ')');
0237: } catch (AccessControlException e) {
0238: System.err
0239: .println("Failed to get home directory.\n"
0240: + "Therefore not retrieving/storing user preferences.\n("
0241: + e.getMessage() + ')');
0242: }
0243: }
0244:
0245: ArrayList localActionList = new ArrayList();
0246: private JFrame jframe = null;
0247: private static final String DEFAULT_RCFILE = homedir
0248: + "/dbmanager.rc";
0249: private static boolean TT_AVAILABLE = false;
0250:
0251: static {
0252: try {
0253: Class.forName(DatabaseManagerSwing.class.getPackage()
0254: .getName()
0255: + ".Transfer");
0256:
0257: TT_AVAILABLE = true;
0258: } catch (Throwable t) {
0259:
0260: //System.err.println("Failed to get "
0261: //+ DatabaseManagerSwing.class.getPackage().getName()
0262: //+ ".Transfer: " + t);
0263: // Enable this print statement for debugging class access problems.
0264: }
0265: }
0266:
0267: private static final String HELP_TEXT = "See the forums, mailing lists, and HSQLDB User Guide\n"
0268: + "at http://hsqldb.org.\n\n"
0269: + "Please paste the following version identifier with any\n"
0270: + "problem reports or help requests: $Revision: 1.76 $"
0271: + (TT_AVAILABLE ? ""
0272: : ("\n\nTransferTool classes are not in CLASSPATH.\n"
0273: + "To enable the Tools menu, add 'transfer.jar' "
0274: + "to your class path."));;
0275: private static final String ABOUT_TEXT = "$Revision: 1.76 $ of DatabaseManagerSwing\n\n"
0276: + "Copyright (c) 1995-2000, The Hypersonic SQL Group.\n"
0277: + "Copyright (c) 2001-2005, The HSQL Development Group.\n"
0278: + "http://hsqldb.org (User Guide available at this site).\n\n\n"
0279: + "You may use and redistribute according to the HSQLDB\n"
0280: + "license documented in the source code and at the web\n"
0281: + "site above."
0282: + (TT_AVAILABLE ? "\n\nTransferTool options are available."
0283: : "");
0284: static final String NL = System.getProperty("line.separator");
0285: static final String NULL_STR = "[null]";
0286: static int iMaxRecent = 24;
0287: Connection cConn;
0288: Connection rowConn; // holds the connetion for getting table row counts
0289: DatabaseMetaData dMeta;
0290: Statement sStatement;
0291: JMenu mRecent;
0292: String[] sRecent;
0293: int iRecent;
0294: JTextArea txtCommand;
0295: JScrollPane txtCommandScroll;
0296: JButton butExecute;
0297: JTree tTree;
0298: JScrollPane tScrollPane;
0299: DefaultTreeModel treeModel;
0300: TableModel tableModel;
0301: DefaultMutableTreeNode rootNode;
0302: JPanel pResult;
0303: long lTime;
0304: GridSwing gResult;
0305:
0306: /**
0307: * I think this is used to store model info whether we're using Grid
0308: * output or not (this object is queried for data to display for
0309: * text output mode).
0310: * If so, the presentation-independent model part should be moved
0311: * to an appropriately-named class instead of storing pure data in
0312: * a Swing-specific class.
0313: */
0314: JTable gResultTable;
0315: JScrollPane gScrollPane;
0316: JTextArea txtResult;
0317: JScrollPane txtResultScroll;
0318: JSplitPane nsSplitPane; // Contains query over results
0319: JSplitPane ewSplitPane; // Contains tree beside nsSplitPane
0320: boolean bHelp;
0321: RootPaneContainer fMain;
0322: static boolean bMustExit;
0323:
0324: /** Value of this variable only retained if huge input script read in. */
0325: String sqlScriptBuffer = null;
0326: JToolBar jtoolbar;
0327: private boolean showSchemas = true;
0328: private boolean showTooltips = true;
0329: private boolean autoRefresh = true;
0330: private boolean gridFormat = true;
0331:
0332: // Added: (weconsultants@users)
0333: static DatabaseManagerSwing refForFontDialogSwing;
0334: boolean displayRowCounts = false;
0335: boolean showSys = false;
0336: boolean showIndexDetails = true;
0337: String currentLAF = null;
0338: JPanel pStatus;
0339: static JButton iReadyStatus;
0340: JRadioButtonMenuItem rbAllSchemas = new JRadioButtonMenuItem("*");
0341: JMenuItem mitemAbout = new JMenuItem("About", 'A');
0342: JMenuItem mitemHelp = new JMenuItem("Help", 'H');
0343: JMenuItem mitemUpdateSchemas = new JMenuItem("Update Schemas");
0344: JCheckBoxMenuItem boxAutoCommit = new JCheckBoxMenuItem(
0345: AUTOCOMMIT_BOX_TEXT);
0346: JCheckBoxMenuItem boxLogging = new JCheckBoxMenuItem(
0347: LOGGING_BOX_TEXT);
0348: JCheckBoxMenuItem boxShowSchemas = new JCheckBoxMenuItem(
0349: SHOWSCHEMAS_BOX_TEXT);
0350: JCheckBoxMenuItem boxAutoRefresh = new JCheckBoxMenuItem(
0351: AUTOREFRESH_BOX_TEXT);
0352: JCheckBoxMenuItem boxTooltips = new JCheckBoxMenuItem(
0353: SHOWTIPS_BOX_TEXT);
0354: JCheckBoxMenuItem boxRowCounts = new JCheckBoxMenuItem(
0355: ROWCOUNTS_BOX_TEXT);
0356: JCheckBoxMenuItem boxShowGrid = new JCheckBoxMenuItem(GRID_BOX_TEXT);
0357: JCheckBoxMenuItem boxShowSys = new JCheckBoxMenuItem(
0358: SHOWSYS_BOX_TEXT);
0359:
0360: // Consider adding GTK and Plaf L&Fs.
0361: JRadioButtonMenuItem rbNativeLF = new JRadioButtonMenuItem(
0362: "Native Look & Feel");
0363: JRadioButtonMenuItem rbJavaLF = new JRadioButtonMenuItem(
0364: "Java Look & Feel");
0365: JRadioButtonMenuItem rbMotifLF = new JRadioButtonMenuItem(
0366: "Motif Look & Feel");
0367: JLabel jStatusLine;
0368: static String READY_STATUS = "Ready";
0369: private static final String AUTOCOMMIT_BOX_TEXT = "Autocommit mode";
0370: private static final String LOGGING_BOX_TEXT = "Logging mode";
0371: private static final String SHOWSCHEMAS_BOX_TEXT = "Show schemas";
0372: private static final String AUTOREFRESH_BOX_TEXT = "Auto-refresh tree";
0373: private static final String SHOWTIPS_BOX_TEXT = "Show Tooltips";
0374: private static final String ROWCOUNTS_BOX_TEXT = "Show row counts";
0375: private static final String SHOWSYS_BOX_TEXT = "Show system tables";
0376: private static final String GRID_BOX_TEXT = "Show results in Grid (a.o.t. Text)";
0377:
0378: // variables to hold the default cursors for these top level swing objects
0379: // so we can restore them when we exit our thread
0380: Cursor fMainCursor;
0381: Cursor txtCommandCursor;
0382: Cursor txtResultCursor;
0383: HashMap tipMap = new HashMap();
0384: private JMenu mnuSchemas = new JMenu("Schemas");
0385:
0386: /**
0387: * Wait Cursor
0388: */
0389:
0390: // Changed: (weconsultants@users): commonted out the, out of the box, cursor to use a custom cursor
0391: private final Cursor waitCursor = new Cursor(Cursor.WAIT_CURSOR);
0392:
0393: //getToolkit().createCustomCursor(CommonSwing.getIcon("SystemCursor"),
0394: // new Point(4, 4), "HourGlass cursor");
0395: // (ulrivo): variables set by arguments from the commandline
0396: static String defDriver = "org.hsqldb.jdbcDriver";
0397: static String defURL = "jdbc:hsqldb:.";
0398: static String defUser = "sa";
0399: static String defPassword = "";
0400: static String defScript;
0401: static String defDirectory;
0402: private String schemaFilter = null;
0403:
0404: public DatabaseManagerSwing() {
0405: jframe = new JFrame("HSQLDB DatabaseManager");
0406: fMain = jframe;
0407: };
0408:
0409: public DatabaseManagerSwing(JFrame frameIn) {
0410: jframe = frameIn;
0411: fMain = jframe;
0412: };
0413:
0414: public void init() {
0415:
0416: javax.swing.AbstractButton btn;
0417:
0418: fMain = this ;
0419:
0420: main();
0421:
0422: for (int i = 0; i < localActionList.size(); i++) {
0423: btn = (javax.swing.AbstractButton) localActionList.get(i);
0424:
0425: btn.setEnabled(false);
0426: }
0427:
0428: Connection c = null;
0429: boolean auto = false;
0430:
0431: if (getParameter("jdbcDriver") != null) {
0432: auto = true;
0433: defDriver = getParameter("jdbcDriver");
0434: }
0435:
0436: if (getParameter("jdbcUrl") != null) {
0437: auto = true;
0438: defURL = getParameter("jdbcUrl");
0439: }
0440:
0441: if (getParameter("jdbcUser") != null) {
0442: auto = true;
0443: defUser = getParameter("jdbcUser");
0444: }
0445:
0446: if (getParameter("jdbcPassword") != null) {
0447: auto = true;
0448: defPassword = getParameter("jdbcPassword");
0449: }
0450:
0451: try {
0452: setWaiting("Initializing");
0453:
0454: //insertTestData();
0455: //updateAutoCommitBox();
0456: c = (auto ? ConnectionDialogSwing.createConnection(
0457: defDriver, defURL, defUser, defPassword)
0458: : ConnectionDialogSwing.createConnection(jframe,
0459: "Connect"));
0460: } catch (Exception e) {
0461:
0462: // Added: (weconsultants@users)
0463: CommonSwing.errorMessage(e);
0464: } finally {
0465: setWaiting(null);
0466: }
0467:
0468: if (c != null) {
0469: connect(c);
0470: }
0471:
0472: if (getParameter("loadSampleData") != null
0473: && getParameter("loadSampleData").equals("true")) {
0474: insertTestData();
0475:
0476: try {
0477: Thread.sleep(1000);
0478: } catch (InterruptedException ie) {
0479: }
0480: ;
0481:
0482: // I don't know why, but the tree refresh below sometimes
0483: // doesn't show all tables unless I put this delay here.
0484: refreshTree();
0485: }
0486:
0487: if (getParameter("schemaFilter") != null) {
0488: schemaFilter = getParameter("schemaFilter");
0489: }
0490: }
0491:
0492: public static void main(String[] arg) {
0493:
0494: System.getProperties().put("sun.java2d.noddraw", "true");
0495:
0496: // (ulrivo): read all arguments from the command line
0497: String lowerArg;
0498: String urlid = null;
0499: String rcFile = null;
0500: boolean autoConnect = false;
0501: boolean urlidConnect = false;
0502:
0503: bMustExit = true;
0504:
0505: for (int i = 0; i < arg.length; i++) {
0506: lowerArg = arg[i].toLowerCase();
0507:
0508: if (lowerArg.length() > 1 && lowerArg.charAt(1) == '-') {
0509: lowerArg = lowerArg.substring(1);
0510: }
0511:
0512: i++;
0513:
0514: if (lowerArg.equals("-driver")) {
0515: defDriver = arg[i];
0516: autoConnect = true;
0517: } else if (lowerArg.equals("-url")) {
0518: defURL = arg[i];
0519: autoConnect = true;
0520: } else if (lowerArg.equals("-user")) {
0521: defUser = arg[i];
0522: autoConnect = true;
0523: } else if (lowerArg.equals("-password")) {
0524: defPassword = arg[i];
0525: autoConnect = true;
0526: } else if (lowerArg.equals("-urlid")) {
0527: urlid = arg[i];
0528: urlidConnect = true;
0529: } else if (lowerArg.equals("-rcfile")) {
0530: rcFile = arg[i];
0531: urlidConnect = true;
0532: } else if (lowerArg.equals("-dir")) {
0533: defDirectory = arg[i];
0534: } else if (lowerArg.equals("-script")) {
0535: defScript = arg[i];
0536: } else if (lowerArg.equals("-noexit")) {
0537: bMustExit = false;
0538:
0539: i--;
0540: } else {
0541: showUsage();
0542:
0543: return;
0544: }
0545: }
0546:
0547: DatabaseManagerSwing m = new DatabaseManagerSwing(new JFrame(
0548: "HSQL Database Manager"));
0549:
0550: // Added: (weconsultants@users): Need databaseManagerSwing for later Reference
0551: refForFontDialogSwing = m;
0552:
0553: m.main();
0554:
0555: Connection c = null;
0556:
0557: m.setWaiting("Initializing");
0558:
0559: try {
0560: if (autoConnect && urlidConnect) {
0561: throw new IllegalArgumentException(
0562: "You may not specify both (urlid) AND (url/user/password).");
0563: }
0564:
0565: if (autoConnect) {
0566: c = ConnectionDialogSwing.createConnection(defDriver,
0567: defURL, defUser, defPassword);
0568: } else if (urlidConnect) {
0569: if (urlid == null) {
0570: throw new IllegalArgumentException(
0571: "You must specify an 'urlid' to use an RC file");
0572: }
0573:
0574: autoConnect = true;
0575:
0576: String rcfilepath = (rcFile == null) ? DEFAULT_RCFILE
0577: : rcFile;
0578: RCData rcdata = new RCData(new File(rcfilepath), urlid);
0579:
0580: c = rcdata.getConnection(null, System
0581: .getProperty("sqlfile.charset"), System
0582: .getProperty("javax.net.ssl.trustStore"));
0583: } else {
0584: c = ConnectionDialogSwing.createConnection(m.jframe,
0585: "Connect");
0586: }
0587: } catch (Exception e) {
0588:
0589: // Added: (weconsultants@users)
0590: CommonSwing.errorMessage(e);
0591: } finally {
0592: m.setWaiting(null);
0593: }
0594:
0595: if (c != null) {
0596: m.connect(c);
0597: }
0598:
0599: // Added: (weconsultants@users): For preloadng FontDialogSwing
0600: FontDialogSwing.CreatFontDialog(refForFontDialogSwing);
0601: m.start();
0602: }
0603:
0604: /**
0605: * This stuff is all quick, except for the refreshTree().
0606: * This unit can be kicked off in main Gui thread. The refreshTree
0607: * will be backgrounded and this method will return.
0608: */
0609: public void connect(Connection c) {
0610:
0611: schemaFilter = null;
0612:
0613: if (c == null) {
0614: return;
0615: }
0616:
0617: if (cConn != null) {
0618: try {
0619: cConn.close();
0620: } catch (SQLException e) {
0621:
0622: // Added: (weconsultants@users)
0623: CommonSwing.errorMessage(e);
0624: }
0625: }
0626:
0627: cConn = c;
0628:
0629: // Added: (weconsultants@users) Need to barrow to get the table rowcounts
0630: rowConn = c;
0631:
0632: try {
0633: dMeta = cConn.getMetaData();
0634: isOracle = (dMeta.getDatabaseProductName()
0635: .indexOf("Oracle") >= 0);
0636: sStatement = cConn.createStatement();
0637:
0638: updateAutoCommitBox();
0639:
0640: // Workaround for EXTREME SLOWNESS getting this info from O.
0641: showIndexDetails = !isOracle;
0642:
0643: Driver driver = DriverManager.getDriver(dMeta.getURL());
0644: ConnectionSetting newSetting = new ConnectionSetting(dMeta
0645: .getDatabaseProductName(), driver.getClass()
0646: .getName(), dMeta.getURL(), dMeta.getUserName()
0647: .replaceAll("@localhost", ""), "");
0648: Hashtable settings = ConnectionDialogCommon
0649: .loadRecentConnectionSettings();
0650:
0651: ConnectionDialogCommon.addToRecentConnectionSettings(
0652: settings, newSetting);
0653: ConnectionDialogSwing.setConnectionSetting(newSetting);
0654: refreshTree();
0655: clearResultPanel();
0656:
0657: if (fMain instanceof JApplet) {
0658: getAppletContext().showStatus(
0659: "JDBC Connection established to a "
0660: + dMeta.getDatabaseProductName()
0661: + " v. "
0662: + dMeta.getDatabaseProductVersion()
0663: + " database as '"
0664: + dMeta.getUserName() + "'.");
0665: }
0666: } catch (SQLException e) {
0667:
0668: // Added: (weconsultants@users)
0669: CommonSwing.errorMessage(e);
0670: } catch (IOException e) {
0671:
0672: // Added: (weconsultants@users)
0673: CommonSwing.errorMessage(e);
0674: } catch (Exception e) {
0675: CommonSwing.errorMessage(e);
0676: }
0677: }
0678:
0679: private static void showUsage() {
0680:
0681: System.out
0682: .println("Usage: java DatabaseManagerSwing [--options]\n"
0683: + "where options include:\n"
0684: + " --driver <classname> jdbc driver class\n"
0685: + " --url <name> jdbc url\n"
0686: + " --user <name> username used for connection\n"
0687: + " --password <password> password for this user\n"
0688: + " --urlid <urlid> use url/user/password/driver in rc file\n"
0689: + " --rcfile <file> (defaults to 'dbmanager.rc' in home dir)\n"
0690: + " --dir <path> default directory\n"
0691: + " --script <file> reads from script file\n"
0692: + " --noexit do not call system.exit()\n"
0693: + "(Single-hypen switches like '-driver' are also supported)");
0694: }
0695:
0696: private void insertTestData() {
0697:
0698: try {
0699: DatabaseManagerCommon.createTestTables(sStatement);
0700: txtCommand.setText(DatabaseManagerCommon
0701: .createTestData(sStatement));
0702:
0703: for (int i = 0; i < DatabaseManagerCommon.testDataSql.length; i++) {
0704: addToRecent(DatabaseManagerCommon.testDataSql[i]);
0705: }
0706:
0707: executeCurrentSQL();
0708: } catch (SQLException e) {
0709:
0710: // Added: (weconsultants@users)
0711: CommonSwing.errorMessage(e);
0712: }
0713: }
0714:
0715: public void setMustExit(boolean b) {
0716: this .bMustExit = b;
0717: }
0718:
0719: private DBMPrefs prefs = null;
0720:
0721: public void main() {
0722:
0723: JMenu jmenu;
0724: JMenuItem mitem;
0725:
0726: try {
0727: prefs = new DBMPrefs(fMain instanceof JApplet);
0728: } catch (Exception e) {
0729: System.err
0730: .println("Failed to load preferences. Proceeding with defaults:\n");
0731: }
0732:
0733: if (prefs == null) {
0734: setLF(CommonSwing.Native);
0735: } else {
0736: autoRefresh = prefs.autoRefresh;
0737: displayRowCounts = prefs.showRowCounts;
0738: showSys = prefs.showSysTables;
0739: showSchemas = prefs.showSchemas;
0740: gridFormat = prefs.resultGrid;
0741: showTooltips = prefs.showTooltips;
0742:
0743: setLF(prefs.laf);
0744: }
0745:
0746: // (ulrivo): An actual icon. N.b., this adds some tips to the tip map
0747: fMain.getContentPane().add(createToolBar(), "North");
0748:
0749: if (fMain instanceof java.awt.Frame) {
0750: ((java.awt.Frame) fMain).setIconImage(CommonSwing
0751: .getIcon("Frame"));
0752: }
0753:
0754: if (fMain instanceof java.awt.Window) {
0755: ((java.awt.Window) fMain).addWindowListener(this );
0756: }
0757:
0758: JMenuBar bar = new JMenuBar();
0759:
0760: // used shortcuts: CERGTSIUDOLM
0761: String[] fitems = { "-Connect...", "--", "OOpen Script...",
0762: "-Save Script...", "-Save Result...", "--", "-Exit" };
0763:
0764: jmenu = addMenu(bar, "File", fitems);
0765:
0766: // All actions after Connect and the divider are local.
0767: for (int i = 2; i < jmenu.getItemCount(); i++) {
0768: mitem = jmenu.getItem(i);
0769:
0770: if (mitem != null) {
0771: localActionList.add(mitem);
0772: }
0773: }
0774:
0775: Object[] vitems = { "RRefresh Tree", boxAutoRefresh, "--",
0776: boxRowCounts, boxShowSys, boxShowSchemas, boxShowGrid };
0777:
0778: addMenu(bar, "View", vitems);
0779:
0780: String[] sitems = { "SSELECT", "IINSERT", "UUPDATE", "DDELETE",
0781: "EEXECUTE", "---", "-CREATE TABLE", "-DROP TABLE",
0782: "-CREATE INDEX", "-DROP INDEX", "--", "CCOMMIT*",
0783: "LROLLBACK*", "-CHECKPOINT*", "-SCRIPT", "-SET",
0784: "-SHUTDOWN", "--", "-Test Script" };
0785:
0786: addMenu(bar, "Command", sitems);
0787:
0788: mRecent = new JMenu("Recent");
0789:
0790: mRecent.setMnemonic(KeyEvent.VK_R);
0791: bar.add(mRecent);
0792:
0793: ButtonGroup lfGroup = new ButtonGroup();
0794:
0795: lfGroup.add(rbNativeLF);
0796: lfGroup.add(rbJavaLF);
0797: lfGroup.add(rbMotifLF);
0798: boxShowSchemas.setSelected(showSchemas);
0799: boxShowGrid.setSelected(gridFormat);
0800: boxTooltips.setSelected(showTooltips);
0801: boxShowGrid.setAccelerator(KeyStroke.getKeyStroke(
0802: KeyEvent.VK_G, Event.CTRL_MASK));
0803: boxAutoRefresh.setSelected(autoRefresh);
0804: boxRowCounts.setSelected(displayRowCounts);
0805: boxShowSys.setSelected(showSys);
0806: rbNativeLF.setActionCommand("LFMODE:" + CommonSwing.Native);
0807: rbJavaLF.setActionCommand("LFMODE:" + CommonSwing.Java);
0808: rbMotifLF.setActionCommand("LFMODE:" + CommonSwing.Motif);
0809: tipMap.put(mitemUpdateSchemas,
0810: "Refresh the schema list in this menu");
0811: tipMap.put(rbAllSchemas, "Display items in all schemas");
0812: tipMap.put(mitemAbout, "Display product information");
0813: tipMap.put(mitemHelp, "Display advice for obtaining help");
0814: tipMap.put(boxAutoRefresh,
0815: "Refresh tree (and schema list) automatically"
0816: + "when YOU modify database objects");
0817: tipMap
0818: .put(boxShowSchemas,
0819: "Display object names in tree like schemaname.basename");
0820: tipMap.put(rbNativeLF,
0821: "Set Look and Feel to Native for your platform");
0822: tipMap.put(rbJavaLF, "Set Look and Feel to Java");
0823: tipMap.put(rbMotifLF, "Set Look and Feel to Motif");
0824: boxTooltips
0825: .setToolTipText("Display tooltips (hover text), like this");
0826: tipMap.put(boxAutoCommit,
0827: "Shows current Auto-commit mode. Click to change");
0828: tipMap
0829: .put(boxLogging,
0830: "Shows current JDBC DriverManager logging mode. Click to change");
0831: tipMap.put(boxShowSys,
0832: "Show system tables in table tree to the left");
0833: tipMap.put(boxShowGrid,
0834: "Show query results in grid (in text if off)");
0835: tipMap.put(boxRowCounts,
0836: "Show row counts with table names in tree");
0837: boxAutoRefresh.setMnemonic(KeyEvent.VK_C);
0838: boxShowSchemas.setMnemonic(KeyEvent.VK_Y);
0839: boxAutoCommit.setMnemonic(KeyEvent.VK_A);
0840: boxShowSys.setMnemonic(KeyEvent.VK_Y);
0841: boxShowGrid.setMnemonic(KeyEvent.VK_G);
0842: boxRowCounts.setMnemonic(KeyEvent.VK_C);
0843: boxLogging.setMnemonic(KeyEvent.VK_L);
0844: rbAllSchemas.setMnemonic(KeyEvent.VK_ASTERISK);
0845: rbNativeLF.setMnemonic(KeyEvent.VK_N);
0846: rbJavaLF.setMnemonic(KeyEvent.VK_J);
0847: rbMotifLF.setMnemonic(KeyEvent.VK_M);
0848: mitemUpdateSchemas.setMnemonic(KeyEvent.VK_U);
0849:
0850: Object[] soptions = {
0851:
0852: // Added: (weconsultants@users) New menu options
0853: rbNativeLF, rbJavaLF, rbMotifLF, "--", "-Set Fonts",
0854: "--", boxAutoCommit, "--", "-Disable MaxRows",
0855: "-Set MaxRows to 100", "--", boxLogging, "--",
0856: "-Insert test data" };
0857:
0858: addMenu(bar, "Options", soptions);
0859:
0860: String[] stools = { "-Dump", "-Restore", "-Transfer" };
0861:
0862: jmenu = addMenu(bar, "Tools", stools);
0863:
0864: jmenu.setEnabled(TT_AVAILABLE);
0865: localActionList.add(jmenu);
0866:
0867: for (int i = 0; i < jmenu.getItemCount(); i++) {
0868: mitem = jmenu.getItem(i);
0869:
0870: if (mitem != null) {
0871: localActionList.add(mitem);
0872: }
0873: }
0874:
0875: mnuSchemas.setMnemonic(KeyEvent.VK_S);
0876: bar.add(mnuSchemas);
0877:
0878: JMenu mnuHelp = new JMenu("Help");
0879:
0880: mnuHelp.setMnemonic(KeyEvent.VK_H);
0881: mnuHelp.add(mitemAbout);
0882: mnuHelp.add(mitemHelp);
0883: mnuHelp.add(boxTooltips);
0884: rbAllSchemas.addActionListener(schemaListListener);
0885:
0886: // May be illegal:
0887: mitemUpdateSchemas.addActionListener(new ActionListener() {
0888:
0889: public void actionPerformed(ActionEvent actionevent) {
0890: updateSchemaList();
0891: }
0892: });
0893: mitemHelp.addActionListener(new ActionListener() {
0894:
0895: public void actionPerformed(ActionEvent actionevent) {
0896:
0897: JOptionPane.showMessageDialog(fMain.getContentPane(),
0898: HELP_TEXT, "HELP",
0899: JOptionPane.INFORMATION_MESSAGE);
0900: }
0901: });
0902: mitemAbout.addActionListener(new ActionListener() {
0903:
0904: public void actionPerformed(ActionEvent actionevent) {
0905:
0906: JOptionPane.showMessageDialog(fMain.getContentPane(),
0907: ABOUT_TEXT, "About",
0908: JOptionPane.INFORMATION_MESSAGE);
0909: }
0910: });
0911: boxTooltips.addActionListener(new ActionListener() {
0912:
0913: public void actionPerformed(ActionEvent actionevent) {
0914:
0915: showTooltips = boxTooltips.isSelected();
0916:
0917: resetTooltips();
0918: }
0919: });
0920: bar.add(mnuHelp);
0921:
0922: if (fMain instanceof JApplet) {
0923: ((JApplet) fMain).setJMenuBar(bar);
0924: } else if (fMain instanceof JFrame) {
0925: ((JFrame) fMain).setJMenuBar(bar);
0926: }
0927:
0928: initGUI();
0929:
0930: sRecent = new String[iMaxRecent];
0931:
0932: // Modified: (weconsultants@users)Mode code to CommonSwing for general use
0933: if (!(fMain instanceof JApplet)) {
0934: CommonSwing.setFramePositon((JFrame) fMain);
0935: }
0936:
0937: // Modified: (weconsultants@users) Changed from deprecated show()
0938: ((Component) fMain).setVisible(true);
0939:
0940: // (ulrivo): load query from command line
0941: if (defScript != null) {
0942: if (defDirectory != null) {
0943: defScript = defDirectory + File.separator + defScript;
0944: }
0945:
0946: // if insert stmet is thousands of records...skip showing it
0947: // as text. Too huge.
0948: sqlScriptBuffer = DatabaseManagerCommon.readFile(defScript);
0949:
0950: if (4096 <= sqlScriptBuffer.length()) {
0951: int eoThirdLine = sqlScriptBuffer.indexOf('\n');
0952:
0953: if (eoThirdLine > 0) {
0954: eoThirdLine = sqlScriptBuffer.indexOf('\n',
0955: eoThirdLine + 1);
0956: }
0957:
0958: if (eoThirdLine > 0) {
0959: eoThirdLine = sqlScriptBuffer.indexOf('\n',
0960: eoThirdLine + 1);
0961: }
0962:
0963: if (eoThirdLine < 1) {
0964: eoThirdLine = 100;
0965: }
0966:
0967: txtCommand
0968: .setText("............... Script File loaded: "
0969: + defScript
0970: + " ..................... \n"
0971: + "............... Click Execute or Clear "
0972: + "...................\n"
0973: + sqlScriptBuffer.substring(0,
0974: eoThirdLine + 1)
0975: + "..........................................."
0976: + "..............................\n"
0977: + "............................................."
0978: + "............................\n");
0979: txtCommand.setEnabled(false);
0980: } else {
0981: txtCommand.setText(sqlScriptBuffer);
0982:
0983: sqlScriptBuffer = null;
0984:
0985: txtCommand.setEnabled(true);
0986: }
0987: }
0988:
0989: // This must be done AFTER all tip texts are put into the map
0990: resetTooltips();
0991: txtCommand.requestFocus();
0992: }
0993:
0994: private JMenu addMenu(JMenuBar b, String name, Object[] items) {
0995:
0996: JMenu menu = new JMenu(name);
0997:
0998: menu.setMnemonic(name.charAt(0));
0999: addMenuItems(menu, items);
1000: b.add(menu);
1001:
1002: return menu;
1003: }
1004:
1005: private void addMenuItems(JMenu f, Object[] m) {
1006:
1007: /*
1008: * This method needs to be completely written or just
1009: * obliterated and we'll use the Menu objects directly.
1010: * Problem is, passing in Strings for menu elements makes it
1011: * extremely difficult to use non-text menu items (an important
1012: * part of a good Gui), hot-keys, mnemonic keys, tooltips.
1013: * Note the "trick" required here to set hot-keys.
1014: */
1015: Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
1016:
1017: for (int i = 0; i < m.length; i++) {
1018: if (m[i].equals("--")) {
1019: f.addSeparator();
1020: } else if (m[i].equals("---")) {
1021:
1022: // (ulrivo): full size on screen with less than 640 width
1023: if (d.width >= 640) {
1024: f.addSeparator();
1025: } else {
1026: return;
1027: }
1028: } else {
1029: JMenuItem item;
1030:
1031: if (m[i] instanceof JMenuItem) {
1032: item = (JMenuItem) m[i];
1033: } else if (m[i] instanceof String) {
1034: item = new JMenuItem(((String) m[i]).substring(1));
1035:
1036: char c = ((String) m[i]).charAt(0);
1037:
1038: if (c != '-') {
1039: KeyStroke key = KeyStroke.getKeyStroke(c,
1040: Event.CTRL_MASK);
1041:
1042: item.setAccelerator(key);
1043: }
1044: } else {
1045: throw new RuntimeException(
1046: "Unexpected element for menu item creation: "
1047: + m[i].getClass().getName());
1048: }
1049:
1050: item.addActionListener(this );
1051: f.add(item);
1052: }
1053: }
1054: }
1055:
1056: public void keyPressed(KeyEvent k) {
1057: }
1058:
1059: public void keyReleased(KeyEvent k) {
1060: }
1061:
1062: public void keyTyped(KeyEvent k) {
1063:
1064: if (k.getKeyChar() == '\n' && k.isControlDown()) {
1065: k.consume();
1066: executeCurrentSQL();
1067: }
1068: }
1069:
1070: Thread dummyThread = new Thread("dummy");
1071:
1072: public void actionPerformed(ActionEvent ev) {
1073:
1074: String s = ev.getActionCommand();
1075:
1076: if (s == null) {
1077: if (ev.getSource() instanceof JMenuItem) {
1078: s = ((JMenuItem) ev.getSource()).getText();
1079: }
1080: }
1081:
1082: if (s == null) {
1083: } else if (s.equals("Exit")) {
1084: windowClosing(null);
1085: } else if (s.equals("Transfer")) {
1086: Transfer.work(null);
1087: } else if (s.equals("Dump")) {
1088: Transfer.work(new String[] { "-d" });
1089: } else if (s.equals("Restore")) {
1090: JOptionPane.showMessageDialog(fMain.getContentPane(),
1091: "Use Ctrl-R or the View menu to\n"
1092: + "update nav. tree after Restoration",
1093: "Suggestion", JOptionPane.INFORMATION_MESSAGE);
1094:
1095: // Regardless of whether autoRefresh is on, half of
1096: // Restore runs asynchronously, so we could only
1097: // update the tree from within the Transfer class.
1098: Transfer.work(new String[] { "-r" });
1099:
1100: // Would be better to put the modal suggestion here, after the
1101: // user selects the import file, but that messes up the z
1102: // layering of the 3 windows already displayed.
1103: } else if (s.equals(LOGGING_BOX_TEXT)) {
1104: JavaSystem.setLogToSystem(boxLogging.isSelected());
1105: } else if (s.equals(AUTOREFRESH_BOX_TEXT)) {
1106: autoRefresh = boxAutoRefresh.isSelected();
1107:
1108: refreshTree();
1109: } else if (s.equals("Refresh Tree")) {
1110: refreshTree();
1111: } else if (s.startsWith("#")) {
1112: int i = Integer.parseInt(s.substring(1));
1113:
1114: txtCommand.setText(sRecent[i]);
1115: } else if (s.equals("Connect...")) {
1116: Connection newCon = null;
1117:
1118: try {
1119: setWaiting("Connecting");
1120:
1121: newCon = ConnectionDialogSwing.createConnection(jframe,
1122: "Connect");
1123: } finally {
1124: setWaiting(null);
1125: }
1126:
1127: connect(newCon);
1128: } else if (s.equals(GRID_BOX_TEXT)) {
1129: gridFormat = boxShowGrid.isSelected();
1130:
1131: displayResults();
1132: } else if (s.equals("Open Script...")) {
1133: JFileChooser f = new JFileChooser(".");
1134:
1135: f.setDialogTitle("Open Script...");
1136:
1137: // (ulrivo): set default directory if set from command line
1138: if (defDirectory != null) {
1139: f.setCurrentDirectory(new File(defDirectory));
1140: }
1141:
1142: int option = f.showOpenDialog((Component) fMain);
1143:
1144: if (option == JFileChooser.APPROVE_OPTION) {
1145: File file = f.getSelectedFile();
1146:
1147: if (file != null) {
1148: sqlScriptBuffer = DatabaseManagerCommon
1149: .readFile(file.getAbsolutePath());
1150:
1151: if (4096 <= sqlScriptBuffer.length()) {
1152: int eoThirdLine = sqlScriptBuffer.indexOf('\n');
1153:
1154: if (eoThirdLine > 0) {
1155: eoThirdLine = sqlScriptBuffer.indexOf('\n',
1156: eoThirdLine + 1);
1157: }
1158:
1159: if (eoThirdLine > 0) {
1160: eoThirdLine = sqlScriptBuffer.indexOf('\n',
1161: eoThirdLine + 1);
1162: }
1163:
1164: if (eoThirdLine < 1) {
1165: eoThirdLine = 100;
1166: }
1167:
1168: txtCommand
1169: .setText("............... Script File loaded: "
1170: + file
1171: + " ..................... \n"
1172: + "............... Click Execute or Clear "
1173: + "...................\n"
1174: + sqlScriptBuffer.substring(0,
1175: eoThirdLine + 1)
1176: + "........................................."
1177: + "................................\n"
1178: + "..........................................."
1179: + "..............................\n");
1180: txtCommand.setEnabled(false);
1181: } else {
1182: txtCommand.setText(sqlScriptBuffer);
1183:
1184: sqlScriptBuffer = null;
1185:
1186: txtCommand.setEnabled(true);
1187: }
1188: }
1189: }
1190: } else if (s.equals("Save Script...")) {
1191: JFileChooser f = new JFileChooser(".");
1192:
1193: f.setDialogTitle("Save Script");
1194:
1195: // (ulrivo): set default directory if set from command line
1196: if (defDirectory != null) {
1197: f.setCurrentDirectory(new File(defDirectory));
1198: }
1199:
1200: int option = f.showSaveDialog((Component) fMain);
1201:
1202: if (option == JFileChooser.APPROVE_OPTION) {
1203: File file = f.getSelectedFile();
1204:
1205: if (file != null) {
1206: DatabaseManagerCommon.writeFile(file
1207: .getAbsolutePath(), txtCommand.getText());
1208: }
1209: }
1210: } else if (s.equals("Save Result...")) {
1211: JFileChooser f = new JFileChooser(".");
1212:
1213: f.setDialogTitle("Save Result...");
1214:
1215: // (ulrivo): set default directory if set from command line
1216: if (defDirectory != null) {
1217: f.setCurrentDirectory(new File(defDirectory));
1218: }
1219:
1220: int option = f.showSaveDialog((Component) fMain);
1221:
1222: if (option == JFileChooser.APPROVE_OPTION) {
1223: File file = f.getSelectedFile();
1224:
1225: if (file != null) {
1226: showResultInText();
1227: DatabaseManagerCommon.writeFile(file
1228: .getAbsolutePath(), txtResult.getText());
1229: }
1230: }
1231: } else if (s.equals(SHOWSYS_BOX_TEXT)) {
1232: showSys = boxShowSys.isSelected();
1233:
1234: refreshTree();
1235: } else if (s.equals(ROWCOUNTS_BOX_TEXT)) {
1236: displayRowCounts = boxRowCounts.isSelected();
1237:
1238: refreshTree();
1239: } else if (s.startsWith("LFMODE:")) {
1240: setLF(s.substring("LFMODE:".length()));
1241: } else if (s.equals("Set Fonts")) {
1242:
1243: // Added: (weconsultants@users)
1244: FontDialogSwing.CreatFontDialog(refForFontDialogSwing);
1245: } else if (s.equals(AUTOCOMMIT_BOX_TEXT)) {
1246: try {
1247: cConn.setAutoCommit(boxAutoCommit.isSelected());
1248: } catch (SQLException e) {
1249: boxAutoCommit.setSelected(!boxAutoCommit.isSelected());
1250:
1251: // Added: (weconsultants@users)
1252: CommonSwing.errorMessage(e);
1253: }
1254: } else if (s.equals("COMMIT*")) {
1255: try {
1256: cConn.commit();
1257: showHelp(new String[] { "", "COMMIT executed" });
1258: } catch (SQLException e) {
1259:
1260: // Added: (weconsultants@users)
1261: CommonSwing.errorMessage(e);
1262: }
1263: } else if (s.equals("Insert test data")) {
1264: insertTestData();
1265: refreshTree();
1266: } else if (s.equals("ROLLBACK*")) {
1267: try {
1268: cConn.rollback();
1269: showHelp(new String[] { "", "ROLLBACK executed" });
1270: } catch (SQLException e) {
1271:
1272: // Added: (weconsultants@users)
1273: CommonSwing.errorMessage(e);
1274: }
1275: } else if (s.equals("Disable MaxRows")) {
1276: try {
1277: sStatement.setMaxRows(0);
1278: } catch (SQLException e) {
1279:
1280: // Added: (weconsultants@users)
1281: CommonSwing.errorMessage(e);
1282: }
1283: } else if (s.equals("Set MaxRows to 100")) {
1284: try {
1285: sStatement.setMaxRows(100);
1286: } catch (SQLException e) {
1287: CommonSwing.errorMessage(e);
1288: }
1289: } else if (s.equals("SELECT")) {
1290: showHelp(DatabaseManagerCommon.selectHelp);
1291: } else if (s.equals("INSERT")) {
1292: showHelp(DatabaseManagerCommon.insertHelp);
1293: } else if (s.equals("UPDATE")) {
1294: showHelp(DatabaseManagerCommon.updateHelp);
1295: } else if (s.equals("DELETE")) {
1296: showHelp(DatabaseManagerCommon.deleteHelp);
1297: } else if (s.equals("EXECUTE")) {
1298: executeCurrentSQL();
1299: } else if (s.equals("CREATE TABLE")) {
1300: showHelp(DatabaseManagerCommon.createTableHelp);
1301: } else if (s.equals("DROP TABLE")) {
1302: showHelp(DatabaseManagerCommon.dropTableHelp);
1303: } else if (s.equals("CREATE INDEX")) {
1304: showHelp(DatabaseManagerCommon.createIndexHelp);
1305: } else if (s.equals("DROP INDEX")) {
1306: showHelp(DatabaseManagerCommon.dropIndexHelp);
1307: } else if (s.equals("CHECKPOINT*")) {
1308: try {
1309: cConn.createStatement().executeUpdate("CHECKPOINT");
1310: showHelp(new String[] { "", "CHECKPOINT executed" });
1311: } catch (SQLException e) {
1312: CommonSwing.errorMessage(e);
1313: }
1314: } else if (s.equals("SCRIPT")) {
1315: showHelp(DatabaseManagerCommon.scriptHelp);
1316: } else if (s.equals("SHUTDOWN")) {
1317: showHelp(DatabaseManagerCommon.shutdownHelp);
1318: } else if (s.equals("SET")) {
1319: showHelp(DatabaseManagerCommon.setHelp);
1320: } else if (s.equals("Test Script")) {
1321: showHelp(DatabaseManagerCommon.testHelp);
1322: } else if (s.equals(SHOWSCHEMAS_BOX_TEXT)) {
1323: showSchemas = boxShowSchemas.isSelected();
1324:
1325: refreshTree();
1326: } else {
1327: throw new RuntimeException("Unexpected action triggered: "
1328: + s);
1329: }
1330: }
1331:
1332: private void displayResults() {
1333:
1334: if (gridFormat) {
1335: setResultsInGrid();
1336: } else {
1337: setResultsInText();
1338: }
1339: }
1340:
1341: private void setResultsInGrid() {
1342:
1343: pResult.removeAll();
1344: pResult.add(gScrollPane, BorderLayout.CENTER);
1345: pResult.doLayout();
1346: gResult.fireTableChanged(null);
1347: pResult.repaint();
1348: }
1349:
1350: private void setResultsInText() {
1351:
1352: pResult.removeAll();
1353: pResult.add(txtResultScroll, BorderLayout.CENTER);
1354: pResult.doLayout();
1355: showResultInText();
1356: pResult.repaint();
1357: }
1358:
1359: private void showHelp(String[] help) {
1360:
1361: txtCommand.setText(help[0]);
1362:
1363: bHelp = true;
1364:
1365: pResult.removeAll();
1366: pResult.add(txtResultScroll, BorderLayout.CENTER);
1367: pResult.doLayout();
1368: txtResult.setText(help[1]);
1369: pResult.repaint();
1370: txtCommand.requestFocus();
1371: txtCommand.setCaretPosition(help[0].length());
1372: }
1373:
1374: public void windowActivated(WindowEvent e) {
1375: }
1376:
1377: public void windowDeactivated(WindowEvent e) {
1378: }
1379:
1380: public void windowClosed(WindowEvent e) {
1381: }
1382:
1383: public void windowDeiconified(WindowEvent e) {
1384: }
1385:
1386: public void windowIconified(WindowEvent e) {
1387: }
1388:
1389: public void windowOpened(WindowEvent e) {
1390: }
1391:
1392: public void windowClosing(WindowEvent ev) {
1393:
1394: stop();
1395:
1396: try {
1397: if (cConn != null) {
1398: cConn.close();
1399: }
1400:
1401: if (prefs != null) {
1402: prefs.autoRefresh = autoRefresh;
1403: prefs.showRowCounts = displayRowCounts;
1404: prefs.showSysTables = showSys;
1405: prefs.showSchemas = showSchemas;
1406: prefs.resultGrid = gridFormat;
1407: prefs.showTooltips = showTooltips;
1408: prefs.laf = currentLAF;
1409:
1410: prefs.store();
1411: }
1412: } catch (Exception e) {
1413:
1414: // Added: (weconsultants@users)
1415: CommonSwing.errorMessage(e);
1416: }
1417:
1418: if (fMain instanceof java.awt.Window) {
1419: ((java.awt.Window) fMain).dispose();
1420: }
1421:
1422: if (bMustExit) {
1423: System.exit(0);
1424: }
1425: }
1426:
1427: private void clear() {
1428:
1429: sqlScriptBuffer = null;
1430:
1431: txtCommand.setText("");
1432: txtCommand.setEnabled(true);
1433: }
1434:
1435: private String busyText = null;
1436:
1437: private void backgroundIt(Runnable r, String description) {
1438:
1439: if (busyText != null) {
1440: Toolkit.getDefaultToolkit().beep();
1441:
1442: return;
1443: }
1444:
1445: // set Waiting mode here. Inverse op must be called by final()
1446: // in the Thread.run() of every background thread.
1447: setWaiting(description);
1448: SwingUtilities.invokeLater(r);
1449: }
1450:
1451: private void clearResultPanel() {
1452:
1453: gResult.setHead(new Object[0]);
1454: gResult.clear();
1455:
1456: if (gridFormat) {
1457: gResult.fireTableChanged(null);
1458: } else {
1459: showResultInText();
1460: }
1461: }
1462:
1463: public void setWaiting(String description) {
1464:
1465: busyText = description;
1466:
1467: if (busyText == null) {
1468:
1469: // restore the cursors we saved
1470: if (fMain instanceof java.awt.Frame) {
1471: ((java.awt.Frame) fMain).setCursor(fMainCursor);
1472: } else {
1473: ((Component) fMain).setCursor(fMainCursor);
1474: }
1475:
1476: txtCommand.setCursor(txtCommandCursor);
1477: txtResult.setCursor(txtResultCursor);
1478:
1479: //TODO: Enable actionButtons
1480: } else {
1481:
1482: // save the old cursors
1483: if (fMainCursor == null) {
1484: fMainCursor = ((fMain instanceof java.awt.Frame) ? (((java.awt.Frame) fMain)
1485: .getCursor())
1486: : (((Component) fMain).getCursor()));
1487: txtCommandCursor = txtCommand.getCursor();
1488: txtResultCursor = txtResult.getCursor();
1489: }
1490:
1491: // set the cursors to the wait cursor
1492: if (fMain instanceof java.awt.Frame) {
1493: ((java.awt.Frame) fMain).setCursor(waitCursor);
1494: } else {
1495: ((Component) fMain).setCursor(waitCursor);
1496: }
1497:
1498: txtCommand.setCursor(waitCursor);
1499: txtResult.setCursor(waitCursor);
1500:
1501: //TODO: Disable actionButtons
1502: }
1503:
1504: setStatusLine(busyText, ((busyText == null) ? gResult
1505: .getRowCount() : 0));
1506: }
1507:
1508: private Runnable enableButtonRunnable = new Runnable() {
1509:
1510: public void run() {
1511: jbuttonClear.setEnabled(true);
1512: jbuttonExecute.setEnabled(true);
1513: }
1514: };
1515: private Runnable disableButtonRunnable = new Runnable() {
1516:
1517: public void run() {
1518: jbuttonClear.setEnabled(false);
1519: jbuttonExecute.setEnabled(false);
1520: }
1521: };
1522: private Thread buttonUpdaterThread = null;
1523: private static final int BUTTON_CHECK_PERIOD = 500;
1524: private Runnable buttonUpdater = new Runnable() {
1525:
1526: public void run() {
1527:
1528: boolean havesql;
1529:
1530: while (true) {
1531: try {
1532: Thread.sleep(BUTTON_CHECK_PERIOD);
1533: } catch (InterruptedException ie) {
1534: }
1535:
1536: if (buttonUpdaterThread == null) { // Pointer to me
1537: return;
1538: }
1539:
1540: havesql = (txtCommand.getText().length() > 0);
1541:
1542: if (jbuttonClear.isEnabled() != havesql) {
1543: SwingUtilities
1544: .invokeLater(havesql ? enableButtonRunnable
1545: : disableButtonRunnable);
1546: }
1547: }
1548: }
1549: };
1550: private JButton jbuttonClear;
1551: private JButton jbuttonExecute;
1552:
1553: public void start() {
1554:
1555: if (buttonUpdaterThread == null) {
1556: buttonUpdaterThread = new Thread(buttonUpdater);
1557: }
1558:
1559: buttonUpdaterThread.start();
1560: }
1561:
1562: public void stop() {
1563:
1564: System.err.println("Stopping");
1565:
1566: buttonUpdaterThread = null;
1567: }
1568:
1569: private Runnable treeRefreshRunnable = new Runnable() {
1570:
1571: public void run() {
1572:
1573: try {
1574: directRefreshTree();
1575: } catch (RuntimeException re) {
1576: CommonSwing.errorMessage(re);
1577:
1578: throw re;
1579: } finally {
1580: setWaiting(null);
1581: }
1582: }
1583: };
1584:
1585: /**
1586: * Schedules to run in a Gui-safe thread
1587: */
1588: protected void executeCurrentSQL() {
1589:
1590: if (txtCommand.getText().length() < 1) {
1591: CommonSwing.errorMessage("No SQL to execute");
1592:
1593: return;
1594: }
1595:
1596: backgroundIt(new StatementExecRunnable(), "Executing SQL");
1597: }
1598:
1599: protected class StatementExecRunnable implements Runnable {
1600:
1601: public void run() {
1602:
1603: gResult.clear();
1604:
1605: try {
1606: if (txtCommand.getText().startsWith("-->>>TEST<<<--")) {
1607: testPerformance();
1608: } else {
1609: executeSQL();
1610: }
1611:
1612: updateResult();
1613: displayResults();
1614: updateAutoCommitBox();
1615: System.gc();
1616: } catch (RuntimeException re) {
1617: CommonSwing.errorMessage(re);
1618:
1619: throw re;
1620: } finally {
1621: setWaiting(null);
1622: }
1623: }
1624: };
1625:
1626: private void executeSQL() {
1627:
1628: String[] g = new String[1];
1629: String sql = null;
1630:
1631: try {
1632: lTime = System.currentTimeMillis();
1633: sql = ((sqlScriptBuffer == null ? txtCommand.getText()
1634: : sqlScriptBuffer));
1635:
1636: sStatement.execute(sql);
1637:
1638: int r = sStatement.getUpdateCount();
1639:
1640: if (r == -1) {
1641: formatResultSet(sStatement.getResultSet());
1642: } else {
1643: g[0] = "update count";
1644:
1645: gResult.setHead(g);
1646:
1647: g[0] = "" + r;
1648:
1649: gResult.addRow(g);
1650: }
1651:
1652: lTime = System.currentTimeMillis() - lTime;
1653:
1654: if (sqlScriptBuffer == null) {
1655: addToRecent(sql);
1656: txtCommand.setEnabled(true); // clear() does this otherwise
1657: } else {
1658: clear();
1659: }
1660: } catch (SQLException e) {
1661: lTime = System.currentTimeMillis() - lTime;
1662: g[0] = "SQL Error";
1663:
1664: gResult.setHead(g);
1665:
1666: String s = e.getMessage();
1667:
1668: s += " / Error Code: " + e.getErrorCode();
1669: s += " / State: " + e.getSQLState();
1670: g[0] = s;
1671:
1672: gResult.addRow(g);
1673:
1674: // Added: (weconsultants@users)
1675: CommonSwing.errorMessage(e);
1676:
1677: return;
1678: }
1679:
1680: if (autoRefresh) {
1681:
1682: // We're already running in a "busy" thread. Just update the
1683: // status text.
1684: setStatusLine("Refreshing object tree", 0);
1685:
1686: String upper = sql.toUpperCase(Locale.ENGLISH);
1687:
1688: // This test can be very liberal. Too liberal will just do
1689: // some extra refreshes. Too conservative will display
1690: // obsolete info.
1691: if (upper.indexOf("ALTER") > -1
1692: || upper.indexOf("DROP") > -1
1693: || upper.indexOf("CREATE") > -1) {
1694: directRefreshTree();
1695: }
1696: }
1697: }
1698:
1699: /**
1700: * Could somebody explain what the purpose of this method is?
1701: * Contrary to the method name, it looks like it displays
1702: * results only if gridFormat is off (seems like it does
1703: * nothing otherwise, except for clearing help text and moving focus).
1704: */
1705: private void updateResult() {
1706:
1707: if (gridFormat) {
1708:
1709: // in case 'help' has removed the grid
1710: if (bHelp) {
1711: pResult.removeAll();
1712: pResult.add(gScrollPane, BorderLayout.CENTER);
1713: pResult.doLayout();
1714: gResult.fireTableChanged(null);
1715: pResult.repaint();
1716:
1717: bHelp = false;
1718: }
1719: } else {
1720: showResultInText();
1721: }
1722:
1723: txtCommand.selectAll();
1724: txtCommand.requestFocus();
1725: }
1726:
1727: /**
1728: * We let Swing handle displaying nulls (which it generally does by
1729: * printing nothing for them), except for the case of database
1730: * VARCHARs, because this is the only class where there is any
1731: * ambiguity about whether there is a null stored or not.
1732: */
1733: private void formatResultSet(ResultSet r) {
1734:
1735: if (r == null) {
1736: String[] g = new String[1];
1737:
1738: g[0] = "Result";
1739:
1740: gResult.setHead(g);
1741:
1742: g[0] = "(empty)";
1743:
1744: gResult.addRow(g);
1745:
1746: return;
1747: }
1748:
1749: try {
1750: ResultSetMetaData m = r.getMetaData();
1751: int col = m.getColumnCount();
1752: Object[] h = new Object[col];
1753: boolean[] isVarChar = new boolean[col];
1754:
1755: for (int i = 1; i <= col; i++) {
1756: h[i - 1] = m.getColumnLabel(i);
1757: isVarChar[i - 1] = (m.getColumnType(i) == java.sql.Types.VARCHAR);
1758: }
1759:
1760: gResult.setHead(h);
1761:
1762: while (r.next()) {
1763: for (int i = 1; i <= col; i++) {
1764: try {
1765: h[i - 1] = r.getObject(i);
1766:
1767: if (r.wasNull()) {
1768: h[i - 1] = (isVarChar[i - 1] ? NULL_STR
1769: : null);
1770: }
1771: } catch (SQLException e) {
1772: }
1773: }
1774:
1775: gResult.addRow(h);
1776: }
1777:
1778: r.close();
1779: } catch (SQLException e) {
1780:
1781: // Added: (weconsultants@users)
1782: CommonSwing.errorMessage(e);
1783: }
1784: }
1785:
1786: private void testPerformance() {
1787:
1788: String all = txtCommand.getText();
1789: StringBuffer b = new StringBuffer();
1790: long total = 0;
1791:
1792: for (int i = 0; i < all.length(); i++) {
1793: char c = all.charAt(i);
1794:
1795: if (c != '\n') {
1796: b.append(c);
1797: }
1798: }
1799:
1800: all = b.toString();
1801:
1802: String[] g = new String[4];
1803:
1804: g[0] = "ms";
1805: g[1] = "count";
1806: g[2] = "sql";
1807: g[3] = "error";
1808:
1809: gResult.setHead(g);
1810:
1811: int max = 1;
1812:
1813: lTime = System.currentTimeMillis() - lTime;
1814:
1815: while (!all.equals("")) {
1816: int i = all.indexOf(';');
1817: String sql;
1818:
1819: if (i != -1) {
1820: sql = all.substring(0, i);
1821: all = all.substring(i + 1);
1822: } else {
1823: sql = all;
1824: all = "";
1825: }
1826:
1827: if (sql.startsWith("--#")) {
1828: max = Integer.parseInt(sql.substring(3));
1829:
1830: continue;
1831: } else if (sql.startsWith("--")) {
1832: continue;
1833: }
1834:
1835: g[2] = sql;
1836:
1837: long l = 0;
1838:
1839: try {
1840: l = DatabaseManagerCommon.testStatement(sStatement,
1841: sql, max);
1842: total += l;
1843: g[0] = "" + l;
1844: g[1] = "" + max;
1845: g[3] = "";
1846: } catch (SQLException e) {
1847: g[0] = g[1] = "n/a";
1848: g[3] = e.toString();
1849:
1850: // Added: (weconsultants@users)
1851: CommonSwing.errorMessage(e);
1852: }
1853:
1854: gResult.addRow(g);
1855: System.out.println(l + " ms : " + sql);
1856: }
1857:
1858: g[0] = "" + total;
1859: g[1] = "total";
1860: g[2] = "";
1861:
1862: gResult.addRow(g);
1863:
1864: lTime = System.currentTimeMillis() - lTime;
1865: }
1866:
1867: /**
1868: * Method declaration
1869: *
1870: */
1871: private void showResultInText() {
1872:
1873: Object[] col = gResult.getHead();
1874: int width = col.length;
1875: int[] size = new int[width];
1876: Vector data = gResult.getData();
1877: Object[] row;
1878: int height = data.size();
1879:
1880: for (int i = 0; i < width; i++) {
1881: size[i] = col[i].toString().length();
1882: }
1883:
1884: for (int i = 0; i < height; i++) {
1885: row = (Object[]) data.elementAt(i);
1886:
1887: for (int j = 0; j < width; j++) {
1888: String item = ((row[j] == null) ? "" : row[j]
1889: .toString());
1890: int l = item.length();
1891:
1892: if (l > size[j]) {
1893: size[j] = l;
1894: }
1895: }
1896: }
1897:
1898: StringBuffer b = new StringBuffer();
1899:
1900: for (int i = 0; i < width; i++) {
1901: b.append(col[i]);
1902:
1903: for (int l = col[i].toString().length(); l <= size[i]; l++) {
1904: b.append(' ');
1905: }
1906: }
1907:
1908: b.append(NL);
1909:
1910: for (int i = 0; i < width; i++) {
1911: for (int l = 0; l < size[i]; l++) {
1912: b.append('-');
1913: }
1914:
1915: b.append(' ');
1916: }
1917:
1918: b.append(NL);
1919:
1920: for (int i = 0; i < height; i++) {
1921: row = (Object[]) data.elementAt(i);
1922:
1923: for (int j = 0; j < width; j++) {
1924: String item = ((row[j] == null) ? "" : row[j]
1925: .toString());
1926:
1927: b.append(item);
1928:
1929: for (int l = item.length(); l <= size[j]; l++) {
1930: b.append(' ');
1931: }
1932: }
1933:
1934: b.append(NL);
1935: }
1936:
1937: // b.append(NL + height + " row(s) in " + lTime + " ms");
1938: // There is no reason why this report should be text-output-specific.
1939: // Moving it to bottom of the setWaiting method (where the report
1940: // gets written to the status line).
1941: // I'm only doing the rowcount now. Add the time report there if
1942: // you are so inclined.
1943: txtResult.setText(b.toString());
1944: }
1945:
1946: private void addToRecent(String s) {
1947:
1948: for (int i = 0; i < iMaxRecent; i++) {
1949: if (s.equals(sRecent[i])) {
1950: return;
1951: }
1952: }
1953:
1954: if (sRecent[iRecent] != null) {
1955: mRecent.remove(iRecent);
1956: }
1957:
1958: sRecent[iRecent] = s;
1959:
1960: if (s.length() > 43) {
1961: s = s.substring(0, 40) + "...";
1962: }
1963:
1964: JMenuItem item = new JMenuItem(s);
1965:
1966: item.setActionCommand("#" + iRecent);
1967: item.addActionListener(this );
1968: mRecent.insert(item, iRecent);
1969:
1970: iRecent = (iRecent + 1) % iMaxRecent;
1971: }
1972:
1973: private void initGUI() {
1974:
1975: JPanel pCommand = new JPanel();
1976:
1977: pResult = new JPanel();
1978: nsSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
1979: pCommand, pResult);
1980:
1981: // Added: (weconsultants@users)
1982: nsSplitPane.setOneTouchExpandable(true);
1983: pCommand.setLayout(new BorderLayout());
1984: pResult.setLayout(new BorderLayout());
1985:
1986: Font fFont = new Font("Dialog", Font.PLAIN, 12);
1987:
1988: txtCommand = new JTextArea(5, 40);
1989:
1990: txtCommand.setMargin(new Insets(5, 5, 5, 5));
1991: txtCommand.addKeyListener(this );
1992:
1993: txtCommandScroll = new JScrollPane(txtCommand);
1994: txtResult = new JTextArea(20, 40);
1995:
1996: txtResult.setMargin(new Insets(5, 5, 5, 5));
1997:
1998: txtResultScroll = new JScrollPane(txtResult);
1999:
2000: txtCommand.setFont(fFont);
2001: txtResult.setFont(new Font("Courier", Font.PLAIN, 12));
2002: pCommand.add(txtCommandScroll, BorderLayout.CENTER);
2003:
2004: gResult = new GridSwing();
2005:
2006: TableSorter sorter = new TableSorter(gResult);
2007:
2008: tableModel = sorter;
2009: gResultTable = new JTable(sorter);
2010:
2011: sorter.setTableHeader(gResultTable.getTableHeader());
2012:
2013: gScrollPane = new JScrollPane(gResultTable);
2014:
2015: gResultTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
2016: gResult.setJTable(gResultTable);
2017:
2018: //getContentPane().setLayout(new BorderLayout());
2019: pResult.add(gScrollPane, BorderLayout.CENTER);
2020:
2021: // Set up the tree
2022: rootNode = new DefaultMutableTreeNode("Connection");
2023: treeModel = new DefaultTreeModel(rootNode);
2024: tTree = new JTree(treeModel);
2025: tScrollPane = new JScrollPane(tTree);
2026:
2027: tScrollPane.setPreferredSize(new Dimension(120, 400));
2028: tScrollPane.setMinimumSize(new Dimension(70, 100));
2029: txtCommandScroll.setPreferredSize(new Dimension(360, 100));
2030: txtCommandScroll.setMinimumSize(new Dimension(180, 100));
2031: gScrollPane.setPreferredSize(new Dimension(460, 300));
2032:
2033: ewSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
2034: tScrollPane, nsSplitPane);
2035:
2036: // Added: (weconsultants@users)
2037: ewSplitPane.setOneTouchExpandable(true);
2038: fMain.getContentPane().add(ewSplitPane, BorderLayout.CENTER);
2039:
2040: // Added: (weconsultants@users)
2041: jStatusLine = new JLabel();
2042: iReadyStatus = new JButton(new ImageIcon(CommonSwing
2043: .getIcon("StatusReady")));
2044:
2045: iReadyStatus.setSelectedIcon(new ImageIcon(CommonSwing
2046: .getIcon("StatusRunning")));
2047:
2048: pStatus = new JPanel();
2049:
2050: pStatus.setLayout(new BorderLayout());
2051: pStatus.add(iReadyStatus, BorderLayout.WEST);
2052: pStatus.add(jStatusLine, BorderLayout.CENTER);
2053: fMain.getContentPane().add(pStatus, "South");
2054: doLayout();
2055:
2056: if (fMain instanceof java.awt.Window) {
2057: ((java.awt.Window) fMain).pack();
2058: } else {
2059: ((Container) fMain).validate();
2060: }
2061: }
2062:
2063: /* Simple tree node factory method - set's parent and user object.
2064: */
2065: private DefaultMutableTreeNode makeNode(Object userObject,
2066: MutableTreeNode parent) {
2067:
2068: DefaultMutableTreeNode node = new DefaultMutableTreeNode(
2069: userObject);
2070:
2071: if (parent != null) {
2072: treeModel.insertNodeInto(node, parent, parent
2073: .getChildCount());
2074: }
2075:
2076: return node;
2077: }
2078:
2079: private static final String[] usertables = { "TABLE",
2080: "GLOBAL TEMPORARY", "VIEW", "SYSTEM TABLE" };
2081: private static final String[] nonSystables = { "TABLE",
2082: "GLOBAL TEMPORARY", "VIEW" };
2083: private static final HashSet oracleSysUsers = new HashSet();
2084: private static final String[] oracleSysSchemas = { "SYS", "SYSTEM",
2085: "OUTLN", "DBSNMP", "OUTLN", "MDSYS", "ORDSYS",
2086: "ORDPLUGINS", "CTXSYS", "DSSYS", "PERFSTAT", "WKPROXY",
2087: "WKSYS", "WMSYS", "XDB", "ANONYMOUS", "ODM", "ODM_MTR",
2088: "OLAPSYS", "TRACESVR", "REPADMIN" };
2089:
2090: static {
2091: for (int i = 0; i < oracleSysSchemas.length; i++) {
2092: oracleSysUsers.add(oracleSysSchemas[i]);
2093: }
2094: }
2095:
2096: /**
2097: * Schedules to run in a Gui-safe thread
2098: */
2099: protected void refreshTree() {
2100: backgroundIt(treeRefreshRunnable, "Refreshing object tree");
2101: }
2102:
2103: /**
2104: * Clear all existing nodes from the tree model and rebuild from scratch.
2105: *
2106: * This method executes in current thread
2107: */
2108: protected void directRefreshTree() {
2109:
2110: int[] rowCounts;
2111: DefaultMutableTreeNode propertiesNode;
2112:
2113: // Added: (weconsultants@users) Moved tableNode here for visibiity nd new DECFM
2114: DefaultMutableTreeNode tableNode;
2115: DecimalFormat DECFMT = new DecimalFormat(
2116: " ( ####,###,####,##0 )");
2117:
2118: // First clear the existing tree by simply enumerating
2119: // over the root node's children and removing them one by one.
2120: while (treeModel.getChildCount(rootNode) > 0) {
2121: DefaultMutableTreeNode child = (DefaultMutableTreeNode) treeModel
2122: .getChild(rootNode, 0);
2123:
2124: treeModel.removeNodeFromParent(child);
2125: child.removeAllChildren();
2126: child.removeFromParent();
2127: }
2128:
2129: treeModel.nodeStructureChanged(rootNode);
2130: treeModel.reload();
2131: tScrollPane.repaint();
2132:
2133: ResultSet result = null;
2134:
2135: // Now rebuild the tree below its root
2136: try {
2137:
2138: // Start by naming the root node from its URL:
2139: rootNode.setUserObject(dMeta.getURL());
2140:
2141: // get metadata about user tables by building a vector of table names
2142: result = dMeta.getTables(null, null, null,
2143: (showSys ? usertables : nonSystables));
2144:
2145: Vector tables = new Vector();
2146: Vector schemas = new Vector();
2147:
2148: // sqlbob@users Added remarks.
2149: Vector remarks = new Vector();
2150: String schema;
2151:
2152: while (result.next()) {
2153: schema = result.getString(2);
2154:
2155: if ((!showSys) && isOracle
2156: && oracleSysUsers.contains(schema)) {
2157: continue;
2158: }
2159:
2160: if (schemaFilter == null || schema.equals(schemaFilter)) {
2161: schemas.addElement(schema);
2162: tables.addElement(result.getString(3));
2163: remarks.addElement(result.getString(5));
2164:
2165: continue;
2166: }
2167: }
2168:
2169: result.close();
2170:
2171: result = null;
2172:
2173: // Added: (weconsultants@users)
2174: // Sort not to go into production. Have to sync with 'remarks Vector' for DBMS that has it
2175: // Collections.sort(tables);
2176: // Added: (weconsultants@users) - Add rowCounts if needed.
2177: rowCounts = new int[tables.size()];
2178:
2179: try {
2180: rowCounts = getRowCounts(tables, schemas);
2181: } catch (Exception e) {
2182:
2183: // Added: (weconsultants@users)
2184: CommonSwing.errorMessage(e);
2185: }
2186:
2187: ResultSet col;
2188:
2189: // For each table, build a tree node with interesting info
2190: for (int i = 0; i < tables.size(); i++) {
2191: col = null;
2192:
2193: String name;
2194:
2195: try {
2196: name = (String) tables.elementAt(i);
2197: if (isOracle && name.startsWith("BIN$")) {
2198: continue;
2199: // Oracle Recyle Bin tables.
2200: // Contains metacharacters which screw up metadata
2201: // queries below.
2202: }
2203: schema = (String) schemas.elementAt(i);
2204:
2205: String schemaname = "";
2206:
2207: if (schema != null && showSchemas) {
2208: schemaname = schema + '.';
2209: }
2210:
2211: String rowcount = displayRowCounts ? (" " + DECFMT
2212: .format(rowCounts[i])) : "";
2213: String displayedName = schemaname + name + rowcount;
2214:
2215: // weconsul@ptd.net Add rowCounts if needed.
2216: tableNode = makeNode(displayedName, rootNode);
2217: col = dMeta.getColumns(null, schema, name, null);
2218:
2219: if ((schema != null) && !schema.trim().equals("")) {
2220: makeNode(schema, tableNode);
2221: }
2222:
2223: // sqlbob@users Added remarks.
2224: String remark = (String) remarks.elementAt(i);
2225:
2226: if ((remark != null) && !remark.trim().equals("")) {
2227: makeNode(remark, tableNode);
2228: }
2229:
2230: // This block is very slow for some Oracle tables.
2231: // With a child for each column containing pertinent attributes
2232: while (col.next()) {
2233: String c = col.getString(4);
2234: DefaultMutableTreeNode columnNode = makeNode(c,
2235: tableNode);
2236: String type = col.getString(6);
2237:
2238: makeNode("Type: " + type, columnNode);
2239:
2240: boolean nullable = col.getInt(11) != DatabaseMetaData.columnNoNulls;
2241:
2242: makeNode("Nullable: " + nullable, columnNode);
2243: }
2244: } finally {
2245: if (col != null) {
2246: try {
2247: col.close();
2248: } catch (SQLException se) {
2249: }
2250: }
2251: }
2252:
2253: DefaultMutableTreeNode indexesNode = makeNode(
2254: "Indices", tableNode);
2255:
2256: if (showIndexDetails) {
2257: ResultSet ind = null;
2258:
2259: try {
2260: ind = dMeta.getIndexInfo(null, schema, name,
2261: false, false);
2262:
2263: String oldiname = null;
2264: DefaultMutableTreeNode indexNode = null;
2265:
2266: // A child node to contain each index - and its attributes
2267: while (ind.next()) {
2268: boolean nonunique = ind.getBoolean(4);
2269: String iname = ind.getString(6);
2270:
2271: if ((oldiname == null || !oldiname
2272: .equals(iname))) {
2273: indexNode = makeNode(iname, indexesNode);
2274:
2275: makeNode("Unique: " + !nonunique,
2276: indexNode);
2277:
2278: oldiname = iname;
2279: }
2280:
2281: // And the ordered column list for index components
2282: makeNode(ind.getString(9), indexNode);
2283: }
2284: } catch (SQLException se) {
2285:
2286: // Workaround for Oracle
2287: if (se.getMessage() == null
2288: || ((!se.getMessage().startsWith(
2289: "ORA-25191:"))
2290: && (!se.getMessage()
2291: .startsWith(
2292: "ORA-01702:")) && !se
2293: .getMessage().startsWith(
2294: "ORA-01031:"))) {
2295: throw se;
2296: }
2297: } finally {
2298: if (ind != null) {
2299: ind.close();
2300:
2301: ind = null;
2302: }
2303: }
2304: }
2305: }
2306:
2307: // Finally - a little additional metadata on this connection
2308: propertiesNode = makeNode("Properties", rootNode);
2309:
2310: makeNode("User: " + dMeta.getUserName(), propertiesNode);
2311: makeNode("ReadOnly: " + cConn.isReadOnly(), propertiesNode);
2312: makeNode("AutoCommit: " + cConn.getAutoCommit(),
2313: propertiesNode);
2314: makeNode("Driver: " + dMeta.getDriverName(), propertiesNode);
2315: makeNode("Product: " + dMeta.getDatabaseProductName(),
2316: propertiesNode);
2317: makeNode("Version: " + dMeta.getDatabaseProductVersion(),
2318: propertiesNode);
2319: } catch (SQLException se) {
2320: propertiesNode = makeNode("Error getting metadata:",
2321: rootNode);
2322:
2323: makeNode(se.getMessage(), propertiesNode);
2324: makeNode(se.getSQLState(), propertiesNode);
2325: CommonSwing.errorMessage(se);
2326: } finally {
2327: if (result != null) {
2328: try {
2329: result.close();
2330: } catch (SQLException se) {
2331: }
2332: }
2333: }
2334:
2335: treeModel.nodeStructureChanged(rootNode);
2336: treeModel.reload();
2337: tScrollPane.repaint();
2338:
2339: // We want the Schema List to always be in sync with the displayed tree
2340: updateSchemaList();
2341: }
2342:
2343: // Added: (weconsultants@users) Sets up\changes the running status icon
2344: void setStatusLine(String busyBaseString, int rowCount) {
2345:
2346: iReadyStatus.setSelected(busyBaseString != null);
2347:
2348: if (busyBaseString == null) {
2349: String additionalMsg = "";
2350:
2351: if (schemaFilter != null) {
2352: additionalMsg = " / Tree showing objects in schema '"
2353: + schemaFilter + "'";
2354: }
2355:
2356: if (rowCount > 1) {
2357: additionalMsg += " / " + rowCount + " rows retrieved";
2358: }
2359:
2360: jStatusLine.setText(" " + READY_STATUS + additionalMsg);
2361: } else {
2362: jStatusLine.setText(" " + busyBaseString + "...");
2363: }
2364: }
2365:
2366: // Added: (weconsultants@users) Needed to aggragate counts per table in jTree
2367: protected int[] getRowCounts(Vector inTable, Vector inSchema)
2368: throws Exception {
2369:
2370: if (!displayRowCounts) {
2371: return (null);
2372: }
2373:
2374: String rowCountSelect = "SELECT COUNT(*) FROM ";
2375: int[] counts;
2376: String name;
2377:
2378: counts = new int[inTable.size()];
2379:
2380: try {
2381: Statement select = rowConn.createStatement();
2382:
2383: for (int i = 0; i < inTable.size(); i++) {
2384: try {
2385: String schemaPart = (String) inSchema.elementAt(i);
2386:
2387: schemaPart = schemaPart == null ? ""
2388: : (schemaPart + '.');
2389: name = schemaPart + (String) inTable.elementAt(i);
2390:
2391: ResultSet resultSet = select
2392: .executeQuery(rowCountSelect + name);
2393:
2394: while (resultSet.next()) {
2395: counts[i] = resultSet.getInt(1);
2396: }
2397: } catch (Exception e) {
2398: System.err
2399: .println("Unable to get row count for table "
2400: + inSchema.elementAt(i)
2401: + '.'
2402: + inTable.elementAt(i)
2403: + ". Using value '0': " + e);
2404: }
2405: }
2406: } catch (Exception e) {
2407: CommonSwing.errorMessage(e);
2408: }
2409:
2410: return (counts);
2411: }
2412:
2413: protected JToolBar createToolBar() {
2414:
2415: // Build jtoolbar and jtoolbar Buttons
2416: JToolBar jtoolbar = new JToolBar();
2417:
2418: jtoolbar.putClientProperty("JToolBar.isRollover", Boolean.TRUE);
2419:
2420: // I'm dropping "Statement" from "Execute SQL Statement", etc.,
2421: // because it may or may not be "one statement", but it is SQL.
2422: // Build jbuttonClear Buttons - blaine
2423: jbuttonClear = new JButton("Clear SQL", new ImageIcon(
2424: CommonSwing.getIcon("Clear")));
2425:
2426: jbuttonClear.putClientProperty("is3DEnabled", Boolean.TRUE);
2427: tipMap.put(jbuttonClear, "Clear SQL");
2428: jbuttonClear.addActionListener(new ActionListener() {
2429:
2430: public void actionPerformed(ActionEvent actionevent) {
2431:
2432: if (sqlScriptBuffer == null
2433: && txtCommand.getText().length() < 1) {
2434: CommonSwing.errorMessage("No SQL to clear");
2435:
2436: return;
2437: }
2438:
2439: clear();
2440: }
2441: });
2442:
2443: jbuttonExecute = new JButton("Execute SQL", new ImageIcon(
2444: CommonSwing.getIcon("Execute")));
2445:
2446: tipMap.put(jbuttonExecute, "Execute SQL");
2447: jbuttonExecute.putClientProperty("is3DEnabled", Boolean.TRUE);
2448: jbuttonExecute.addActionListener(new ActionListener() {
2449:
2450: public void actionPerformed(ActionEvent actionevent) {
2451: executeCurrentSQL();
2452: }
2453: });
2454: jtoolbar.addSeparator();
2455: jtoolbar.add(jbuttonClear);
2456: jtoolbar.addSeparator();
2457: jtoolbar.add(jbuttonExecute);
2458: jtoolbar.addSeparator();
2459: jbuttonClear.setAlignmentY(0.5F);
2460: jbuttonClear.setAlignmentX(0.5F);
2461: jbuttonExecute.setAlignmentY(0.5F);
2462: jbuttonExecute.setAlignmentX(0.5F);
2463:
2464: return jtoolbar;
2465: }
2466:
2467: void updateAutoCommitBox() {
2468:
2469: try {
2470: boxAutoCommit.setSelected(cConn.getAutoCommit());
2471: } catch (SQLException se) {
2472: CommonSwing.errorMessage(se);
2473: }
2474: }
2475:
2476: private void setLF(String newLAF) {
2477:
2478: if (currentLAF != null && currentLAF == newLAF) { // No change
2479: return;
2480: }
2481:
2482: if (pResult != null && gridFormat) {
2483: pResult.removeAll();
2484: }
2485:
2486: CommonSwing.setSwingLAF((Component) fMain, newLAF);
2487:
2488: if (pResult != null && gridFormat) {
2489: setResultsInGrid();
2490: }
2491:
2492: currentLAF = newLAF;
2493:
2494: if (currentLAF.equals(CommonSwing.Native)) {
2495: rbNativeLF.setSelected(true);
2496: } else if (currentLAF.equals(CommonSwing.Java)) {
2497: rbJavaLF.setSelected(true);
2498: } else if (currentLAF.equals(CommonSwing.Motif)) {
2499: rbMotifLF.setSelected(true);
2500: }
2501: }
2502:
2503: void resetTooltips() {
2504:
2505: Iterator it = tipMap.keySet().iterator();
2506: JComponent component;
2507:
2508: while (it.hasNext()) {
2509: component = (JComponent) it.next();
2510:
2511: component.setToolTipText(showTooltips ? ((String) tipMap
2512: .get(component)) : (String) null);
2513: }
2514: }
2515:
2516: private void updateSchemaList() {
2517:
2518: ButtonGroup group = new ButtonGroup();
2519: ArrayList list = new ArrayList();
2520: ResultSet result = null;
2521:
2522: try {
2523: result = dMeta.getSchemas();
2524:
2525: if (result == null) {
2526: throw new SQLException(
2527: "Failed to get metadata from database");
2528: }
2529:
2530: while (result.next()) {
2531: list.add(result.getString(1));
2532: }
2533: } catch (SQLException se) {
2534: CommonSwing.errorMessage(se);
2535: } finally {
2536: if (result != null) {
2537: try {
2538: result.close();
2539: } catch (SQLException se) {
2540: }
2541: }
2542: }
2543:
2544: mnuSchemas.removeAll();
2545: rbAllSchemas.setSelected(schemaFilter == null);
2546: group.add(rbAllSchemas);
2547: mnuSchemas.add(rbAllSchemas);
2548:
2549: String s;
2550: JRadioButtonMenuItem radioButton;
2551:
2552: for (int i = 0; i < list.size(); i++) {
2553: s = (String) list.get(i);
2554: radioButton = new JRadioButtonMenuItem(s);
2555:
2556: group.add(radioButton);
2557: mnuSchemas.add(radioButton);
2558: radioButton.setSelected(schemaFilter != null
2559: && schemaFilter.equals(s));
2560: radioButton.addActionListener(schemaListListener);
2561: radioButton.setEnabled(list.size() > 1);
2562: }
2563:
2564: mnuSchemas.addSeparator();
2565: mnuSchemas.add(mitemUpdateSchemas);
2566: }
2567:
2568: ActionListener schemaListListener = (new ActionListener() {
2569:
2570: public void actionPerformed(ActionEvent actionevent) {
2571:
2572: schemaFilter = actionevent.getActionCommand();
2573:
2574: if (schemaFilter.equals("*")) {
2575: schemaFilter = null;
2576: }
2577:
2578: refreshTree();
2579: }
2580: });
2581:
2582: /**
2583: * Persisted User Preferences for DatabaseManagerSwing.
2584: *
2585: * These are settings for items in the View and Options pulldown menus,
2586: * plus Help/Show Tooltips.
2587: */
2588: public class DBMPrefs {
2589:
2590: public File prefsFile = null;
2591:
2592: /**
2593: * The constructor guarantees that this will be null for Applet,
2594: * non-null if using a local preferences file
2595: */
2596:
2597: // Set defaults from Data
2598: boolean autoRefresh = true;
2599: boolean showRowCounts = false;
2600: boolean showSysTables = false;
2601: boolean showSchemas = true;
2602: boolean resultGrid = true;
2603: String laf = CommonSwing.Native;
2604:
2605: // Somebody with more time can store the font settings. IMO, that
2606: // menu item shouldn't even be there if the settings aren't persisted.
2607: boolean showTooltips = true;
2608:
2609: public DBMPrefs(boolean isApplet) throws IOException {
2610:
2611: if (isApplet) {
2612: } else {
2613: if (homedir == null) {
2614: throw new IOException(
2615: "Skipping preferences since do not know home dir");
2616: }
2617:
2618: prefsFile = new File(homedir, "dbmprefs.properties");
2619: }
2620:
2621: load();
2622: }
2623:
2624: public void load() throws IOException {
2625:
2626: String tmpString;
2627:
2628: if (prefsFile == null) {
2629:
2630: // LOAD PREFERENCES FROM APPLET PARAMS
2631: tmpString = getParameter("autoRefresh");
2632:
2633: if (tmpString != null) {
2634: autoRefresh = Boolean.valueOf(tmpString)
2635: .booleanValue();
2636: }
2637:
2638: tmpString = getParameter("showRowCounts");
2639:
2640: if (tmpString != null) {
2641: showRowCounts = Boolean.valueOf(tmpString)
2642: .booleanValue();
2643: }
2644:
2645: tmpString = getParameter("showSysTables");
2646:
2647: if (tmpString != null) {
2648: showSysTables = Boolean.valueOf(tmpString)
2649: .booleanValue();
2650: }
2651:
2652: tmpString = getParameter("showSchemas");
2653:
2654: if (tmpString != null) {
2655: showSchemas = Boolean.valueOf(tmpString)
2656: .booleanValue();
2657: }
2658:
2659: tmpString = getParameter("resultGrid");
2660:
2661: if (tmpString != null) {
2662: resultGrid = Boolean.valueOf(tmpString)
2663: .booleanValue();
2664: }
2665:
2666: tmpString = getParameter("laf");
2667: laf = ((tmpString == null) ? CommonSwing.Native
2668: : tmpString);
2669: tmpString = getParameter("showTooltips");
2670:
2671: if (tmpString != null) {
2672: showTooltips = Boolean.valueOf(tmpString)
2673: .booleanValue();
2674: }
2675: } else {
2676:
2677: // LOAD PREFERENCES FROM LOCAL PREFERENCES FILE
2678: if (!prefsFile.exists()) {
2679: throw new IOException("No such file: " + prefsFile);
2680: }
2681:
2682: Properties props = new Properties();
2683:
2684: try {
2685: FileInputStream fis = new FileInputStream(prefsFile);
2686:
2687: props.load(fis);
2688: fis.close();
2689: } catch (IOException ioe) {
2690: throw new IOException(
2691: "Failed to read preferences file '"
2692: + prefsFile + "': "
2693: + ioe.getMessage());
2694: }
2695:
2696: tmpString = props.getProperty("autoRefresh");
2697:
2698: if (tmpString != null) {
2699: autoRefresh = Boolean.valueOf(tmpString)
2700: .booleanValue();
2701: }
2702:
2703: tmpString = props.getProperty("showRowCounts");
2704:
2705: if (tmpString != null) {
2706: showRowCounts = Boolean.valueOf(tmpString)
2707: .booleanValue();
2708: }
2709:
2710: tmpString = props.getProperty("showSysTables");
2711:
2712: if (tmpString != null) {
2713: showSysTables = Boolean.valueOf(tmpString)
2714: .booleanValue();
2715: }
2716:
2717: tmpString = props.getProperty("showSchemas");
2718:
2719: if (tmpString != null) {
2720: showSchemas = Boolean.valueOf(tmpString)
2721: .booleanValue();
2722: }
2723:
2724: tmpString = props.getProperty("resultGrid");
2725:
2726: if (tmpString != null) {
2727: resultGrid = Boolean.valueOf(tmpString)
2728: .booleanValue();
2729: }
2730:
2731: tmpString = props.getProperty("laf");
2732: laf = ((tmpString == null) ? CommonSwing.Native
2733: : tmpString);
2734: tmpString = props.getProperty("showTooltips");
2735:
2736: if (tmpString != null) {
2737: showTooltips = Boolean.valueOf(tmpString)
2738: .booleanValue();
2739: }
2740: }
2741: }
2742:
2743: public void store() {
2744:
2745: if (prefsFile == null) {
2746:
2747: // Can't persist Applet settings.
2748: return;
2749: }
2750:
2751: Properties props = new Properties();
2752:
2753: // Boolean.toString(boolean) was new with Java 1.4, so don't use that.
2754: props.setProperty("autoRefresh", (autoRefresh ? tString
2755: : fString));
2756: props.setProperty("showRowCounts", (showRowCounts ? tString
2757: : fString));
2758: props.setProperty("showSysTables", (showSysTables ? tString
2759: : fString));
2760: props.setProperty("showSchemas", (showSchemas ? tString
2761: : fString));
2762: props.setProperty("resultGrid", (resultGrid ? tString
2763: : fString));
2764: props.setProperty("laf", laf);
2765: props.setProperty("showTooltips", (showTooltips ? tString
2766: : fString));
2767:
2768: try {
2769: FileOutputStream fos = new FileOutputStream(prefsFile);
2770:
2771: props.store(fos,
2772: "DatabaseManagerSwing user preferences");
2773: fos.flush();
2774: fos.close();
2775: } catch (IOException ioe) {
2776: throw new RuntimeException(
2777: "Failed to prepare preferences file '"
2778: + prefsFile + "': " + ioe.getMessage());
2779: }
2780: }
2781: }
2782:
2783: private static final String tString = Boolean.TRUE.toString();
2784: private static final String fString = Boolean.FALSE.toString();
2785: }
|