Coverage Report - us.daveread.basicquery.BasicQuery
 
Classes in this File Line Coverage Branch Coverage Complexity
BasicQuery
0%
0/2296
0%
0/411
0
BasicQuery$ExportResultsAsTriplesListener
0%
0/4
N/A
0
 
 1  
 package us.daveread.basicquery;
 2  
 
 3  
 import java.awt.BorderLayout;
 4  
 import java.awt.Color;
 5  
 import java.awt.Cursor;
 6  
 import java.awt.Desktop;
 7  
 import java.awt.EventQueue;
 8  
 import java.awt.FlowLayout;
 9  
 import java.awt.Font;
 10  
 import java.awt.GridLayout;
 11  
 import java.awt.event.ActionEvent;
 12  
 import java.awt.event.ActionListener;
 13  
 import java.awt.event.KeyEvent;
 14  
 import java.awt.event.KeyListener;
 15  
 import java.awt.event.WindowEvent;
 16  
 import java.awt.event.WindowListener;
 17  
 import java.io.BufferedReader;
 18  
 import java.io.File;
 19  
 import java.io.FileNotFoundException;
 20  
 import java.io.FileOutputStream;
 21  
 import java.io.FileReader;
 22  
 import java.io.FileWriter;
 23  
 import java.io.InputStream;
 24  
 import java.io.PrintWriter;
 25  
 import java.io.StringWriter;
 26  
 import java.lang.reflect.Constructor;
 27  
 import java.lang.reflect.Method;
 28  
 import java.lang.reflect.Array;
 29  
 import java.sql.CallableStatement;
 30  
 import java.sql.Connection;
 31  
 import java.sql.DatabaseMetaData;
 32  
 import java.sql.Driver;
 33  
 import java.sql.DriverManager;
 34  
 import java.sql.PreparedStatement;
 35  
 import java.sql.ResultSet;
 36  
 import java.sql.ResultSetMetaData;
 37  
 import java.sql.SQLException;
 38  
 import java.sql.SQLWarning;
 39  
 import java.sql.Statement;
 40  
 import java.util.ArrayList;
 41  
 import java.util.Date;
 42  
 import java.util.HashMap;
 43  
 import java.util.Iterator;
 44  
 import java.util.List;
 45  
 import java.util.Locale;
 46  
 import java.util.Map;
 47  
 import java.util.Observable;
 48  
 import java.util.Observer;
 49  
 import java.util.Properties;
 50  
 import java.util.Set;
 51  
 
 52  
 import javax.swing.Action;
 53  
 import javax.swing.BorderFactory;
 54  
 import javax.swing.ButtonGroup;
 55  
 import javax.swing.DefaultComboBoxModel;
 56  
 import javax.swing.ImageIcon;
 57  
 import javax.swing.JButton;
 58  
 import javax.swing.JCheckBox;
 59  
 import javax.swing.JCheckBoxMenuItem;
 60  
 import javax.swing.JComboBox;
 61  
 import javax.swing.JFileChooser;
 62  
 import javax.swing.JFrame;
 63  
 import javax.swing.JLabel;
 64  
 import javax.swing.JMenu;
 65  
 import javax.swing.JMenuBar;
 66  
 import javax.swing.JMenuItem;
 67  
 import javax.swing.JOptionPane;
 68  
 import javax.swing.JPanel;
 69  
 import javax.swing.JPasswordField;
 70  
 import javax.swing.JRadioButton;
 71  
 import javax.swing.JRadioButtonMenuItem;
 72  
 import javax.swing.JScrollPane;
 73  
 import javax.swing.JTable;
 74  
 import javax.swing.JTextArea;
 75  
 import javax.swing.JTextField;
 76  
 import javax.swing.JTextPane;
 77  
 import javax.swing.KeyStroke;
 78  
 import javax.swing.ListSelectionModel;
 79  
 import javax.swing.ProgressMonitor;
 80  
 import javax.swing.TransferHandler;
 81  
 import javax.swing.WindowConstants;
 82  
 import javax.swing.border.Border;
 83  
 import javax.swing.filechooser.FileFilter;
 84  
 import javax.swing.table.TableModel;
 85  
 import javax.swing.text.AttributeSet;
 86  
 import javax.swing.text.BadLocationException;
 87  
 import javax.swing.text.DefaultStyledDocument;
 88  
 import javax.swing.text.StyledDocument;
 89  
 
 90  
 import org.apache.commons.dbcp.DriverManagerConnectionFactory;
 91  
 import org.apache.commons.dbcp.PoolableConnectionFactory;
 92  
 import org.apache.commons.dbcp.PoolingDriver;
 93  
 import org.apache.commons.pool.ObjectPool;
 94  
 import org.apache.commons.pool.impl.GenericObjectPool;
 95  
 import org.apache.log4j.PropertyConfigurator;
 96  
 import org.apache.log4j.Logger;
 97  
 
 98  
 import us.daveread.basicquery.gui.ColoredCellRenderer;
 99  
 import us.daveread.basicquery.gui.FlashForeground;
 100  
 import us.daveread.basicquery.gui.FocusRequestor;
 101  
 import us.daveread.basicquery.gui.FontChooser;
 102  
 import us.daveread.basicquery.gui.InsertTime;
 103  
 import us.daveread.basicquery.gui.MaxHeightJScrollPane;
 104  
 import us.daveread.basicquery.gui.MessageStyleFactory;
 105  
 import us.daveread.basicquery.images.ImageUtility;
 106  
 import us.daveread.basicquery.queries.Query;
 107  
 import us.daveread.basicquery.queries.QueryHistory;
 108  
 import us.daveread.basicquery.queries.QueryInfo;
 109  
 import us.daveread.basicquery.util.CheckLatestVersion;
 110  
 import us.daveread.basicquery.util.Configuration;
 111  
 import us.daveread.basicquery.util.FileFilterDefinition;
 112  
 import us.daveread.basicquery.util.ListTableModel;
 113  
 import us.daveread.basicquery.util.NewVersionInformation;
 114  
 import us.daveread.basicquery.util.RdbToRdf;
 115  
 import us.daveread.basicquery.util.Resources;
 116  
 import us.daveread.basicquery.util.SuffixFileFilter;
 117  
 import us.daveread.basicquery.util.TableSorter;
 118  
 import us.daveread.basicquery.util.Utility;
 119  
 
 120  
 /**
 121  
  * Title: Basic Query Utility
 122  
  * <p>
 123  
  * Execute arbitrary SQL against database accessible with any JDBC-compliant
 124  
  * driver.
 125  
  * </p>
 126  
  * 
 127  
  * <p>
 128  
  * Copyright: Copyright (c) 2004-2014, David Read
 129  
  * </p>
 130  
  * 
 131  
  * <p>
 132  
  * This program is free software; you can redistribute it and/or modify it under
 133  
  * the terms of the GNU General Public License as published by the Free Software
 134  
  * Foundation; either version 2 of the License, or (at your option) any later
 135  
  * version.
 136  
  * </p>
 137  
  * 
 138  
  * <p>
 139  
  * This program is distributed in the hope that it will be useful, but WITHOUT
 140  
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 141  
  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 142  
  * details.
 143  
  * </p>
 144  
  * 
 145  
  * <p>
 146  
  * You should have received a copy of the GNU General Public License along with
 147  
  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 148  
  * Place, Suite 330, Boston, MA 02111-1307 USA
 149  
  * </p>
 150  
  * 
 151  
  * <p>
 152  
  * </p>
 153  
  * 
 154  
  * @author David Read
 155  
  */
 156  
 
 157  0
 public class BasicQuery extends JFrame implements Runnable, ActionListener,
 158  
     WindowListener, Observer, KeyListener {
 159  
 
 160  
   /**
 161  
    * Serial version id - update if the serialization of this classes changes
 162  
    */
 163  
   private static final long serialVersionUID = 5162L;
 164  
 
 165  
   /**
 166  
    * Program version - MUST be in ##.##.## format
 167  
    */
 168  
   private static final String VERSION = "02.00.05";
 169  
 
 170  
   /**
 171  
    * Logger
 172  
    */
 173  0
   private static final Logger LOGGER = Logger.getLogger(BasicQuery.class);
 174  
 
 175  
   /**
 176  
    * Database drivers file
 177  
    */
 178  
   private static final String FILENAME_DRIVERS = "BasicQuery.Drivers";
 179  
 
 180  
   /**
 181  
    * Logging configuration file
 182  
    */
 183  
   private static final String FILENAME_LOGGER = "BasicQuery.Logger";
 184  
 
 185  
   /**
 186  
    * Default file for storing queries
 187  
    */
 188  
   private static final String FILENAME_DEFAULTQUERIES = "BasicQuery.SQL";
 189  
 
 190  
   /**
 191  
    * File containing connection strings
 192  
    */
 193  
   private static final String FILENAME_CONNECTSTRINGS = "BasicQuery.Connect";
 194  
 
 195  
   /**
 196  
    * Name of the DB connection pool
 197  
    */
 198  
   private static final String DBPOOL_NAME = "BasicQuery.DBPool";
 199  
 
 200  
   /**
 201  
    * File containing statistics, when enabled
 202  
    */
 203  
   private static final String DBSTATS_NAME = "BasicQuery.Stats.csv";
 204  
 
 205  
   /**
 206  
    * File containing query results, when enabled
 207  
    */
 208  
   private static final String DBRESULTS_NAME = "BasicQuery.Results.csv";
 209  
 
 210  
   /**
 211  
    * Property name - user id
 212  
    */
 213  
   private static final String PROP_USERID = "USERID";
 214  
 
 215  
   /**
 216  
    * Property name - password
 217  
    */
 218  
   private static final String PROP_PASSWORD = "PASSWORD";
 219  
 
 220  
   /**
 221  
    * Property name - connection autocommit setting
 222  
    */
 223  
   private static final String PROP_AUTOCOMMIT = "AUTOCOMMIT";
 224  
 
 225  
   /**
 226  
    * Property name - connection readonly setting
 227  
    */
 228  
   private static final String PROP_READONLY = "READONLY";
 229  
 
 230  
   /**
 231  
    * Property name - connection pooling enabled
 232  
    */
 233  
   private static final String PROP_POOLING = "POOLING";
 234  
 
 235  
   /**
 236  
    * Property name - last connection string used
 237  
    */
 238  
   private static final String PROP_CONNECTION = "CONNECTION";
 239  
 
 240  
   /**
 241  
    * Property name - last SQL statement executed
 242  
    */
 243  
   private static final String PROP_SQL = "SQL";
 244  
 
 245  
   /**
 246  
    * Propert name - last SQL statement file used
 247  
    */
 248  
   private static final String PROP_SQLFILENAME = "SQLFILE";
 249  
 
 250  
   /**
 251  
    * Property name - maximum number of display rows setting
 252  
    */
 253  
   private static final String PROP_MAXROWS = "MAXROWS";
 254  
 
 255  
   /**
 256  
    * Property name - log statistics setting
 257  
    */
 258  
   private static final String PROP_LOGSTATS = "LOGSTATS";
 259  
 
 260  
   /**
 261  
    * Property name - log query results setting
 262  
    */
 263  
   private static final String PROP_LOGRESULTS = "LOGRESULTS";
 264  
 
 265  
   /**
 266  
    * Property name - export raw query results setting
 267  
    */
 268  
   private static final String PROP_EXPORTRAW = "EXPORTRAW";
 269  
 
 270  
   /**
 271  
    * Property name - export without CR setting
 272  
    */
 273  
   private static final String PROP_EXPORTNOCR = "EXPORTNOCR";
 274  
 
 275  
   /**
 276  
    * Property name - associate query and connection setting
 277  
    */
 278  
   private static final String PROP_ASSOCSQLURL = "ASSOCSQLURL";
 279  
 
 280  
   /**
 281  
    * Property name - parse queries on semicolon setting
 282  
    */
 283  
   private static final String PROP_PARSESEMICOLON = "PARSESEMICOLON";
 284  
 
 285  
   /**
 286  
    * Property name - save password setting
 287  
    */
 288  
   private static final String PROP_SAVEPASSWORD = "SAVEPASSWORD";
 289  
 
 290  
   /**
 291  
    * Property name - last window upper left corner X position
 292  
    */
 293  
   private static final String PROP_UPPERLEFTX = "UPPERLEFTX";
 294  
 
 295  
   /**
 296  
    * Property name - last window upper left corner Y position
 297  
    */
 298  
   private static final String PROP_UPPERLEFTY = "UPPERLEFTY";
 299  
 
 300  
   /**
 301  
    * Property name - last window width
 302  
    */
 303  
   private static final String PROP_WIDTH = "WIDTH";
 304  
 
 305  
   /**
 306  
    * Property name - last window height
 307  
    */
 308  
   private static final String PROP_HEIGHT = "HEIGHT";
 309  
 
 310  
   /**
 311  
    * Property name - last window maximized setting
 312  
    */
 313  
   private static final String PROP_MAXIMIZED = "MAXIMIZED";
 314  
 
 315  
   /**
 316  
    * Property name - directory containing DB driver files
 317  
    */
 318  
   private static final String PROP_DBDRIVERDIR = "DBDRIVERDIR";
 319  
 
 320  
   /**
 321  
    * Property name - keywords that should not occur in an update statement
 322  
    */
 323  
   private static final String PROP_WARNUPDATEPATTERNS = "WARNUPDATEPATTERNS";
 324  
 
 325  
   /**
 326  
    * Property name - keywords that should not occur in a select statement
 327  
    */
 328  
   private static final String PROP_WARNSELECTPATTERNS = "WARNSELECTPATTERNS";
 329  
 
 330  
   /**
 331  
    * Property name - display DB server information setting
 332  
    */
 333  
   private static final String PROP_DISPLAYDBSERVERINFO = "DISPLAYDBSERVERINFO";
 334  
 
 335  
   /**
 336  
    * Property name - display client information setting
 337  
    */
 338  
   private static final String PROP_DISPLAYCLIENTINFO = "DISPLAYCLIENTINFO";
 339  
 
 340  
   /**
 341  
    * Property name - display column type setting
 342  
    */
 343  
   private static final String PROP_DISPLAYCOLUMNDATATYPE =
 344  
       "DISPLAYCOLUMNDATATYPE";
 345  
 
 346  
   /**
 347  
    * Property name - row coloring setting
 348  
    */
 349  
   private static final String PROP_TABLE_COLORING = "TABLECOLORING";
 350  
 
 351  
   /**
 352  
    * Property name - user defined row coloring setting
 353  
    */
 354  
   private static final String PROP_TABLE_COLOR_USERDEF = "TABLECOLORUSERDEF";
 355  
 
 356  
   /**
 357  
    * Property name - interface language setting
 358  
    */
 359  
   private static final String PROP_LANGUAGE = "LANGUAGE";
 360  
 
 361  
   /**
 362  
    * Property name - font setting
 363  
    */
 364  
   private static final String PROP_FONT_FAMILY = "FONTFAMILY";
 365  
 
 366  
   /**
 367  
    * Property name - fint size setting
 368  
    */
 369  
   private static final String PROP_FONT_SIZE = "FONTSIZE";
 370  
 
 371  
   /**
 372  
    * Property name - font bold setting
 373  
    */
 374  
   private static final String PROP_FONT_BOLD = "FONTBOLD";
 375  
 
 376  
   /**
 377  
    * Property name - font italic setting
 378  
    */
 379  
   private static final String PROP_FONT_ITALIC = "FONTITALIC";
 380  
 
 381  
   /**
 382  
    * Latest directory used when choosing a file
 383  
    */
 384  
   private static final String PROP_LATEST_DIRECTORY = "LATEST_FILE_DIRECTORY";
 385  
 
 386  
   /**
 387  
    * Default directory name for DB driver files
 388  
    */
 389  
   private static final String DEFAULT_DBDRIVERDIR = "DBDrivers";
 390  
 
 391  
   /**
 392  
    * Default update warning statement keywords
 393  
    */
 394  
   private static final String DEFAULTWARNUPDATEPATTERNS =
 395  
       "SELECT,SHOW,DESCRIBE,DESC";
 396  
 
 397  
   /**
 398  
    * Default select warning statement keywords
 399  
    */
 400  
   private static final String DEFAULTWARNSELECTPATTERNS =
 401  
       "INSERT,UPDATE,DELETE,ALTER,DROP,CREATE";
 402  
 
 403  
   /**
 404  
    * Normal text style
 405  
    */
 406  
   private static final String STYLE_NORMAL = "Normal";
 407  
 
 408  
   /**
 409  
    * Bold text style
 410  
    */
 411  
   private static final String STYLE_BOLD = "Bold";
 412  
 
 413  
   /**
 414  
    * Green text
 415  
    */
 416  
   private static final String STYLE_GREEN = "Green";
 417  
 
 418  
   /**
 419  
    * Yellow text
 420  
    */
 421  
   private static final String STYLE_YELLOW = "Yellow";
 422  
 
 423  
   /**
 424  
    * Red text
 425  
    */
 426  
   private static final String STYLE_RED = "Red";
 427  
 
 428  
   /**
 429  
    * Subtle text style
 430  
    */
 431  
   private static final String STYLE_SUBTLE = "Subtle";
 432  
 
 433  
   /**
 434  
    * Subtle and underlined text style
 435  
    */
 436  
   private static final String STYLE_SUBTLE_UL = "SubtleUL";
 437  
 
 438  
   /**
 439  
    * Table row alternating green and white
 440  
    */
 441  
   private static final String TABLECOLORING_GREENBAR = "GREENBAR";
 442  
 
 443  
   /**
 444  
    * Table row alternating yellow and white
 445  
    */
 446  
   private static final String TABLECOLORING_YELLOWBAR = "YELLOWBAR";
 447  
 
 448  
   /**
 449  
    * Table row coloring is user defined
 450  
    */
 451  
   private static final String TABLECOLORING_USERDEFINED = "USERDEFINED";
 452  
 
 453  
   /**
 454  
    * Table rows not colored (background white)
 455  
    */
 456  
   private static final String TABLECOLORING_NONE = "NONE";
 457  
 
 458  
   /**
 459  
    * Display long form of DB information
 460  
    */
 461  
   private static final String DBSERVERINFO_LONG = "LONG";
 462  
 
 463  
   /**
 464  
    * Display brief form of DB information
 465  
    */
 466  
   private static final String DBSERVERINFO_BRIEF = "BRIEF";
 467  
 
 468  
   /**
 469  
    * The Yes (True) value for a parameter
 470  
    */
 471  
   private static final String PARAMVALUE_NO = "NO";
 472  
 
 473  
   /**
 474  
    * The No (False) value for a parameter
 475  
    */
 476  
   private static final String PARAMVALUE_YES = "YES";
 477  
 
 478  
   /**
 479  
    * Query run mode - single statement
 480  
    */
 481  
   private static final int RUNTYPE_SINGLE = 0;
 482  
 
 483  
   /**
 484  
    * Query run mode - all statements
 485  
    */
 486  
   private static final int RUNTYPE_ALL = 1;
 487  
 
 488  
   /**
 489  
    * Query run mode - export results as triples
 490  
    */
 491  
   private static final int RUNTYPE_TRIPLE_EXPORT = 2;
 492  
 
 493  
   /**
 494  
    * System property supplying user's configured language code
 495  
    */
 496  
   private static final String PROP_SYSTEM_DEFAULTLANGUAGE = "user.language";
 497  
 
 498  
   /**
 499  
    * System property supplying user's configured country code
 500  
    */
 501  
   private static final String PROP_SYSTEM_DEFAULTCOUNTRY = "user.country";
 502  
 
 503  
   /**
 504  
    * Interface: Use default language (e.g. from system property)
 505  
    */
 506  
   private static final String LANG_DEFAULT = "DEFAULT";
 507  
 
 508  
   /**
 509  
    * Interface: Use English
 510  
    */
 511  
   private static final String LANG_ENGLISH = "ENGLISH";
 512  
 
 513  
   /**
 514  
    * Interface: Use French
 515  
    */
 516  
   private static final String LANG_FRENCH = "FRENCH";
 517  
 
 518  
   /**
 519  
    * Interface: Use German
 520  
    */
 521  
   private static final String LANG_GERMAN = "GERMAN";
 522  
 
 523  
   /**
 524  
    * Interface: Use Italian
 525  
    */
 526  
   private static final String LANG_ITALIAN = "ITALIAN";
 527  
 
 528  
   /**
 529  
    * Interface: Use Portuguese
 530  
    */
 531  
   private static final String LANG_PORTUGUESE = "PORTUGUESE";
 532  
 
 533  
   /**
 534  
    * Interface: Use Spanish
 535  
    */
 536  
   private static final String LANG_SPANISH = "SPANISH";
 537  
 
 538  
   /**
 539  
    * Prefix to comment-out queries
 540  
    */
 541  
   private static final String COMMENT_PREFIX = "//";
 542  
 
 543  
   /**
 544  
    * Rows for the query input text area
 545  
    */
 546  
   private static final int QUERY_AREA_ROWS = 5;
 547  
 
 548  
   /**
 549  
    * Minimum width, in characters, for the query input text area
 550  
    */
 551  
   private static final int QUERY_AREA_COLUMNS = 60;
 552  
 
 553  
   /**
 554  
    * Fraction of available window for the scroll pane
 555  
    */
 556  
   private static final int MAX_SCROLL_PANE_DIVISOR_FOR_MAX_HEIGHT = 6;
 557  
 
 558  
   /**
 559  
    * Colors per user-defined color entry
 560  
    */
 561  
   private static final int USER_DEFINED_COLORING_COLORS_PER_ENTRY = 2;
 562  
 
 563  
   /**
 564  
    * Color code length
 565  
    */
 566  
   private static final int USER_DEFINED_COLORING_COLOR_CODE_LENGTH = 6;
 567  
 
 568  
   /**
 569  
    * Numeric base for the color coding value
 570  
    */
 571  
   private static final int COLOR_CODING_NUMERIC_BASE = 16;
 572  
 
 573  
   /**
 574  
    * Position of the red color value
 575  
    */
 576  
   private static final int COLOR_CODING_COLOR_1_START = 0;
 577  
 
 578  
   /**
 579  
    * Position of the green color value
 580  
    */
 581  
   private static final int COLOR_CODING_COLOR_2_START = 2;
 582  
 
 583  
   /**
 584  
    * Position of the blue color value
 585  
    */
 586  
   private static final int COLOR_CODING_COLOR_3_START = 4;
 587  
 
 588  
   /**
 589  
    * End of the blue color value
 590  
    */
 591  
   private static final int COLOR_CODING_COLOR_3_END = 6;
 592  
 
 593  
   /**
 594  
    * Maximum wait time for a connection to be available from the pool
 595  
    */
 596  
   private static final int CONN_POOL_MAX_WAIT_MS = 5000;
 597  
 
 598  
   /**
 599  
    * Maximum number of connections to hold in the pool
 600  
    */
 601  
   private static final int CONN_POOL_MAX_IDLE_CONNECTIONS = 1;
 602  
 
 603  
   /**
 604  
    * Time to wait between connection pool eviction runs
 605  
    */
 606  
   private static final int CONN_POOL_TIME_BETWEEN_EVICT_RUNS_MS = 30000;
 607  
 
 608  
   /**
 609  
    * Number of connections in the connection pool to test per eviction run
 610  
    */
 611  
   private static final int CONN_POOL_NUM_TESTS_PER_EVICT_RUN = 5;
 612  
 
 613  
   /**
 614  
    * Maximum age for a connection before evicting it
 615  
    */
 616  
   private static final int CONN_POOL_EVICT_IDLE_TIME_MS = 60000;
 617  
 
 618  
   /**
 619  
    * Minimum length for a line before inserting a carriage return
 620  
    */
 621  
   private static final int TEXT_WRAP_MIN_LINE_LENGTH_BEFORE_WRAP = 60;
 622  
 
 623  
   /**
 624  
    * Maximum length for a line before inserting a carriage return
 625  
    */
 626  
   private static final int TEXT_WRAP_MAX_LINE_LENGTH = 80;
 627  
 
 628  
   /**
 629  
    * Maximum number of digits in a value before storing as a long
 630  
    */
 631  
   private static final int MAX_DIGITS_FOR_INT = 7;
 632  
 
 633  
   /**
 634  
    * Number of columns reported for a table describe
 635  
    */
 636  
   private static final int DESC_TABLE_COLUMN_COUNT = 6;
 637  
 
 638  
   /**
 639  
    * Table describe: Column containing the column name
 640  
    */
 641  
   private static final int DESC_TABLE_NAME_COLUMN = 0;
 642  
 
 643  
   /**
 644  
    * Table describe: Column containing the column name
 645  
    */
 646  
   private static final int DESC_TABLE_TYPE_COLUMN = 1;
 647  
 
 648  
   /**
 649  
    * Table describe: Column containing the column length
 650  
    */
 651  
   private static final int DESC_TABLE_LENGTH_COLUMN = 2;
 652  
 
 653  
   /**
 654  
    * Table describe: Column containing the column precision
 655  
    */
 656  
   private static final int DESC_TABLE_PRECISION_COLUMN = 3;
 657  
 
 658  
   /**
 659  
    * Table describe: Column containing the column scale
 660  
    */
 661  
   private static final int DESC_TABLE_SCALE_COLUMN = 4;
 662  
 
 663  
   /**
 664  
    * Table describe: Column containing the nulls-allowed indicator
 665  
    */
 666  
   private static final int DESC_TABLE_NULLS_OK_COLUMN = 5;
 667  
 
 668  
   /**
 669  
    * Column data type: string
 670  
    */
 671  
   private static final int COLUMN_DATA_TYPE_STRING = 0;
 672  
 
 673  
   /**
 674  
    * Column data type: integer
 675  
    */
 676  
   private static final int COLUMN_DATA_TYPE_INT = 1;
 677  
 
 678  
   /**
 679  
    * Column data type: long
 680  
    */
 681  
   private static final int COLUMN_DATA_TYPE_LONG = 2;
 682  
 
 683  
   /**
 684  
    * Column data type: double
 685  
    */
 686  
   private static final int COLUMN_DATA_TYPE_DOUBLE = 3;
 687  
 
 688  
   /**
 689  
    * Column data type: date
 690  
    */
 691  
   private static final int COLUMN_DATA_TYPE_DATE = 5;
 692  
 
 693  
   /**
 694  
    * Column data type: datetime
 695  
    */
 696  
   private static final int COLUMN_DATA_TYPE_DATETIME = 5;
 697  
 
 698  
   /**
 699  
    * Column data type: BLOB
 700  
    */
 701  
   private static final int COLUMN_DATA_TYPE_BLOB = 6;
 702  
 
 703  
   /**
 704  
    * Token prefix for a parameter
 705  
    */
 706  
   private static final String PARAM_TOKEN_START = "$PARAM[";
 707  
 
 708  
   /**
 709  
    * Token suffix for a parameter
 710  
    */
 711  
   private static final String PARAM_TOKEN_END = "]$";
 712  
 
 713  
   /**
 714  
    * Length of the parameter token prefix
 715  
    */
 716  0
   private static final int PARAM_TOKEN_START_LENGTH = PARAM_TOKEN_START
 717  
       .length();
 718  
 
 719  
   /**
 720  
    * Length of the parameter token suffix
 721  
    */
 722  0
   private static final int PARAM_TOKEN_END_LENGTH = PARAM_TOKEN_END.length();
 723  
 
 724  
   /**
 725  
    * Bloxk size used when storing a BLOB field to a file
 726  
    */
 727  
   private static final int BLOB_LOAD_BLOCK_SIZE = 4096;
 728  
 
 729  
   /**
 730  
    * Time, in milliseconds, to delay between updates of the query execution
 731  
    * timer display
 732  
    */
 733  
   private static final int QUERY_EXECUTION_TIMER_UPDATE_DELAY_MS = 250;
 734  
 
 735  
   /**
 736  
    * Number of rows to write between status message updates
 737  
    */
 738  
   private static final int RESULT_PROCESSING_ROWS_PER_STATUS_MESSAGE = 100000;
 739  
 
 740  
   /**
 741  
    * Number of seconds in an hour
 742  
    */
 743  
   private static final int SECONDS_PER_HOUR = 3600;
 744  
 
 745  
   /**
 746  
    * Number of seconds in a minute
 747  
    */
 748  
   private static final int SECONDS_PER_MINUTE = 60;
 749  
 
 750  
   /**
 751  
    * For color green: red component value
 752  
    */
 753  
   private static final int COLOR_GREEN_R_VALUE = 192;
 754  
 
 755  
   /**
 756  
    * For color green: green component value
 757  
    */
 758  
   private static final int COLOR_GREEN_G_VALUE = 255;
 759  
 
 760  
   /**
 761  
    * For color green: blue component value
 762  
    */
 763  
   private static final int COLOR_GREEN_B_VALUE = 192;
 764  
 
 765  
   /**
 766  
    * For color yellow: red component value
 767  
    */
 768  
   private static final int COLOR_YELLOW_R_VALUE = 255;
 769  
 
 770  
   /**
 771  
    * For color yellow: green component value
 772  
    */
 773  
   private static final int COLOR_YELLOW_G_VALUE = 255;
 774  
 
 775  
   /**
 776  
    * For color yellow: blue component value
 777  
    */
 778  
   private static final int COLOR_YELLOW_B_VALUE = 192;
 779  
 
 780  
   /**
 781  
    * File export format: CSV
 782  
    */
 783  
   private static final int FILE_EXPORT_CSV = 0;
 784  
 
 785  
   /**
 786  
    * File export format: Triples
 787  
    */
 788  
   private static final int FILE_EXPORT_TRIPLES = 1;
 789  
 
 790  
   /**
 791  
    * SQL results table
 792  
    */
 793  
   private JTable table;
 794  
 
 795  
   /**
 796  
    * Renderer for result cells
 797  
    */
 798  
   private ColoredCellRenderer cellRenderer;
 799  
 
 800  
   /**
 801  
    * Is the select output to render data or metadata
 802  
    */
 803  
   private int modeOfCurrentTable;
 804  
 
 805  
   /**
 806  
    * Collection of tables currently used by the latest query
 807  
    */
 808  
   private Map<String, String> mapOfCurrentTables;
 809  
 
 810  
   /**
 811  
    * User defined result row coloring pattern
 812  
    */
 813  
   private String userDefTableColoring;
 814  
 
 815  
   /**
 816  
    * Set of defined queries
 817  
    */
 818  
   private JComboBox querySelection;
 819  
 
 820  
   /**
 821  
    * Filename for current set of queries
 822  
    */
 823  
   private String queryFilename;
 824  
 
 825  
   /**
 826  
    * The query file filter description last used by the user
 827  
    */
 828  
   private String latestChosenQueryFileFilterDescription;
 829  
 
 830  
   /**
 831  
    * SQL input text area
 832  
    */
 833  
   private JTextArea queryText;
 834  
 
 835  
   /**
 836  
    * Set of defined connection strings
 837  
    */
 838  
   private JComboBox connectString;
 839  
 
 840  
   /**
 841  
    * User Id to authenticate with the DB server
 842  
    */
 843  
   private JTextField userId;
 844  
 
 845  
   /**
 846  
    * Password to authenticate with the DB server
 847  
    */
 848  
   private JPasswordField password;
 849  
 
 850  
   /**
 851  
    * Modes of SQL operation
 852  
    */
 853  
   private JRadioButton asQuery, asUpdate, asDescribe;
 854  
 
 855  
   /**
 856  
    * Connection feature settings
 857  
    */
 858  
   private JCheckBox autoCommit, readOnly, poolConnect;
 859  
 
 860  
   /**
 861  
    * Selection for maximum number of rows to retrieve and display
 862  
    */
 863  
   private JComboBox maxRows;
 864  
 
 865  
   /**
 866  
    * Buttons to move through history of executed queries
 867  
    */
 868  
   private JButton previousQuery, nextQuery;
 869  
 
 870  
   /**
 871  
    * Collection of message styles used in status output text pane
 872  
    */
 873  
   private Map<String, AttributeSet> messageStyles;
 874  
 
 875  
   /**
 876  
    * Execute the currently entered/selected SQL statement
 877  
    */
 878  
   private JButton execute;
 879  
 
 880  
   /**
 881  
    * Remove the currently selected SQL statement from the collection of stored
 882  
    * statements
 883  
    */
 884  
   private JButton remove;
 885  
 
 886  
   /**
 887  
    * Comment or un-comment the currently selected SQL statement
 888  
    */
 889  
   private JButton commentToggle;
 890  
 
 891  
   /**
 892  
    * Select the next SQL statement in the list of stored statements
 893  
    */
 894  
   private JButton nextInList;
 895  
 
 896  
   /**
 897  
    * The status text pane
 898  
    */
 899  
   private JTextPane message;
 900  
 
 901  
   /**
 902  
    * The status document backing the status text pane
 903  
    */
 904  
   private StyledDocument messageDocument;
 905  
 
 906  
   /**
 907  
    * Menu item - open a SQL statement file
 908  
    */
 909  
   private JMenuItem fileOpenSQL;
 910  
 
 911  
   /**
 912  
    * Menu item - choose whether to log SQL execution statistics
 913  
    */
 914  
   private JCheckBoxMenuItem fileLogStats;
 915  
 
 916  
   /**
 917  
    * Menu item - choose whether to log SQL execution results
 918  
    */
 919  
   private JCheckBoxMenuItem fileLogResults;
 920  
 
 921  
   /**
 922  
    * Menu item - write current results to a CSV file
 923  
    */
 924  
   private JMenuItem fileSaveAsCSV;
 925  
 
 926  
   /**
 927  
    * Menu item - write current results to an ontology file
 928  
    */
 929  
   private JMenuItem fileSaveAsTriples;
 930  
 
 931  
   /**
 932  
    * Menu item - choose whether to export BLOBs to files when exporting results
 933  
    */
 934  
   private JMenuItem fileSaveBLOBs;
 935  
 
 936  
   /**
 937  
    * Menu item - choose whether to export result raw (unquoted)
 938  
    */
 939  
   private JCheckBoxMenuItem fileExportsRaw;
 940  
 
 941  
   /**
 942  
    * Menu item - choose whether to add a carriage return to exported rows
 943  
    */
 944  
   private JCheckBoxMenuItem fileNoCRAddedToExportRows;
 945  
 
 946  
   /**
 947  
    * Menu item - sort by selected column(s)
 948  
    */
 949  
   private JMenuItem editSort;
 950  
 
 951  
   /**
 952  
    * Menu item - select all displayed rows
 953  
    */
 954  
   private JMenuItem editSelectAll;
 955  
 
 956  
   /**
 957  
    * Menu item - copy selected rows to the clipboard
 958  
    */
 959  
   private JMenuItem editCopy;
 960  
 
 961  
   /**
 962  
    * Menu item - create a select statement that lists all columns using the
 963  
    * current result set
 964  
    */
 965  
   private JMenuItem queryMakeVerboseSelect;
 966  
 
 967  
   /**
 968  
    * Menu item - create an insert statement template listing all fields using
 969  
    * the current result set
 970  
    */
 971  
   private JMenuItem queryMakeInsert;
 972  
 
 973  
   /**
 974  
    * Menu item - create an update statement template listing all fields using
 975  
    * the current result set
 976  
    */
 977  
   private JMenuItem queryMakeUpdate;
 978  
 
 979  
   /**
 980  
    * Menu item - create a "select *" statement with the table name based on the
 981  
    * currently selected cell
 982  
    */
 983  
   private JMenuItem querySelectStar;
 984  
 
 985  
   /**
 986  
    * Menu item - create a describe statement with the table name based on the
 987  
    * currently selected cell
 988  
    */
 989  
   private JMenuItem queryDescribeStar;
 990  
 
 991  
   /**
 992  
    * Menu item - edit the order of the list of currently stored SQL statements
 993  
    * (e.g. from the current SQL statement file)
 994  
    */
 995  
   private JMenuItem querySetOrder;
 996  
 
 997  
   /**
 998  
    * Menu item - run all stored SQL statements (e.g. from the current SQL
 999  
    * statement file)
 1000  
    */
 1001  
   private JMenuItem queryRunAll;
 1002  
 
 1003  
   /**
 1004  
    * Menu item - choose whether SQL statements and connection settings are
 1005  
    * linked
 1006  
    */
 1007  
   private JCheckBoxMenuItem configHistoryAssocSQLAndConnect;
 1008  
 
 1009  
   /**
 1010  
    * Menu item - choose whether to parse SQL statements on semicolons
 1011  
    */
 1012  
   private JCheckBoxMenuItem configParseSemicolons;
 1013  
 
 1014  
   /**
 1015  
    * Menu item - choose whether to save the password in the properties file
 1016  
    */
 1017  
   private JCheckBoxMenuItem configSavePassword;
 1018  
 
 1019  
   /**
 1020  
    * Menu item - choose whether to display the column data type in the results
 1021  
    * table
 1022  
    */
 1023  
   private JCheckBoxMenuItem configDisplayColumnDataType;
 1024  
 
 1025  
   /**
 1026  
    * Menu item - choose whether to display the client system information in the
 1027  
    * status text area
 1028  
    */
 1029  
   private JCheckBoxMenuItem configDisplayClientInfo;
 1030  
 
 1031  
   /**
 1032  
    * Menu item - set the font
 1033  
    */
 1034  
   private JMenuItem configFont;
 1035  
 
 1036  
   /**
 1037  
    * Menu item - choose to display server information in brief format
 1038  
    */
 1039  
   private JRadioButtonMenuItem configDisplayDBServerInfoShort;
 1040  
 
 1041  
   /**
 1042  
    * Menu item - choose to display server information in long format
 1043  
    */
 1044  
   private JRadioButtonMenuItem configDisplayDBServerInfoLong;
 1045  
 
 1046  
   /**
 1047  
    * Menu item - choose to not display any server information
 1048  
    */
 1049  
   private JRadioButtonMenuItem configDisplayDBServerInfoNone;
 1050  
 
 1051  
   /**
 1052  
    * Menu item - choose to leave the result table uncolored (white background)
 1053  
    */
 1054  
   private JRadioButtonMenuItem configTableColoringNone;
 1055  
 
 1056  
   /**
 1057  
    * Menu item - choose to color the result table with alternating green/white
 1058  
    * background
 1059  
    */
 1060  
   private JRadioButtonMenuItem configTableColoringGreenBar;
 1061  
 
 1062  
   /**
 1063  
    * Menu item - choose to color the result table with alternating yellow/white
 1064  
    * background
 1065  
    */
 1066  
   private JRadioButtonMenuItem configTableColoringYellowBar;
 1067  
 
 1068  
   /**
 1069  
    * Menu item - choose to color the result table with a user defined pattern
 1070  
    * background
 1071  
    */
 1072  
   private JRadioButtonMenuItem configTableColoringUserDefined;
 1073  
 
 1074  
   /**
 1075  
    * Menu item - choose to use the system default language
 1076  
    */
 1077  
   private JRadioButtonMenuItem configLanguageDefault;
 1078  
 
 1079  
   /**
 1080  
    * Menu item - choose to use English
 1081  
    */
 1082  
   private JRadioButtonMenuItem configLanguageEnglish;
 1083  
 
 1084  
   /**
 1085  
    * Menu item - choose to use Italian
 1086  
    */
 1087  
   private JRadioButtonMenuItem configLanguageItalian;
 1088  
 
 1089  
   /**
 1090  
    * Menu item - choose to use Spanish
 1091  
    */
 1092  
   private JRadioButtonMenuItem configLanguageSpanish;
 1093  
 
 1094  
   /**
 1095  
    * Menu item - choose to use French
 1096  
    */
 1097  
   private JRadioButtonMenuItem configLanguageFrench;
 1098  
 
 1099  
   /**
 1100  
    * Menu item - choose to use German
 1101  
    */
 1102  
   private JRadioButtonMenuItem configLanguageGerman;
 1103  
 
 1104  
   /**
 1105  
    * Menu item - choose to use Portuguese
 1106  
    */
 1107  
   private JRadioButtonMenuItem configLanguagePortuguese;
 1108  
 
 1109  
   /**
 1110  
    * Menu item - display the About dialog box
 1111  
    */
 1112  
   private JMenuItem helpAbout;
 1113  
 
 1114  
   /**
 1115  
    * Menu item - display help on the parameterized SQL statement syntax
 1116  
    */
 1117  
   private JMenuItem helpParameterizedSQL;
 1118  
 
 1119  
   /**
 1120  
    * Database connection
 1121  
    */
 1122  
   private Connection conn;
 1123  
 
 1124  
   /**
 1125  
    * Last connection string used
 1126  
    */
 1127  
   private String lastConnection;
 1128  
 
 1129  
   /**
 1130  
    * Last user id
 1131  
    */
 1132  
   private String lastUserId;
 1133  
 
 1134  
   /**
 1135  
    * Last password
 1136  
    */
 1137  
   private String lastPassword;
 1138  
 
 1139  
   /**
 1140  
    * Run mode (select, update, describe)
 1141  
    */
 1142  
   private int runType;
 1143  
 
 1144  
   /**
 1145  
    * Currently executing query thread
 1146  
    */
 1147  
   private Thread runningQuery;
 1148  
 
 1149  
   /**
 1150  
    * Indicator for executing query
 1151  
    */
 1152  
   private JLabel runIndicator;
 1153  
 
 1154  
   /**
 1155  
    * Elapsed time for running query
 1156  
    */
 1157  
   private JLabel timeIndicator;
 1158  
 
 1159  
   /**
 1160  
    * Thread to animate the query execution indicator
 1161  
    */
 1162  
   private Thread flashRunIndicator;
 1163  
 
 1164  
   /**
 1165  
    * Thread to maintain the query timer display
 1166  
    */
 1167  
   private Thread timeRunIndicator;
 1168  
 
 1169  
   /**
 1170  
    * Directory containing DB driver files
 1171  
    */
 1172  
   private String dbDriverDir;
 1173  
 
 1174  
   /**
 1175  
    * Indicator that a DB driver was loaded
 1176  
    */
 1177  
   private boolean loadedDBDriver;
 1178  
 
 1179  
   // Query mode warning patterns, if the SQL begins with an "incorrect"
 1180  
   // term for the query type selected, a warning message will be displayed
 1181  
   /**
 1182  
    * Query mode warning patterns for an update statement. If the SQL begins with
 1183  
    * an "incorrect" term for the query type selected, a warning message will be
 1184  
    * displayed
 1185  
    */
 1186  
   private String scWarnUpdatePatterns;
 1187  
 
 1188  
   /**
 1189  
    * Query mode warning patterns for a select statement. If the SQL begins with
 1190  
    * an "incorrect" term for the query type selected, a warning message will be
 1191  
    * displayed
 1192  
    */
 1193  
   private String scWarnSelectPatterns;
 1194  
 
 1195  
   /**
 1196  
    * File for exporting results
 1197  
    */
 1198  
   private File exportFile;
 1199  
 
 1200  
   /**
 1201  
    * Latest directory used when choosing a file
 1202  
    */
 1203  
   private File latestFileDirectory;
 1204  
 
 1205  
   /**
 1206  
    * Constructs a Basic Query instance
 1207  
    * 
 1208  
    * @param wantGUI
 1209  
    *          If true, the GUI is presented.
 1210  
    */
 1211  
   public BasicQuery(boolean wantGUI) {
 1212  0
     super();
 1213  
 
 1214  0
     setupLogger();
 1215  
 
 1216  0
     setupLanguage();
 1217  
 
 1218  0
     if (wantGUI) {
 1219  0
       addWindowListener(this);
 1220  0
       setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
 1221  0
       setTitle("BasicQuery");
 1222  0
       setIconImage(new ImageIcon(ImageUtility.getImageAsByteArray(
 1223  
           "BasicQueryLogo32x32.gif")).getImage());
 1224  0
       setup();
 1225  
 
 1226  0
       checkForNewVersion();
 1227  
     }
 1228  0
   }
 1229  
 
 1230  
   /**
 1231  
    * Setup the correct locale based on the user language choice. If the user
 1232  
    * has chosen default, then the system language defaults are used.
 1233  
    */
 1234  
   private void setupLanguage() {
 1235  
     String temp;
 1236  
 
 1237  0
     temp = Configuration.instance().getProperty(PROP_LANGUAGE, LANG_DEFAULT);
 1238  
 
 1239  0
     if (temp.equalsIgnoreCase(LANG_DEFAULT)) {
 1240  0
       if (System.getProperty(PROP_SYSTEM_DEFAULTLANGUAGE) != null) {
 1241  0
         if (System.getProperty(PROP_SYSTEM_DEFAULTCOUNTRY) != null) {
 1242  0
           Locale.setDefault(new Locale(System.getProperty(
 1243  
               PROP_SYSTEM_DEFAULTLANGUAGE),
 1244  
               System.getProperty(PROP_SYSTEM_DEFAULTCOUNTRY)));
 1245  
         } else {
 1246  0
           Locale.setDefault(new Locale(System.getProperty(
 1247  
               PROP_SYSTEM_DEFAULTLANGUAGE)));
 1248  
         }
 1249  
       }
 1250  0
     } else if (temp.equalsIgnoreCase(LANG_ENGLISH)) {
 1251  0
       Locale.setDefault(new Locale("en"));
 1252  0
     } else if (temp.equalsIgnoreCase(LANG_FRENCH)) {
 1253  0
       Locale.setDefault(new Locale("fr"));
 1254  0
     } else if (temp.equalsIgnoreCase(LANG_GERMAN)) {
 1255  0
       Locale.setDefault(new Locale("de"));
 1256  0
     } else if (temp.equalsIgnoreCase(LANG_ITALIAN)) {
 1257  0
       Locale.setDefault(new Locale("it"));
 1258  0
     } else if (temp.equalsIgnoreCase(LANG_PORTUGUESE)) {
 1259  0
       Locale.setDefault(new Locale("pt"));
 1260  0
     } else if (temp.equalsIgnoreCase(LANG_SPANISH)) {
 1261  0
       Locale.setDefault(new Locale("es"));
 1262  
     }
 1263  0
   }
 1264  
 
 1265  
   /**
 1266  
    * Does a shutdown and startup of the application so that it will
 1267  
    * redraw its interface.
 1268  
    */
 1269  
   private void changeLanguage() {
 1270  0
     saveConfig();
 1271  0
     cleanUp();
 1272  0
     dispose();
 1273  0
     new BasicQuery(true);
 1274  0
   }
 1275  
 
 1276  
   /**
 1277  
    * Configure the logger
 1278  
    */
 1279  
   private void setupLogger() {
 1280  0
     PropertyConfigurator.configure(Configuration.instance().getFile(
 1281  
         FILENAME_LOGGER).getAbsolutePath());
 1282  
 
 1283  0
     if (LOGGER.isDebugEnabled()) {
 1284  0
       final Properties props = System.getProperties();
 1285  0
       final Set<Object> keys = props.keySet();
 1286  0
       final Iterator<Object> keyItr = keys.iterator();
 1287  
 
 1288  0
       while (keyItr.hasNext()) {
 1289  0
         final String key = (String) keyItr.next();
 1290  0
         LOGGER.debug("Prop: [" + key + "]=[" + System.getProperty(key) + "]");
 1291  0
       }
 1292  
     }
 1293  0
   }
 1294  
 
 1295  
   /**
 1296  
    * Adds packages (JARs) to the classpath. By default it adds any JARs
 1297  
    * in the database driver directory (set in the properties file) to the
 1298  
    * classpath.
 1299  
    * 
 1300  
    * @return A DynamicClassLoader containing jars and zip-file based classes
 1301  
    */
 1302  
   private DynamicClassLoader getDBClassLoader() {
 1303  
     File dir;
 1304  
     File[] files;
 1305  
     List<File> archives;
 1306  
     DynamicClassLoader dbClassLoader;
 1307  
     String archivesAdded;
 1308  
 
 1309  0
     dir = new File(dbDriverDir);
 1310  0
     messageOut(Resources.getString("msgDBDriverDir", dir.getAbsolutePath()));
 1311  0
     files = dir.listFiles();
 1312  0
     archives = new ArrayList<File>();
 1313  0
     archivesAdded = "";
 1314  
 
 1315  0
     for (int f = 0; files != null && f < files.length; ++f) {
 1316  0
       if (files[f].getName().toLowerCase().endsWith(".jar")
 1317  
           || files[f].getName().toLowerCase().endsWith(".zip")) {
 1318  0
         archives.add(files[f]);
 1319  0
         archivesAdded += files[f].getName() + ", ";
 1320  0
         loadedDBDriver = true;
 1321  
       }
 1322  
     }
 1323  0
     if (archivesAdded.length() > 0) {
 1324  0
       archivesAdded = archivesAdded.substring(0, archivesAdded.length() - 2);
 1325  
     } else {
 1326  0
       archivesAdded = Resources.getString("errNoJARZIP");
 1327  
     }
 1328  0
     messageOut(Resources.getString("msgDBDriverLocated", archivesAdded));
 1329  
 
 1330  0
     dbClassLoader = new DynamicClassLoader(archives);
 1331  
 
 1332  0
     return dbClassLoader;
 1333  
   }
 1334  
 
 1335  
   /**
 1336  
    * Sets the Border style and color to black for the interface
 1337  
    * 
 1338  
    * @return Border A line border of black lines
 1339  
    */
 1340  
   private Border getStandardBorder() {
 1341  0
     return BorderFactory.createLineBorder(Color.black);
 1342  
   }
 1343  
 
 1344  
   /**
 1345  
    * Setup instance components
 1346  
    */
 1347  
   private void setupComponents() {
 1348  0
     table = new JTable();
 1349  0
     cellRenderer = new ColoredCellRenderer();
 1350  0
     table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
 1351  0
     table.setColumnSelectionAllowed(true);
 1352  0
     table.setRowSelectionAllowed(true);
 1353  0
     table.setCellSelectionEnabled(true);
 1354  0
     table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
 1355  0
     table.setDefaultRenderer(new Object().getClass(), cellRenderer);
 1356  0
     table.getTableHeader().setToolTipText(Resources.getString(
 1357  
         "tipClickHeaderToSort"));
 1358  
 
 1359  0
     maxRows = new JComboBox();
 1360  0
     maxRows.setEditable(false);
 1361  0
     ((DefaultComboBoxModel) maxRows.getModel()).addElement(Resources.getString(
 1362  
         "proNoLimit"));
 1363  0
     ((DefaultComboBoxModel) maxRows.getModel()).addElement("50");
 1364  0
     ((DefaultComboBoxModel) maxRows.getModel()).addElement("100");
 1365  0
     ((DefaultComboBoxModel) maxRows.getModel()).addElement("500");
 1366  0
     ((DefaultComboBoxModel) maxRows.getModel()).addElement("1000");
 1367  0
     ((DefaultComboBoxModel) maxRows.getModel()).addElement("5000");
 1368  0
     ((DefaultComboBoxModel) maxRows.getModel()).addElement("10000");
 1369  0
     ((DefaultComboBoxModel) maxRows.getModel()).addElement("20000");
 1370  0
     ((DefaultComboBoxModel) maxRows.getModel()).addElement("30000");
 1371  0
     ((DefaultComboBoxModel) maxRows.getModel()).addElement("50000");
 1372  0
     ((DefaultComboBoxModel) maxRows.getModel()).addElement("100000");
 1373  0
     ((DefaultComboBoxModel) maxRows.getModel()).addElement("200000");
 1374  0
     ((DefaultComboBoxModel) maxRows.getModel()).addElement("500000");
 1375  0
     ((DefaultComboBoxModel) maxRows.getModel()).addElement("1000000");
 1376  0
     ((DefaultComboBoxModel) maxRows.getModel()).addElement("1500000");
 1377  0
     ((DefaultComboBoxModel) maxRows.getModel()).addElement("2000000");
 1378  0
     ((DefaultComboBoxModel) maxRows.getModel()).addElement("3000000");
 1379  0
     maxRows.setSelectedItem("100");
 1380  
 
 1381  0
   }
 1382  
 
 1383  
   /**
 1384  
    * Builds the GUI for the application
 1385  
    */
 1386  
   private void setup() {
 1387  
     JPanel panel;
 1388  
     JPanel gridPanel;
 1389  
     JPanel outerPanel;
 1390  
     JPanel flowPanel;
 1391  
     JPanel boxedPanel;
 1392  
     ButtonGroup bGroup;
 1393  
     MaxHeightJScrollPane maxHeightJScrollPane;
 1394  
 
 1395  0
     setupComponents();
 1396  
 
 1397  0
     getContentPane().setLayout(new BorderLayout());
 1398  
 
 1399  
     // table.getTableHeader().setFont(new Font(table.getTableHeader().getFont().
 1400  
     // getName(), table.getTableHeader().getFont().getStyle(),
 1401  
     // MessageStyleFactory.instance().getFontSize()));
 1402  0
     getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
 1403  
 
 1404  0
     panel = new JPanel();
 1405  0
     panel.setLayout(new BorderLayout());
 1406  
 
 1407  0
     outerPanel = new JPanel();
 1408  0
     outerPanel.setLayout(new BorderLayout());
 1409  
 
 1410  0
     gridPanel = new JPanel();
 1411  0
     gridPanel.setLayout(new GridLayout(0, 1));
 1412  
 
 1413  0
     gridPanel.add(connectString = new JComboBox());
 1414  0
     connectString.setEditable(true);
 1415  0
     gridPanel.add(querySelection = new JComboBox());
 1416  0
     querySelection.setEditable(false);
 1417  0
     querySelection.addActionListener(this);
 1418  0
     outerPanel.add(gridPanel, BorderLayout.NORTH);
 1419  
 
 1420  0
     outerPanel.add(new JScrollPane(queryText = new JTextArea(QUERY_AREA_ROWS,
 1421  
         QUERY_AREA_COLUMNS)),
 1422  
         BorderLayout.SOUTH);
 1423  0
     queryText.setLineWrap(true);
 1424  0
     queryText.setWrapStyleWord(true);
 1425  0
     queryText.addKeyListener(this);
 1426  
 
 1427  0
     panel.add(outerPanel, BorderLayout.CENTER);
 1428  
 
 1429  0
     outerPanel = new JPanel();
 1430  0
     outerPanel.setLayout(new BorderLayout());
 1431  
 
 1432  0
     boxedPanel = new JPanel();
 1433  0
     boxedPanel.setLayout(new GridLayout(0, 2));
 1434  0
     boxedPanel.add(new JLabel(Resources.getString("proUserId")));
 1435  0
     boxedPanel.add(userId = new JTextField(10));
 1436  0
     boxedPanel.add(new JLabel(Resources.getString("proPassword")));
 1437  0
     boxedPanel.add(password = new JPasswordField(10));
 1438  0
     outerPanel.add(boxedPanel, BorderLayout.WEST);
 1439  
 
 1440  
     // Prev/Next and the checkboxes are all on the flowPanel - Center of
 1441  
     // outerPanel
 1442  0
     flowPanel = new JPanel();
 1443  0
     flowPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
 1444  
 
 1445  
     // Previous/Next buttons
 1446  0
     boxedPanel = new JPanel();
 1447  0
     boxedPanel.setLayout(new FlowLayout());
 1448  0
     boxedPanel.add(previousQuery = new JButton(Resources.getString("ctlPrev"),
 1449  
         new ImageIcon(ImageUtility.
 1450  
             getImageAsByteArray("ArrowLeftGreen.gif"))));
 1451  0
     previousQuery.setToolTipText(
 1452  
         Resources.getString("tipPrev"));
 1453  0
     previousQuery.addActionListener(this);
 1454  0
     boxedPanel.add(nextQuery = new JButton(Resources.getString("ctlNext"),
 1455  
         new ImageIcon(ImageUtility.
 1456  
             getImageAsByteArray("ArrowRightGreen.gif"))));
 1457  0
     nextQuery.setToolTipText(Resources.getString("tipNext"));
 1458  0
     nextQuery.addActionListener(this);
 1459  0
     flowPanel.add(boxedPanel);
 1460  
 
 1461  
     // Checkboxes: Autocommit, Read Only and Pooling
 1462  0
     boxedPanel = new JPanel();
 1463  0
     boxedPanel.setLayout(new FlowLayout());
 1464  0
     boxedPanel.setBorder(getStandardBorder());
 1465  0
     boxedPanel.add(autoCommit = new JCheckBox(Resources.getString(
 1466  
         "ctlAutoCommit"), true));
 1467  0
     boxedPanel.add(readOnly = new JCheckBox(Resources.getString("ctlReadOnly"),
 1468  
         false));
 1469  0
     boxedPanel.add(poolConnect = new JCheckBox(Resources.getString(
 1470  
         "ctlConnPool"), false));
 1471  0
     poolConnect.setEnabled(false);
 1472  0
     flowPanel.add(boxedPanel);
 1473  0
     outerPanel.add(flowPanel, BorderLayout.CENTER);
 1474  
 
 1475  0
     boxedPanel = new JPanel();
 1476  0
     boxedPanel.setLayout(new GridLayout(0, 1));
 1477  0
     boxedPanel.setBorder(getStandardBorder());
 1478  0
     boxedPanel.add(runIndicator = new JLabel(Resources.getString("ctlRunning"),
 1479  
         JLabel.CENTER));
 1480  0
     runIndicator.setForeground(Color.lightGray);
 1481  0
     boxedPanel.add(timeIndicator = new JLabel("", JLabel.RIGHT));
 1482  0
     outerPanel.add(boxedPanel, BorderLayout.EAST);
 1483  
 
 1484  0
     panel.add(outerPanel, BorderLayout.NORTH);
 1485  
 
 1486  0
     flowPanel = new JPanel();
 1487  0
     flowPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
 1488  
 
 1489  0
     boxedPanel = new JPanel();
 1490  0
     boxedPanel.setLayout(new FlowLayout());
 1491  0
     boxedPanel.setBorder(getStandardBorder());
 1492  0
     boxedPanel.add(new JLabel(Resources.getString("proQueryType")));
 1493  0
     boxedPanel.add(asQuery = new JRadioButton(Resources.getString("ctlSelect"),
 1494  
         true));
 1495  0
     boxedPanel
 1496  
         .add(asUpdate = new JRadioButton(Resources.getString("ctlUpdate")));
 1497  0
     boxedPanel.add(asDescribe = new JRadioButton(Resources.getString(
 1498  
         "ctlDescribe")));
 1499  0
     bGroup = new ButtonGroup();
 1500  0
     bGroup.add(asQuery);
 1501  0
     bGroup.add(asUpdate);
 1502  0
     bGroup.add(asDescribe);
 1503  0
     asQuery.addActionListener(this);
 1504  0
     asUpdate.addActionListener(this);
 1505  0
     asDescribe.addActionListener(this);
 1506  0
     flowPanel.add(boxedPanel);
 1507  
 
 1508  0
     flowPanel.add(new JLabel("     "));
 1509  
 
 1510  0
     boxedPanel = new JPanel();
 1511  0
     boxedPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
 1512  0
     boxedPanel.setBorder(getStandardBorder());
 1513  0
     boxedPanel.add(new JLabel(Resources.getString("proMaxRows")));
 1514  0
     boxedPanel.add(maxRows);
 1515  0
     flowPanel.add(boxedPanel);
 1516  
 
 1517  0
     flowPanel.add(new JLabel("     "));
 1518  
 
 1519  0
     flowPanel.add(execute = new JButton(Resources.getString("ctlExecute")));
 1520  0
     execute.addActionListener(this);
 1521  0
     flowPanel.add(remove = new JButton(Resources.getString("ctlRemove")));
 1522  0
     remove.addActionListener(this);
 1523  0
     flowPanel
 1524  
         .add(commentToggle = new JButton(Resources.getString("ctlComment")));
 1525  0
     commentToggle.addActionListener(this);
 1526  0
     flowPanel.add(nextInList = new JButton(Resources.getString("ctlDown")));
 1527  0
     nextInList.addActionListener(this);
 1528  
 
 1529  0
     panel.add(flowPanel, BorderLayout.SOUTH);
 1530  
 
 1531  0
     getContentPane().add(panel, BorderLayout.NORTH);
 1532  0
     getRootPane().setDefaultButton(execute);
 1533  
 
 1534  0
     messageDocument = new DefaultStyledDocument();
 1535  0
     getContentPane().add(maxHeightJScrollPane = new MaxHeightJScrollPane(
 1536  
         message = new JTextPane(messageDocument)), BorderLayout.SOUTH);
 1537  0
     message.setEditable(false);
 1538  
 
 1539  0
     loadedDBDriver = false;
 1540  
 
 1541  0
     loadMenu();
 1542  
 
 1543  0
     setupTextStyles();
 1544  0
     loadProperties();
 1545  0
     setupUserDefinedColoring();
 1546  0
     setupResultsTableColoring();
 1547  0
     loadConfig();
 1548  0
     loadConnectStrings();
 1549  0
     loadQueries();
 1550  
 
 1551  0
     loadDrivers();
 1552  
 
 1553  
     // Check for avail of pool - enable/disable pooling option as appropriate
 1554  
     // Not really useful until we get the pooling classes out of this code
 1555  
     try {
 1556  0
       new GenericObjectPool(null);
 1557  0
       poolConnect.setEnabled(true);
 1558  0
       poolConnect.setSelected(true);
 1559  0
     } catch (Throwable any) {
 1560  
       // No Apache Commons DB Pooling Library Found (DBCP)
 1561  0
       LOGGER.error(
 1562  
           Resources.getString("errNoPoolLib"),
 1563  
           any);
 1564  0
     }
 1565  
 
 1566  0
     setDefaults();
 1567  
 
 1568  0
     maxHeightJScrollPane.lockHeight(getHeight()
 1569  
         / MAX_SCROLL_PANE_DIVISOR_FOR_MAX_HEIGHT);
 1570  
 
 1571  
     // Font
 1572  0
     setFontFromConfig(Configuration.instance());
 1573  
 
 1574  0
     setVisible(true);
 1575  0
   }
 1576  
 
 1577  
   /**
 1578  
    * Parse the color definition placed in the properties file, if one
 1579  
    * is provided.
 1580  
    * 
 1581  
    * If the user places a legitimate color definition in the properties
 1582  
    * file, it can be chosen for rendering by using the "USer Defined" option
 1583  
    * for the result row coloring.
 1584  
    * 
 1585  
    * The colors are defined in pairs using the RGB hex values for foreground
 1586  
    * and background. Multiple pairs can be defined and the colors will
 1587  
    * alternate between rows. The foreground and background colors are
 1588  
    * separated by slashes (/) and the pairs are separated by commas (,).
 1589  
    * 
 1590  
    * For example:
 1591  
    * 
 1592  
    * TABLECOLORUSERDEF=000000/ffffff,000000/c0ffc0
 1593  
    * 
 1594  
    * would lead to a "green bar" appearance with black text (000000) on
 1595  
    * each row and alternating white (ffffff) and green (c0ffc0) backgrounds.
 1596  
    * 
 1597  
    * Another example:
 1598  
    * 
 1599  
    * TABLECOLORUSERDEF=000000/ffc0c0,000000/ffffff,000000/c0c0ff,000000/ffffff
 1600  
    * 
 1601  
    * would lead to a red, white and blue theme with black text on alternating
 1602  
    * red, white, blue and again white backgrounds.
 1603  
    */
 1604  
   private void setupUserDefinedColoring() {
 1605  
     String temp;
 1606  
     String[] groups, colors;
 1607  0
     if (configTableColoringUserDefined.isSelected()
 1608  
         && userDefTableColoring != null) {
 1609  0
       temp = userDefTableColoring.trim();
 1610  0
       if (temp.length() > 0) {
 1611  0
         groups = temp.split(",");
 1612  
 
 1613  0
         LOGGER.debug("User def color group count=" + groups.length);
 1614  
 
 1615  0
         for (int group = 0; group < groups.length; ++group) {
 1616  0
           LOGGER.debug("Group[" + group + "] = [" + groups[group] + "]");
 1617  0
           colors = groups[group].split("/");
 1618  0
           LOGGER.debug("User def color count=" + colors.length);
 1619  0
           if (colors.length == USER_DEFINED_COLORING_COLORS_PER_ENTRY
 1620  
               && colors[0].length() == USER_DEFINED_COLORING_COLOR_CODE_LENGTH
 1621  
               && colors[1].length() == USER_DEFINED_COLORING_COLOR_CODE_LENGTH) {
 1622  0
             addDisplayRowColor(colors[0], colors[1]);
 1623  0
             configTableColoringUserDefined.setEnabled(true);
 1624  
           } else {
 1625  0
             LOGGER.warn("Unable to parse the user-defined color pattern: "
 1626  
                 + groups[group]);
 1627  0
             messageOut(Resources.getString("errUserDefinedColorErrorParse",
 1628  
                 groups[group]), STYLE_RED);
 1629  
           }
 1630  
         }
 1631  
       }
 1632  
     }
 1633  0
   }
 1634  
 
 1635  
   /**
 1636  
    * Does the actual parsing of foreground and background colors. Colors
 1637  
    * are supplied as 6 digit (hex) strings (e.g. 000000=black, ffffff=white)
 1638  
    * 
 1639  
    * @param foregroundColor
 1640  
    *          String The foregound color as RGB hex
 1641  
    * @param backgroundColor
 1642  
    *          String The background color as RGB hex
 1643  
    */
 1644  
   private void addDisplayRowColor(String foregroundColor,
 1645  
       String backgroundColor) {
 1646  0
     LOGGER.debug("Add user defined display color row FG:" + foregroundColor
 1647  
         + " BG:" + backgroundColor);
 1648  
 
 1649  
     try {
 1650  0
       cellRenderer.addAlternatingRowColor(
 1651  
           new Color(Integer.parseInt(
 1652  
               foregroundColor.substring(COLOR_CODING_COLOR_1_START,
 1653  
                   COLOR_CODING_COLOR_2_START), COLOR_CODING_NUMERIC_BASE),
 1654  
               Integer.parseInt(
 1655  
                   foregroundColor.
 1656  
                       substring(COLOR_CODING_COLOR_2_START,
 1657  
                           COLOR_CODING_COLOR_3_START),
 1658  
                   COLOR_CODING_NUMERIC_BASE),
 1659  
               Integer.parseInt(
 1660  
                   foregroundColor.substring(COLOR_CODING_COLOR_3_START,
 1661  
                       COLOR_CODING_COLOR_3_END), COLOR_CODING_NUMERIC_BASE)),
 1662  
           new Color(Integer.parseInt(
 1663  
               backgroundColor.substring(COLOR_CODING_COLOR_1_START,
 1664  
                   COLOR_CODING_COLOR_2_START), COLOR_CODING_NUMERIC_BASE),
 1665  
               Integer.parseInt(backgroundColor.
 1666  
                   substring(COLOR_CODING_COLOR_2_START,
 1667  
                       COLOR_CODING_COLOR_3_START), COLOR_CODING_NUMERIC_BASE),
 1668  
               Integer.parseInt(backgroundColor.substring(
 1669  
                   COLOR_CODING_COLOR_3_START, COLOR_CODING_COLOR_3_END),
 1670  
                   COLOR_CODING_NUMERIC_BASE))
 1671  
           );
 1672  0
     } catch (Throwable any) {
 1673  
       // Probably a bad hex value
 1674  0
       LOGGER.warn("Error setting row coloring for FG(" + foregroundColor
 1675  
           + ") BG(" + backgroundColor + ")");
 1676  0
       messageOut(Resources.getString("errUserDefinedColorError",
 1677  
           foregroundColor, backgroundColor, any.getMessage()), STYLE_RED);
 1678  0
     }
 1679  0
   }
 1680  
 
 1681  
   /**
 1682  
    * Sets-up the collection of text styles that can be used to format the
 1683  
    * information in the message area.
 1684  
    */
 1685  
   private void setupTextStyles() {
 1686  0
     messageStyles = new HashMap<String, AttributeSet>();
 1687  
 
 1688  0
     messageStyles.put(STYLE_BOLD,
 1689  
         MessageStyleFactory.instance().createStyle(Color.black,
 1690  
             MessageStyleFactory.BOLD));
 1691  0
     messageStyles.put(STYLE_GREEN,
 1692  
         MessageStyleFactory.instance().createStyle(Color.green,
 1693  
             MessageStyleFactory.BOLD));
 1694  0
     messageStyles.put(STYLE_NORMAL,
 1695  
         MessageStyleFactory.instance().createStyle(Color.black));
 1696  0
     messageStyles.put(STYLE_RED,
 1697  
         MessageStyleFactory.instance().createStyle(Color.red,
 1698  
             MessageStyleFactory.BOLD));
 1699  0
     messageStyles.put(STYLE_SUBTLE,
 1700  
         MessageStyleFactory.instance().createStyle(Color.blue.
 1701  
             brighter(), MessageStyleFactory.ITALIC));
 1702  0
     messageStyles.put(STYLE_SUBTLE_UL,
 1703  
         MessageStyleFactory.instance().
 1704  
             createStyle(Color.blue.brighter(),
 1705  
                 MessageStyleFactory.ITALIC
 1706  
                     | MessageStyleFactory.UNDERLINE));
 1707  0
     messageStyles.put(STYLE_YELLOW,
 1708  
         MessageStyleFactory.instance().createStyle(Color.black,
 1709  
             Color.yellow, MessageStyleFactory.BOLD));
 1710  0
   }
 1711  
 
 1712  
   /**
 1713  
    * Saves the current settings into the properties file.
 1714  
    */
 1715  
   private void saveProperties() {
 1716  
     Configuration props;
 1717  
 
 1718  
     // props = new Properties();
 1719  0
     props = Configuration.instance();
 1720  
 
 1721  0
     props.setProperty(PROP_USERID, userId.getText());
 1722  
 
 1723  0
     if (configSavePassword.isSelected()) {
 1724  0
       props.setProperty(PROP_PASSWORD, new String(password.getPassword()));
 1725  
     }
 1726  
 
 1727  0
     props.setProperty(PROP_AUTOCOMMIT,
 1728  
         autoCommit.isSelected() ? PARAMVALUE_YES : PARAMVALUE_NO);
 1729  0
     props.setProperty(PROP_READONLY,
 1730  
         readOnly.isSelected() ? PARAMVALUE_YES : PARAMVALUE_NO);
 1731  0
     props.setProperty(PROP_POOLING,
 1732  
         poolConnect.isSelected() ? PARAMVALUE_YES : PARAMVALUE_NO);
 1733  0
     props.setProperty(PROP_CONNECTION, connectString.getSelectedIndex() + "");
 1734  0
     props.setProperty(PROP_SQL, querySelection.getSelectedIndex() + "");
 1735  0
     props.setProperty(PROP_SQLFILENAME, queryFilename);
 1736  0
     props.setProperty(PROP_MAXROWS, maxRows.getSelectedIndex() + "");
 1737  0
     props.setProperty(PROP_LOGSTATS,
 1738  
         fileLogStats.isSelected() ? PARAMVALUE_YES : PARAMVALUE_NO);
 1739  0
     props.setProperty(PROP_LOGRESULTS,
 1740  
         fileLogResults.isSelected() ? PARAMVALUE_YES : PARAMVALUE_NO);
 1741  0
     props.setProperty(PROP_EXPORTRAW,
 1742  
         fileExportsRaw.isSelected() ? PARAMVALUE_YES : PARAMVALUE_NO);
 1743  0
     props
 1744  
         .setProperty(PROP_EXPORTNOCR,
 1745  
             fileNoCRAddedToExportRows.isSelected() ? PARAMVALUE_YES
 1746  
                 : PARAMVALUE_NO);
 1747  0
     props.setProperty(PROP_SAVEPASSWORD,
 1748  
         configSavePassword.isSelected() ? PARAMVALUE_YES : PARAMVALUE_NO);
 1749  0
     props.setProperty(PROP_ASSOCSQLURL,
 1750  
         configHistoryAssocSQLAndConnect.isSelected() ? PARAMVALUE_YES
 1751  
             : PARAMVALUE_NO);
 1752  0
     props.setProperty(PROP_PARSESEMICOLON,
 1753  
         configParseSemicolons.isSelected() ? PARAMVALUE_YES
 1754  
             : PARAMVALUE_NO);
 1755  0
     props.setProperty(PROP_DISPLAYCOLUMNDATATYPE,
 1756  
         configDisplayColumnDataType.isSelected() ? PARAMVALUE_YES
 1757  
             : PARAMVALUE_NO);
 1758  0
     props.setProperty(PROP_DISPLAYCLIENTINFO,
 1759  
         configDisplayClientInfo.isSelected() ? PARAMVALUE_YES
 1760  
             : PARAMVALUE_NO);
 1761  0
     props.setProperty(PROP_DISPLAYDBSERVERINFO,
 1762  
         configDisplayDBServerInfoLong.isSelected() ? DBSERVERINFO_LONG
 1763  
             : configDisplayDBServerInfoShort.isSelected() ? DBSERVERINFO_BRIEF
 1764  
                 : PARAMVALUE_NO);
 1765  0
     props.setProperty(PROP_UPPERLEFTX, getLocation().x + "");
 1766  0
     props.setProperty(PROP_UPPERLEFTY, getLocation().y + "");
 1767  0
     props.setProperty(PROP_WIDTH, getSize().width + "");
 1768  0
     props.setProperty(PROP_HEIGHT, getSize().height + "");
 1769  0
     props.setProperty(PROP_MAXIMIZED,
 1770  
         getExtendedState() == JFrame.MAXIMIZED_BOTH ? PARAMVALUE_YES
 1771  
             : PARAMVALUE_NO);
 1772  0
     props.setProperty(PROP_DBDRIVERDIR, dbDriverDir);
 1773  
 
 1774  
     // Add the select and update query type warning patterns to the properties.
 1775  
     // Technically don't need to do this since the user can't change in app,
 1776  
     // but want to be sure they are in the property file so the user has a
 1777  
     // clue that they can be modified.
 1778  0
     props.setProperty(PROP_WARNSELECTPATTERNS, scWarnSelectPatterns);
 1779  0
     props.setProperty(PROP_WARNUPDATEPATTERNS, scWarnUpdatePatterns);
 1780  
 
 1781  
     // Data Row Coloring
 1782  0
     props
 1783  
         .setProperty(
 1784  
             PROP_TABLE_COLORING,
 1785  
             configTableColoringGreenBar.isSelected() ? TABLECOLORING_GREENBAR
 1786  
                 :
 1787  
                 configTableColoringYellowBar.isSelected() ? TABLECOLORING_YELLOWBAR
 1788  
                     :
 1789  
                     configTableColoringUserDefined.isSelected() ? TABLECOLORING_USERDEFINED
 1790  
                         :
 1791  
                         TABLECOLORING_NONE);
 1792  
 
 1793  0
     if (userDefTableColoring != null) {
 1794  0
       props.setProperty(PROP_TABLE_COLOR_USERDEF, userDefTableColoring);
 1795  
     }
 1796  
 
 1797  
     // Language
 1798  0
     props
 1799  
         .setProperty(
 1800  
             PROP_LANGUAGE,
 1801  
             configLanguageDefault.isSelected() ? LANG_DEFAULT
 1802  
                 :
 1803  
                 configLanguageEnglish.isSelected() ? LANG_ENGLISH
 1804  
                     :
 1805  
                     configLanguageFrench.isSelected() ? LANG_FRENCH
 1806  
                         :
 1807  
                         configLanguageGerman.isSelected() ? LANG_GERMAN
 1808  
                             :
 1809  
                             configLanguageItalian.isSelected() ? LANG_ITALIAN
 1810  
                                 :
 1811  
                                 configLanguagePortuguese.isSelected() ? LANG_PORTUGUESE
 1812  
                                     :
 1813  
                                     configLanguageSpanish.isSelected() ? LANG_SPANISH
 1814  
                                         :
 1815  
                                         LANG_DEFAULT);
 1816  
 
 1817  
     // Font
 1818  0
     props.setProperty(PROP_FONT_FAMILY, getFont().getFamily());
 1819  0
     props.setProperty(PROP_FONT_SIZE, getFont().getSize() + "");
 1820  0
     props.setProperty(PROP_FONT_BOLD, getFont().isBold() ? "YES" : "NO");
 1821  0
     props.setProperty(PROP_FONT_ITALIC, getFont().isItalic() ? "YES" : "NO");
 1822  
 
 1823  
     // File access
 1824  0
     if (latestFileDirectory != null) {
 1825  0
       if (latestFileDirectory.isDirectory()) {
 1826  0
         props.setProperty(PROP_LATEST_DIRECTORY,
 1827  
             latestFileDirectory.getAbsolutePath());
 1828  
       } else {
 1829  0
         props.setProperty(PROP_LATEST_DIRECTORY, latestFileDirectory
 1830  
             .getParentFile().getAbsolutePath());
 1831  
       }
 1832  
     }
 1833  
     // Write out the properties to the file
 1834  
 
 1835  0
     props.store();
 1836  0
   }
 1837  
 
 1838  
   /**
 1839  
    * Sets the configuration based on the values in the configuration file.
 1840  
    */
 1841  
   private void loadProperties() {
 1842  
     Properties props;
 1843  
     String temp;
 1844  
 
 1845  
     // props = new Properties();
 1846  0
     props = Configuration.instance();
 1847  
 
 1848  0
     userId.setText(props.getProperty(PROP_USERID, ""));
 1849  0
     password.setText(props.getProperty(PROP_PASSWORD, ""));
 1850  
 
 1851  0
     if (props.getProperty(PROP_AUTOCOMMIT, PARAMVALUE_NO)
 1852  
         .equals(PARAMVALUE_YES)) {
 1853  0
       autoCommit.setSelected(true);
 1854  
     } else {
 1855  0
       autoCommit.setSelected(false);
 1856  
     }
 1857  
 
 1858  0
     if (props.getProperty(PROP_READONLY, PARAMVALUE_NO).equals(PARAMVALUE_YES)) {
 1859  0
       readOnly.setSelected(true);
 1860  
     } else {
 1861  0
       readOnly.setSelected(false);
 1862  
     }
 1863  
 
 1864  0
     setQueryFilename(props.getProperty(PROP_SQLFILENAME,
 1865  
         Configuration.instance().getFile(FILENAME_DEFAULTQUERIES).
 1866  
             getAbsolutePath()));
 1867  0
     fileLogStats.setSelected(props.getProperty(PROP_LOGSTATS,
 1868  
         PARAMVALUE_NO).equals(PARAMVALUE_YES));
 1869  0
     fileLogResults.setSelected(props.getProperty(PROP_LOGRESULTS,
 1870  
         PARAMVALUE_NO).equals(PARAMVALUE_YES));
 1871  0
     fileExportsRaw.setSelected(props.getProperty(PROP_EXPORTRAW,
 1872  
         PARAMVALUE_NO).equals(PARAMVALUE_YES));
 1873  0
     fileNoCRAddedToExportRows.setSelected(props.getProperty(PROP_EXPORTNOCR,
 1874  
         PARAMVALUE_NO).equals(PARAMVALUE_YES));
 1875  0
     configSavePassword.setSelected(props.getProperty(PROP_SAVEPASSWORD,
 1876  
         PARAMVALUE_NO).
 1877  
         equals(PARAMVALUE_YES));
 1878  0
     configHistoryAssocSQLAndConnect.setSelected(props.getProperty(
 1879  
         PROP_ASSOCSQLURL, PARAMVALUE_NO).equals(PARAMVALUE_YES));
 1880  0
     configParseSemicolons.setSelected(props.getProperty(PROP_PARSESEMICOLON,
 1881  
         PARAMVALUE_NO).equals(PARAMVALUE_YES));
 1882  0
     configDisplayColumnDataType.setSelected(props.getProperty(
 1883  
         PROP_DISPLAYCOLUMNDATATYPE, PARAMVALUE_NO).equals(PARAMVALUE_YES));
 1884  0
     configDisplayClientInfo.setSelected(props.getProperty(
 1885  
         PROP_DISPLAYCLIENTINFO, PARAMVALUE_NO).equals(PARAMVALUE_YES));
 1886  
 
 1887  0
     if (props.getProperty(PROP_DISPLAYDBSERVERINFO,
 1888  
         PARAMVALUE_NO).equals(DBSERVERINFO_LONG)) {
 1889  0
       configDisplayDBServerInfoLong.setSelected(true);
 1890  0
     } else if (props.getProperty(PROP_DISPLAYDBSERVERINFO,
 1891  
         PARAMVALUE_NO).equals(DBSERVERINFO_BRIEF)) {
 1892  0
       configDisplayDBServerInfoShort.setSelected(true);
 1893  
     } else {
 1894  0
       configDisplayDBServerInfoNone.setSelected(true);
 1895  
     }
 1896  
 
 1897  
     // Results table row coloring
 1898  0
     if (props.getProperty(PROP_TABLE_COLORING,
 1899  
         TABLECOLORING_NONE).equals(TABLECOLORING_GREENBAR)) {
 1900  0
       configTableColoringGreenBar.setSelected(true);
 1901  0
     } else if (props.getProperty(PROP_TABLE_COLORING,
 1902  
         TABLECOLORING_NONE).equals(TABLECOLORING_YELLOWBAR)) {
 1903  0
       configTableColoringYellowBar.setSelected(true);
 1904  0
     } else if (props.getProperty(PROP_TABLE_COLORING,
 1905  
         TABLECOLORING_NONE).equals(TABLECOLORING_USERDEFINED)) {
 1906  0
       configTableColoringUserDefined.setSelected(true);
 1907  
     } else {
 1908  0
       configTableColoringNone.setSelected(true);
 1909  
     }
 1910  
 
 1911  
     // Language
 1912  0
     temp = props.getProperty(PROP_LANGUAGE, LANG_DEFAULT);
 1913  0
     if (temp.equalsIgnoreCase(LANG_DEFAULT)) {
 1914  0
       configLanguageDefault.setSelected(true);
 1915  0
     } else if (temp.equalsIgnoreCase(LANG_ENGLISH)) {
 1916  0
       configLanguageEnglish.setSelected(true);
 1917  0
     } else if (temp.equalsIgnoreCase(LANG_FRENCH)) {
 1918  0
       configLanguageFrench.setSelected(true);
 1919  0
     } else if (temp.equalsIgnoreCase(LANG_GERMAN)) {
 1920  0
       configLanguageGerman.setSelected(true);
 1921  0
     } else if (temp.equalsIgnoreCase(LANG_ITALIAN)) {
 1922  0
       configLanguageItalian.setSelected(true);
 1923  0
     } else if (temp.equalsIgnoreCase(LANG_PORTUGUESE)) {
 1924  0
       configLanguagePortuguese.setSelected(true);
 1925  0
     } else if (temp.equalsIgnoreCase(LANG_SPANISH)) {
 1926  0
       configLanguageSpanish.setSelected(true);
 1927  
     } else {
 1928  0
       configLanguageDefault.setSelected(true);
 1929  
     }
 1930  
 
 1931  
     // Frame's window state (maximized/normal)
 1932  0
     setExtendedState(props.getProperty(PROP_MAXIMIZED,
 1933  
         PARAMVALUE_NO).equals(PARAMVALUE_YES)
 1934  
         ? JFrame.MAXIMIZED_BOTH : JFrame.NORMAL);
 1935  
 
 1936  0
     if (!props.getProperty(PROP_MAXIMIZED, PARAMVALUE_NO)
 1937  
         .equals(PARAMVALUE_YES)) {
 1938  
       try {
 1939  0
         setLocation(Integer.parseInt(props.getProperty(PROP_UPPERLEFTX,
 1940  
             "0")),
 1941  
             Integer.parseInt(props.getProperty(PROP_UPPERLEFTY,
 1942  
                 "0")));
 1943  0
         setSize(Integer.parseInt(props.getProperty(PROP_WIDTH, "800")),
 1944  
             Integer.parseInt(props.getProperty(PROP_HEIGHT, "600")));
 1945  0
       } catch (Throwable any) {
 1946  0
         LOGGER.info("Missing property?", any);
 1947  0
       }
 1948  
     }
 1949  
 
 1950  0
     userDefTableColoring = props.getProperty(PROP_TABLE_COLOR_USERDEF);
 1951  
 
 1952  0
     dbDriverDir = props.getProperty(PROP_DBDRIVERDIR, DEFAULT_DBDRIVERDIR);
 1953  
 
 1954  
     // Query type versus SQL warning patterns
 1955  0
     scWarnSelectPatterns = props.getProperty(PROP_WARNSELECTPATTERNS,
 1956  
         DEFAULTWARNSELECTPATTERNS);
 1957  0
     scWarnUpdatePatterns = props.getProperty(PROP_WARNUPDATEPATTERNS,
 1958  
         DEFAULTWARNUPDATEPATTERNS);
 1959  
 
 1960  
     // File access
 1961  0
     temp = props.getProperty(PROP_LATEST_DIRECTORY);
 1962  0
     if (temp != null && temp.trim().length() > 0) {
 1963  
       try {
 1964  0
         latestFileDirectory = new File(temp);
 1965  0
       } catch (Throwable throwable) {
 1966  0
         LOGGER.warn("Unable to set the default file directory to: " + temp,
 1967  
             throwable);
 1968  0
       }
 1969  
     }
 1970  0
   }
 1971  
 
 1972  
   /**
 1973  
    * Set the fonts for the interface from the configuration in the properties
 1974  
    * collection
 1975  
    * 
 1976  
    * @param props
 1977  
    *          The properties collection with font information
 1978  
    */
 1979  
   private void setFontFromConfig(Properties props) {
 1980  
     String fontFamily;
 1981  
     int fontSize, fontStyle;
 1982  
     boolean bold, italic;
 1983  
 
 1984  
     try {
 1985  0
       fontFamily = props.getProperty(PROP_FONT_FAMILY, "Arial");
 1986  0
       fontSize = Integer.parseInt(props.getProperty(PROP_FONT_SIZE, "12"));
 1987  0
       bold = props.getProperty(PROP_FONT_BOLD, "NO").equals("YES");
 1988  0
       italic = props.getProperty(PROP_FONT_ITALIC, "NO").equals("YES");
 1989  
 
 1990  0
       fontStyle = 0;
 1991  0
       if (bold) {
 1992  0
         fontStyle |= Font.BOLD;
 1993  
       }
 1994  
 
 1995  0
       if (italic) {
 1996  0
         fontStyle |= Font.ITALIC;
 1997  
       }
 1998  
 
 1999  0
       setupFont(new Font(fontFamily, fontStyle, fontSize));
 2000  0
     } catch (Throwable any) {
 2001  
       // Probably font is not configured in property file - just ignore
 2002  
       // and use system default font
 2003  0
       LOGGER.info("Failed to setup a font from the properties file", any);
 2004  0
     }
 2005  0
   }
 2006  
 
 2007  
   /**
 2008  
    * Set default values at startup.
 2009  
    */
 2010  
   private void setDefaults() {
 2011  
     Properties props;
 2012  
 
 2013  
     // props = new Properties();
 2014  0
     props = Configuration.instance();
 2015  
 
 2016  0
     if (props.getProperty(PROP_POOLING, PARAMVALUE_YES).equals(PARAMVALUE_YES)) {
 2017  0
       poolConnect.setSelected(true);
 2018  
     } else {
 2019  0
       poolConnect.setSelected(false);
 2020  
     }
 2021  
 
 2022  
     try {
 2023  0
       connectString.setSelectedIndex(Integer.parseInt(props.getProperty(
 2024  
           PROP_CONNECTION)));
 2025  0
     } catch (Throwable any) {
 2026  
       // Probably the list changed
 2027  0
       LOGGER.info("Value not on list", any);
 2028  0
     }
 2029  
 
 2030  
     try {
 2031  0
       querySelection.setSelectedIndex(Integer.parseInt(props.getProperty(
 2032  
           PROP_SQL)));
 2033  0
     } catch (Throwable any) {
 2034  
       // Probably the list changed
 2035  0
       LOGGER.info("Value not on list", any);
 2036  0
     }
 2037  
 
 2038  
     try {
 2039  0
       maxRows
 2040  
           .setSelectedIndex(Integer.parseInt(props.getProperty(PROP_MAXROWS)));
 2041  0
     } catch (Throwable any) {
 2042  
       // Probably the list changed
 2043  0
       LOGGER.info("Value not on list", any);
 2044  0
     }
 2045  
 
 2046  
     // No queries executed yet, disable prev/next buttons
 2047  
     // TODO is this working?
 2048  0
     setPrevNextIndication();
 2049  
     // previousQuery.setEnabled(false);
 2050  
     // nextQuery.setEnabled(false);
 2051  0
   }
 2052  
 
 2053  
   /**
 2054  
    * Sets the database connection pool.
 2055  
    * 
 2056  
    * @param connectURI
 2057  
    *          The url specifying the database to which it connects
 2058  
    * @param pUserId
 2059  
    *          The user id field
 2060  
    * @param pPassword
 2061  
    *          The password field
 2062  
    */
 2063  
   private void setupDBPool(String connectURI, String pUserId, String pPassword) {
 2064  0
     removeDBPool();
 2065  
 
 2066  
     try {
 2067  0
       final GenericObjectPool connectionPool = new GenericObjectPool(null);
 2068  
 
 2069  0
       configurePool(connectionPool, connectURI, pUserId, pPassword);
 2070  
 
 2071  0
       final PoolingDriver driver = new PoolingDriver();
 2072  0
       driver.registerPool(DBPOOL_NAME, connectionPool);
 2073  0
       LOGGER.info("DB Connection Pool setup [" + DBPOOL_NAME + "]");
 2074  0
     } catch (Throwable any) {
 2075  0
       LOGGER.error("Unable to setup database connection pool", any);
 2076  0
       messageOut(Resources.getString("errFailSetupDBPool", any.getMessage()),
 2077  
           STYLE_RED);
 2078  0
     }
 2079  0
   }
 2080  
 
 2081  
   /**
 2082  
    * Configures the database connection pool and sets the pool configuration.
 2083  
    * 
 2084  
    * @param connectionPool
 2085  
    *          The ObjectPool
 2086  
    * @param connectURI
 2087  
    *          The url specifying the database to which it
 2088  
    *          connects using JDBC
 2089  
    * @param pUserId
 2090  
    *          The user id attribute
 2091  
    * @param pPassword
 2092  
    *          The password attribute
 2093  
    * 
 2094  
    * @throws java.lang.Exception
 2095  
    *           Throws an SQL exception that provides
 2096  
    *           information on a database access error
 2097  
    *           or other errors
 2098  
    * 
 2099  
    * @todo Make the pool access dynamic (use the dynamic class loader?)
 2100  
    *       so that the application will compile/run without the Apache
 2101  
    *       commons library.
 2102  
    */
 2103  
   private void configurePool(GenericObjectPool connectionPool,
 2104  
       String connectURI, String pUserId, String pPassword) throws
 2105  
       Exception {
 2106  
     String lowerCaseConnectURI;
 2107  
     String validationQuery;
 2108  
 
 2109  0
     lowerCaseConnectURI = connectURI.toLowerCase();
 2110  0
     validationQuery = null;
 2111  
 
 2112  0
     if (lowerCaseConnectURI.startsWith("jdbc:sybase")) {
 2113  0
       validationQuery = "select getdate()";
 2114  0
     } else if (lowerCaseConnectURI.startsWith("jdbc:mysql")) {
 2115  0
       validationQuery = "select 1";
 2116  0
     } else if (lowerCaseConnectURI.startsWith("jdbc:oracle")) {
 2117  0
       validationQuery = "select sysdate from dual";
 2118  0
     } else if (lowerCaseConnectURI.startsWith("jdbc:mssql")) {
 2119  0
       validationQuery = "select 1";
 2120  
     }
 2121  
 
 2122  
     // Pool settings - someday a dialog and persistence should be
 2123  
     // added to put these under user control
 2124  0
     connectionPool.setMaxActive(1);
 2125  0
     connectionPool.setWhenExhaustedAction(GenericObjectPool.
 2126  
         WHEN_EXHAUSTED_BLOCK);
 2127  0
     connectionPool.setMaxWait(CONN_POOL_MAX_WAIT_MS);
 2128  0
     connectionPool.setMaxIdle(CONN_POOL_MAX_IDLE_CONNECTIONS);
 2129  0
     connectionPool
 2130  
         .setTimeBetweenEvictionRunsMillis(CONN_POOL_TIME_BETWEEN_EVICT_RUNS_MS);
 2131  0
     connectionPool.setNumTestsPerEvictionRun(CONN_POOL_NUM_TESTS_PER_EVICT_RUN);
 2132  0
     connectionPool.setMinEvictableIdleTimeMillis(CONN_POOL_EVICT_IDLE_TIME_MS);
 2133  
 
 2134  0
     final DriverManagerConnectionFactory connectionFactory = new
 2135  
         DriverManagerConnectionFactory(connectURI, pUserId, pPassword);
 2136  0
     final PoolableConnectionFactory poolableConnectionFactory = new
 2137  
         PoolableConnectionFactory(connectionFactory, connectionPool, null,
 2138  
             null, false, true);
 2139  
 
 2140  0
     if (validationQuery != null) {
 2141  0
       connectionPool.setTestOnBorrow(true);
 2142  0
       connectionPool.setTestWhileIdle(true);
 2143  0
       poolableConnectionFactory.setValidationQuery(validationQuery);
 2144  
     }
 2145  0
   }
 2146  
 
 2147  
   /**
 2148  
    * Closes the database connection pool
 2149  
    */
 2150  
   private void removeDBPool() {
 2151  0
     final ObjectPool dbpool = getDBPool();
 2152  
 
 2153  0
     if (dbpool != null) {
 2154  
       try {
 2155  0
         dbpool.close();
 2156  0
       } catch (Throwable any) {
 2157  0
         LOGGER.error("Unable to close the database connection pool", any);
 2158  0
         messageOut(Resources.getString("errFailCloseDBPool", any.getMessage()),
 2159  
             STYLE_RED);
 2160  0
       }
 2161  
     }
 2162  0
   }
 2163  
 
 2164  
   /**
 2165  
    * Gets the driver for the database pool
 2166  
    * 
 2167  
    * @return ObjectPool Returns the driver object for the specific
 2168  
    *         pool name
 2169  
    */
 2170  
   private ObjectPool getDBPool() {
 2171  
     try {
 2172  0
       return new PoolingDriver().getConnectionPool(DBPOOL_NAME);
 2173  0
     } catch (SQLException excSQL) {
 2174  0
       LOGGER.error("Unable to load DB Pool", excSQL);
 2175  0
       return null;
 2176  
     }
 2177  
   }
 2178  
 
 2179  
   /**
 2180  
    * File menu setup
 2181  
    * 
 2182  
    * @return The file menu
 2183  
    */
 2184  
   private JMenu fileMenu() {
 2185  
     JMenu menu;
 2186  
 
 2187  
     // File Menu
 2188  0
     menu = new JMenu(Resources.getString("mnuFileLabel"));
 2189  0
     menu.setMnemonic(Resources.getChar("mnuFileAccel"));
 2190  0
     menu.getAccessibleContext().setAccessibleDescription(Resources.getString(
 2191  
         "mnuFileDesc"));
 2192  
 
 2193  
     // File | Open SQL File
 2194  0
     fileOpenSQL = new JMenuItem(Resources.getString("mnuFileOpenLabel"));
 2195  0
     fileOpenSQL.setAccelerator(KeyStroke.getKeyStroke(Resources.getChar(
 2196  
         "mnuFileOpenAccel"),
 2197  
         ActionEvent.ALT_MASK));
 2198  0
     fileOpenSQL.setMnemonic(Resources.getChar("mnuFileOpenAccel"));
 2199  0
     fileOpenSQL.getAccessibleContext().setAccessibleDescription(Resources.
 2200  
         getString("mnuFileOpenDesc"));
 2201  0
     fileOpenSQL.addActionListener(this);
 2202  0
     fileOpenSQL.setEnabled(true);
 2203  0
     menu.add(fileOpenSQL);
 2204  
 
 2205  0
     menu.addSeparator();
 2206  
 
 2207  
     // File | Log Stats
 2208  0
     fileLogStats = new JCheckBoxMenuItem(Resources.getString(
 2209  
         "mnuFileLogStatsLabel"));
 2210  0
     fileLogStats.setAccelerator(KeyStroke.getKeyStroke(Resources.getChar(
 2211  
         "mnuFileLogStatsAccel"),
 2212  
         ActionEvent.ALT_MASK));
 2213  0
     fileLogStats.setMnemonic(Resources.getChar("mnuFileLogStatsAccel"));
 2214  0
     fileLogStats.getAccessibleContext().setAccessibleDescription(
 2215  
         Resources.getString("mnuFileLogStatsAccel", DBSTATS_NAME));
 2216  0
     fileLogStats.setEnabled(true);
 2217  0
     fileLogStats.setSelected(false);
 2218  0
     menu.add(fileLogStats);
 2219  
 
 2220  
     // File | Log Results
 2221  0
     fileLogResults = new JCheckBoxMenuItem(Resources.getString(
 2222  
         "mnuFileLogResultsLabel"));
 2223  0
     fileLogResults.setAccelerator(KeyStroke.getKeyStroke(Resources.getChar(
 2224  
         "mnuFileLogResultsAccel"),
 2225  
         ActionEvent.ALT_MASK));
 2226  0
     fileLogResults.setMnemonic(Resources.getString("mnuFileLogResultsAccel").
 2227  
         charAt(0));
 2228  0
     fileLogResults.getAccessibleContext().setAccessibleDescription(
 2229  
         Resources.getString("mnuFileLogResultsDesc", DBRESULTS_NAME));
 2230  0
     fileLogResults.setEnabled(true);
 2231  0
     fileLogResults.setSelected(false);
 2232  0
     menu.add(fileLogResults);
 2233  
 
 2234  0
     menu.addSeparator();
 2235  
 
 2236  
     // File | Export Results As CSV
 2237  0
     fileSaveAsCSV = new JMenuItem(Resources.getString("mnuFileExportCSVLabel"));
 2238  0
     fileSaveAsCSV.setAccelerator(KeyStroke.getKeyStroke(Resources.getChar(
 2239  
         "mnuFileExportCSVAccel"),
 2240  
         ActionEvent.ALT_MASK));
 2241  0
     fileSaveAsCSV.setMnemonic(Resources.getChar("mnuFileExportCSVAccel"));
 2242  0
     fileSaveAsCSV.getAccessibleContext().setAccessibleDescription(Resources.
 2243  
         getString("mnuFileExportCSVDesc"));
 2244  0
     fileSaveAsCSV.addActionListener(this);
 2245  0
     fileSaveAsCSV.setEnabled(false);
 2246  0
     menu.add(fileSaveAsCSV);
 2247  
 
 2248  
     // File | Export Results As Triples
 2249  0
     fileSaveAsTriples = new JMenuItem(
 2250  
         Resources.getString("mnuFileExportTriplesLabel"));
 2251  0
     fileSaveAsTriples.setAccelerator(KeyStroke.getKeyStroke(Resources.getChar(
 2252  
         "mnuFileExportTriplesAccel"),
 2253  
         ActionEvent.ALT_MASK));
 2254  0
     fileSaveAsTriples.setMnemonic(Resources
 2255  
         .getChar("mnuFileExportTriplesAccel"));
 2256  0
     fileSaveAsTriples.getAccessibleContext().setAccessibleDescription(
 2257  
         Resources.
 2258  
             getString("mnuFileExportTriplesDesc"));
 2259  0
     fileSaveAsTriples.addActionListener(new ExportResultsAsTriplesListener());
 2260  0
     fileSaveAsTriples.setEnabled(false);
 2261  0
     menu.add(fileSaveAsTriples);
 2262  
 
 2263  
     // File | Save BLOBs
 2264  0
     fileSaveBLOBs = new JMenuItem(Resources.getString("mnuFileSaveBLOBLabel"));
 2265  0
     fileSaveBLOBs.setAccelerator(KeyStroke.getKeyStroke(Resources.getChar(
 2266  
         "mnuFileSaveBLOBAccel"),
 2267  
         ActionEvent.ALT_MASK));
 2268  0
     fileSaveBLOBs.setMnemonic(Resources.getChar("mnuFileSaveBLOBAccel"));
 2269  0
     fileSaveBLOBs.getAccessibleContext().setAccessibleDescription(Resources.
 2270  
         getString("mnuFileSaveBLOBDesc"));
 2271  0
     fileSaveBLOBs.addActionListener(this);
 2272  0
     fileSaveBLOBs.setEnabled(false);
 2273  0
     menu.add(fileSaveBLOBs);
 2274  
 
 2275  0
     menu.addSeparator();
 2276  
 
 2277  
     // File | Raw Export
 2278  0
     fileExportsRaw = new JCheckBoxMenuItem(Resources.getString(
 2279  
         "mnuFileRawExportLabel"));
 2280  0
     fileExportsRaw.setMnemonic(Resources.getChar("mnuFileRawExportAccel"));
 2281  0
     fileExportsRaw.getAccessibleContext().setAccessibleDescription(Resources.
 2282  
         getString("mnuFileRawExportDesc"));
 2283  0
     fileExportsRaw.setEnabled(true);
 2284  0
     fileExportsRaw.setSelected(false);
 2285  0
     menu.add(fileExportsRaw);
 2286  
 
 2287  
     // File | No CR Added to Export
 2288  0
     fileNoCRAddedToExportRows = new JCheckBoxMenuItem(Resources.getString(
 2289  
         "mnuFileNoCRLabel"));
 2290  0
     fileNoCRAddedToExportRows
 2291  
         .setMnemonic(Resources.getChar("mnuFileNoCRAccel"));
 2292  0
     fileNoCRAddedToExportRows.getAccessibleContext().setAccessibleDescription(
 2293  
         Resources.getString("mnuFileNoCRDesc"));
 2294  0
     fileNoCRAddedToExportRows.setEnabled(true);
 2295  0
     fileNoCRAddedToExportRows.setSelected(false);
 2296  0
     menu.add(fileNoCRAddedToExportRows);
 2297  
 
 2298  0
     return menu;
 2299  
   }
 2300  
 
 2301  
   /**
 2302  
    * Edit menu setup
 2303  
    * 
 2304  
    * @return The edit menu
 2305  
    */
 2306  
   private JMenu editMenu() {
 2307  
     JMenu menu;
 2308  
 
 2309  
     // Edit Menu
 2310  0
     menu = new JMenu(Resources.getString("mnuEditLabel"));
 2311  0
     menu.setMnemonic(Resources.getChar("mnuEditAccel"));
 2312  0
     menu.getAccessibleContext().setAccessibleDescription(Resources.getString(
 2313  
         "mnuEditDesc"));
 2314  
 
 2315  
     // Edit | Copy
 2316  0
     editCopy = new JMenuItem(Resources.getString("mnuEditCopyLabel"));
 2317  0
     editCopy.setAccelerator(KeyStroke.getKeyStroke(Resources.getChar(
 2318  
         "mnuEditCopyAccel"),
 2319  
         ActionEvent.ALT_MASK));
 2320  0
     editCopy.setMnemonic(Resources.getChar("mnuEditCopyAccel"));
 2321  0
     editCopy.getAccessibleContext().setAccessibleDescription(Resources.
 2322  
         getString("mnuEditCopyDesc"));
 2323  0
     editCopy.addActionListener(this);
 2324  0
     editCopy.setEnabled(true);
 2325  0
     menu.add(editCopy);
 2326  
 
 2327  
     // Edit | Select All
 2328  0
     editSelectAll = new JMenuItem(Resources.getString("mnuEditSelectAllLabel"));
 2329  0
     editSelectAll.setAccelerator(KeyStroke.getKeyStroke(Resources.getChar(
 2330  
         "mnuEditSelectAllAccel"),
 2331  
         ActionEvent.ALT_MASK));
 2332  0
     editSelectAll.setMnemonic(Resources.getChar("mnuEditSelectAllAccel"));
 2333  0
     editSelectAll.getAccessibleContext().setAccessibleDescription(Resources.
 2334  
         getString("mnuEditSelectAllDesc"));
 2335  0
     editSelectAll.addActionListener(this);
 2336  0
     editSelectAll.setEnabled(true);
 2337  0
     menu.add(editSelectAll);
 2338  
 
 2339  0
     menu.addSeparator();
 2340  
 
 2341  
     // Edit | Sort by Selected Columns
 2342  0
     editSort = new JMenuItem(Resources.getString("mnuEditSortLabel"));
 2343  0
     editSort.setMnemonic(Resources.getChar("mnuEditSortAccel"));
 2344  0
     editSort.getAccessibleContext().setAccessibleDescription(Resources.
 2345  
         getString("mnuEditSortDesc"));
 2346  0
     editSort.addActionListener(this);
 2347  0
     editSort.setEnabled(true);
 2348  0
     menu.add(editSort);
 2349  
 
 2350  0
     return menu;
 2351  
   }
 2352  
 
 2353  
   /**
 2354  
    * Query menu set
 2355  
    * 
 2356  
    * @return The query menu
 2357  
    */
 2358  
   private JMenu queryMenu() {
 2359  
     JMenu menu;
 2360  
 
 2361  
     // Query Menu
 2362  0
     menu = new JMenu(Resources.getString("mnuQueryLabel"));
 2363  0
     menu.setMnemonic(Resources.getChar("mnuQueryAccel"));
 2364  0
     menu.getAccessibleContext().setAccessibleDescription(Resources.getString(
 2365  
         "mnuQueryDesc"));
 2366  
 
 2367  
     // Query | Select Statement
 2368  0
     queryMakeVerboseSelect = new JMenuItem(Resources.getString(
 2369  
         "mnuQuerySelectLabel"));
 2370  0
     queryMakeVerboseSelect.setAccelerator(KeyStroke.getKeyStroke(Resources.
 2371  
         getChar("mnuQuerySelectAccel"),
 2372  
         ActionEvent.ALT_MASK));
 2373  0
     queryMakeVerboseSelect
 2374  
         .setMnemonic(Resources.getChar("mnuQuerySelectAccel"));
 2375  0
     queryMakeVerboseSelect.getAccessibleContext().setAccessibleDescription(
 2376  
         Resources.getString("mnuQuerySelectDesc"));
 2377  0
     queryMakeVerboseSelect.addActionListener(this);
 2378  0
     queryMakeVerboseSelect.setEnabled(true);
 2379  0
     menu.add(queryMakeVerboseSelect);
 2380  
 
 2381  
     // Query | Insert Statement
 2382  0
     queryMakeInsert = new JMenuItem(Resources.getString("mnuQueryInsertLabel"));
 2383  0
     queryMakeInsert.setAccelerator(KeyStroke.getKeyStroke(Resources.getChar(
 2384  
         "mnuQueryInsertAccel"),
 2385  
         ActionEvent.ALT_MASK));
 2386  0
     queryMakeInsert.setMnemonic(Resources.getChar("mnuQueryInsertAccel"));
 2387  0
     queryMakeInsert.getAccessibleContext().setAccessibleDescription(Resources.
 2388  
         getString("mnuQueryInsertDesc"));
 2389  0
     queryMakeInsert.addActionListener(this);
 2390  0
     queryMakeInsert.setEnabled(true);
 2391  0
     menu.add(queryMakeInsert);
 2392  
 
 2393  
     // Query | Update Statement
 2394  0
     queryMakeUpdate = new JMenuItem(Resources.getString("mnuQueryUpdateLabel"));
 2395  0
     queryMakeUpdate.setAccelerator(KeyStroke.getKeyStroke(Resources.getChar(
 2396  
         "mnuQueryUpdateAccel"),
 2397  
         ActionEvent.ALT_MASK));
 2398  0
     queryMakeUpdate.setMnemonic(Resources.getChar("mnuQueryUpdateAccel"));
 2399  0
     queryMakeUpdate.getAccessibleContext().setAccessibleDescription(Resources.
 2400  
         getString("mnuQueryUpdateDesc"));
 2401  0
     queryMakeUpdate.addActionListener(this);
 2402  0
     queryMakeUpdate.setEnabled(true);
 2403  0
     menu.add(queryMakeUpdate);
 2404  
 
 2405  0
     menu.addSeparator();
 2406  
 
 2407  
     // Query | Select *
 2408  0
     querySelectStar = new JMenuItem(Resources.getString(
 2409  
         "mnuQuerySelectStarLabel"));
 2410  0
     querySelectStar.setAccelerator(KeyStroke.getKeyStroke(Resources.getChar(
 2411  
         "mnuQuerySelectStarAccel"),
 2412  
         ActionEvent.ALT_MASK));
 2413  0
     querySelectStar.setMnemonic(Resources.getChar("mnuQuerySelectStarAccel"));
 2414  0
     querySelectStar.getAccessibleContext().setAccessibleDescription(Resources.
 2415  
         getString("mnuQuerySelectStarDesc"));
 2416  0
     querySelectStar.addActionListener(this);
 2417  0
     querySelectStar.setEnabled(true);
 2418  0
     menu.add(querySelectStar);
 2419  
 
 2420  
     // Query | Describe Select *
 2421  0
     queryDescribeStar = new JMenuItem(Resources.getString(
 2422  
         "mnuQueryDescSelectStarLabel"));
 2423  0
     queryDescribeStar.setAccelerator(KeyStroke.getKeyStroke(Resources.getChar(
 2424  
         "mnuQueryDescSelectStarAccel"),
 2425  
         ActionEvent.ALT_MASK));
 2426  0
     queryDescribeStar.setMnemonic(Resources.getChar(
 2427  
         "mnuQueryDescSelectStarAccel"));
 2428  0
     queryDescribeStar.getAccessibleContext().setAccessibleDescription(
 2429  
         Resources.
 2430  
             getString("mnuQueryDescSelectStarDesc"));
 2431  0
     queryDescribeStar.addActionListener(this);
 2432  0
     queryDescribeStar.setEnabled(true);
 2433  0
     menu.add(queryDescribeStar);
 2434  
 
 2435  0
     menu.addSeparator();
 2436  
 
 2437  
     // Query | Reorder Queries
 2438  0
     querySetOrder = new JMenuItem(Resources.getString("mnuQueryReorderLabel"));
 2439  0
     querySetOrder.setMnemonic(Resources.getChar("mnuQueryReorderAccel"));
 2440  0
     querySetOrder.getAccessibleContext().setAccessibleDescription(Resources.
 2441  
         getString("mnuQueryReorderDesc"));
 2442  0
     querySetOrder.addActionListener(this);
 2443  0
     querySetOrder.setEnabled(true);
 2444  0
     menu.add(querySetOrder);
 2445  
 
 2446  0
     menu.addSeparator();
 2447  
 
 2448  
     // Query | Run All
 2449  0
     queryRunAll = new JMenuItem(Resources.getString("mnuQueryRunAllLabel"));
 2450  0
     queryRunAll.setAccelerator(KeyStroke.getKeyStroke(Resources.getChar(
 2451  
         "mnuQueryRunAllAccel"),
 2452  
         ActionEvent.ALT_MASK));
 2453  0
     queryRunAll.setMnemonic(Resources.getChar("mnuQueryRunAllAccel"));
 2454  0
     queryRunAll.getAccessibleContext().setAccessibleDescription(Resources.
 2455  
         getString("mnuQueryRunAllDesc"));
 2456  0
     queryRunAll.addActionListener(this);
 2457  0
     queryRunAll.setEnabled(true);
 2458  0
     menu.add(queryRunAll);
 2459  
 
 2460  0
     return menu;
 2461  
   }
 2462  
 
 2463  
   /**
 2464  
    * Language selection menu
 2465  
    * 
 2466  
    * @return The language selection menu
 2467  
    */
 2468  
   private JMenu languageMenu() {
 2469  
     JMenu subMenu;
 2470  
     ButtonGroup buttonGroup;
 2471  
 
 2472  
     // Setup | Language
 2473  0
     subMenu = new JMenu(Resources.getString("mnuSetupLanguageLabel"));
 2474  0
     subMenu.setMnemonic(Resources.getChar("mnuSetupLanguageAccel"));
 2475  0
     subMenu.getAccessibleContext().setAccessibleDescription(
 2476  
         Resources.getString(
 2477  
             "mnuSetupLanguageDesc"));
 2478  
 
 2479  
     // Setup | Language | System Default
 2480  0
     if (System.getProperty(PROP_SYSTEM_DEFAULTLANGUAGE) != null) {
 2481  0
       if (System.getProperty(PROP_SYSTEM_DEFAULTCOUNTRY) != null) {
 2482  0
         configLanguageDefault = new JRadioButtonMenuItem(
 2483  
             Resources.getString("mnuSetupLanguageDefaultLabel") + " ("
 2484  
                 + System.getProperty(PROP_SYSTEM_DEFAULTLANGUAGE) + "_"
 2485  
                 + System.getProperty(PROP_SYSTEM_DEFAULTCOUNTRY) + ")");
 2486  
       } else {
 2487  0
         configLanguageDefault = new JRadioButtonMenuItem(
 2488  
             Resources.getString("mnuSetupLanguageDefaultLabel") + " ("
 2489  
                 + System.getProperty(PROP_SYSTEM_DEFAULTLANGUAGE) + ")");
 2490  
       }
 2491  
     } else {
 2492  0
       configLanguageDefault = new JRadioButtonMenuItem(
 2493  
           Resources.getString("mnuSetupLanguageDefaultLabel"));
 2494  
     }
 2495  0
     configLanguageDefault.setMnemonic(Resources.getChar(
 2496  
         "mnuSetupLanguageDefaultAccel"));
 2497  0
     configLanguageDefault.getAccessibleContext().
 2498  
         setAccessibleDescription(Resources.getString(
 2499  
             "mnuSetupLanguageDefaultDesc"));
 2500  0
     configLanguageDefault.addActionListener(this);
 2501  0
     subMenu.add(configLanguageDefault);
 2502  
 
 2503  
     // Setup | Language | Deutsche (German)
 2504  0
     configLanguageGerman = new JRadioButtonMenuItem(
 2505  
         Resources.getString("mnuSetupLanguageGermanLabel"));
 2506  0
     configLanguageGerman.setMnemonic(Resources.getChar(
 2507  
         "mnuSetupLanguageGermanAccel"));
 2508  0
     configLanguageGerman.getAccessibleContext().
 2509  
         setAccessibleDescription(Resources.getString(
 2510  
             "mnuSetupLanguageGermanDesc"));
 2511  0
     configLanguageGerman.addActionListener(this);
 2512  0
     subMenu.add(configLanguageGerman);
 2513  
 
 2514  
     // Setup | Language | English
 2515  0
     configLanguageEnglish = new JRadioButtonMenuItem(
 2516  
         Resources.getString("mnuSetupLanguageEnglishLabel"));
 2517  0
     configLanguageEnglish.setMnemonic(Resources.getChar(
 2518  
         "mnuSetupLanguageEnglishAccel"));
 2519  0
     configLanguageEnglish.getAccessibleContext().
 2520  
         setAccessibleDescription(Resources.getString(
 2521  
             "mnuSetupLanguageEnglishDesc"));
 2522  0
     configLanguageEnglish.addActionListener(this);
 2523  0
     subMenu.add(configLanguageEnglish);
 2524  
 
 2525  
     // Setup | Language | Espanola (Spanish)
 2526  0
     configLanguageSpanish = new JRadioButtonMenuItem(
 2527  
         Resources.getString("mnuSetupLanguageSpanishLabel"));
 2528  0
     configLanguageSpanish.setMnemonic(Resources.getChar(
 2529  
         "mnuSetupLanguageSpanishAccel"));
 2530  0
     configLanguageSpanish.getAccessibleContext().
 2531  
         setAccessibleDescription(Resources.getString(
 2532  
             "mnuSetupLanguageSpanishDesc"));
 2533  0
     configLanguageSpanish.addActionListener(this);
 2534  0
     subMenu.add(configLanguageSpanish);
 2535  
 
 2536  
     // Setup | Language | Francaise (French)
 2537  0
     configLanguageFrench = new JRadioButtonMenuItem(
 2538  
         Resources.getString("mnuSetupLanguageFrenchLabel"));
 2539  0
     configLanguageFrench.setMnemonic(Resources.getChar(
 2540  
         "mnuSetupLanguageFrenchAccel"));
 2541  0
     configLanguageFrench.getAccessibleContext().
 2542  
         setAccessibleDescription(Resources.getString(
 2543  
             "mnuSetupLanguageFrenchDesc"));
 2544  0
     configLanguageFrench.addActionListener(this);
 2545  0
     subMenu.add(configLanguageFrench);
 2546  
 
 2547  
     // Setup | Language | Italiana (Italian)
 2548  0
     configLanguageItalian = new JRadioButtonMenuItem(
 2549  
         Resources.getString("mnuSetupLanguageItalianLabel"));
 2550  0
     configLanguageItalian.setMnemonic(Resources.getChar(
 2551  
         "mnuSetupLanguageItalianAccel"));
 2552  0
     configLanguageItalian.getAccessibleContext().
 2553  
         setAccessibleDescription(Resources.getString(
 2554  
             "mnuSetupLanguageItalianDesc"));
 2555  0
     configLanguageItalian.addActionListener(this);
 2556  0
     subMenu.add(configLanguageItalian);
 2557  
 
 2558  
     // Setup | Language | Portugues (Portuguese)
 2559  0
     configLanguagePortuguese = new JRadioButtonMenuItem(
 2560  
         Resources.getString("mnuSetupLanguagePortugueseLabel"));
 2561  0
     configLanguagePortuguese.setMnemonic(Resources.getChar(
 2562  
         "mnuSetupLanguagePortugueseAccel"));
 2563  0
     configLanguagePortuguese.getAccessibleContext().
 2564  
         setAccessibleDescription(Resources.getString(
 2565  
             "mnuSetupLanguagePortugueseDesc"));
 2566  0
     configLanguagePortuguese.addActionListener(this);
 2567  0
     subMenu.add(configLanguagePortuguese);
 2568  
 
 2569  0
     buttonGroup = new ButtonGroup();
 2570  0
     buttonGroup.add(configLanguageDefault);
 2571  0
     buttonGroup.add(configLanguageEnglish);
 2572  0
     buttonGroup.add(configLanguageFrench);
 2573  0
     buttonGroup.add(configLanguageGerman);
 2574  0
     buttonGroup.add(configLanguageItalian);
 2575  0
     buttonGroup.add(configLanguagePortuguese);
 2576  0
     buttonGroup.add(configLanguageSpanish);
 2577  
 
 2578  0
     return subMenu;
 2579  
   }
 2580  
 
 2581  
   /**
 2582  
    * Configuration menu setup
 2583  
    * 
 2584  
    * @return The configuration menu
 2585  
    */
 2586  
   private JMenu configurationMenu() {
 2587  
     JMenu menu;
 2588  
     JMenu subMenu;
 2589  
     ButtonGroup buttonGroup;
 2590  
 
 2591  
     // Configuration Menu
 2592  0
     menu = new JMenu(Resources.getString("mnuSetupLabel"));
 2593  0
     menu.setMnemonic(Resources.getChar("mnuSetupAccel"));
 2594  0
     menu.getAccessibleContext().setAccessibleDescription(Resources.getString(
 2595  
         "mnuSetupDesc"));
 2596  
 
 2597  0
     menu.add(languageMenu());
 2598  
 
 2599  
     // Setup | Font
 2600  0
     configFont = new JMenuItem(Resources.getString("mnuConfigFontLabel"));
 2601  0
     configFont.setMnemonic(Resources.getChar("mnuConfigFontAccel"));
 2602  0
     configFont.getAccessibleContext().setAccessibleDescription(Resources.
 2603  
         getString("mnuConfigFontDesc"));
 2604  0
     configFont.addActionListener(this);
 2605  0
     configFont.setEnabled(true);
 2606  0
     menu.add(configFont);
 2607  
 
 2608  
     // Setup | Display DB Server Info
 2609  0
     subMenu = new JMenu(Resources.getString("mnuSetupDBServerLabel"));
 2610  0
     subMenu.setMnemonic(Resources.getChar("mnuSetupDBServerAccel"));
 2611  0
     subMenu.getAccessibleContext().setAccessibleDescription(
 2612  
         Resources.getString(
 2613  
             "mnuSetupDBServerDesc"));
 2614  0
     menu.add(subMenu);
 2615  
 
 2616  
     // Configuration | Display DB Server Info | None
 2617  0
     configDisplayDBServerInfoNone = new JRadioButtonMenuItem(
 2618  
         Resources.getString("mnuSetupDBServerNoneLabel"));
 2619  0
     configDisplayDBServerInfoNone.setMnemonic(Resources.getChar(
 2620  
         "mnuSetupDBServerNoneAccel"));
 2621  0
     configDisplayDBServerInfoNone.getAccessibleContext().
 2622  
         setAccessibleDescription(
 2623  
             Resources.getString("mnuSetupDBServerNoneDesc"));
 2624  0
     subMenu.add(configDisplayDBServerInfoNone);
 2625  
 
 2626  
     // Configuration | Display DB Server Info | Brief
 2627  0
     configDisplayDBServerInfoShort = new JRadioButtonMenuItem(
 2628  
         Resources.getString("mnuSetupDBServerBriefLabel"));
 2629  0
     configDisplayDBServerInfoShort.setMnemonic(Resources.getChar(
 2630  
         "mnuSetupDBServerBriefAccel"));
 2631  0
     configDisplayDBServerInfoShort.getAccessibleContext().
 2632  
         setAccessibleDescription(Resources.getString(
 2633  
             "mnuSetupDBServerBriefDesc"));
 2634  0
     subMenu.add(configDisplayDBServerInfoShort);
 2635  
 
 2636  
     // Configuration | Display DB Server Info | Long
 2637  0
     configDisplayDBServerInfoLong = new JRadioButtonMenuItem(
 2638  
         Resources.getString("mnuSetupDBServerLongLabel"));
 2639  0
     configDisplayDBServerInfoLong.setMnemonic(Resources.getChar(
 2640  
         "mnuSetupDBServerLongAccel"));
 2641  0
     configDisplayDBServerInfoLong.getAccessibleContext().
 2642  
         setAccessibleDescription(
 2643  
             Resources.getString("mnuSetupDBServerLongDesc"));
 2644  0
     subMenu.add(configDisplayDBServerInfoLong);
 2645  
 
 2646  0
     buttonGroup = new ButtonGroup();
 2647  0
     buttonGroup.add(configDisplayDBServerInfoNone);
 2648  0
     buttonGroup.add(configDisplayDBServerInfoLong);
 2649  0
     buttonGroup.add(configDisplayDBServerInfoShort);
 2650  
 
 2651  
     // Default is short display of DB server info
 2652  0
     configDisplayDBServerInfoShort.setSelected(true);
 2653  
 
 2654  
     // Setup | Table Row Coloring
 2655  0
     subMenu = new JMenu(Resources.getString("mnuSetupRowColorLabel"));
 2656  0
     subMenu.setMnemonic(Resources.getChar("mnuSetupRowColorAccel"));
 2657  0
     subMenu.getAccessibleContext().setAccessibleDescription(
 2658  
         Resources.getString(
 2659  
             "mnuSetupRowColorDesc"));
 2660  0
     menu.add(subMenu);
 2661  
 
 2662  
     // Setup | Table Row Coloring | None
 2663  0
     configTableColoringNone = new JRadioButtonMenuItem(
 2664  
         Resources.getString("mnuSetupRowColorNoneLabel"));
 2665  0
     configTableColoringNone.setMnemonic(Resources.getChar(
 2666  
         "mnuSetupRowColorNoneAccel"));
 2667  0
     configTableColoringNone.getAccessibleContext().
 2668  
         setAccessibleDescription(
 2669  
             Resources.getString("mnuSetupRowColorNoneDesc"));
 2670  0
     configTableColoringNone.addActionListener(this);
 2671  0
     subMenu.add(configTableColoringNone);
 2672  
 
 2673  
     // Setup | Table Row Coloring | Green Bar
 2674  0
     configTableColoringGreenBar = new JRadioButtonMenuItem(
 2675  
         Resources.getString("mnuSetupRowColorGreenBarLabel"));
 2676  0
     configTableColoringGreenBar.setMnemonic(Resources.getChar(
 2677  
         "mnuSetupRowColorGreenBarAccel"));
 2678  0
     configTableColoringGreenBar.getAccessibleContext().
 2679  
         setAccessibleDescription(Resources.getString(
 2680  
             "mnuSetupRowColorGreenBarDesc"));
 2681  0
     configTableColoringGreenBar.addActionListener(this);
 2682  0
     subMenu.add(configTableColoringGreenBar);
 2683  
 
 2684  
     // Setup | Table Row Coloring | Yellow Bar
 2685  0
     configTableColoringYellowBar = new JRadioButtonMenuItem(
 2686  
         Resources.getString("mnuSetupRowColorYellowBarLabel"));
 2687  0
     configTableColoringYellowBar.setMnemonic(Resources.getChar(
 2688  
         "mnuSetupRowColorYellowBarAccel"));
 2689  0
     configTableColoringYellowBar.getAccessibleContext().
 2690  
         setAccessibleDescription(Resources.getString(
 2691  
             "mnuSetupRowColorYellowBarDesc"));
 2692  0
     configTableColoringYellowBar.addActionListener(this);
 2693  0
     subMenu.add(configTableColoringYellowBar);
 2694  
 
 2695  0
     subMenu.addSeparator();
 2696  
 
 2697  
     // Setup | Table Row Coloring | User Defined
 2698  0
     configTableColoringUserDefined = new JRadioButtonMenuItem(
 2699  
         Resources.getString("mnuSetupRowColorUserDefLabel"));
 2700  0
     configTableColoringUserDefined.setMnemonic(Resources.getChar(
 2701  
         "mnuSetupRowColorUserDefAccel"));
 2702  0
     configTableColoringUserDefined.getAccessibleContext().
 2703  
         setAccessibleDescription(Resources.getString(
 2704  
             "mnuSetupRowColorUserDefDesc"));
 2705  0
     configTableColoringUserDefined.addActionListener(this);
 2706  0
     subMenu.add(configTableColoringUserDefined);
 2707  
 
 2708  0
     buttonGroup = new ButtonGroup();
 2709  0
     buttonGroup.add(configTableColoringNone);
 2710  0
     buttonGroup.add(configTableColoringGreenBar);
 2711  0
     buttonGroup.add(configTableColoringYellowBar);
 2712  0
     buttonGroup.add(configTableColoringUserDefined);
 2713  
 
 2714  
     // Default is no special coloring of data rows
 2715  0
     configTableColoringNone.setSelected(true);
 2716  
 
 2717  0
     menu.addSeparator();
 2718  
 
 2719  
     // Configuration | Associate SQL and Connect URL
 2720  0
     configHistoryAssocSQLAndConnect = new JCheckBoxMenuItem(
 2721  
         Resources.getString("mnuSetupAssocSQLURLLabel"));
 2722  0
     configHistoryAssocSQLAndConnect.setMnemonic(Resources.getChar(
 2723  
         "mnuSetupAssocSQLURLAccel"));
 2724  0
     configHistoryAssocSQLAndConnect
 2725  
         .getAccessibleContext()
 2726  
         .
 2727  
         setAccessibleDescription(Resources.getString("mnuSetupAssocSQLURLDesc"));
 2728  0
     configHistoryAssocSQLAndConnect.setEnabled(true);
 2729  0
     menu.add(configHistoryAssocSQLAndConnect);
 2730  
 
 2731  
     // Configuration | Parse SQL at Semi-Colons
 2732  0
     configParseSemicolons = new JCheckBoxMenuItem(
 2733  
         Resources.getString("mnuSetupParseSQLSemicolonLabel"));
 2734  0
     configParseSemicolons.setMnemonic(Resources.getChar(
 2735  
         "mnuSetupParseSQLSemicolonAccel"));
 2736  0
     configParseSemicolons.getAccessibleContext().
 2737  
         setAccessibleDescription(Resources.getString(
 2738  
             "mnuSetupParseSQLSemicolonDesc"));
 2739  0
     configParseSemicolons.setEnabled(true);
 2740  0
     menu.add(configParseSemicolons);
 2741  
 
 2742  0
     menu.addSeparator();
 2743  
 
 2744  
     // Configuration | Display Column Data Type
 2745  0
     configDisplayColumnDataType = new JCheckBoxMenuItem(
 2746  
         Resources.getString("mnuSetupDispColTypeLabel"));
 2747  0
     configDisplayColumnDataType.setMnemonic(Resources.getChar(
 2748  
         "mnuSetupDispColTypeAccel"));
 2749  0
     configDisplayColumnDataType.getAccessibleContext()
 2750  
         .setAccessibleDescription(
 2751  
             Resources.getString("mnuSetupDispColTypeDesc"));
 2752  0
     configDisplayColumnDataType.setEnabled(true);
 2753  0
     configDisplayColumnDataType.setSelected(false);
 2754  0
     menu.add(configDisplayColumnDataType);
 2755  
 
 2756  
     // Configuration | Display Client Info
 2757  0
     configDisplayClientInfo = new JCheckBoxMenuItem(
 2758  
         Resources.getString("mnuSetupClientInfoLabel"));
 2759  0
     configDisplayClientInfo.setMnemonic(Resources.getChar(
 2760  
         "mnuSetupClientInfoAccel"));
 2761  0
     configDisplayClientInfo.getAccessibleContext().setAccessibleDescription(
 2762  
         Resources.getString("mnuSetupClientInfoDesc"));
 2763  0
     configDisplayClientInfo.setEnabled(true);
 2764  0
     configDisplayClientInfo.setSelected(false);
 2765  0
     menu.add(configDisplayClientInfo);
 2766  
 
 2767  0
     menu.addSeparator();
 2768  
 
 2769  
     // Configuration | Save Password
 2770  0
     configSavePassword = new JCheckBoxMenuItem(Resources.getString(
 2771  
         "mnuSetupSavePasswordLabel"));
 2772  0
     configSavePassword.setMnemonic(Resources.getChar(
 2773  
         "mnuSetupSavePasswordAccel"));
 2774  0
     configSavePassword.getAccessibleContext().setAccessibleDescription(
 2775  
         Resources.getString("mnuSetupSavePasswordDesc"));
 2776  0
     configSavePassword.setEnabled(true);
 2777  0
     configSavePassword.setSelected(false);
 2778  0
     menu.add(configSavePassword);
 2779  
 
 2780  0
     return menu;
 2781  
   }
 2782  
 
 2783  
   /**
 2784  
    * Help menu setup
 2785  
    * 
 2786  
    * @return The help menu
 2787  
    */
 2788  
   private JMenu helpMenu() {
 2789  
     JMenu menu;
 2790  
 
 2791  
     // Help Menu
 2792  0
     menu = new JMenu(Resources.getString("mnuHelpLabel"));
 2793  0
     menu.setMnemonic(Resources.getChar("mnuHelpAccel"));
 2794  0
     menu.getAccessibleContext().setAccessibleDescription(Resources.getString(
 2795  
         "mnuHelpDesc"));
 2796  
 
 2797  
     // Help | Parameterized SQL Statement
 2798  0
     helpParameterizedSQL = new JMenuItem(Resources.getString(
 2799  
         "mnuHelpParamSQLLabel"));
 2800  0
     helpParameterizedSQL.setMnemonic(Resources.getChar("mnuHelpParamSQLAccel"));
 2801  0
     helpParameterizedSQL.getAccessibleContext().setAccessibleDescription(
 2802  
         Resources.getString("mnuHelpParamSQLDesc"));
 2803  0
     helpParameterizedSQL.addActionListener(this);
 2804  0
     helpParameterizedSQL.setEnabled(true);
 2805  0
     menu.add(helpParameterizedSQL);
 2806  
 
 2807  0
     menu.addSeparator();
 2808  
 
 2809  
     // Help | About
 2810  0
     helpAbout = new JMenuItem(Resources.getString("mnuHelpAboutLabel"));
 2811  0
     helpAbout.setMnemonic(Resources.getChar("mnuHelpAboutAccel"));
 2812  0
     helpAbout.getAccessibleContext().setAccessibleDescription(Resources.
 2813  
         getString("mnuHelpAboutDesc"));
 2814  0
     helpAbout.addActionListener(this);
 2815  0
     helpAbout.setEnabled(true);
 2816  0
     menu.add(helpAbout);
 2817  
 
 2818  0
     return menu;
 2819  
   }
 2820  
 
 2821  
   /**
 2822  
    * Creates the various menu options and attaches the mnemonics and
 2823  
    * registers listeners.
 2824  
    */
 2825  
   private void loadMenu() {
 2826  
     JMenuBar menubar;
 2827  
 
 2828  0
     menubar = new JMenuBar();
 2829  0
     setJMenuBar(menubar);
 2830  
 
 2831  0
     menubar.add(fileMenu());
 2832  
 
 2833  0
     menubar.add(editMenu());
 2834  
 
 2835  0
     menubar.add(queryMenu());
 2836  
 
 2837  0
     menubar.add(configurationMenu());
 2838  
 
 2839  0
     menubar.add(helpMenu());
 2840  0
   }
 2841  
 
 2842  
   /**
 2843  
    * Loads the drivers to allow connection to the database. Driver definitions
 2844  
    * are read from a driver configuration file.
 2845  
    */
 2846  
   private void loadDrivers() {
 2847  
     boolean isFromFile;
 2848  
     BufferedReader drivers;
 2849  
     String driverName;
 2850  
     int sepPosit;
 2851  0
     final DynamicClassLoader dbClassLoader = getDBClassLoader();
 2852  
 
 2853  0
     isFromFile = false;
 2854  0
     drivers = null;
 2855  
 
 2856  
     try {
 2857  0
       drivers = new BufferedReader(new FileReader(Configuration.instance().
 2858  
           getFile(FILENAME_DRIVERS)));
 2859  0
       while ((driverName = drivers.readLine()) != null) {
 2860  0
         if (driverName.trim().length() > 0) {
 2861  0
           isFromFile = true;
 2862  0
           if ((sepPosit = driverName.lastIndexOf(",")) > 0) {
 2863  0
             loadDriver(driverName.substring(0, sepPosit),
 2864  
                 driverName.substring(sepPosit + 1), dbClassLoader);
 2865  
           } else {
 2866  0
             loadDriver(driverName, driverName, dbClassLoader);
 2867  
           }
 2868  
         }
 2869  
       }
 2870  0
     } catch (Exception any) {
 2871  
       /*
 2872  
        * Keep the output silent when the file doesn't exist, which would be
 2873  
        * typical for new installation.
 2874  
        */
 2875  0
       if (!(any instanceof FileNotFoundException)) {
 2876  0
         LOGGER.error("Problem loading the database driver(s)", any);
 2877  0
         messageOut(
 2878  
             Resources.getString("errFailLoadingDBDrivers",
 2879  
                 Configuration.instance().getFile(FILENAME_DRIVERS)
 2880  
                     .getAbsolutePath()
 2881  
                     + ": " + any.getMessage()),
 2882  
             STYLE_RED);
 2883  
       }
 2884  
     } finally {
 2885  0
       if (drivers != null) {
 2886  
         try {
 2887  0
           drivers.close();
 2888  0
         } catch (Exception any) {
 2889  0
           LOGGER.error("Unable to close the drivers configuration file", any);
 2890  0
         }
 2891  
       }
 2892  
     }
 2893  
 
 2894  0
     if (!isFromFile) {
 2895  0
       loadDriver("com.sybase.jdbc2.jdbc.SybDriver", "Sybase", dbClassLoader);
 2896  0
       loadDriver("org.gjt.mm.mysql.Driver", "MySQL", dbClassLoader);
 2897  0
       loadDriver("oracle.jdbc.driver.OracleDriver", "Oracle", dbClassLoader);
 2898  
     }
 2899  0
   }
 2900  
 
 2901  
   /**
 2902  
    * Writes the output message onto the message document
 2903  
    * 
 2904  
    * @param text
 2905  
    *          The string to be inserted
 2906  
    * @param style
 2907  
    *          The message display style
 2908  
    */
 2909  
   private void messageOut(String text, String style) {
 2910  0
     messageOut(text, style, true);
 2911  0
   }
 2912  
 
 2913  
   /**
 2914  
    * Places a message in the message display area using the style supplied.
 2915  
    * 
 2916  
    * @param text
 2917  
    *          String The message to display
 2918  
    * @param style
 2919  
    *          String The predefined style to use for the text
 2920  
    * @param newLine
 2921  
    *          boolean Whether to force a newline after the message
 2922  
    */
 2923  
   private void messageOut(String text, String style, boolean newLine) {
 2924  
     try {
 2925  0
       messageDocument.insertString(messageDocument.getLength(), text,
 2926  
           (AttributeSet) messageStyles.get(style));
 2927  
 
 2928  0
       if (newLine) {
 2929  0
         messageDocument.insertString(messageDocument.getLength(), "\n",
 2930  
             (AttributeSet) messageStyles.get(
 2931  
                 STYLE_NORMAL));
 2932  
       }
 2933  0
     } catch (BadLocationException excLoc) {
 2934  0
       LOGGER.warn("Bad location while inserting message text", excLoc);
 2935  0
     }
 2936  
 
 2937  0
     if (messageDocument.getLength() > 0) {
 2938  0
       message.setCaretPosition(messageDocument.getLength() - 1);
 2939  
     }
 2940  0
   }
 2941  
 
 2942  
   /**
 2943  
    * writes the string onto the message document, displayed in the lower
 2944  
    * portion of the GUI.
 2945  
    * 
 2946  
    * @param text
 2947  
    *          The string that is to be inserted
 2948  
    */
 2949  
   private void messageOut(String text) {
 2950  0
     LOGGER.info(text);
 2951  0
     if (messageDocument != null) {
 2952  0
       messageOut(text, STYLE_NORMAL);
 2953  
     }
 2954  0
   }
 2955  
 
 2956  
   /**
 2957  
    * Loads the driver into the JVM making it available for usage by the
 2958  
    * driver class
 2959  
    * 
 2960  
    * @param driverClass
 2961  
    *          String specifying the class name for the driver
 2962  
    * @param productName
 2963  
    *          String specifying the product name - oracle,sybase or
 2964  
    *          mySql
 2965  
    * @param dbClassLoader
 2966  
    *          The classloader for accessing DB drivers
 2967  
    */
 2968  
   private void loadDriver(String driverClass, String productName,
 2969  
       DynamicClassLoader dbClassLoader) {
 2970  
     Constructor<?> constructDriver;
 2971  
 
 2972  
     try {
 2973  0
       constructDriver = Class.forName(driverClass, true, dbClassLoader).
 2974  
           getConstructor();
 2975  0
       DriverManager.registerDriver(new DynamicDriver((Driver) constructDriver.
 2976  
           newInstance()));
 2977  
 
 2978  0
       messageOut(Resources.getString("msgDriverLoaded", productName),
 2979  
           STYLE_GREEN);
 2980  0
     } catch (Exception any) {
 2981  0
       LOGGER.error("Unable to load DB driver [" + driverClass + "]", any);
 2982  0
       messageOut(Resources.getString("errDriverNotFound", productName),
 2983  
           STYLE_RED);
 2984  0
     }
 2985  0
   }
 2986  
 
 2987  
   /**
 2988  
    * Loads the connect strings from an external file
 2989  
    */
 2990  
   private void loadConnectStrings() {
 2991  
     // If no connect strings loaded, supply some defaults
 2992  0
     if (connectString.getModel().getSize() == 0) {
 2993  0
       addToCombo(connectString,
 2994  
           "jdbc:sybase:Tds:localhost:3144/database?charset=iso_1");
 2995  0
       addToCombo(connectString, "jdbc:mysql://localhost:3306/kyn");
 2996  0
       addToCombo(connectString, "jdbc:oracle:thin:@localhost:1521:DEV1");
 2997  0
       addToCombo(connectString, "jdbc:oracle:thin:@dbprod1:1521:prod1");
 2998  
     }
 2999  0
   }
 3000  
 
 3001  
   /**
 3002  
    * Loads default queries (to give a new user some idea of how the interface
 3003  
    * works) if there are no queries stored in the external query file.
 3004  
    */
 3005  
   private void loadQueries() {
 3006  
     // If no queries loaded, supply some defaults
 3007  0
     if (querySelection.getModel().getSize() == 0) {
 3008  0
       addToCombo(querySelection, new Query("{call sp_help}", Query.MODE_QUERY));
 3009  0
       addToCombo(querySelection,
 3010  
           new Query(
 3011  
               "{call stored_proc('ARG1', '', '','ARG4')}",
 3012  
               Query.MODE_QUERY));
 3013  0
       addToCombo(querySelection,
 3014  
           new Query("select * from all_tables", Query.MODE_QUERY));
 3015  0
       addToCombo(querySelection,
 3016  
           new Query("$PARAM[OUT,INTEGER]$ = {call sp_help}",
 3017  
               Query.MODE_QUERY));
 3018  0
       addToCombo(
 3019  
           querySelection,
 3020  
           new Query(
 3021  
               "$PARAM[OUT,INTEGER]$ = {call function($PARAM[IN,STRING,ARG1]$, '', '', 'ARG4'}",
 3022  
               Query.MODE_QUERY));
 3023  
     }
 3024  0
   }
 3025  
 
 3026  
   /**
 3027  
    * Checks whether an input (query or connect string) is already in its
 3028  
    * associated combo box. If not, the new information is added to the combo
 3029  
    * list
 3030  
    * 
 3031  
    * @param combo
 3032  
    *          JComboBox which has a list of the query statements or connect
 3033  
    *          strings.
 3034  
    */
 3035  
   private void checkForNewString(JComboBox combo) {
 3036  
     // String newString, foundString;
 3037  
     Object newValue;
 3038  
     int checkDups, matchAt;
 3039  
     boolean match;
 3040  
     // boolean newCommented, foundCommented;
 3041  
 
 3042  
     // newCommented = foundCommented = false;
 3043  0
     matchAt = -1;
 3044  
 
 3045  0
     if (combo == querySelection) {
 3046  0
       newValue = new Query(queryText.getText(), whichModeValue());
 3047  
       // newString = queryText.getText();
 3048  
       // newString = newString.replace('\n', ' ');
 3049  
     } else {
 3050  
       // newString = (String)combo.getEditor().getItem();
 3051  0
       newValue = combo.getEditor().getItem();
 3052  
     }
 3053  
 
 3054  
     // if (newString.startsWith(COMMENT_PREFIX)) {
 3055  
     // newCommented = true;
 3056  
     // newString = newString.substring(2);
 3057  
     // }
 3058  
 
 3059  
     // if (newString.trim().length() > 0) {
 3060  0
     if (newValue.toString().length() > 0) {
 3061  0
       match = false;
 3062  0
       for (checkDups = 0; checkDups < combo.getItemCount() && !match; ++checkDups) {
 3063  
         // if (combo == querySelection) {
 3064  
         // foundString = ((Query)combo.getItemAt(checkDups)).getSQL();
 3065  
         // } else {
 3066  
         // foundString = ((String)combo.getItemAt(checkDups));
 3067  
         // }
 3068  
 
 3069  
         // if (foundString.startsWith(COMMENT_PREFIX)) {
 3070  
         // foundString = foundString.substring(2);
 3071  
         // foundCommented = true;
 3072  
         // } else {
 3073  
         // foundCommented = false;
 3074  
         // }
 3075  
 
 3076  
         // if (newString.equals(foundString)) {
 3077  0
         if (newValue.equals(combo.getItemAt(checkDups))) {
 3078  0
           match = true;
 3079  0
           if (combo == querySelection) {
 3080  0
             ((Query) combo.getItemAt(checkDups)).setMode(whichModeValue());
 3081  
           }
 3082  0
           combo.setSelectedIndex(checkDups);
 3083  0
           matchAt = checkDups;
 3084  
         }
 3085  
       }
 3086  
 
 3087  
       // if (newCommented) {
 3088  
       // newString = COMMENT_PREFIX + newString;
 3089  
       // }
 3090  
 
 3091  0
       if (!match) {
 3092  0
         addToCombo(combo, newValue);
 3093  0
         if (combo == querySelection) {
 3094  
           // addToCombo(combo, new Query(newString, whichModeValue()));
 3095  0
           combo.setSelectedIndex(combo.getModel().getSize() - 1);
 3096  0
           matchAt = combo.getSelectedIndex();
 3097  
         }
 3098  
       }
 3099  
       // if (foundCommented != newCommented) {
 3100  
       // if (combo == querySelection) {
 3101  
       // replaceInCombo(combo, matchAt,
 3102  
       // new Query(newString, whichModeValue()));
 3103  
       // } else {
 3104  
       // replaceInCombo(combo, matchAt, newString);
 3105  
       // }
 3106  
       // }
 3107  0
       if (combo == querySelection) {
 3108  0
         if (((Query) newValue).isCommented() != ((Query) combo
 3109  
             .getSelectedItem()).isCommented()) {
 3110  0
           replaceInCombo(combo, matchAt, newValue);
 3111  
         }
 3112  
       }
 3113  
     }
 3114  0
   }
 3115  
 
 3116  
   /**
 3117  
    * Finds the Mode Value depending on the query option selected
 3118  
    * 
 3119  
    * @return int The integer values for the different modes
 3120  
    */
 3121  
   private int whichModeValue() {
 3122  
     int mode;
 3123  
 
 3124  0
     if (asQuery.isSelected()) {
 3125  0
       mode = Query.MODE_QUERY;
 3126  0
     } else if (asUpdate.isSelected()) {
 3127  0
       mode = Query.MODE_UPDATE;
 3128  
     } else {
 3129  0
       mode = Query.MODE_DESCRIBE;
 3130  
     }
 3131  
 
 3132  0
     return mode;
 3133  
   }
 3134  
 
 3135  
   /**
 3136  
    * Selects the Query action that is specified by the mode
 3137  
    * 
 3138  
    * @param mode
 3139  
    *          The integer value for the mode that is selected
 3140  
    */
 3141  
   private void selectMode(int mode) {
 3142  0
     if (mode == Query.MODE_QUERY) {
 3143  0
       asQuery.setSelected(true);
 3144  0
     } else if (mode == Query.MODE_UPDATE) {
 3145  0
       asUpdate.setSelected(true);
 3146  
     } else {
 3147  0
       asDescribe.setSelected(true);
 3148  
     }
 3149  0
   }
 3150  
 
 3151  
   /**
 3152  
    * Assumes that selected item in the combo box is a string and returns
 3153  
    * the query object.Otherwise it converts the string to a query object
 3154  
    * and returns it.
 3155  
    * 
 3156  
    * @return Query The Query Object
 3157  
    */
 3158  
   private Query getQuery() {
 3159  0
     LOGGER.debug("getSelectItem[" + querySelection.getSelectedItem() + "]");
 3160  
 
 3161  0
     if (querySelection.getSelectedItem() == null) {
 3162  0
       return null;
 3163  0
     } else if (querySelection.getSelectedItem() instanceof Query) {
 3164  0
       return (Query) querySelection.getSelectedItem();
 3165  
     } else {
 3166  0
       return new Query((String) querySelection.getSelectedItem(),
 3167  
           whichModeValue());
 3168  
     }
 3169  
   }
 3170  
 
 3171  
   /**
 3172  
    * Adds a new object in the combo box
 3173  
    * 
 3174  
    * @param combo
 3175  
    *          The JComboBox
 3176  
    * @param newData
 3177  
    *          The Object that is to be added
 3178  
    */
 3179  
   private void addToCombo(JComboBox combo, Object newData) {
 3180  0
     ((DefaultComboBoxModel) combo.getModel()).addElement(newData);
 3181  0
   }
 3182  
 
 3183  
   /**
 3184  
    * Replaces an existing object with a new one
 3185  
    * 
 3186  
    * @param combo
 3187  
    *          The JComboBox
 3188  
    * @param position
 3189  
    *          The int value of the positon where the
 3190  
    *          repalcement occurs
 3191  
    * @param newData
 3192  
    *          The new Object that is to be inserted in the combobox
 3193  
    */
 3194  
   private void replaceInCombo(JComboBox combo, int position, Object newData) {
 3195  0
     ((DefaultComboBoxModel) combo.getModel()).removeElementAt(position);
 3196  0
     ((DefaultComboBoxModel) combo.getModel()).insertElementAt(newData,
 3197  
         position);
 3198  0
     combo.setSelectedIndex(position);
 3199  0
   }
 3200  
 
 3201  
   /**
 3202  
    * Run the current SQL statement independently
 3203  
    */
 3204  
   private void processStatement() {
 3205  0
     processStatement(false);
 3206  0
   }
 3207  
 
 3208  
   /**
 3209  
    * Run the current SQL statement either independently or as part of a batch of
 3210  
    * statements
 3211  
    * 
 3212  
    * @param batch
 3213  
    *          Whether the statement is run as part of a batch
 3214  
    */
 3215  
   private void processStatement(boolean batch) {
 3216  
     String rawStatement;
 3217  
 
 3218  0
     rawStatement = getQuery().getRawSql();
 3219  
 
 3220  0
     if (rawStatement != null) {
 3221  0
       rawStatement = rawStatement.trim();
 3222  
 
 3223  0
       if (fileSaveAsCSV.isEnabled() && rawStatement.startsWith(">")
 3224  
           && rawStatement.length() > 1) {
 3225  0
         saveResultAsCSV(table.getModel(), new File(rawStatement.substring(1)));
 3226  
       } else {
 3227  0
         displayResultsAsTable(batch);
 3228  
       }
 3229  
     } else {
 3230  0
       displayResultsAsTable(batch);
 3231  
     }
 3232  0
   }
 3233  
 
 3234  
   /**
 3235  
    * Displays the query results in the JTable.
 3236  
    * 
 3237  
    * @param batch
 3238  
    *          If true, prevents error pop-up dialog boxes from being created
 3239  
    */
 3240  
   private void displayResultsAsTable(boolean batch) {
 3241  
     TableSorter sorter;
 3242  
     ListTableModel<Object> model;
 3243  
     String rawSQL, sqlStatement;
 3244  
     String[] eachQuery;
 3245  
     int queryIndex;
 3246  
 
 3247  
     // Clear the Message Area
 3248  0
     message.setText("");
 3249  
 
 3250  
     // Parse the SQL for semicolons (separates multiple statements)
 3251  0
     rawSQL = getQuery().getRawSql();
 3252  
 
 3253  0
     if (configParseSemicolons.isSelected()) {
 3254  0
       eachQuery = Utility.splitWithQuotes(rawSQL, ";");
 3255  0
       LOGGER.info("Queries embedded in this string: " + eachQuery.length);
 3256  0
       if (LOGGER.isDebugEnabled()) {
 3257  0
         for (int i = 0; i < eachQuery.length; ++i) {
 3258  0
           LOGGER.debug("Embedded Query " + i + ": " + eachQuery[i]);
 3259  
         }
 3260  
       }
 3261  
     } else {
 3262  0
       eachQuery = new String[1];
 3263  0
       eachQuery[0] = rawSQL;
 3264  
     }
 3265  
 
 3266  
     // Execute each query embedded in the input string
 3267  0
     for (queryIndex = 0; queryIndex < eachQuery.length; ++queryIndex) {
 3268  0
       LOGGER.debug("Embedded query index=" + queryIndex);
 3269  
 
 3270  0
       sqlStatement = eachQuery[queryIndex];
 3271  
 
 3272  0
       LOGGER.info("Query to execute: " + sqlStatement);
 3273  
 
 3274  
       // For multiple statements executed at once, separate messages
 3275  0
       if (queryIndex > 0) {
 3276  0
         messageOut("\n------------------------------------------------");
 3277  
       }
 3278  
 
 3279  
       // If old sorter exists, remove its mouse listener(s) from table and
 3280  
       // temporarily point table to empty model while real model is updated
 3281  
       try {
 3282  0
         sorter = (TableSorter) table.getModel();
 3283  0
         sorter.removeMouseListenerFromHeaderInTable(table);
 3284  0
       } catch (Throwable any) {
 3285  
         // Probably table was empty
 3286  0
         if (LOGGER.isDebugEnabled()) {
 3287  0
           LOGGER.debug("Error when sorting results table", any);
 3288  
         }
 3289  0
       }
 3290  
 
 3291  0
       table.setModel(new ListTableModel<Object>());
 3292  
 
 3293  0
       getQuery().setMode(whichModeValue());
 3294  
 
 3295  
       /*
 3296  
        * Initializes the table model - either creates it, or, clears-out the
 3297  
        * existing one.
 3298  
        */
 3299  0
       model = new ListTableModel<Object>();
 3300  0
       sorter = new TableSorter(model);
 3301  
 
 3302  0
       if (!commentedQuery()) { // if query is not commented-out
 3303  0
         execute(sqlStatement, model, null);
 3304  0
         if (!Thread.currentThread().isInterrupted()) {
 3305  0
           table.setModel(sorter);
 3306  0
           sorter.addMouseListenerToHeaderInTable(table);
 3307  
         }
 3308  0
       } else if (!batch) {
 3309  0
         userMessage(
 3310  
             Resources.getString("msgSQLCommentedText"),
 3311  
             Resources.getString("msgSQLCommentedTitle"),
 3312  
             JOptionPane.WARNING_MESSAGE);
 3313  
         // Skip all remaining statements (comments apply to the entire string)
 3314  0
         queryIndex = eachQuery.length;
 3315  
       }
 3316  
 
 3317  0
       Utility.initColumnSizes(table, model);
 3318  0
       histMaintQueryExecuted(model);
 3319  
     }
 3320  0
   }
 3321  
 
 3322  
   /**
 3323  
    * Displays a popup message dialog. If the message is likely to be a long
 3324  
    * string without line breaks, the reformatMessage parameter can be set
 3325  
    * true and line breaks will be added to allow the message to fit neatly
 3326  
    * on the screen.
 3327  
    * 
 3328  
    * @param pMessage
 3329  
    *          The message to be displayed to the user.
 3330  
    * @param title
 3331  
    *          The title of the message dialog
 3332  
    * @param messageType
 3333  
    *          The message type as defined in JOptionPane
 3334  
    * @param reformatMessage
 3335  
    *          Whether to insert line breaks within the message
 3336  
    */
 3337  
   private void userMessage(String pMessage, String title, int messageType,
 3338  
       boolean reformatMessage) {
 3339  0
     if (reformatMessage) {
 3340  0
       JOptionPane.showMessageDialog(this,
 3341  
           Utility.characterInsert(pMessage, "\n",
 3342  
               TEXT_WRAP_MIN_LINE_LENGTH_BEFORE_WRAP, TEXT_WRAP_MAX_LINE_LENGTH,
 3343  
               " .,"), title, messageType);
 3344  
     } else {
 3345  0
       JOptionPane.showMessageDialog(this, pMessage, title, messageType);
 3346  
     }
 3347  0
   }
 3348  
 
 3349  
   /**
 3350  
    * Displays a popup message dialog.
 3351  
    * 
 3352  
    * @param pMessage
 3353  
    *          The message to be displayed to the user.
 3354  
    * @param title
 3355  
    *          The title of the message dialog
 3356  
    * @param messageType
 3357  
    *          The message type as defined in JOptionPane
 3358  
    */
 3359  
   private void userMessage(String pMessage, String title, int messageType) {
 3360  0
     userMessage(pMessage, title, messageType, true);
 3361  0
   }
 3362  
 
 3363  
   /**
 3364  
    * Looks for queries that have been commented out
 3365  
    * 
 3366  
    * @return boolean Returns true if there are any commented queries
 3367  
    */
 3368  
   private boolean commentedQuery() {
 3369  0
     if (getQuery() != null && getQuery().getSql() != null) {
 3370  0
       return getQuery().getSql().startsWith(COMMENT_PREFIX);
 3371  
     } else {
 3372  0
       return false;
 3373  
     }
 3374  
   }
 3375  
 
 3376  
   /**
 3377  
    * Test that SQL agrees with query type selected, otherwise warn user.
 3378  
    * 
 3379  
    * TODO This needs a lot of work dealing with the parsing of the SQL since
 3380  
    * it could have $PARAM[...]$ type syntax at the beginning and the
 3381  
    * simple
 3382  
    * grabbing of the first set of characters is not useful.
 3383  
    * 
 3384  
    * @param saQuery
 3385  
    *          The SQL being executed
 3386  
    * @return True is the query type and the SQL are compatible or if the user
 3387  
    *         agrees to force the query type.
 3388  
    */
 3389  
   private boolean isOkayQueryType(String saQuery) {
 3390  
     boolean blOkay;
 3391  
     String slFirstWord;
 3392  
     String slQueryType;
 3393  
 
 3394  0
     blOkay = true;
 3395  
     // slQueryType = "Undefined";
 3396  0
     slQueryType = Resources.getString("proUnknown");
 3397  
 
 3398  0
     if (asQuery.isSelected()) {
 3399  
       // slQueryType = "Select";
 3400  0
       slQueryType = Resources.getString("ctlSelect");
 3401  0
     } else if (asDescribe.isSelected()) {
 3402  
       // slQueryType = "Describe Result (Select)";
 3403  0
       slQueryType = Resources.getString("ctlDescribe");
 3404  0
     } else if (asUpdate.isSelected()) {
 3405  
       // slQueryType = "Update";
 3406  0
       slQueryType = Resources.getString("ctlUpdate");
 3407  
     }
 3408  
 
 3409  0
     if (saQuery != null && saQuery.trim().length() > 0) {
 3410  0
       slFirstWord = saQuery.split(" ", 2)[0].toUpperCase();
 3411  
     } else {
 3412  0
       slFirstWord = null;
 3413  
     }
 3414  
 
 3415  0
     if (slFirstWord != null) {
 3416  
       // Test is a little weird, don't want to object if we don't recognize the
 3417  
       // beginning of the SQL. For instance, EXEC and CALL are used for stored
 3418  
       // proc
 3419  
       // execution, but they may return a resultset or not, can't warn user in
 3420  
       // that case. So just test for likely mistakes.
 3421  0
       if (asQuery.isSelected() || asDescribe.isSelected()) {
 3422  0
         blOkay = scWarnSelectPatterns.indexOf(slFirstWord) == -1;
 3423  
       } else {
 3424  0
         blOkay = scWarnUpdatePatterns.indexOf(slFirstWord) == -1;
 3425  
       }
 3426  
     }
 3427  
 
 3428  0
     if (!blOkay) {
 3429  0
       messageOut(Resources.getString("msgQueryTypeSuspicious", slQueryType,
 3430  
           slFirstWord), STYLE_RED);
 3431  0
       blOkay = JOptionPane.showConfirmDialog(this,
 3432  
           Utility.characterInsert(
 3433  
               Resources.getString("msgQueryTypeSuspiciousText", slQueryType,
 3434  
                   slFirstWord),
 3435  
               "\n", TEXT_WRAP_MIN_LINE_LENGTH_BEFORE_WRAP,
 3436  
               TEXT_WRAP_MAX_LINE_LENGTH, " "),
 3437  
           Resources.getString("msgQueryTypeSuspiciousTitle"),
 3438  
           JOptionPane.YES_NO_OPTION,
 3439  
           JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION;
 3440  0
       if (blOkay) {
 3441  0
         messageOut(
 3442  
             Resources.getString("msgUserForcingQuery"),
 3443  
             STYLE_RED);
 3444  
       } else {
 3445  0
         messageOut(Resources.getString("msgQueryCanceled"), STYLE_BOLD);
 3446  
       }
 3447  
     }
 3448  
 
 3449  0
     return blOkay;
 3450  
   }
 3451  
 
 3452  
   /**
 3453  
    * Populates model with the query results. The query executed is the
 3454  
    * currently selected query in the combo-box.
 3455  
    * 
 3456  
    * @param rawSqlStatement
 3457  
    *          The SQL statement to execute
 3458  
    * @param model
 3459  
    *          The model to populate with the results
 3460  
    * @param tripleFile
 3461  
    *          The location to write the results to as triples.
 3462  
    */
 3463  
   private void execute(String rawSqlStatement, ListTableModel<Object> model,
 3464  
       File tripleFile) {
 3465  0
     String sqlStatement = rawSqlStatement;
 3466  0
     Statement stmt = null;
 3467  0
     ResultSet result = null;
 3468  0
     ResultSetMetaData meta = null;
 3469  0
     List<Object> rowData = null;
 3470  0
     int retValue = 0;
 3471  0
     SQLWarning warning = null;
 3472  
     int[] myType;
 3473  
     Object value;
 3474  
     String typeName;
 3475  
     String colName;
 3476  
     String metaName;
 3477  0
     boolean hasResults = false;
 3478  0
     boolean hasBLOB = false;
 3479  0
     Date connAsk = null;
 3480  0
     Date connGot = null;
 3481  0
     Date stmtGot = null;
 3482  0
     Date queryStart = null;
 3483  0
     Date queryReady = null;
 3484  0
     Date queryRSFetched = null;
 3485  0
     Date queryRSProcessed = null;
 3486  0
     long rows = 0;
 3487  0
     int cols = 0;
 3488  0
     boolean hasParams = false;
 3489  0
     final List<StatementParameter> allParams = new ArrayList<StatementParameter>();
 3490  0
     List<Object> outParams = null;
 3491  
 
 3492  0
     modeOfCurrentTable = whichModeValue();
 3493  0
     mapOfCurrentTables = new HashMap<String, String>();
 3494  
 
 3495  
     // Try to prevent incorrect selection of query type by checking
 3496  
     // beginning of SQL statement for obvious stuff
 3497  
     // First check "Select" and Describe query types
 3498  0
     if (!isOkayQueryType(getQuery().getSql())) {
 3499  
       // If the query type is wrong, and the user doesn't override then
 3500  
       // Get Out Of Here!
 3501  0
       return;
 3502  
     }
 3503  
 
 3504  
     // If there were BLOB columns included in the last query the connection
 3505  
     // will have been left open. Since we are executing a new query we
 3506  
     // can close that old connection now.
 3507  0
     if (conn != null) {
 3508  
       try {
 3509  0
         conn.close();
 3510  0
       } catch (Throwable any) {
 3511  0
         if (LOGGER.isDebugEnabled()) {
 3512  0
           LOGGER.debug("Error (expected) closing connection", any);
 3513  
         }
 3514  0
       }
 3515  
     }
 3516  
 
 3517  0
     conn = null;
 3518  
 
 3519  
     try {
 3520  0
       messageOut(Resources.getString(
 3521  
           "msgExecuteQuery",
 3522  
           asQuery.isSelected() ? Resources.getString("msgQuery")
 3523  
               : asDescribe.isSelected()
 3524  
                   ? Resources.getString("msgDescribe") : Resources
 3525  
                       .getString("msgUpdate"),
 3526  
           sqlStatement), STYLE_BOLD);
 3527  0
       if (poolConnect.isSelected()) {
 3528  0
         messageOut(Resources.getString("msgPoolStats") + " ", STYLE_SUBTLE,
 3529  
             false);
 3530  0
         if (getDBPool() != null) {
 3531  0
           messageOut(Resources.getString("msgPoolStatsCount",
 3532  
               getDBPool().getNumActive() + "", getDBPool().getNumIdle() + ""));
 3533  0
           LOGGER.debug("Retrieved existing DB connection pool");
 3534  
         } else {
 3535  0
           LOGGER.debug("No existing DB pool");
 3536  0
           messageOut(Resources.getString("msgPoolNone"));
 3537  
         }
 3538  
       }
 3539  0
       if (getDBPool() == null || /* conn == null */
 3540  
       !((String) connectString.getEditor().getItem()).equals(
 3541  
           lastConnection) || !userId.getText().equals(lastUserId)
 3542  
           || !new String(password.getPassword()).equals(lastPassword)) {
 3543  
 
 3544  0
         removeDBPool();
 3545  
 
 3546  0
         lastConnection = (String) connectString.getEditor().getItem();
 3547  0
         lastUserId = userId.getText();
 3548  0
         lastPassword = new String(password.getPassword());
 3549  
 
 3550  0
         if (poolConnect.isSelected()) {
 3551  0
           setupDBPool(lastConnection, lastUserId, lastPassword);
 3552  
         }
 3553  
 
 3554  0
         messageOut(Resources.getString("msgConnCreated", lastConnection,
 3555  
             lastUserId), STYLE_SUBTLE);
 3556  
       }
 3557  0
       connAsk = new java.util.Date();
 3558  0
       if (poolConnect.isSelected()) {
 3559  0
         conn = DriverManager.getConnection("jdbc:apache:commons:dbcp:"
 3560  
             + DBPOOL_NAME);
 3561  0
         LOGGER.debug("Got pooled connection");
 3562  0
         messageOut(Resources.getString("msgGotPoolConn"), STYLE_GREEN);
 3563  
       } else {
 3564  0
         conn = DriverManager.getConnection(lastConnection, lastUserId,
 3565  
             lastPassword);
 3566  0
         LOGGER.debug("Got non-pooled connection");
 3567  0
         messageOut(Resources.getString("msgGotDirectConn"), STYLE_GREEN);
 3568  
       }
 3569  
 
 3570  0
       if (hasParams = sqlStatement.indexOf("$PARAM[") > -1) {
 3571  0
         sqlStatement = makeParams(sqlStatement, allParams);
 3572  
       }
 3573  
 
 3574  0
       connGot = new java.util.Date();
 3575  
 
 3576  0
       conn.setAutoCommit(autoCommit.isSelected());
 3577  0
       conn.setReadOnly(readOnly.isSelected());
 3578  
 
 3579  0
       if (!hasParams) {
 3580  0
         stmt = conn.createStatement();
 3581  
       } else {
 3582  0
         stmt = conn.prepareCall(sqlStatement);
 3583  0
         setupCall((CallableStatement) stmt, allParams);
 3584  
       }
 3585  
 
 3586  0
       stmtGot = new java.util.Date();
 3587  
 
 3588  
       try {
 3589  0
         if (!maxRows.getSelectedItem()
 3590  
             .equals(Resources.getString("proNoLimit"))) {
 3591  0
           stmt.setMaxRows(Integer.parseInt((String) maxRows.getSelectedItem()));
 3592  0
           messageOut("\n" + Resources.getString("msgMaxRows",
 3593  
               stmt.getMaxRows() + ""), STYLE_SUBTLE);
 3594  
         }
 3595  0
       } catch (Exception any) {
 3596  0
         LOGGER.warn("Unable to set maximum rows", any);
 3597  0
         messageOut(Resources.getString("errFailSetMaxRows",
 3598  
             (String) maxRows.getSelectedItem(), any.getMessage()), STYLE_YELLOW);
 3599  0
       }
 3600  
 
 3601  0
       if (asQuery.isSelected() || asDescribe.isSelected()) {
 3602  0
         queryStart = new java.util.Date();
 3603  0
         if (!hasParams) {
 3604  
           int updateCount;
 3605  
 
 3606  
           // Execute the query synchronously
 3607  0
           stmt.execute(sqlStatement);
 3608  0
           messageOut(Resources.getString("msgQueryExecutedByDB"), STYLE_GREEN);
 3609  
 
 3610  
           // Process the query results and/or report status
 3611  0
           if ((updateCount = stmt.getUpdateCount()) > -1) {
 3612  
             do {
 3613  0
               LOGGER.debug("Looking for results [update="
 3614  
                   + updateCount + "]");
 3615  0
               stmt.getMoreResults();
 3616  0
             } while ((updateCount = stmt.getUpdateCount()) > -1);
 3617  
           }
 3618  0
           result = stmt.getResultSet();
 3619  0
         } else {
 3620  0
           result = ((PreparedStatement) stmt).executeQuery();
 3621  
         }
 3622  0
         queryReady = new java.util.Date();
 3623  0
         meta = result.getMetaData();
 3624  0
         cols = meta.getColumnCount();
 3625  
       } else {
 3626  0
         queryStart = new java.util.Date();
 3627  0
         if (!hasParams) {
 3628  0
           retValue = stmt.executeUpdate(sqlStatement);
 3629  
         } else {
 3630  0
           retValue = ((PreparedStatement) stmt).executeUpdate();
 3631  
         }
 3632  0
         queryReady = new java.util.Date();
 3633  
       }
 3634  
 
 3635  0
       if (asQuery.isSelected()) {
 3636  0
         for (int col = 0; col < cols; ++col) {
 3637  0
           colName = meta.getColumnName(col + 1);
 3638  0
           if (colName == null || colName.trim().length() == 0) {
 3639  0
             colName = Resources.getString("msgUnnamedColumn",
 3640  
                 meta.getColumnLabel(col + 1));
 3641  
           }
 3642  
 
 3643  0
           if (configDisplayColumnDataType.isSelected()) {
 3644  0
             metaName = meta.getColumnTypeName(col + 1) + " "
 3645  
                 + meta.getColumnDisplaySize(col + 1) + " (";
 3646  
 
 3647  
             // have had oracle tables report large precision values
 3648  
             // for BLOB fields that caused exception to be thrown
 3649  
             // by getPrecision() since the value was beyond int
 3650  
             try {
 3651  0
               metaName += meta.getPrecision(col + 1);
 3652  0
             } catch (Exception any) {
 3653  0
               metaName += "?";
 3654  0
               LOGGER.warn("Unable to get column precision", any);
 3655  0
             }
 3656  0
             metaName += ".";
 3657  0
             metaName += meta.getScale(col + 1);
 3658  0
             metaName += ")";
 3659  
 
 3660  0
             colName += " [" + metaName + "]";
 3661  
           }
 3662  
 
 3663  0
           model.addColumn(colName);
 3664  
           // Keep collection of tables used for Insert and Update Menu
 3665  
           // Selections
 3666  
           try {
 3667  0
             mapOfCurrentTables.put(meta.getTableName(col + 1), null);
 3668  0
           } catch (Exception any) {
 3669  
             // Probably unimplemented method - Sybase driver
 3670  0
             LOGGER.warn("Failed to obtain table name from metadata", any);
 3671  0
             messageOut(Resources.getString("errFailReqTableName",
 3672  
                 any.getMessage()), STYLE_SUBTLE);
 3673  0
           }
 3674  
         }
 3675  
 
 3676  0
         rowData = new ArrayList<Object>();
 3677  
 
 3678  0
         myType = new int[cols];
 3679  
 
 3680  0
         for (int col = 0; col < cols; ++col) {
 3681  0
           typeName = meta.getColumnTypeName(col + 1).toUpperCase();
 3682  0
           if (typeName.equals("NUMBER")) {
 3683  0
             if (meta.getScale(col + 1) > 0) {
 3684  0
               myType[col] = COLUMN_DATA_TYPE_DOUBLE; // DOUBLE
 3685  0
             } else if (meta.getPrecision(col + 1) <= MAX_DIGITS_FOR_INT) {
 3686  0
               myType[col] = COLUMN_DATA_TYPE_INT; // INTEGER
 3687  
             } else {
 3688  0
               myType[col] = COLUMN_DATA_TYPE_LONG; // LONG
 3689  
             }
 3690  0
           } else if (typeName.equals("LONG")) {
 3691  0
             myType[col] = COLUMN_DATA_TYPE_LONG;
 3692  0
           } else if (typeName.equals("DATETIME")) {
 3693  0
             myType[col] = COLUMN_DATA_TYPE_DATETIME; // Date/Time
 3694  0
           } else if (typeName.equals("DATE")) {
 3695  0
             myType[col] = COLUMN_DATA_TYPE_DATE; // Date/Time
 3696  0
           } else if (typeName.equals("BLOB")) {
 3697  0
             myType[col] = COLUMN_DATA_TYPE_BLOB;
 3698  0
             hasBLOB = true;
 3699  
           } else {
 3700  0
             myType[col] = 0; // Default - String
 3701  
           }
 3702  
         }
 3703  
 
 3704  0
         if (tripleFile != null) {
 3705  
           try {
 3706  0
             final RdbToRdf exporter = new RdbToRdf(
 3707  
                 tripleFile.getAbsolutePath(), getQuery().getSql(), result);
 3708  0
             exporter.run();
 3709  0
             rows = exporter.getLatestNumberOfRowsExported();
 3710  0
             messageOut("");
 3711  0
             messageOut(Resources.getString("msgEndExportToFile"), STYLE_BOLD);
 3712  0
           } catch (Throwable throwable) {
 3713  0
             messageOut(
 3714  
                 Resources.getString("errFailDataSave", throwable.toString()),
 3715  
                 STYLE_RED);
 3716  0
             LOGGER.error(
 3717  
                 "Failed to save data to triples file: "
 3718  
                     + tripleFile.getAbsolutePath(), throwable);
 3719  0
           }
 3720  0
         } else if (fileLogResults.isSelected()) {
 3721  0
           writeDataAsCSV(sqlStatement, model, DBRESULTS_NAME, result, myType,
 3722  
               false);
 3723  
         } else {
 3724  0
           while (result.next()) {
 3725  0
             ++rows;
 3726  0
             rowData = new ArrayList<Object>();
 3727  
 
 3728  0
             for (int col = 0; col < cols; ++col) {
 3729  0
               value = getResultField(result, col + 1, myType[col]);
 3730  0
               rowData.add(value);
 3731  
             }
 3732  
 
 3733  0
             model.addRowFast(rowData);
 3734  0
             hasResults = true;
 3735  
           }
 3736  0
           model.updateCompleted();
 3737  
         }
 3738  
 
 3739  0
         queryRSProcessed = new java.util.Date();
 3740  0
       } else if (asDescribe.isSelected()) {
 3741  
         String colLabel;
 3742  
 
 3743  0
         meta = result.getMetaData();
 3744  
 
 3745  0
         myType = new int[DESC_TABLE_COLUMN_COUNT];
 3746  
 
 3747  0
         for (int col = 0; col < DESC_TABLE_COLUMN_COUNT; ++col) {
 3748  0
           switch (col) {
 3749  
             case DESC_TABLE_NAME_COLUMN: // Col Name
 3750  0
               colLabel = Resources.getString("proColumnName");
 3751  0
               myType[col] = COLUMN_DATA_TYPE_STRING;
 3752  0
               break;
 3753  
             case DESC_TABLE_TYPE_COLUMN: // Col Type
 3754  0
               colLabel = Resources.getString("proColumnType");
 3755  0
               myType[col] = COLUMN_DATA_TYPE_STRING;
 3756  0
               break;
 3757  
             case DESC_TABLE_LENGTH_COLUMN: // Col Length
 3758  0
               colLabel = Resources.getString("proColumnLength");
 3759  0
               myType[col] = COLUMN_DATA_TYPE_INT;
 3760  0
               break;
 3761  
             case DESC_TABLE_PRECISION_COLUMN: // Col precision
 3762  0
               colLabel = Resources.getString("proColPrecision");
 3763  0
               myType[col] = COLUMN_DATA_TYPE_INT;
 3764  0
               break;
 3765  
             case DESC_TABLE_SCALE_COLUMN: // Col scale
 3766  0
               colLabel = Resources.getString("proColScale");
 3767  0
               myType[col] = COLUMN_DATA_TYPE_INT;
 3768  0
               break;
 3769  
             case DESC_TABLE_NULLS_OK_COLUMN: // Nulls Okay?
 3770  0
               colLabel = Resources.getString("proColNullsAllowed");
 3771  0
               myType[col] = COLUMN_DATA_TYPE_STRING;
 3772  0
               break;
 3773  
             default: // oops
 3774  0
               colLabel = Resources.getString("proColUndefined");
 3775  
               break;
 3776  
           }
 3777  
 
 3778  0
           if (configDisplayColumnDataType.isSelected()) {
 3779  0
             colLabel += " [";
 3780  0
             colLabel += myType[col] == 0 ? Resources
 3781  
                 .getString("proColCharType") : Resources
 3782  
                 .getString("proColNumeric");
 3783  0
             colLabel += "]";
 3784  
           }
 3785  
 
 3786  0
           model.addColumn(colLabel);
 3787  
         }
 3788  
 
 3789  0
         rowData = new ArrayList<Object>();
 3790  
 
 3791  0
         for (int col = 0; col < cols; ++col) {
 3792  0
           rowData = new ArrayList<Object>();
 3793  
 
 3794  0
           for (int row = 0; row < DESC_TABLE_COLUMN_COUNT; ++row) {
 3795  0
             switch (row) {
 3796  
               case DESC_TABLE_NAME_COLUMN: // Name
 3797  0
                 colName = meta.getColumnName(col + 1);
 3798  0
                 if (colName == null || colName.trim().length() == 0) {
 3799  0
                   colName = Resources.getString("msgUnnamedColumn",
 3800  
                       meta.getColumnLabel(col + 1));
 3801  
                 }
 3802  0
                 value = colName;
 3803  0
                 break;
 3804  
               case DESC_TABLE_TYPE_COLUMN: // Type
 3805  0
                 value = meta.getColumnTypeName(col + 1) + " (" + meta.getColumnType(col + 1) + ")";
 3806  0
                 break;
 3807  
               case DESC_TABLE_LENGTH_COLUMN: // Length
 3808  0
                 value = new Integer(meta.getColumnDisplaySize(col + 1));
 3809  0
                 break;
 3810  
               case DESC_TABLE_PRECISION_COLUMN: // Precision
 3811  
                 try {
 3812  0
                   value = new Integer(meta.getPrecision(col + 1));
 3813  0
                 } catch (Exception any) {
 3814  0
                   value = "?";
 3815  0
                   LOGGER.warn("Unable to obtain column precision", any);
 3816  0
                 }
 3817  0
                 break;
 3818  
               case DESC_TABLE_SCALE_COLUMN: // Scale
 3819  0
                 value = new Integer(meta.getScale(col + 1));
 3820  0
                 break;
 3821  
               case DESC_TABLE_NULLS_OK_COLUMN: // Nulls Okay?
 3822  0
                 value = meta.isNullable(col + 1) == ResultSetMetaData.columnNullable ? Resources
 3823  
                     .getString("proYes")
 3824  
                     : meta.isNullable(col + 1) == ResultSetMetaData.columnNoNulls ? Resources
 3825  
                         .getString("proNo")
 3826  
                         : Resources.getString("proUnknown");
 3827  0
                 break;
 3828  
               default:
 3829  0
                 value = null;
 3830  
                 break;
 3831  
             }
 3832  
 
 3833  0
             rowData.add(value);
 3834  
 
 3835  
             // Keep collection of tables used for Insert and Update Menu
 3836  
             // Selections
 3837  
             try {
 3838  0
               mapOfCurrentTables.put(meta.getTableName(col + 1), null);
 3839  0
             } catch (Exception any) {
 3840  
               // Probably unimplemented method - Sybase driver
 3841  0
               LOGGER.warn("Failed to obtain table name from metadata", any);
 3842  0
               messageOut(Resources.getString("errFailReqTableName",
 3843  
                   any.getMessage()), STYLE_SUBTLE);
 3844  0
             }
 3845  
           }
 3846  0
           model.addRow(rowData);
 3847  
         }
 3848  
 
 3849  0
         while (result.next()) {
 3850  0
           rows++;
 3851  0
           for (int col = 0; col < cols; ++col) {
 3852  0
             result.getObject(col + 1);
 3853  
           }
 3854  
         }
 3855  
 
 3856  0
         queryRSFetched = new java.util.Date();
 3857  
 
 3858  
       } else {
 3859  0
         messageOut("\n" + Resources.getString("msgReturnValue") + " "
 3860  
             + retValue, STYLE_BOLD, false);
 3861  0
         rows = stmt.getUpdateCount();
 3862  
       }
 3863  
 
 3864  0
       messageOut("\n" + Resources.getString("msgRows") + " ", STYLE_NORMAL,
 3865  
           false);
 3866  0
       if (rows == stmt.getMaxRows() && rows > 0) {
 3867  0
         messageOut("" + rows, STYLE_YELLOW);
 3868  
       } else {
 3869  0
         messageOut("" + rows, STYLE_BOLD);
 3870  
       }
 3871  0
       messageOut("");
 3872  0
     } catch (SQLException sql) {
 3873  0
       LOGGER.error("Error executing SQL", sql);
 3874  0
       messageOut(Resources.getString("errFailSQL", sql.getClass().getName(),
 3875  
           sql.getMessage()), STYLE_RED);
 3876  0
       userMessage(Resources.getString("errFailSQLText", sql.getMessage()),
 3877  
           Resources.getString("errFailSQLTitle"), JOptionPane.ERROR_MESSAGE);
 3878  0
       while ((sql = sql.getNextException()) != null) {
 3879  0
         LOGGER.error("Next Exception", sql);
 3880  
       }
 3881  0
       modeOfCurrentTable = -1;
 3882  0
     } catch (Throwable any) {
 3883  0
       LOGGER.error("Error executing SQL", any);
 3884  0
       messageOut(Resources.getString("errFailSQL", any.getClass().getName(),
 3885  
           any.getMessage()), STYLE_RED);
 3886  0
       userMessage(Resources.getString("errFailSQLText", any.getMessage()),
 3887  
           Resources.getString("errFailSQLTitle"), JOptionPane.ERROR_MESSAGE);
 3888  0
       modeOfCurrentTable = -1;
 3889  
     } finally {
 3890  0
       fileSaveBLOBs.setEnabled(hasBLOB);
 3891  0
       setExportAvailable((hasResults && model.getRowCount() > 0)
 3892  
           || tripleFile != null);
 3893  0
       queryMakeInsert.setEnabled(modeOfCurrentTable == Query.MODE_DESCRIBE
 3894  
           || modeOfCurrentTable == Query.MODE_QUERY);
 3895  
 
 3896  0
       if (hasParams) {
 3897  0
         outParams = getOutParams((CallableStatement) stmt, allParams);
 3898  
       }
 3899  
 
 3900  0
       LOGGER.debug("Check for more results");
 3901  
 
 3902  
       try {
 3903  0
         int resultCount = 0;
 3904  0
         while (stmt.getMoreResults()) {
 3905  
           int updateCount;
 3906  0
           ++resultCount;
 3907  0
           updateCount = stmt.getUpdateCount();
 3908  0
           LOGGER.debug("More results ["
 3909  
               + resultCount + "][updateCount="
 3910  
               + updateCount + "]");
 3911  0
         }
 3912  0
       } catch (SQLException sql) {
 3913  0
         LOGGER.error("Failed checking for more results", sql);
 3914  0
         messageOut(Resources.getString("errFailAddlResults",
 3915  
             sql.getClass().getName(), sql.getMessage()));
 3916  0
       }
 3917  
 
 3918  0
       LOGGER.debug("No more results");
 3919  
 
 3920  0
       if (result != null) {
 3921  
         try {
 3922  0
           result.close();
 3923  0
           LOGGER.info("Resultset closed");
 3924  0
         } catch (Throwable any) {
 3925  0
           LOGGER.error("Unable to close resultset", any);
 3926  0
         }
 3927  
       }
 3928  
 
 3929  0
       if (stmt != null) {
 3930  
         try {
 3931  0
           warning = stmt.getWarnings();
 3932  0
           while (warning != null) {
 3933  0
             LOGGER.warn("Stmt Warning: " + warning.toString());
 3934  0
             messageOut(
 3935  
                 Resources.getString("errStmtWarning", warning.toString()),
 3936  
                 STYLE_YELLOW);
 3937  0
             warning = warning.getNextWarning();
 3938  
           }
 3939  0
         } catch (Throwable any) {
 3940  0
           LOGGER.warn("Error retrieving statement SQL warnings", any);
 3941  0
         }
 3942  
 
 3943  
         try {
 3944  0
           stmt.close();
 3945  0
           LOGGER.debug("Statement closed");
 3946  0
         } catch (Throwable any) {
 3947  0
           LOGGER.error("Unable to close statement", any);
 3948  0
         }
 3949  
       }
 3950  
 
 3951  0
       if (conn != null) {
 3952  
         try {
 3953  0
           warning = conn.getWarnings();
 3954  0
           while (warning != null) {
 3955  0
             LOGGER.warn("Connt Warning: " + warning.toString());
 3956  0
             messageOut(
 3957  
                 Resources.getString("errConnWarning", warning.toString()),
 3958  
                 STYLE_YELLOW);
 3959  0
             warning = warning.getNextWarning();
 3960  
           }
 3961  0
         } catch (Throwable any) {
 3962  0
           LOGGER.warn("Error retrieving connection SQL warnings", any);
 3963  0
         }
 3964  
       }
 3965  
 
 3966  
       // Close the connection if there are no BLOBs.
 3967  
       // If the user decides to save a BLOB we will need to DB connection
 3968  
       // to remain open, hence we only close here if there are no BLOBs
 3969  0
       if (!hasBLOB && conn != null) {
 3970  
         try {
 3971  0
           conn.close();
 3972  0
           conn = null;
 3973  0
           LOGGER.debug("DB Connection closed");
 3974  0
         } catch (Throwable any) {
 3975  0
           LOGGER.error("Unable to close DB connection", any);
 3976  0
         }
 3977  
       }
 3978  
 
 3979  0
       reportStats(sqlStatement, connAsk, connGot, stmtGot, queryStart,
 3980  
           queryReady,
 3981  
           queryRSFetched, queryRSProcessed, rows, cols,
 3982  
           asDescribe.isSelected() ? model : null, outParams);
 3983  
       // reportResults(SQL, model);
 3984  0
     }
 3985  0
   }
 3986  
 
 3987  
   /**
 3988  
    * Outputs Connection Meta Data to the message area. This is controlled by
 3989  
    * a configuration menu option.
 3990  
    * 
 3991  
    * @param pConn
 3992  
    *          Connection The DB connection
 3993  
    */
 3994  
   @SuppressWarnings("unused")
 3995  
   private void reportConnectionStats(Connection pConn) {
 3996  
     Class<?> connectionClass;
 3997  
     Method[] allMethods;
 3998  
     Object returnValue;
 3999  
     int numElements, element;
 4000  
     int numColumns, column;
 4001  
     ResultSet resultValues;
 4002  
     ResultSetMetaData metaData;
 4003  
     DatabaseMetaData dbMeta;
 4004  
     StringBuffer msg;
 4005  
     boolean formatBrief, formatLong;
 4006  
     String methodName, returnTypeName;
 4007  
 
 4008  0
     formatBrief = configDisplayDBServerInfoShort.isSelected();
 4009  0
     formatLong = configDisplayDBServerInfoLong.isSelected();
 4010  
 
 4011  0
     if (formatBrief || formatLong) {
 4012  0
       msg = new StringBuffer();
 4013  0
       msg.append('\n');
 4014  0
       msg.append(Resources.getString("msgDBServerInfo"));
 4015  0
       messageOut(msg.toString(), STYLE_SUBTLE);
 4016  
 
 4017  
       try {
 4018  0
         dbMeta = pConn.getMetaData();
 4019  
 
 4020  0
         msg = new StringBuffer();
 4021  0
         connectionClass = Class.forName("java.sql.DatabaseMetaData");
 4022  0
         allMethods = connectionClass.getMethods();
 4023  0
         for (int i = 0; i < allMethods.length; ++i) {
 4024  
           // Only interested in the bean accessor methods with no args
 4025  0
           if (allMethods[i].getName().startsWith("get")
 4026  
               && allMethods[i].getParameterTypes().length == 0) {
 4027  
             try {
 4028  
               // Some methods should not be called - would leak connections
 4029  0
               returnTypeName = allMethods[i].getReturnType().toString();
 4030  0
               if (returnTypeName.indexOf("Connection") > 1
 4031  
                   || returnTypeName.indexOf("Statement") > -1
 4032  
                   || returnTypeName.indexOf("ResultSet") > -1) {
 4033  0
                 LOGGER.debug("Skipping method [" + allMethods[i].getName()
 4034  
                     + "] return type [" + allMethods[i].getReturnType() + "]");
 4035  0
                 continue;
 4036  
               }
 4037  
 
 4038  
               // If brief output, skip the more detailed information
 4039  0
               if (formatBrief) {
 4040  0
                 methodName = allMethods[i].getName();
 4041  0
                 if (methodName.indexOf("Keyword") > -1
 4042  
                     || methodName.indexOf("Functions") > -1
 4043  
                     || methodName.indexOf("Max") > -1) {
 4044  0
                   continue;
 4045  
                 }
 4046  
 
 4047  
               }
 4048  
               // Call the method
 4049  0
               returnValue = allMethods[i].invoke(dbMeta, (Object) null);
 4050  
 
 4051  
               // Check if the returned value is an array
 4052  0
               if (!returnValue.getClass().isArray()) {
 4053  
                 // For nonarray - check if the returned value is a ResultSet
 4054  0
                 if (returnValue instanceof ResultSet) {
 4055  
                   // Only output DB server row-based data for long DB details
 4056  0
                   if (formatLong) {
 4057  
                     // Have a result set with the information
 4058  0
                     messageOut("  " + fixAccessorName(allMethods[i].getName())
 4059  
                         + ": " + Resources.getString("msgSetOfRows"),
 4060  
                         STYLE_SUBTLE);
 4061  0
                     resultValues = (ResultSet) returnValue;
 4062  0
                     metaData = resultValues.getMetaData();
 4063  0
                     numColumns = metaData.getColumnCount();
 4064  
 
 4065  
                     // Output the column names
 4066  0
                     messageOut("    ", STYLE_SUBTLE, false);
 4067  0
                     for (column = 1; column <= numColumns; ++column) {
 4068  0
                       if (column > 1) {
 4069  0
                         messageOut(", ", STYLE_SUBTLE, false);
 4070  
                       }
 4071  0
                       messageOut(metaData.getColumnName(column),
 4072  
                           STYLE_SUBTLE_UL, false);
 4073  
                     }
 4074  0
                     messageOut("", STYLE_SUBTLE);
 4075  
 
 4076  
                     // Output the rows
 4077  0
                     while (resultValues.next()) {
 4078  0
                       msg = new StringBuffer();
 4079  0
                       msg.append("    ");
 4080  0
                       for (column = 1; column <= numColumns; ++column) {
 4081  0
                         if (column > 1) {
 4082  0
                           msg.append(", ");
 4083  
                         }
 4084  0
                         msg.append(resultValues.getString(column));
 4085  
                       }
 4086  0
                       messageOut(msg.toString(), STYLE_SUBTLE);
 4087  
                     }
 4088  
                   }
 4089  
                 } else {
 4090  
                   // Single value - simply output the resulting value
 4091  0
                   messageOut("  " + fixAccessorName(allMethods[i].getName())
 4092  
                       + ": " + returnValue,
 4093  
                       STYLE_SUBTLE);
 4094  
                 }
 4095  0
               } else if (formatLong) {
 4096  
                 // Have an array - display the values in the array
 4097  
                 // Will output if long format details are requested
 4098  0
                 numElements = Array.getLength(returnValue);
 4099  0
                 messageOut("  " + fixAccessorName(allMethods[i].getName())
 4100  
                     + ": " + Resources.getString("msgSetOfValues",
 4101  
                         numElements + ""),
 4102  
                     STYLE_SUBTLE);
 4103  0
                 for (element = 0; element < numElements; ++element) {
 4104  0
                   messageOut("    " + Array.get(returnValue, element),
 4105  
                       STYLE_SUBTLE);
 4106  
 
 4107  
                 }
 4108  
               }
 4109  0
             } catch (Throwable any) {
 4110  
               // Probably an unsupported method exception wrapped in an
 4111  
               // invocation error
 4112  0
               if (any.getCause() != null) {
 4113  0
                 messageOut("  " + Resources.getString("errDBServerMetaError",
 4114  
                     fixAccessorName(allMethods[i].getName()),
 4115  
                     any.getCause().getClass().getName(),
 4116  
                     any.getCause().getMessage()),
 4117  
                     STYLE_SUBTLE);
 4118  
               } else {
 4119  0
                 messageOut("  " + Resources.getString("errDBServerMetaError",
 4120  
                     fixAccessorName(allMethods[i].getName()),
 4121  
                     any.getClass().getName(),
 4122  
                     any.getMessage()),
 4123  
                     STYLE_SUBTLE);
 4124  
               }
 4125  0
             }
 4126  
           }
 4127  
         }
 4128  0
       } catch (Throwable any) {
 4129  0
         LOGGER.error("Error retrieving DB Server Metadata", any);
 4130  0
         messageOut("  " + Resources.getString("errFailDBServerMeta",
 4131  
             any.getClass().getName(), any.getMessage()));
 4132  0
       }
 4133  
     }
 4134  0
   }
 4135  
 
 4136  
   /**
 4137  
    * Convert an accessor name (e.g. getSomeValue) into a user friendly
 4138  
    * label, splitting at uppercase letter boundaries (e.g. Some Value)
 4139  
    * 
 4140  
    * @param rawAccessorName
 4141  
    *          String The name of the accessor method
 4142  
    * @return String The reformatted label
 4143  
    */
 4144  
   private String fixAccessorName(String rawAccessorName) {
 4145  0
     String accessorName = rawAccessorName;
 4146  
     int posit;
 4147  
     byte[] characters;
 4148  
     StringBuffer newName;
 4149  
     boolean prevWasLC;
 4150  
 
 4151  0
     if (accessorName.startsWith("get")) {
 4152  0
       accessorName = accessorName.substring(3);
 4153  
     }
 4154  
 
 4155  0
     newName = new StringBuffer();
 4156  0
     characters = accessorName.getBytes();
 4157  0
     newName.append((char) characters[0]);
 4158  0
     prevWasLC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(characters[0]) == -1;
 4159  0
     for (posit = 1; posit < characters.length; ++posit) {
 4160  0
       if ("ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(characters[posit]) > -1) {
 4161  0
         if (prevWasLC) {
 4162  0
           newName.append(' ');
 4163  
         }
 4164  0
         prevWasLC = false;
 4165  
       } else {
 4166  0
         prevWasLC = true;
 4167  
       }
 4168  0
       newName.append((char) characters[posit]);
 4169  
     }
 4170  
 
 4171  0
     return newName.toString();
 4172  
   }
 4173  
 
 4174  
   /**
 4175  
    * Takes a callable statement and retrieves the out parameters, displaying
 4176  
    * them in the message area of the GUI.
 4177  
    * 
 4178  
    * @param stmt
 4179  
    *          CallableStatement just executed
 4180  
    * @param params
 4181  
    *          List of parameters used in the callable statement
 4182  
    * @return List
 4183  
    */
 4184  
   private List<Object> getOutParams(CallableStatement stmt,
 4185  
       List<StatementParameter> params) {
 4186  
     List<Object> values;
 4187  
     int paramIndex;
 4188  
     StatementParameter param;
 4189  
 
 4190  0
     paramIndex = 0;
 4191  
 
 4192  0
     values = new ArrayList<Object>();
 4193  
     try {
 4194  0
       for (paramIndex = 0; paramIndex < params.size(); ++paramIndex) {
 4195  0
         param = (StatementParameter) params.get(paramIndex);
 4196  0
         if (param.getType() == StatementParameter.OUT) {
 4197  0
           messageOut(Resources.getString("msgOutParam") + " ", STYLE_SUBTLE,
 4198  
               false);
 4199  0
           switch (param.getDataType()) {
 4200  
             case java.sql.Types.VARCHAR:
 4201  0
               messageOut(Resources.getString("msgParamString",
 4202  
                   paramIndex + "") + " ",
 4203  
                   STYLE_SUBTLE, false);
 4204  0
               messageOut(stmt.getString(paramIndex + 1), STYLE_BOLD, true);
 4205  0
               values.add(stmt.getString(paramIndex + 1));
 4206  0
               break;
 4207  
             case java.sql.Types.INTEGER:
 4208  0
               messageOut(Resources.getString("msgParamInteger",
 4209  
                   paramIndex + "") + " ",
 4210  
                   STYLE_SUBTLE, false);
 4211  0
               messageOut("" + stmt.getInt(paramIndex + 1), STYLE_BOLD, true);
 4212  0
               values.add(new Integer(stmt.getInt(paramIndex + 1)));
 4213  0
               break;
 4214  
             default:
 4215  0
               messageOut(Resources.getString("msgParamDefault",
 4216  
                   paramIndex + "") + " ",
 4217  
                   STYLE_SUBTLE, false);
 4218  0
               messageOut("" + stmt.getObject(paramIndex + 1), STYLE_BOLD, true);
 4219  0
               values.add(stmt.getObject(paramIndex + 1));
 4220  
               break;
 4221  
           }
 4222  
         }
 4223  
       }
 4224  0
     } catch (Throwable any) {
 4225  0
       LOGGER.error("Failed to read output parameter at index (" + paramIndex
 4226  
           + ")", any);
 4227  0
       messageOut(Resources.getString("errFailReadingOutParam", paramIndex + "",
 4228  
           any.getMessage()));
 4229  0
     }
 4230  
 
 4231  0
     return values;
 4232  
   }
 4233  
 
 4234  
   /**
 4235  
    * Takes a SQL statement and determines whether the syntax for using
 4236  
    * in/out parameters has been used. For each in parameter the SQL
 4237  
    * is updated to replace the parameter with a "?" and stores the
 4238  
    * parameter value in the parameter list. Out parameters are simply
 4239  
    * stored in the parameters list and the specialized parameter syntax
 4240  
    * removed. The end result is a parameterized SQL statement and a
 4241  
    * list of parameters.
 4242  
    * 
 4243  
    * @param rawSqlStatement
 4244  
    *          The SQL statement to be processed for parameters
 4245  
    * @param params
 4246  
    *          The collection of parameters found in the SQL statement
 4247  
    * @return The updated SQL staement with the specialized parameter syntax
 4248  
    *         removed
 4249  
    */
 4250  
   private String makeParams(String rawSqlStatement,
 4251  
       List<StatementParameter> params) {
 4252  0
     String sqlStatement = rawSqlStatement;
 4253  
     int beginPosit, endPosit;
 4254  
 
 4255  0
     while ((beginPosit = sqlStatement.indexOf(PARAM_TOKEN_START)) > -1) {
 4256  0
       endPosit = sqlStatement.substring(beginPosit).indexOf(PARAM_TOKEN_END);
 4257  0
       if (endPosit == -1) {
 4258  0
         endPosit = sqlStatement.length() - PARAM_TOKEN_END_LENGTH;
 4259  
       } else {
 4260  0
         endPosit += beginPosit;
 4261  
       }
 4262  0
       processParameter(
 4263  
           sqlStatement.substring(beginPosit + PARAM_TOKEN_START_LENGTH,
 4264  
               endPosit).trim(),
 4265  
           params);
 4266  0
       sqlStatement = Utility
 4267  
           .replace(
 4268  
               sqlStatement,
 4269  
               sqlStatement.substring(beginPosit, endPosit
 4270  
                   + PARAM_TOKEN_END_LENGTH), "?",
 4271  
               0, false);
 4272  0
       messageOut(Resources.getString("msgParamSearchLoopBefore", sqlStatement));
 4273  
     }
 4274  
 
 4275  0
     messageOut(Resources.getString("msgParamSearchLoopAfter", sqlStatement));
 4276  
 
 4277  0
     return sqlStatement;
 4278  
   }
 4279  
 
 4280  
   /**
 4281  
    * Parse a parameter. Determines the parameter direction (In/Out) and
 4282  
    * type.
 4283  
    * 
 4284  
    * @param param
 4285  
    *          The parameter as supplied in the input SQL statement
 4286  
    * @param params
 4287  
    *          The collection of parameters. The parameter decoded from the
 4288  
    *          param input is added to this list.
 4289  
    */
 4290  
   private void processParameter(String param, List<StatementParameter> params) {
 4291  
     int type;
 4292  
     String data;
 4293  
 
 4294  0
     if (param.toUpperCase().startsWith("IN,")) {
 4295  0
       type = SQLTypes.getSQLTypeId(param.substring(3));
 4296  0
       data = param.substring(3 + param.substring(3).indexOf(',') + 1);
 4297  0
       messageOut(Resources.getString("msgParamInDesc", type + "", data));
 4298  0
       params.add(new StatementParameter(StatementParameter.IN, type, data));
 4299  0
     } else if (param.toUpperCase().startsWith("OUT,")) {
 4300  0
       type = SQLTypes.getSQLTypeId(param.substring(4));
 4301  0
       messageOut(Resources.getString("msgParamOutDesc", type + ""));
 4302  0
       params.add(new StatementParameter(StatementParameter.OUT, type));
 4303  
     }
 4304  0
   }
 4305  
 
 4306  
   /**
 4307  
    * Setup a callable statement for execution.
 4308  
    * 
 4309  
    * @param stmt
 4310  
    *          The callable statement
 4311  
    * @param params
 4312  
    *          The list of parameters
 4313  
    */
 4314  
   private void setupCall(CallableStatement stmt, List<StatementParameter> params) {
 4315  
     int paramIndex;
 4316  
     StatementParameter param;
 4317  
 
 4318  0
     paramIndex = 0;
 4319  
 
 4320  
     try {
 4321  0
       for (paramIndex = 0; paramIndex < params.size(); ++paramIndex) {
 4322  0
         param = (StatementParameter) params.get(paramIndex);
 4323  
 
 4324  0
         if (param.getType() == StatementParameter.IN) {
 4325  0
           switch (param.getDataType()) {
 4326  
             case java.sql.Types.VARCHAR:
 4327  0
               stmt.setString(paramIndex + 1, param.getDataString());
 4328  0
               break;
 4329  
             case java.sql.Types.INTEGER:
 4330  0
               stmt.setInt(paramIndex + 1,
 4331  
                   Integer.parseInt(param.getDataString()));
 4332  0
               break;
 4333  
             default:
 4334  0
               stmt.setObject(paramIndex + 1, param.getDataString());
 4335  0
               break;
 4336  
           }
 4337  
         } else {
 4338  0
           stmt.registerOutParameter(paramIndex + 1, param.getType());
 4339  
         }
 4340  
       }
 4341  0
     } catch (Throwable any) {
 4342  0
       LOGGER.error("Failed to register output parameter at index ["
 4343  
           + paramIndex + "]", any);
 4344  0
       messageOut(Resources.getString("errFailRegisterOutParam",
 4345  
           paramIndex + "",
 4346  
           any.getMessage()));
 4347  0
     }
 4348  0
   }
 4349  
 
 4350  
   /**
 4351  
    * Log the results of executing the SQL to a flat file
 4352  
    * 
 4353  
    * @param query
 4354  
    *          The SQL statement
 4355  
    * @param model
 4356  
    *          The table model containing the results
 4357  
    */
 4358  
   @SuppressWarnings("unused")
 4359  
   private void reportResults(String query, TableModel model) {
 4360  0
     if (fileLogResults.isSelected() && model != null) {
 4361  0
       writeDataAsCSV(query, model, DBRESULTS_NAME, true);
 4362  
     }
 4363  0
   }
 4364  
 
 4365  
   /**
 4366  
    * Reports statistics on various data such as the date a query was executed
 4367  
    * and
 4368  
    * the date the results were fetched. Other statistics are reported on such as
 4369  
    * the
 4370  
    * the date a connection was asked for, and the date it was actually received.
 4371  
    * The report statistics are written to an external text file
 4372  
    * represented by DBSTATS_NAME.
 4373  
    * 
 4374  
    * @param sqlStatement
 4375  
    *          The SQL statement
 4376  
    * @param connAsk
 4377  
    *          The time when the connection was requested
 4378  
    * @param connGot
 4379  
    *          The time when the connection was returned
 4380  
    * @param stmtGot
 4381  
    *          The time when the statement was returned
 4382  
    * @param queryStart
 4383  
    *          The time when query exeution began
 4384  
    * @param queryReady
 4385  
    *          The time when the query finished exeuting
 4386  
    * @param queryRSFetched
 4387  
    *          The time when the result set had been completely fetched
 4388  
    * @param queryRSProcessed
 4389  
    *          The time when the result set had been completely processed
 4390  
    * @param rows
 4391  
    *          The number of rows in the result set
 4392  
    * @param cols
 4393  
    *          The number of columns in the result set
 4394  
    * @param model
 4395  
    *          The table model for the results
 4396  
    * @param outParams
 4397  
    *          The output parameters defined for this SQL statement
 4398  
    */
 4399  
   private void reportStats(String sqlStatement, java.util.Date connAsk,
 4400  
       java.util.Date connGot,
 4401  
       java.util.Date stmtGot,
 4402  
       java.util.Date queryStart, java.util.Date queryReady,
 4403  
       java.util.Date queryRSFetched,
 4404  
       java.util.Date queryRSProcessed,
 4405  
       long rows, int cols, TableModel model,
 4406  
       List<Object> outParams) {
 4407  
     Runtime runtime;
 4408  
     String runStats;
 4409  
     PrintWriter out;
 4410  
     boolean firstEntry;
 4411  0
     final String valueNotApplicable = "\""
 4412  
         + Resources.getString("proValueNotApplicable") + "\",";
 4413  
 
 4414  0
     runStats = "";
 4415  0
     out = null;
 4416  0
     firstEntry = false;
 4417  
 
 4418  0
     if (fileLogStats.isSelected()) {
 4419  
       // Identify whether file exists, if not create and add header row
 4420  
       try {
 4421  0
         new FileReader(DBSTATS_NAME).close();
 4422  0
       } catch (Exception any) {
 4423  0
         firstEntry = true;
 4424  0
       }
 4425  
 
 4426  
       try {
 4427  0
         out = new PrintWriter(new FileWriter(DBSTATS_NAME, true));
 4428  0
       } catch (Exception any) {
 4429  0
         LOGGER.error("Failed to write the statistics file [" + DBSTATS_NAME
 4430  
             + "]", any);
 4431  0
         messageOut(Resources.getString("errFailWriteStatsFile", DBSTATS_NAME,
 4432  
             any.getMessage()), STYLE_RED);
 4433  0
       }
 4434  
     }
 4435  
 
 4436  
     // Make sure it is always safe to write to "out" -- simplifies logic
 4437  0
     if (out == null) {
 4438  0
       out = new PrintWriter(new StringWriter());
 4439  
     }
 4440  
 
 4441  
     // Header, if needed
 4442  0
     if (firstEntry) {
 4443  0
       out.print(Resources.getString("proQueryStatsExportHeader"));
 4444  0
       if (outParams != null && outParams.size() > 0) {
 4445  0
         for (int param = 0; param < outParams.size(); ++param) {
 4446  0
           out.print(Resources.getString("proQueryStatsExportHeaderParam",
 4447  
               param + ""));
 4448  
         }
 4449  
       }
 4450  0
       out.println();
 4451  
     }
 4452  
 
 4453  
     // Output Query Index Number
 4454  0
     out.print(querySelection.getSelectedIndex() + ",");
 4455  
 
 4456  
     // Output SQL, replacing quotes with apostrophes
 4457  0
     out.print("\""
 4458  
         + sqlStatement.replace('"', '\'')
 4459  
         + "\",");
 4460  
 
 4461  
     // Output timestamp
 4462  0
     out.print(Utility.formattedDate(new java.util.Date()) + ",");
 4463  
 
 4464  
     // Output time required to get connection to database
 4465  0
     if (connAsk != null && connGot != null) {
 4466  0
       runStats += Resources.getString("proTimeConnOpen",
 4467  
           (connGot.getTime() - connAsk.getTime()) + "");
 4468  0
       runStats += "  ";
 4469  0
       out.print((connGot.getTime() - connAsk.getTime()) + ",");
 4470  
     } else {
 4471  0
       out.print(valueNotApplicable);
 4472  
     }
 4473  
 
 4474  
     // Output time required to get statement object
 4475  0
     if (connGot != null && stmtGot != null) {
 4476  0
       runStats += Resources.getString("proTimeStmtAccess",
 4477  
           (stmtGot.getTime() - connGot.getTime()) + "");
 4478  0
       runStats += "  ";
 4479  0
       out.print((stmtGot.getTime() - connGot.getTime()) + ",");
 4480  
     } else {
 4481  0
       out.print(valueNotApplicable);
 4482  
     }
 4483  
 
 4484  
     // Time it took to configure statement
 4485  0
     if (queryStart != null && stmtGot != null) {
 4486  0
       runStats += Resources.getString("proTimeStmtSetup",
 4487  
           (queryStart.getTime() - stmtGot.getTime()) + "");
 4488  0
       runStats += "  ";
 4489  0
       out.print((queryStart.getTime() - stmtGot.getTime()) + ",");
 4490  
     } else {
 4491  0
       out.print(valueNotApplicable);
 4492  
     }
 4493  
 
 4494  0
     runStats += "\n          ";
 4495  
 
 4496  
     // Output time DB took to execute query
 4497  0
     if (queryStart != null && queryReady != null) {
 4498  0
       runStats += Resources.getString("proTimeDBExecute",
 4499  
           (queryReady.getTime() - queryStart.getTime()) + "");
 4500  0
       runStats += "  ";
 4501  0
       out.print((queryReady.getTime() - queryStart.getTime()) + ",");
 4502  
     } else {
 4503  0
       out.print(valueNotApplicable);
 4504  
     }
 4505  
 
 4506  
     // Output time it took to fetch all results
 4507  0
     if (queryReady != null && queryRSFetched != null) {
 4508  0
       runStats += Resources.getString("proTimeResultsFetch",
 4509  
           (queryRSFetched.getTime() - queryReady.getTime()) + "");
 4510  0
       runStats += "  ";
 4511  0
       out.print((queryRSFetched.getTime() - queryReady.getTime()) + ",");
 4512  
     } else {
 4513  0
       out.print(valueNotApplicable);
 4514  
     }
 4515  
 
 4516  
     // Output time it took to process all results
 4517  0
     if (queryReady != null && queryRSProcessed != null) {
 4518  0
       runStats += Resources.getString("proTimeResultSet",
 4519  
           (queryRSProcessed.getTime() - queryReady.getTime()) + "");
 4520  0
       runStats += "  ";
 4521  0
       out.print((queryRSProcessed.getTime() - queryReady.getTime()) + ",");
 4522  
     } else {
 4523  0
       out.print(valueNotApplicable);
 4524  
     }
 4525  
 
 4526  0
     if (runStats.length() > 0) {
 4527  0
       messageOut(Resources.getString("proTimeDBStats") + " ", STYLE_SUBTLE,
 4528  
           false);
 4529  0
       messageOut(runStats, STYLE_NORMAL, false);
 4530  0
       runStats = "";
 4531  
     }
 4532  
 
 4533  
     // Output total time it took to obtain connection, execute SQL and obtain
 4534  
     // results
 4535  0
     if (connAsk != null && queryRSFetched != null) {
 4536  0
       runStats += Resources.getString("proTimeTotal",
 4537  
           (queryRSFetched.getTime() - connAsk.getTime()) + "");
 4538  0
       runStats += "  ";
 4539  0
       out.print((queryRSFetched.getTime() - connAsk.getTime()) + ",");
 4540  0
     } else if (connAsk != null && queryRSProcessed != null) {
 4541  0
       runStats += Resources.getString("proTimeTotal",
 4542  
           (queryRSProcessed.getTime() - connAsk.getTime()) + "");
 4543  0
       runStats += "  ";
 4544  0
       out.print((queryRSProcessed.getTime() - connAsk.getTime()) + ",");
 4545  0
     } else if (connAsk != null && queryReady != null) {
 4546  0
       runStats += Resources.getString("proTimeTotal",
 4547  
           (queryReady.getTime() - connAsk.getTime()) + "");
 4548  0
       runStats += "  ";
 4549  0
       out.print((queryReady.getTime() - connAsk.getTime()) + ",");
 4550  
     } else {
 4551  0
       out.print(valueNotApplicable);
 4552  
     }
 4553  
 
 4554  0
     messageOut(runStats, STYLE_BOLD, true);
 4555  
 
 4556  
     // Output number of columns in resultset
 4557  0
     out.print(cols + ",");
 4558  
 
 4559  
     // Output number of rows returned or modified
 4560  0
     out.print(rows + "," + maxRows.getSelectedItem().toString() + ",");
 4561  
 
 4562  0
     runtime = Runtime.getRuntime();
 4563  
 
 4564  
     // Output environment information
 4565  0
     out.print(runtime.totalMemory() + "," + runtime.freeMemory() + ","
 4566  
         + (runtime.totalMemory() - runtime.freeMemory()) + ","
 4567  
         + runtime.maxMemory() + "," + runtime.availableProcessors());
 4568  
 
 4569  0
     if (configDisplayClientInfo.isSelected()) {
 4570  0
       runStats = Resources.getString("proMemAlloc", runtime.totalMemory() + "");
 4571  0
       runStats += " " + Resources.getString("proMemFree",
 4572  
           runtime.freeMemory() + "");
 4573  0
       runStats += " " + Resources.getString("proMemUsed",
 4574  
           (runtime.totalMemory() - runtime.freeMemory()) + "");
 4575  0
       runStats += " " + Resources.getString("proMemMax",
 4576  
           runtime.maxMemory() + "");
 4577  0
       runStats += " " + Resources.getString("proProcessors",
 4578  
           runtime.availableProcessors() + "");
 4579  
 
 4580  0
       messageOut(Resources.getString("proClientEnv") + " ", STYLE_SUBTLE, false);
 4581  0
       messageOut(runStats);
 4582  
     }
 4583  
 
 4584  0
     if (poolConnect.isSelected()) {
 4585  0
       messageOut(Resources.getString("msgPoolStats") + " ", STYLE_SUBTLE, false);
 4586  0
       messageOut(Resources.getString("msgPoolStatsCount",
 4587  
           getDBPool().getNumActive() + "", getDBPool().getNumIdle() + ""));
 4588  
     }
 4589  
 
 4590  
     // If output parameters, list them
 4591  0
     if (outParams != null && outParams.size() > 0) {
 4592  0
       for (int param = 0; param < outParams.size(); ++param) {
 4593  0
         out.print(",");
 4594  0
         if (outParams.get(param) instanceof String) {
 4595  0
           out.print("\"");
 4596  
         }
 4597  0
         out.print(outParams.get(param));
 4598  0
         if (outParams.get(param) instanceof String) {
 4599  0
           out.print("\"");
 4600  
         }
 4601  
       }
 4602  
     }
 4603  
 
 4604  
     // If model given, output describe content
 4605  0
     if (model != null) {
 4606  0
       for (int row = 1; row < model.getRowCount(); ++row) {
 4607  0
         out.print(",\"");
 4608  
 
 4609  
         // Column Name
 4610  0
         out.print(model.getValueAt(row, 0));
 4611  
 
 4612  
         // Type
 4613  0
         out.print(" " + model.getValueAt(row, 1));
 4614  
 
 4615  
         // Size
 4616  0
         out.print(" " + model.getValueAt(row, 2));
 4617  
 
 4618  
         // Precision
 4619  0
         out.print(" (" + model.getValueAt(row, 3) + ","
 4620  
             + model.getValueAt(row, 4) + ")");
 4621  
 
 4622  0
         out.print("\"");
 4623  
       }
 4624  
     }
 4625  
 
 4626  0
     out.println();
 4627  0
     out.close();
 4628  0
   }
 4629  
 
 4630  
   /**
 4631  
    * Removes a query from the comboBox
 4632  
    */
 4633  
   private void removeSelectedQuery() {
 4634  
     int index;
 4635  0
     if ((index = querySelection.getSelectedIndex()) >= 0) {
 4636  0
       querySelection.removeItemAt(index);
 4637  0
       histMaintQueryDeleted(index);
 4638  
     }
 4639  0
   }
 4640  
 
 4641  
   /**
 4642  
    * Writes the list of queries or connection URLs to the appropriate
 4643  
    * combo boxes
 4644  
    */
 4645  
   private void saveConfig() {
 4646  0
     writeOutCombo(querySelection, queryFilename);
 4647  0
     writeOutCombo(connectString,
 4648  
         Configuration.instance().getFile(FILENAME_CONNECTSTRINGS).
 4649  
             getAbsolutePath());
 4650  0
     saveProperties();
 4651  0
   }
 4652  
 
 4653  
   /**
 4654  
    * Adds a list of queries and connection URLs to the appropriate
 4655  
    * combo boxes
 4656  
    */
 4657  
   private void loadConfig() {
 4658  0
     loadCombo(querySelection, queryFilename);
 4659  0
     loadCombo(connectString,
 4660  
         Configuration.instance().getFile(FILENAME_CONNECTSTRINGS).
 4661  
             getAbsolutePath());
 4662  0
   }
 4663  
 
 4664  
   /**
 4665  
    * Adds the data from the supplied file to the query selection
 4666  
    * (or connect URLs) combobox.
 4667  
    * 
 4668  
    * @param combo
 4669  
    *          The JComboBox - it can be the combobox that contains
 4670  
    *          all the queries or the combobox with the URLs
 4671  
    * @param fileName
 4672  
    *          The name of the file that contains the queries or the
 4673  
    *          connect URLs
 4674  
    */
 4675  
   private void loadCombo(JComboBox combo, String fileName) {
 4676  
     BufferedReader in;
 4677  
     String data;
 4678  
 
 4679  0
     in = null;
 4680  
     try {
 4681  0
       in = new BufferedReader(new FileReader(fileName));
 4682  0
       while ((data = in.readLine()) != null) {
 4683  0
         if (combo == querySelection) {
 4684  0
           addToCombo(combo,
 4685  
               new Query(data.substring(0, data.lastIndexOf("[")).trim(),
 4686  
                   new
 4687  
                   Integer(data.substring(data.lastIndexOf("[") + 1).
 4688  
                       trim()).intValue()));
 4689  
         } else {
 4690  0
           addToCombo(combo, data);
 4691  
         }
 4692  
       }
 4693  0
     } catch (Throwable any) {
 4694  0
       LOGGER.error("Failed to load combo box with lookup values", any);
 4695  
     } finally {
 4696  0
       if (in != null) {
 4697  
         try {
 4698  0
           in.close();
 4699  0
         } catch (Throwable any) {
 4700  0
           LOGGER.error("Failed to close the input file", any);
 4701  0
         }
 4702  
       }
 4703  
     }
 4704  0
   }
 4705  
 
 4706  
   /**
 4707  
    * Writes all the queries in the query selection (or connection URLS) combobox
 4708  
    * to the supplied file in a print formatted representation.
 4709  
    * 
 4710  
    * @param combo
 4711  
    *          The JComboBox - it can be the combobox that contains
 4712  
    *          all the queries or the combobox with the URLs
 4713  
    * @param fileName
 4714  
    *          The fileName to be written to contain the queries or the
 4715  
    *          connect URLs
 4716  
    */
 4717  
   private void writeOutCombo(JComboBox combo, String fileName) {
 4718  
     PrintWriter out;
 4719  
 
 4720  0
     if (combo != null) {
 4721  0
       out = null;
 4722  
       try {
 4723  0
         out = new PrintWriter(new FileWriter(fileName));
 4724  0
         for (int i = 0; i < combo.getModel().getSize(); ++i) {
 4725  0
           if (combo == querySelection) {
 4726  0
             out.println(((Query) combo.getModel().getElementAt(i)).getSql()
 4727  
                 + "["
 4728  
                 + ((Query) combo.getModel().getElementAt(i)).getMode());
 4729  
           } else {
 4730  0
             out.println((String) combo.getModel().getElementAt(i));
 4731  
           }
 4732  
         }
 4733  0
       } catch (Exception any) {
 4734  0
         LOGGER.error("Failed to write out the content of the combobox", any);
 4735  
       } finally {
 4736  0
         if (out != null) {
 4737  
           try {
 4738  0
             out.close();
 4739  0
           } catch (Exception any) {
 4740  0
             LOGGER.error("Failed to close the combobox output file", any);
 4741  0
           }
 4742  
         }
 4743  
       }
 4744  
     }
 4745  0
   }
 4746  
 
 4747  
   /**
 4748  
    * Gets each cell of the selected row - if the object stored in the cell
 4749  
    * is of type java.sql.Blob, the object is written to disk by calling
 4750  
    * writeBlob(String, java.sql.Blob) on the DB connection.
 4751  
    */
 4752  
   private void saveBLOBs() {
 4753  
     TableModel model;
 4754  
     int selectedRow;
 4755  
     String filesWritten;
 4756  
 
 4757  0
     if (table.getSelectedRowCount() != 1) {
 4758  0
       userMessage(Resources.getString("errChooseOneRowText"),
 4759  
           Resources.getString("errChooseOneRowTitle"),
 4760  
           JOptionPane.ERROR_MESSAGE);
 4761  
     } else {
 4762  0
       model = table.getModel();
 4763  0
       selectedRow = table.getSelectedRow();
 4764  0
       filesWritten = "";
 4765  0
       for (int col = 1; col < model.getColumnCount(); col++) {
 4766  0
         if (model.getValueAt(selectedRow, col) instanceof java.sql.Blob) {
 4767  0
           LOGGER.debug("Blob["
 4768  
               + (java.sql.Blob) model.getValueAt(selectedRow, col) + "]");
 4769  0
           filesWritten +=
 4770  
               writeBlob(model.getColumnName(col),
 4771  
                   (java.sql.Blob) model.getValueAt(selectedRow, col))
 4772  
                   + "\n";
 4773  
         }
 4774  
       }
 4775  0
       userMessage(Resources.getString("msgBLOBWrittenText", filesWritten),
 4776  
           Resources.getString("msgBLOBWrittenTitle"),
 4777  
           JOptionPane.INFORMATION_MESSAGE);
 4778  
     }
 4779  0
   }
 4780  
 
 4781  
   /**
 4782  
    * Writes the contents of BLOB to disk. The name of the file created is
 4783  
    * based on the column name and the string representation of the
 4784  
    * BLOB object.
 4785  
    * 
 4786  
    * @param rawColName
 4787  
    *          The column that contains the BLOB object
 4788  
    * @param blob
 4789  
    *          The BLOB object that is written onto the file
 4790  
    * 
 4791  
    * @return The name of the file created
 4792  
    */
 4793  
   private String writeBlob(String rawColName, java.sql.Blob blob) {
 4794  0
     String colName = rawColName;
 4795  
     FileOutputStream out;
 4796  
     InputStream in;
 4797  
     byte[] block;
 4798  
     int bytesRead;
 4799  
     String fileName;
 4800  
 
 4801  0
     out = null;
 4802  
 
 4803  0
     if (colName == null || colName.trim().length() == 0) {
 4804  0
       colName = Resources.getString("msgBLOBColNoName");
 4805  
     }
 4806  
 
 4807  
     // If the option to display column type is on, strip off col type info
 4808  0
     if (colName.indexOf(' ') > 0) {
 4809  0
       colName = colName.substring(0, colName.indexOf(' '));
 4810  
     }
 4811  
 
 4812  0
     fileName = colName + "." + new java.util.Date().getTime() + ".dat";
 4813  
 
 4814  
     try {
 4815  0
       block = new byte[BLOB_LOAD_BLOCK_SIZE];
 4816  0
       out = new FileOutputStream(fileName, false);
 4817  0
       in = blob.getBinaryStream();
 4818  0
       while ((bytesRead = in.read(block)) > 0) {
 4819  0
         out.write(block, 0, bytesRead);
 4820  
       }
 4821  0
     } catch (Exception any) {
 4822  0
       LOGGER.error("Failed to write BLOB field value to file [" + fileName
 4823  
           + "]", any);
 4824  0
       fileName += " (" + Resources.getString("errFailBLOBWrite",
 4825  
           any.getClass().getName(), any.getMessage()) + ")";
 4826  
     } finally {
 4827  0
       if (out != null) {
 4828  
         try {
 4829  0
           out.close();
 4830  0
         } catch (Exception any) {
 4831  0
           LOGGER.error("Failed to close the BLOB output file", any);
 4832  0
         }
 4833  
       }
 4834  
     }
 4835  
 
 4836  0
     return fileName;
 4837  
   }
 4838  
 
 4839  
   /**
 4840  
    * Create the query 'select * from' for selected the column in the table
 4841  
    * 
 4842  
    * @param mode
 4843  
    *          The integer value for the different modes
 4844  
    */
 4845  
   private void queryStar(int mode) {
 4846  
     String value;
 4847  
 
 4848  0
     LOGGER.debug("Row:" + table.getSelectedRow() + " Col:"
 4849  
         + table.getSelectedColumn());
 4850  0
     LOGGER.debug("Row Count:" + table.getSelectedRowCount()
 4851  
         + " Col Count:" + table.getSelectedColumnCount());
 4852  0
     if (table.getSelectedRowCount() != 1 || table.getSelectedColumnCount() != 1) {
 4853  0
       userMessage(Resources.getString("errChooseOneCellText"),
 4854  
           Resources.getString("errChooseOneCellTitle"),
 4855  
           JOptionPane.ERROR_MESSAGE);
 4856  
     } else {
 4857  0
       value = table.getModel().getValueAt(table.getSelectedRow(),
 4858  
           table.getSelectedColumn()).toString();
 4859  0
       LOGGER.debug("Value class: " + value.getClass().getName());
 4860  0
       if (value == null || value.trim().length() == 0) {
 4861  0
         userMessage(Resources.getString("errNoDataInCellText"),
 4862  
             Resources.getString("errNoDataInCellTitle"),
 4863  
             JOptionPane.WARNING_MESSAGE);
 4864  
       } else {
 4865  0
         value = "select * from " + value;
 4866  0
         messageOut(Resources.getString("msgMadeSQL", value));
 4867  0
         queryText.setText(value);
 4868  0
         checkForNewString(querySelection);
 4869  0
         querySelection.setSelectedItem(value);
 4870  0
         selectMode(mode);
 4871  
       }
 4872  
     }
 4873  
 
 4874  0
   }
 4875  
 
 4876  
   /**
 4877  
    * Create an insert statement depending on the tables and the columns that
 4878  
    * were selected.The insert statement is then listed in the querySelection
 4879  
    * comboBox as the selected item.
 4880  
    */
 4881  
   private void makeInsert() {
 4882  
     String[][] columns;
 4883  
     String tables;
 4884  
     String sqlStatement;
 4885  
 
 4886  0
     tables = getTablesInQuery();
 4887  0
     columns = getColumnNamesForTable();
 4888  
 
 4889  0
     sqlStatement = "insert into " + tables + "(";
 4890  
 
 4891  0
     for (int i = 0; i < columns.length; ++i) {
 4892  0
       if (i > 0) {
 4893  0
         sqlStatement += ",";
 4894  
       }
 4895  0
       sqlStatement += columns[i][0];
 4896  
     }
 4897  
 
 4898  0
     sqlStatement += ") values (";
 4899  
 
 4900  0
     for (int i = 0; i < columns.length; ++i) {
 4901  0
       if (columns[i][1].startsWith("VARCHAR")
 4902  
           || columns[i][1].startsWith("CHAR")) {
 4903  0
         sqlStatement += "''";
 4904  
       }
 4905  0
       if (i < columns.length - 1) {
 4906  0
         sqlStatement += ",";
 4907  
       }
 4908  
     }
 4909  
 
 4910  0
     sqlStatement += ")";
 4911  
 
 4912  0
     messageOut(Resources.getString("msgMadeSQL", sqlStatement));
 4913  0
     queryText.setText(sqlStatement);
 4914  0
     checkForNewString(querySelection);
 4915  0
     querySelection.setSelectedItem(sqlStatement);
 4916  0
   }
 4917  
 
 4918  
   /**
 4919  
    * Create an update statement depending on the tables and the columns that
 4920  
    * were selected.The update statement is then listed in the querySelection
 4921  
    * comboBox as the selected item.
 4922  
    */
 4923  
   private void makeUpdate() {
 4924  
     String[][] columns;
 4925  
     String tables;
 4926  
     String thisPhrase;
 4927  
     String sqlStatement;
 4928  
     String where;
 4929  
     boolean firstColOut;
 4930  
 
 4931  0
     tables = getTablesInQuery();
 4932  0
     columns = getColumnNamesForTable();
 4933  0
     firstColOut = true;
 4934  
 
 4935  0
     where = "";
 4936  0
     sqlStatement = "update " + tables + " ";
 4937  
 
 4938  0
     for (int i = 0; i < columns.length; ++i) {
 4939  0
       thisPhrase = columns[i][0] + "=";
 4940  0
       if (columns[i][1].startsWith("VARCHAR")
 4941  
           || columns[i][1].startsWith("CHAR")) {
 4942  0
         thisPhrase += "''";
 4943  
       }
 4944  
 
 4945  0
       if (columns[i][2] != null) {
 4946  0
         if (where.length() > 0) {
 4947  0
           where += " and ";
 4948  
         }
 4949  0
         where += thisPhrase;
 4950  
       } else {
 4951  0
         if (firstColOut) {
 4952  0
           sqlStatement += "set ";
 4953  0
           firstColOut = false;
 4954  
         } else {
 4955  0
           sqlStatement += ", ";
 4956  
         }
 4957  
 
 4958  0
         sqlStatement += thisPhrase;
 4959  
       }
 4960  
     }
 4961  
 
 4962  0
     if (where.length() > 0) {
 4963  0
       sqlStatement += " where " + where;
 4964  
     }
 4965  
 
 4966  0
     messageOut(Resources.getString("msgMadeSQL", sqlStatement));
 4967  0
     queryText.setText(sqlStatement);
 4968  0
     checkForNewString(querySelection);
 4969  0
     querySelection.setSelectedItem(sqlStatement);
 4970  0
   }
 4971  
 
 4972  
   /**
 4973  
    * Write a select statement depending on the tables and the columns that
 4974  
    * were selected.The select statement is then listed in the querySelection
 4975  
    * comboBox as the selected item.
 4976  
    */
 4977  
   private void makeVerboseSelect() {
 4978  
     String[][] columns;
 4979  
     String tables;
 4980  
     String thisPhrase;
 4981  
     String sqlStatement;
 4982  
     String where;
 4983  
     boolean firstColOut;
 4984  
 
 4985  0
     tables = getTablesInQuery();
 4986  0
     columns = getColumnNamesForTable();
 4987  0
     firstColOut = true;
 4988  
 
 4989  0
     where = "";
 4990  0
     sqlStatement = "";
 4991  
 
 4992  0
     for (int i = 0; i < columns.length; ++i) {
 4993  0
       thisPhrase = columns[i][0] + "=";
 4994  0
       if (columns[i][1].startsWith("VARCHAR")
 4995  
           || columns[i][1].startsWith("CHAR")) {
 4996  0
         thisPhrase += "''";
 4997  
       }
 4998  
 
 4999  0
       if (columns[i][2] != null) {
 5000  0
         if (where.length() > 0) {
 5001  0
           where += " and ";
 5002  
         }
 5003  0
         where += thisPhrase;
 5004  
       } else {
 5005  0
         if (firstColOut) {
 5006  0
           sqlStatement += "select ";
 5007  0
           firstColOut = false;
 5008  
         } else {
 5009  0
           sqlStatement += ", ";
 5010  
         }
 5011  
 
 5012  0
         sqlStatement += columns[i][0];
 5013  
       }
 5014  
     }
 5015  
 
 5016  0
     sqlStatement += " from " + tables;
 5017  
 
 5018  0
     if (where.length() > 0) {
 5019  0
       sqlStatement += " where " + where;
 5020  
     }
 5021  
 
 5022  0
     messageOut(Resources.getString("msgMadeSQL", sqlStatement));
 5023  0
     queryText.setText(sqlStatement);
 5024  0
     checkForNewString(querySelection);
 5025  0
     querySelection.setSelectedItem(sqlStatement);
 5026  0
   }
 5027  
 
 5028  
   /**
 5029  
    * Gets the names of the tables that are referenced during the query
 5030  
    * 
 5031  
    * @return tableNames A String that contains the table names
 5032  
    */
 5033  
   private String getTablesInQuery() {
 5034  
     Iterator<String> tables;
 5035  
     String tableNames;
 5036  
 
 5037  0
     tables = mapOfCurrentTables.keySet().iterator();
 5038  0
     tableNames = "";
 5039  
 
 5040  0
     while (tables.hasNext()) {
 5041  0
       tableNames += "," + tables.next();
 5042  
     }
 5043  
 
 5044  0
     if (tableNames.length() > 0) {
 5045  0
       tableNames = tableNames.substring(1); // Remove first comma
 5046  
     }
 5047  
 
 5048  0
     return tableNames;
 5049  
   }
 5050  
 
 5051  
   /**
 5052  
    * Gets the column name for the column that is being selected in the table
 5053  
    * 
 5054  
    * @return columns A string array with the Column Names and Values
 5055  
    */
 5056  
   private String[][] getColumnNamesForTable() {
 5057  
     String[][] columns;
 5058  
     TableModel model;
 5059  
 
 5060  0
     model = table.getModel();
 5061  
 
 5062  0
     if (modeOfCurrentTable == Query.MODE_DESCRIBE) {
 5063  0
       columns = new String[model.getRowCount()][3];
 5064  0
       for (int i = 0; i < model.getRowCount(); ++i) {
 5065  0
         columns[i][0] = model.getValueAt(i, 0).toString();
 5066  0
         columns[i][1] = model.getValueAt(i, 1).toString(); // Type
 5067  0
         if (table.isRowSelected(i)) {
 5068  0
           columns[i - 1][2] = "Selected";
 5069  
         } else {
 5070  0
           columns[i - 1][2] = null;
 5071  
         }
 5072  
       }
 5073  
     } else {
 5074  0
       columns = new String[model.getColumnCount()][3];
 5075  0
       for (int i = 0; i < model.getColumnCount(); ++i) {
 5076  0
         columns[i][0] = model.getColumnName(i);
 5077  
 
 5078  
         // Remove type if present
 5079  0
         if (columns[i][0].indexOf("[") > -1) {
 5080  0
           columns[i][1] = columns[i][0].substring(columns[i][0].indexOf("[")
 5081  
               + 1);
 5082  0
           columns[i][0] = columns[i][0].substring(0,
 5083  
               columns[i][0].indexOf("[")).trim();
 5084  
         } else {
 5085  
           /**
 5086  
            * Todo: change column name/type design so that we can easily get the
 5087  
            * column type.
 5088  
            */
 5089  0
           columns[i][1] = "Number";
 5090  
         }
 5091  
 
 5092  0
         if (table.isColumnSelected(i)) {
 5093  0
           columns[i][2] = "Selected";
 5094  
         } else {
 5095  0
           columns[i][2] = null;
 5096  
         }
 5097  
       }
 5098  
     }
 5099  
 
 5100  0
     return columns;
 5101  
   }
 5102  
 
 5103  
   /**
 5104  
    * Exports the results to a file
 5105  
    * 
 5106  
    * @param model
 5107  
    *          The model for the current results
 5108  
    * @param fileType
 5109  
    *          The export file type
 5110  
    */
 5111  
   private void chooseFileForSave(TableModel model, int fileType) {
 5112  0
     final JFileChooser chooser = new JFileChooser();
 5113  
     int returnVal;
 5114  
 
 5115  0
     chooser.setDialogTitle(Resources.getString("dlgSaveDataTitle"));
 5116  0
     chooser.setApproveButtonText(Resources.getString("dlgSaveDataButton"));
 5117  0
     chooser.setApproveButtonMnemonic(Resources.getChar(
 5118  
         "dlgSaveDataButtonMnemonic"));
 5119  
 
 5120  0
     if (latestFileDirectory != null) {
 5121  0
       if (latestFileDirectory.isDirectory()) {
 5122  0
         chooser.setCurrentDirectory(latestFileDirectory);
 5123  0
       } else if (latestFileDirectory.getParentFile().isDirectory()) {
 5124  0
         chooser.setCurrentDirectory(latestFileDirectory.getParentFile());
 5125  
       }
 5126  
     }
 5127  
 
 5128  0
     returnVal = chooser.showOpenDialog(this);
 5129  
 
 5130  0
     if (returnVal == JFileChooser.APPROVE_OPTION) {
 5131  0
       latestFileDirectory = chooser.getSelectedFile().getParentFile();
 5132  
 
 5133  0
       switch (fileType) {
 5134  
         case FILE_EXPORT_CSV:
 5135  0
           saveResultAsCSV(model, chooser.getSelectedFile().getAbsoluteFile());
 5136  0
           break;
 5137  
         case FILE_EXPORT_TRIPLES:
 5138  0
           saveResultsAsTriples(model, chooser.getSelectedFile()
 5139  
               .getAbsoluteFile());
 5140  0
           break;
 5141  
         default:
 5142  0
           throw new IllegalArgumentException(
 5143  
               "Unknown file type mode for export: " + fileType);
 5144  
       }
 5145  
     }
 5146  0
   }
 5147  
 
 5148  
   /**
 5149  
    * Saves the Result in a file with the .csv extension
 5150  
    * 
 5151  
    * @param model
 5152  
    *          The model for the current results
 5153  
    * @param fileToWrite
 5154  
    *          The file to write the result to
 5155  
    */
 5156  
   private void saveResultAsCSV(TableModel model, File fileToWrite) {
 5157  
     String fileName;
 5158  
     FileReader testExist;
 5159  
     boolean okToWrite;
 5160  
 
 5161  0
     fileName = fileToWrite.getAbsolutePath();
 5162  
 
 5163  0
     okToWrite = false;
 5164  
 
 5165  0
     if (fileName == null || fileName.trim().length() == 0) {
 5166  0
       userMessage(Resources.getString("errNoFileNameWriteText"),
 5167  
           Resources.getString("errNoFileNameWriteTitle"),
 5168  
           JOptionPane.ERROR_MESSAGE);
 5169  
     } else {
 5170  0
       fileName = fileName.trim();
 5171  0
       if (!fileName.toLowerCase().endsWith(".csv") && !fileName.endsWith(".")) {
 5172  0
         fileName += ".csv";
 5173  
       }
 5174  
 
 5175  
       try {
 5176  0
         testExist = new FileReader(fileName);
 5177  0
         testExist.close();
 5178  0
         okToWrite = JOptionPane.showConfirmDialog(this,
 5179  
             Resources.getString("dlgVerifyOverwriteText", fileName),
 5180  
             Resources.getString("dlgVerifyOverwriteTitle"),
 5181  
             JOptionPane.YES_NO_OPTION,
 5182  
             JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION;
 5183  0
       } catch (FileNotFoundException fnf) {
 5184  0
         okToWrite = true;
 5185  0
       } catch (Exception any) {
 5186  0
         LOGGER.error("Error preparing to save data", any);
 5187  0
         messageOut(
 5188  
             Resources.getString("errFailDataSavePrep", any.getMessage()),
 5189  
             STYLE_RED);
 5190  0
       }
 5191  
     }
 5192  
 
 5193  0
     if (okToWrite) {
 5194  0
       writeDataAsCSV(getQuery().getSql(), model, fileName, false);
 5195  
     }
 5196  0
   }
 5197  
 
 5198  
   /**
 5199  
    * Saves the Result in a file to a Turtle file with the .ttl extension
 5200  
    * 
 5201  
    * @param model
 5202  
    *          The model for the current results
 5203  
    * @param fileToWrite
 5204  
    *          The file to write the result to
 5205  
    */
 5206  
   private void saveResultsAsTriples(TableModel model, File fileToWrite) {
 5207  
     String fileName;
 5208  
     FileReader testExist;
 5209  
     boolean okToWrite;
 5210  
 
 5211  0
     fileName = fileToWrite.getAbsolutePath();
 5212  
 
 5213  0
     okToWrite = false;
 5214  
 
 5215  0
     if (fileName == null || fileName.trim().length() == 0) {
 5216  0
       userMessage(Resources.getString("errNoFileNameWriteText"),
 5217  
           Resources.getString("errNoFileNameWriteTitle"),
 5218  
           JOptionPane.ERROR_MESSAGE);
 5219  
     } else {
 5220  0
       fileName = fileName.trim();
 5221  0
       if (!fileName.toLowerCase().endsWith(".ttl") && !fileName.endsWith(".")) {
 5222  0
         fileName += ".ttl";
 5223  
       }
 5224  
 
 5225  
       try {
 5226  0
         testExist = new FileReader(fileName);
 5227  0
         testExist.close();
 5228  0
         okToWrite = JOptionPane.showConfirmDialog(this,
 5229  
             Resources.getString("dlgVerifyOverwriteText", fileName),
 5230  
             Resources.getString("dlgVerifyOverwriteTitle"),
 5231  
             JOptionPane.YES_NO_OPTION,
 5232  
             JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION;
 5233  0
       } catch (FileNotFoundException fnf) {
 5234  0
         okToWrite = true;
 5235  0
       } catch (Exception any) {
 5236  0
         LOGGER.error("Error preparing to save data", any);
 5237  0
         messageOut(
 5238  
             Resources.getString("errFailDataSavePrep", any.getMessage()),
 5239  
             STYLE_RED);
 5240  0
       }
 5241  
     }
 5242  
 
 5243  0
     if (okToWrite) {
 5244  0
       exportFile = new File(fileName);
 5245  0
       runType = RUNTYPE_TRIPLE_EXPORT;
 5246  0
       new Thread(this).start();
 5247  
       // execute(getQuery().getSql(), new ListTableModel<Object>(), new File(
 5248  
       // fileName));
 5249  
     }
 5250  0
   }
 5251  
 
 5252  
   /**
 5253  
    * Writes the data onto a file that is specified by the filePath
 5254  
    * 
 5255  
    * @param query
 5256  
    *          The SQL statement
 5257  
    * @param model
 5258  
    *          The model for the current results
 5259  
    * @param filePath
 5260  
    *          A String that denotes the filepath
 5261  
    * @param append
 5262  
    *          Whether to append the current results into the file
 5263  
    * 
 5264  
    * @todo Make this handle other data types (especially Date/Time) better
 5265  
    *       for cleaner import to spreadsheet.
 5266  
    */
 5267  
   private void writeDataAsCSV(String query, TableModel model, String filePath,
 5268  
       boolean append) {
 5269  
     PrintWriter out;
 5270  
     int row, col;
 5271  
     boolean[] quote;
 5272  
     boolean quoteThis;
 5273  
     String temp;
 5274  
     Object value;
 5275  
 
 5276  0
     out = null;
 5277  
 
 5278  0
     this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
 5279  0
     (flashRunIndicator = new Thread(new FlashForeground(runIndicator,
 5280  
         Color.red.brighter(), Color.lightGray, 5))).start();
 5281  0
     (timeRunIndicator = new Thread(new InsertTime(timeIndicator,
 5282  
         new java.util.Date().getTime(),
 5283  
         QUERY_EXECUTION_TIMER_UPDATE_DELAY_MS))).start();
 5284  
 
 5285  
     try {
 5286  0
       out = new PrintWriter(new FileWriter(filePath, append));
 5287  
 
 5288  0
       messageOut("");
 5289  0
       messageOut(Resources.getString("msgStartExportToFile", filePath));
 5290  
 
 5291  
       // Output query
 5292  0
       if (!fileExportsRaw.isSelected()) {
 5293  
         // Make it look like a comment using hash comment character
 5294  0
         out.print("#,");
 5295  
 
 5296  0
         out.print("\"");
 5297  
       }
 5298  
       // out.print(getQuery().getSQL());
 5299  0
       out.print(query.replaceAll("\n", " "));
 5300  0
       if (!fileExportsRaw.isSelected()) {
 5301  0
         out.print("\"");
 5302  
       }
 5303  0
       out.println();
 5304  
 
 5305  
       // Setup array to hold which columns need to be quoted
 5306  0
       quote = new boolean[model.getColumnCount()];
 5307  
 
 5308  
       // Output column headings - determine if column needs quotes
 5309  0
       for (col = 0; col < model.getColumnCount(); ++col) {
 5310  0
         if (col > 0) {
 5311  0
           out.print(",");
 5312  
         }
 5313  0
         out.print("\"" + model.getColumnName(col) + "\"");
 5314  
 
 5315  
         /**
 5316  
          * todo: use column type to set need for quotes
 5317  
          */
 5318  0
         quote[col] = false;
 5319  
       }
 5320  0
       out.println();
 5321  
 
 5322  
       // Output data
 5323  0
       for (row = 0; row < model.getRowCount(); ++row) {
 5324  0
         for (col = 0; col < model.getColumnCount(); ++col) {
 5325  0
           if (col > 0) {
 5326  0
             out.print(",");
 5327  
           }
 5328  
 
 5329  
           // Get the field content
 5330  
           try {
 5331  0
             value = model.getValueAt(row, col);
 5332  0
             if (value == null) {
 5333  0
               temp = "";
 5334  0
             } else if (value instanceof java.sql.Timestamp) {
 5335  0
               temp = Utility.formattedDate((java.sql.Timestamp) value);
 5336  
             } else {
 5337  0
               temp = model.getValueAt(row, col).toString();
 5338  0
               if (!fileExportsRaw.isSelected()) {
 5339  0
                 temp = temp.replace('"', '\'');
 5340  0
                 temp = temp.replace('\n', '~');
 5341  
               }
 5342  
             }
 5343  0
           } catch (Exception any) {
 5344  0
             LOGGER.error("Failed to export data", any);
 5345  
 
 5346  
             // Display error and move on
 5347  0
             messageOut(Resources.getString("errFailDuringExport",
 5348  
                 any.getMessage()), STYLE_RED);
 5349  0
             temp = "";
 5350  0
           }
 5351  
 
 5352  
           // Decide if quotes are needed:
 5353  
           // -If the row is a known character type
 5354  
           // -If this field contains a comma
 5355  0
           quoteThis = !fileExportsRaw.isSelected()
 5356  
               && (quote[col] || temp.indexOf(",") > -1);
 5357  
 
 5358  
           // Output the field
 5359  0
           if (quoteThis) {
 5360  0
             out.print("\"");
 5361  
           }
 5362  0
           out.print(temp);
 5363  0
           if (quoteThis) {
 5364  0
             out.print("\"");
 5365  
           }
 5366  
         }
 5367  0
         if (!fileNoCRAddedToExportRows.isSelected()) {
 5368  0
           out.println();
 5369  
         }
 5370  
       }
 5371  
 
 5372  
       // Assume that if writing multiple resultsets to file the
 5373  
       // user would appreciate a separation line between them.
 5374  0
       if (append) {
 5375  0
         out.println("\n********");
 5376  
       }
 5377  
 
 5378  0
       messageOut(Resources.getString("msgEndExportToFile"));
 5379  0
     } catch (Exception any) {
 5380  0
       LOGGER.error("Unable to write data to file", any);
 5381  0
       messageOut(Resources.getString("errFailDataSave", any.toString()),
 5382  
           STYLE_RED);
 5383  
     } finally {
 5384  0
       if (out != null) {
 5385  
         try {
 5386  0
           out.close();
 5387  0
         } catch (Exception any) {
 5388  0
           LOGGER.error("Failed while writing data to CSV file", any);
 5389  0
         }
 5390  
       }
 5391  
     }
 5392  
 
 5393  0
     flashRunIndicator.interrupt();
 5394  0
     flashRunIndicator = null;
 5395  0
     timeRunIndicator.interrupt();
 5396  0
     timeRunIndicator = null;
 5397  0
     this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
 5398  0
   }
 5399  
 
 5400  
   /**
 5401  
    * Get a field from the result set
 5402  
    * 
 5403  
    * @param result
 5404  
    *          The result set
 5405  
    * @param columnNumber
 5406  
    *          The column to read data from
 5407  
    * @param columnType
 5408  
    *          The data type for the column being read
 5409  
    * 
 5410  
    * @return An object representing the data in the current row and selected
 5411  
    *         column
 5412  
    */
 5413  
   private Object getResultField(ResultSet result, int columnNumber,
 5414  
       int columnType) {
 5415  0
     Object value = null;
 5416  
 
 5417  
     try {
 5418  0
       switch (columnType) {
 5419  
         case COLUMN_DATA_TYPE_INT: // Integer
 5420  0
           value = new Integer(result.getInt(columnNumber));
 5421  0
           break;
 5422  
         case COLUMN_DATA_TYPE_LONG: // Long
 5423  0
           value = new Long(result.getLong(columnNumber));
 5424  0
           break;
 5425  
         case COLUMN_DATA_TYPE_DOUBLE: // Double
 5426  0
           value = new Double(result.getDouble(columnNumber));
 5427  0
           break;
 5428  
         case COLUMN_DATA_TYPE_DATETIME: // Date/Time
 5429  0
           value = result.getTimestamp(columnNumber);
 5430  0
           break;
 5431  
         case COLUMN_DATA_TYPE_BLOB: // BLOB
 5432  
           try {
 5433  0
             value = result.getBlob(columnNumber);
 5434  0
           } catch (Throwable any) {
 5435  0
             LOGGER.error("Error retrieving BLOB field key", any);
 5436  
 
 5437  
             // Probably unsupported method (first found in a MySQL Driver)
 5438  0
             value = result.getString(columnNumber);
 5439  0
           }
 5440  0
           break;
 5441  
         case 0: // Fall through to default
 5442  
         default:
 5443  0
           value = result.getString(columnNumber);
 5444  
           break;
 5445  
       }
 5446  0
     } catch (Exception any) {
 5447  0
       LOGGER.error("Error Column["
 5448  
           + columnNumber + " Type[" + columnType + "]", any);
 5449  0
       messageOut(Resources.getString("errFailDataRead",
 5450  
           "" + columnNumber, any.getMessage()),
 5451  
           STYLE_YELLOW);
 5452  
       try {
 5453  0
         value = result.getString(columnNumber);
 5454  0
       } catch (Throwable throwable) {
 5455  0
         LOGGER.error("Error Column["
 5456  
             + columnNumber + " Type[" + columnType + "]", any);
 5457  0
         messageOut(Resources.getString("errFailDataRead",
 5458  
                   "" + columnNumber, any.getMessage()),
 5459  
                   STYLE_RED);
 5460  0
         throw new IllegalStateException("Error Column["
 5461  
             + columnNumber + " Type[" + columnType + "]");
 5462  0
       }
 5463  0
     }
 5464  
 
 5465  0
     return value;
 5466  
   }
 5467  
 
 5468  
   /**
 5469  
    * Writes the data onto a file that is specified by the filePath
 5470  
    * This version writes the data from the ResultSet instance
 5471  
    * so that the results do not need to be loaded into memory.
 5472  
    * 
 5473  
    * @param query
 5474  
    *          The SQL statement for the current data
 5475  
    * @param model
 5476  
    *          The model for the current data
 5477  
    * @param filePath
 5478  
    *          A String that denotes the filepath
 5479  
    * @param result
 5480  
    *          The result set for the query
 5481  
    * @param myType
 5482  
    *          The data type ids for the columns in the result set
 5483  
    * @param append
 5484  
    *          Whether to append the data in the file
 5485  
    * 
 5486  
    * @todo Make this handle other data types (especially Date/Time) better
 5487  
    *       for cleaner import to spreadsheet.
 5488  
    */
 5489  
   private void writeDataAsCSV(String query, TableModel model, String filePath,
 5490  
       ResultSet result, int[] myType, boolean append) {
 5491  
     PrintWriter out;
 5492  
     int row, col;
 5493  
     boolean[] quote;
 5494  
     boolean quoteThis;
 5495  
     String temp;
 5496  
     Object value;
 5497  
 
 5498  0
     out = null;
 5499  
 
 5500  
     /*
 5501  
      * this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
 5502  
      * (flashRunIndicator = new Thread(new FlashForeground(runIndicator,
 5503  
      * Color.red.brighter(), Color.lightGray, 5))).start();
 5504  
      * (timeRunIndicator = new Thread(new InsertTime(timeIndicator,
 5505  
      * new java.util.Date().getTime(),
 5506  
      * 250))).start();
 5507  
      */
 5508  
 
 5509  
     try {
 5510  0
       out = new PrintWriter(new FileWriter(filePath, append));
 5511  
 
 5512  0
       messageOut("");
 5513  0
       messageOut(Resources.getString("msgStartExportToFile", filePath));
 5514  
 
 5515  
       // Output query
 5516  0
       if (!fileExportsRaw.isSelected()) {
 5517  
         // Make it look like a comment using hash comment character
 5518  0
         out.print("#,");
 5519  
 
 5520  0
         out.print("\"");
 5521  
       }
 5522  
       // out.print(getQuery().getSQL());
 5523  0
       out.print(query.replaceAll("\n", " "));
 5524  0
       if (!fileExportsRaw.isSelected()) {
 5525  0
         out.print("\"");
 5526  
       }
 5527  0
       out.println();
 5528  
 
 5529  
       // Setup array to hold which columns need to be quoted
 5530  0
       quote = new boolean[model.getColumnCount()];
 5531  
 
 5532  
       // Output column headings - determine if column needs quotes
 5533  0
       for (col = 0; col < model.getColumnCount(); ++col) {
 5534  0
         if (col > 0) {
 5535  0
           out.print(",");
 5536  
         }
 5537  0
         out.print("\"" + model.getColumnName(col) + "\"");
 5538  
 
 5539  
         /**
 5540  
          * todo: use column type to set need for quotes
 5541  
          */
 5542  0
         quote[col] = false;
 5543  
       }
 5544  0
       out.println();
 5545  
 
 5546  
       // Output data
 5547  0
       row = 0;
 5548  0
       while (result.next()) {
 5549  0
         if (row % RESULT_PROCESSING_ROWS_PER_STATUS_MESSAGE == 0) {
 5550  0
           messageOut("" + row, STYLE_SUBTLE);
 5551  
         }
 5552  0
         for (col = 0; col < model.getColumnCount(); ++col) {
 5553  0
           if (col > 0) {
 5554  0
             out.print(",");
 5555  
           }
 5556  
 
 5557  
           // Get the field content
 5558  0
           value = getResultField(result, col + 1, myType[col]);
 5559  
           try {
 5560  0
             if (value == null) {
 5561  0
               temp = "";
 5562  0
             } else if (value instanceof java.sql.Timestamp) {
 5563  0
               temp = Utility.formattedDate((java.sql.Timestamp) value);
 5564  
             } else {
 5565  0
               temp = value.toString();
 5566  0
               if (!fileExportsRaw.isSelected()) {
 5567  0
                 temp = temp.replace('"', '\'');
 5568  0
                 temp = temp.replace('\n', '~');
 5569  
               }
 5570  
             }
 5571  0
           } catch (Exception any) {
 5572  0
             LOGGER.error("Failed to export data", any);
 5573  
 
 5574  
             // Display error and move on
 5575  0
             messageOut(Resources.getString("errFailDuringExport",
 5576  
                 any.getMessage()), STYLE_RED);
 5577  0
             temp = "";
 5578  0
           }
 5579  
 
 5580  
           // Decide if quotes are needed:
 5581  
           // -If the row is a known character type
 5582  
           // -If this field contains a comma
 5583  0
           quoteThis = !fileExportsRaw.isSelected()
 5584  
               && (quote[col] || temp.indexOf(",") > -1);
 5585  
 
 5586  
           // Output the field
 5587  0
           if (quoteThis) {
 5588  0
             out.print("\"");
 5589  
           }
 5590  0
           out.print(temp);
 5591  0
           if (quoteThis) {
 5592  0
             out.print("\"");
 5593  
           }
 5594  
         }
 5595  0
         if (!fileNoCRAddedToExportRows.isSelected()) {
 5596  0
           out.println();
 5597  
         }
 5598  0
         ++row;
 5599  
       }
 5600  
 
 5601  
       // Assume that if writing multiple resultsets to file the
 5602  
       // user would appreciate a separation line between them.
 5603  0
       if (append) {
 5604  0
         out.println("\n********");
 5605  
       }
 5606  
 
 5607  0
       messageOut(Resources.getString("msgEndExportToFile"));
 5608  0
     } catch (Exception any) {
 5609  0
       LOGGER.error("Unable to write data to file", any);
 5610  0
       messageOut(Resources.getString("errFailDataSave", any.toString()),
 5611  
           STYLE_RED);
 5612  
     } finally {
 5613  0
       if (out != null) {
 5614  
         try {
 5615  0
           out.close();
 5616  0
         } catch (Exception any) {
 5617  0
           LOGGER.error("Failed while writing data to CSV file", any);
 5618  0
         }
 5619  
       }
 5620  
     }
 5621  
 
 5622  
     /*
 5623  
      * flashRunIndicator.interrupt();
 5624  
      * flashRunIndicator = null;
 5625  
      * timeRunIndicator.interrupt();
 5626  
      * timeRunIndicator = null;
 5627  
      * this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
 5628  
      */
 5629  0
   }
 5630  
 
 5631  
   /**
 5632  
    * Sets the selected query as the text in the querytext area
 5633  
    */
 5634  
   private void setupSelectedQuery() {
 5635  
     Query query;
 5636  
 
 5637  0
     query = getQuery();
 5638  
 
 5639  0
     if (query != null) {
 5640  0
       selectMode(getQuery().getMode());
 5641  0
       queryText.setText(getQuery().getSql());
 5642  
 
 5643  0
       if (commentedQuery()) {
 5644  0
         commentToggle.setText(Resources.getString("ctlUncomment"));
 5645  0
         execute.setEnabled(false);
 5646  
       } else {
 5647  0
         commentToggle.setText(Resources.getString("ctlComment"));
 5648  0
         execute.setEnabled(true);
 5649  
       }
 5650  
     } else {
 5651  0
       queryText.setText("");
 5652  
     }
 5653  
 
 5654  0
     setPrevNextIndication();
 5655  0
     setExportAvailable(false);
 5656  0
   }
 5657  
 
 5658  
   /**
 5659  
    * Executes the query(ies). It is expected that this will be
 5660  
    * run on its own thread -- hence it is a run method.
 5661  
    */
 5662  
   public void run() {
 5663  
 
 5664  0
     this.setCursor(new Cursor(Cursor.WAIT_CURSOR));
 5665  0
     (flashRunIndicator = new Thread(new FlashForeground(runIndicator,
 5666  
         Color.red.brighter(), Color.lightGray, 5))).start();
 5667  0
     (timeRunIndicator = new Thread(new InsertTime(timeIndicator,
 5668  
         new java.util.Date().getTime(),
 5669  
         QUERY_EXECUTION_TIMER_UPDATE_DELAY_MS))).start();
 5670  
     try {
 5671  0
       if (runType == RUNTYPE_ALL) {
 5672  0
         runAllQueries();
 5673  0
       } else if (runType == RUNTYPE_TRIPLE_EXPORT) {
 5674  0
         message.setText("");
 5675  0
         messageOut(Resources.getString("msgStartExportToFile",
 5676  
             exportFile.getAbsolutePath()), STYLE_BOLD);
 5677  0
         messageOut("");
 5678  0
         execute(getQuery().getSql(), new ListTableModel<Object>(), exportFile);
 5679  
       } else {
 5680  0
         checkForNewString(querySelection);
 5681  0
         checkForNewString(connectString);
 5682  0
         processStatement();
 5683  
       }
 5684  0
     } catch (Throwable any) {
 5685  0
       LOGGER.error("Failure while trying to execute query", any);
 5686  0
       messageOut(Resources.getString("errFailSQLText", any.getMessage()),
 5687  
           STYLE_RED);
 5688  0
     }
 5689  0
     flashRunIndicator.interrupt();
 5690  0
     flashRunIndicator = null;
 5691  0
     timeRunIndicator.interrupt();
 5692  0
     timeRunIndicator = null;
 5693  0
     this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
 5694  0
   }
 5695  
 
 5696  
   /**
 5697  
    * Executes all the queries
 5698  
    */
 5699  
   private void runAllQueries() {
 5700  
     int numExecutions, numQueries;
 5701  
     int execution, query;
 5702  
     ProgressMonitor monitor;
 5703  
     boolean canceled;
 5704  
     java.util.Date start;
 5705  
     int elapsed;
 5706  
     long remaining;
 5707  
     int hours, minutes, seconds;
 5708  
 
 5709  0
     numQueries = querySelection.getModel().getSize();
 5710  
     try {
 5711  0
       numExecutions = Integer.parseInt(JOptionPane.showInputDialog(this,
 5712  
           Resources.getString("dlgAllQueriesText"),
 5713  
           Resources.getString("dlgAllQueriesTitle"),
 5714  
           JOptionPane.QUESTION_MESSAGE));
 5715  0
     } catch (Exception any) {
 5716  0
       numExecutions = 0;
 5717  0
     }
 5718  
 
 5719  0
     messageOut(Resources.getString("msgNumExecutions", numExecutions + ""));
 5720  
 
 5721  0
     monitor = new ProgressMonitor(this,
 5722  
         Resources.getString("dlgRunAllQueriesProgressTitle"),
 5723  
         Resources.getString("dlgRunAllQueriesProgressNote",
 5724  
             "0", numExecutions + "", "0", numQueries + ""), 0,
 5725  
         numQueries * Math.abs(numExecutions));
 5726  
 
 5727  0
     getContentPane().setCursor(new Cursor(Cursor.WAIT_CURSOR));
 5728  
 
 5729  0
     if (numExecutions < 0) {
 5730  0
       numExecutions = Math.abs(numExecutions);
 5731  
 
 5732  0
       for (query = 0; !monitor.isCanceled() && query < numQueries; ++query) {
 5733  0
         querySelection.setSelectedIndex(query);
 5734  0
         elapsed = -1;
 5735  0
         for (execution = 0; !monitor.isCanceled() && execution < numExecutions; ++execution) {
 5736  0
           monitor.setProgress(query * numExecutions + execution);
 5737  0
           if (elapsed <= 0) {
 5738  0
             monitor.setNote(Resources.getString("dlgRunAllQueriesProgressNote",
 5739  
                 (execution + 1) + "", numExecutions + "", (query + 1) + "",
 5740  
                 numQueries + ""));
 5741  
           } else {
 5742  0
             remaining = elapsed
 5743  
                 * ((numExecutions * (numQueries - (query + 1)))
 5744  
                     + (numExecutions - execution));
 5745  0
             hours = (int) (remaining / SECONDS_PER_HOUR);
 5746  0
             remaining -= hours * SECONDS_PER_HOUR;
 5747  0
             minutes = (int) (remaining / SECONDS_PER_MINUTE);
 5748  0
             remaining -= minutes * SECONDS_PER_MINUTE;
 5749  0
             seconds = (int) remaining;
 5750  
 
 5751  0
             monitor.setNote(Resources.getString(
 5752  
                 "dlgRunAllQueriesProgressNoteWithRemainTime",
 5753  
                 (execution + 1) + "", numExecutions + "", (query + 1) + "",
 5754  
                 numQueries + "", Utility.formattedNumber(hours, "00"),
 5755  
                 Utility.formattedNumber(minutes, "00"),
 5756  
                 Utility.formattedNumber(seconds, "00")));
 5757  
           }
 5758  0
           messageOut(Resources.getString("dlgRunAllQueriesProgressNote",
 5759  
               (execution + 1) + "", numExecutions + "", (query + 1) + "",
 5760  
               numQueries + ""));
 5761  0
           start = new java.util.Date();
 5762  0
           processStatement(true);
 5763  0
           elapsed = (int) ((new java.util.Date().getTime()
 5764  
               - start.getTime()) / 1000);
 5765  
         }
 5766  
       }
 5767  
     } else {
 5768  0
       elapsed = -1;
 5769  0
       for (execution = 0; !monitor.isCanceled() && execution < numExecutions; ++execution) {
 5770  0
         start = new java.util.Date();
 5771  0
         for (query = 0; !monitor.isCanceled() && query < numQueries; ++query) {
 5772  0
           querySelection.setSelectedIndex(query);
 5773  0
           monitor.setProgress(execution * numQueries + query);
 5774  
 
 5775  0
           if (elapsed <= 0) {
 5776  0
             monitor.setNote(Resources.getString("dlgRunAllQueriesProgressNote",
 5777  
                 (execution + 1) + "", numExecutions + "", (query + 1) + "",
 5778  
                 numQueries + ""));
 5779  
           } else {
 5780  0
             remaining = elapsed * (numExecutions - execution);
 5781  0
             hours = (int) (remaining / SECONDS_PER_HOUR);
 5782  0
             remaining -= hours * SECONDS_PER_HOUR;
 5783  0
             minutes = (int) (remaining / SECONDS_PER_MINUTE);
 5784  0
             remaining -= minutes * SECONDS_PER_MINUTE;
 5785  0
             seconds = (int) remaining;
 5786  
 
 5787  0
             monitor.setNote(Resources.getString(
 5788  
                 "dlgRunAllQueriesProgressNoteWithRemainTime",
 5789  
                 (execution + 1) + "", numExecutions + "", (query + 1) + "",
 5790  
                 numQueries + "", Utility.formattedNumber(hours, "00"),
 5791  
                 Utility.formattedNumber(minutes, "00"),
 5792  
                 Utility.formattedNumber(seconds, "00")));
 5793  
           }
 5794  
 
 5795  0
           messageOut(Resources.getString("dlgRunAllQueriesProgressNote",
 5796  
               (execution + 1) + "", numExecutions + "", (query + 1) + "",
 5797  
               numQueries + ""));
 5798  0
           processStatement(true);
 5799  
         }
 5800  0
         elapsed = (int) ((new java.util.Date().getTime()
 5801  
             - start.getTime()) / 1000);
 5802  
       }
 5803  
     }
 5804  
 
 5805  0
     canceled = monitor.isCanceled();
 5806  
 
 5807  0
     monitor.close();
 5808  
 
 5809  0
     getContentPane().setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
 5810  
 
 5811  0
     if (canceled) {
 5812  0
       userMessage(Resources.getString("dlgExecutionsCanceledText"),
 5813  
           Resources.getString("dlgExecutionsCanceledTitle"),
 5814  
           JOptionPane.WARNING_MESSAGE);
 5815  0
     } else if (numExecutions != 0) {
 5816  0
       userMessage(Resources.getString("dlgExecutionsCompletedText"),
 5817  
           Resources.getString("dlgExecutionsCompletedTitle"),
 5818  
           JOptionPane.INFORMATION_MESSAGE);
 5819  
     } else {
 5820  0
       userMessage(Resources.getString("dlgExecutionsNoneText"),
 5821  
           Resources.getString("dlgExecutionsNoneTitle"),
 5822  
           JOptionPane.INFORMATION_MESSAGE);
 5823  
     }
 5824  0
   }
 5825  
 
 5826  
   /**
 5827  
    * Uncomments the selected query statement if it is commented or
 5828  
    * comments the statement if it is uncommented and replaces the query in
 5829  
    * the combo box.
 5830  
    */
 5831  
   private void commentToggle() {
 5832  
     String newSQL;
 5833  
     int position;
 5834  
     Query query;
 5835  
 
 5836  0
     if ((position = querySelection.getSelectedIndex()) > -1) {
 5837  0
       query = getQuery();
 5838  0
       newSQL = query.getSql();
 5839  
 
 5840  0
       LOGGER.debug("commentToggle::Orig[" + newSQL + "]");
 5841  
 
 5842  0
       if (newSQL.startsWith(COMMENT_PREFIX)) {
 5843  0
         newSQL = newSQL.substring(2);
 5844  
       } else {
 5845  0
         newSQL = COMMENT_PREFIX + newSQL;
 5846  
       }
 5847  
 
 5848  0
       LOGGER.debug("commentToggle:New[" + newSQL + "]");
 5849  
 
 5850  0
       replaceInCombo(querySelection, position,
 5851  
           new Query(newSQL, query.getMode()));
 5852  
     }
 5853  0
   }
 5854  
 
 5855  
   /**
 5856  
    * Builds the GUI window title - including the currently open SQL statement
 5857  
    * file.
 5858  
    * 
 5859  
    * @param pathToSQLFile
 5860  
    *          The path to the currently open SQL statement file
 5861  
    */
 5862  
   private void setQueryFilename(String pathToSQLFile) {
 5863  0
     queryFilename = pathToSQLFile;
 5864  0
     setTitle("BasicQuery - " + queryFilename);
 5865  0
   }
 5866  
 
 5867  
   /**
 5868  
    * Open or create a SQL statement file.
 5869  
    */
 5870  
   private void openSQLFile() {
 5871  
     JFileChooser fileMenu;
 5872  0
     FileFilter defaultFileFilter = null;
 5873  0
     FileFilter preferredFileFilter = null;
 5874  
     File chosenSQLFile;
 5875  
     int returnVal;
 5876  
 
 5877  0
     chosenSQLFile = null;
 5878  
 
 5879  
     // Save current information, including SQL Statements
 5880  0
     saveConfig();
 5881  
 
 5882  
     // Allow user to choose/create new file for SQL Statements
 5883  0
     fileMenu = new JFileChooser(new File(queryFilename));
 5884  
 
 5885  0
     for (FileFilterDefinition filterDefinition : FileFilterDefinition.values()) {
 5886  0
       if (filterDefinition.name().startsWith("QUERY")) {
 5887  0
         final FileFilter fileFilter = new SuffixFileFilter(
 5888  
             filterDefinition.description(), filterDefinition.acceptedSuffixes());
 5889  0
         if (filterDefinition.isPreferredOption()) {
 5890  0
           preferredFileFilter = fileFilter;
 5891  
         }
 5892  0
         fileMenu.addChoosableFileFilter(fileFilter);
 5893  0
         if (filterDefinition.description().equals(
 5894  
             latestChosenQueryFileFilterDescription)) {
 5895  0
           defaultFileFilter = fileFilter;
 5896  
         }
 5897  
       }
 5898  
     }
 5899  
 
 5900  0
     if (defaultFileFilter != null) {
 5901  0
       fileMenu.setFileFilter(defaultFileFilter);
 5902  0
     } else if (latestChosenQueryFileFilterDescription != null
 5903  
         && latestChosenQueryFileFilterDescription.startsWith("All")) {
 5904  0
       fileMenu.setFileFilter(fileMenu.getAcceptAllFileFilter());
 5905  0
     } else if (preferredFileFilter != null) {
 5906  0
       fileMenu.setFileFilter(preferredFileFilter);
 5907  
     }
 5908  
 
 5909  0
     fileMenu.setSelectedFile(new File(queryFilename));
 5910  0
     fileMenu.setDialogTitle(Resources.getString("dlgSQLFileTitle"));
 5911  0
     fileMenu.setDialogType(JFileChooser.OPEN_DIALOG);
 5912  0
     fileMenu.setFileSelectionMode(JFileChooser.FILES_ONLY);
 5913  0
     fileMenu.setMultiSelectionEnabled(false);
 5914  
 
 5915  0
     if (fileMenu.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
 5916  0
       chosenSQLFile = fileMenu.getSelectedFile();
 5917  
       
 5918  
       // Adjust file suffix if necessary
 5919  0
       final FileFilter fileFilter = fileMenu.getFileFilter();
 5920  0
       if (fileFilter != null && fileFilter instanceof SuffixFileFilter
 5921  
           && !fileMenu.getFileFilter().accept(chosenSQLFile)) {
 5922  0
         chosenSQLFile = ((SuffixFileFilter) fileFilter)
 5923  
             .makeWithPrimarySuffix(chosenSQLFile);
 5924  
       }
 5925  
       
 5926  0
       if (!chosenSQLFile.exists()) {
 5927  0
         returnVal = JOptionPane.showConfirmDialog(this,
 5928  
             Resources.getString("dlgNewSQLFileText", chosenSQLFile.getName()),
 5929  
             Resources.getString("dlgNewSQLFileTitle"),
 5930  
             JOptionPane.
 5931  
             YES_NO_CANCEL_OPTION,
 5932  
             JOptionPane.QUESTION_MESSAGE);
 5933  0
         if (returnVal == JOptionPane.NO_OPTION) {
 5934  0
           querySelection.removeAllItems();
 5935  0
           queryText.setText("");
 5936  0
           QueryHistory.getInstance().clearAllQueries();
 5937  
 
 5938  
           // Update GUI
 5939  0
           setPrevNextIndication();
 5940  0
         } else if (returnVal == JOptionPane.CANCEL_OPTION) {
 5941  0
           chosenSQLFile = null;
 5942  
         }
 5943  
       } else {
 5944  0
         setQueryFilename(chosenSQLFile.getAbsolutePath());
 5945  0
         querySelection.removeAllItems();
 5946  0
         queryText.setText("");
 5947  0
         loadCombo(querySelection, queryFilename);
 5948  0
         QueryHistory.getInstance().clearAllQueries();
 5949  
 
 5950  
         // Update GUI
 5951  0
         setPrevNextIndication();
 5952  
       }
 5953  
     }
 5954  
 
 5955  
     try {
 5956  0
       latestChosenQueryFileFilterDescription = fileMenu.getFileFilter()
 5957  
           .getDescription();
 5958  0
     } catch (Throwable throwable) {
 5959  0
       LOGGER.warn("Unable to determine which ontology file filter was chosen",
 5960  
           throwable);
 5961  0
     }
 5962  
 
 5963  0
     if (chosenSQLFile != null) {
 5964  0
       setQueryFilename(chosenSQLFile.getAbsolutePath());
 5965  0
       saveConfig();
 5966  
     }
 5967  0
   }
 5968  
 
 5969  
   /**
 5970  
    * Add latest query index to the history of executed queries
 5971  
    * The query is added after the currently selected query in the history list.
 5972  
    * The associated connect URL is also saved, though its use is controlled by a
 5973  
    * menu checkbox setting.
 5974  
    * 
 5975  
    * @param results
 5976  
    *          The table model with the current query results
 5977  
    */
 5978  
   private void histMaintQueryExecuted(TableModel results) {
 5979  0
     final int thisQuery = querySelection.getSelectedIndex();
 5980  
 
 5981  0
     if (thisQuery >= 0) {
 5982  0
       QueryHistory.getInstance().addQuery(new QueryInfo(thisQuery,
 5983  
             connectString.getSelectedIndex(),
 5984  
             results));
 5985  
     }
 5986  
 
 5987  
     // Update GUI
 5988  0
     setPrevNextIndication();
 5989  0
   }
 5990  
 
 5991  
   /**
 5992  
    * Activate/deactivate the previous and next query history indicators based
 5993  
    * on the number of history entries and the current position within the
 5994  
    * history
 5995  
    * list.
 5996  
    */
 5997  
   private void setPrevNextIndication() {
 5998  0
     previousQuery
 5999  
         .setEnabled(QueryHistory.getInstance().hasPrevious()
 6000  
             || (QueryHistory.getInstance().getNumberOfQueries() > 0 && QueryHistory
 6001  
                 .getInstance().getCurrentQueryInfo().getSQLIndex() != querySelection
 6002  
                 .getSelectedIndex()));
 6003  0
     nextQuery.setEnabled(QueryHistory.getInstance().hasNext());
 6004  0
   }
 6005  
 
 6006  
   /**
 6007  
    * Maintain the query history list when an entry is deleted from the
 6008  
    * collection stored of SQL queries. For each entry in the history list the
 6009  
    * impact of a deletion may be:
 6010  
    * <ul>
 6011  
    * <li>None, if the deleted query follows the index of the history entry
 6012  
    * <li>Require subtracting one from the SQL history index position if it
 6013  
    * follows the deleted query; or
 6014  
    * <li>Require removal of the history entry if the SQL index held is the index
 6015  
    * of the deleted query.
 6016  
    * </ul>
 6017  
    * 
 6018  
    * @param queryIndex
 6019  
    *          The index of the deleted query in the stored query list.
 6020  
    */
 6021  
   private void histMaintQueryDeleted(int queryIndex) {
 6022  0
     QueryHistory.getInstance().deleteQueryAtIndex(queryIndex);
 6023  
 
 6024  
     // Update GUI
 6025  0
     setPrevNextIndication();
 6026  0
   }
 6027  
 
 6028  
   /**
 6029  
    * Set the currently selected query to the previous SQL index in the history
 6030  
    * list.
 6031  
    * If the user has selected to also associate the connect URL, then the last
 6032  
    * connect
 6033  
    * URL used for the query will also be selected.
 6034  
    */
 6035  
   private void histSelectPrev() {
 6036  
     int currentSQLIndex, currentConnectIndex;
 6037  
     int histSQLIndex, histConnectIndex;
 6038  0
     boolean newQuery = false;
 6039  0
     TableModel histModel = null;
 6040  
     TableSorter sorter;
 6041  
     QueryInfo queryInfo;
 6042  
 
 6043  0
     currentSQLIndex = querySelection.getSelectedIndex();
 6044  0
     currentConnectIndex = connectString.getSelectedIndex();
 6045  
 
 6046  
     /**
 6047  
      * Two possibilities, the user has changed the selected query and/or
 6048  
      * connection string without executing and wants to return to the last
 6049  
      * executed; or the latest executed query is currently selected in which
 6050  
      * case the user expects to return to a query before this one
 6051  
      */
 6052  0
     if (QueryHistory.getInstance().getNumberOfQueries() > 0) {
 6053  0
       queryInfo = QueryHistory.getInstance().getCurrentQueryInfo();
 6054  0
       histSQLIndex = queryInfo.getSQLIndex();
 6055  0
       histConnectIndex = queryInfo.getURLIndex();
 6056  
 
 6057  0
       if (histSQLIndex == currentSQLIndex
 6058  
           && histConnectIndex == currentConnectIndex) {
 6059  0
         QueryHistory.getInstance().moveBackward();
 6060  0
         queryInfo = QueryHistory.getInstance().getCurrentQueryInfo();
 6061  0
         histSQLIndex = queryInfo.getSQLIndex();
 6062  0
         histConnectIndex = queryInfo.getURLIndex();
 6063  0
         histModel = queryInfo.getResults();
 6064  0
         newQuery = true;
 6065  
       }
 6066  
 
 6067  0
       querySelection.setSelectedIndex(histSQLIndex);
 6068  
 
 6069  0
       if (configHistoryAssocSQLAndConnect.isSelected()) {
 6070  0
         connectString.setSelectedIndex(histConnectIndex);
 6071  
       }
 6072  
 
 6073  0
       if (newQuery) {
 6074  
         try {
 6075  0
           sorter = (TableSorter) table.getModel();
 6076  0
           sorter.removeMouseListenerFromHeaderInTable(table);
 6077  0
         } catch (Throwable any) {
 6078  
           // Probably table was empty
 6079  0
           if (LOGGER.isDebugEnabled()) {
 6080  0
             LOGGER
 6081  
                 .debug(
 6082  
                     "Error when sorting results, probably no results in model",
 6083  
                     any);
 6084  
           }
 6085  0
         }
 6086  0
         table.setModel(new ListTableModel<Object>());
 6087  0
         if (histModel != null) {
 6088  0
           sorter = new TableSorter(histModel);
 6089  0
           table.setModel(sorter);
 6090  0
           sorter.addMouseListenerToHeaderInTable(table);
 6091  0
           Utility.initColumnSizes(table, sorter);
 6092  
         }
 6093  
       }
 6094  
 
 6095  
       // Update GUI
 6096  0
       setPrevNextIndication();
 6097  
     }
 6098  0
   }
 6099  
 
 6100  
   /**
 6101  
    * Set the currently selected query to the next SQL index in the history list.
 6102  
    * If the user has selected to also associate the connect URL, then the last
 6103  
    * connect
 6104  
    * URL used for the query will also be selected.
 6105  
    */
 6106  
   private void histSelectNext() {
 6107  
     int histSQLIndex, histConnectIndex;
 6108  0
     TableModel histModel = null;
 6109  
     TableSorter sorter;
 6110  
     QueryInfo queryInfo;
 6111  
 
 6112  0
     QueryHistory.getInstance().moveForward();
 6113  0
     queryInfo = QueryHistory.getInstance().getCurrentQueryInfo();
 6114  0
     histSQLIndex = queryInfo.getSQLIndex();
 6115  0
     histConnectIndex = queryInfo.getURLIndex();
 6116  0
     histModel = queryInfo.getResults();
 6117  
 
 6118  0
     querySelection.setSelectedIndex(histSQLIndex);
 6119  
 
 6120  0
     if (configHistoryAssocSQLAndConnect.isSelected()) {
 6121  0
       connectString.setSelectedIndex(histConnectIndex);
 6122  
     }
 6123  
 
 6124  
     try {
 6125  0
       sorter = (TableSorter) table.getModel();
 6126  0
       sorter.removeMouseListenerFromHeaderInTable(table);
 6127  0
     } catch (Throwable any) {
 6128  
       // Probably table was empty
 6129  0
       if (LOGGER.isDebugEnabled()) {
 6130  0
         LOGGER.debug(
 6131  
               "Error when sorting results, probably no results in model", any);
 6132  
       }
 6133  0
     }
 6134  0
     table.setModel(new ListTableModel<Object>());
 6135  0
     if (histModel != null) {
 6136  0
       sorter = new TableSorter(histModel);
 6137  0
       table.setModel(sorter);
 6138  0
       sorter.addMouseListenerToHeaderInTable(table);
 6139  0
       Utility.initColumnSizes(table, sorter);
 6140  
     }
 6141  
 
 6142  
     // Update GUI
 6143  0
     setPrevNextIndication();
 6144  0
   }
 6145  
 
 6146  
   /**
 6147  
    * Allow the user to place the queries into a particluar order. A separate
 6148  
    * dialog is used that permits rearranging the list of queries.
 6149  
    */
 6150  
   private void reorderQueries() {
 6151  
     List<Object> queries;
 6152  
 
 6153  0
     queries = new ArrayList<Object>();
 6154  
 
 6155  0
     for (int loop = 0; loop < querySelection.getItemCount(); ++loop) {
 6156  0
       queries.add(querySelection.getItemAt(loop));
 6157  
     }
 6158  
 
 6159  0
     final ReorderDialog setOrder = new ReorderDialog(this, queries);
 6160  
 
 6161  0
     if (setOrder.isReordered()) {
 6162  0
       rebuildSQLListing(setOrder.getAsOrdered());
 6163  
     }
 6164  0
   }
 6165  
 
 6166  
   /**
 6167  
    * Reloads the list of queries in the combobox.
 6168  
    * 
 6169  
    * @param queries
 6170  
    *          List The collection of queries
 6171  
    */
 6172  
   private void rebuildSQLListing(List<Object> queries) {
 6173  0
     QueryHistory.getInstance().clearAllQueries();
 6174  
 
 6175  0
     querySelection.removeAllItems();
 6176  0
     for (int loop = 0; loop < queries.size(); ++loop) {
 6177  0
       addToCombo(querySelection, queries.get(loop));
 6178  
     }
 6179  0
   }
 6180  
 
 6181  
   /**
 6182  
    * Sort a table model based on the selected columns.
 6183  
    */
 6184  
   private void sortSelectedColumns() {
 6185  
     int[] selectedViewColumns;
 6186  
     int[] selectedModelColumns;
 6187  
     TableSorter sorter;
 6188  
 
 6189  0
     selectedViewColumns = table.getSelectedColumns();
 6190  0
     selectedModelColumns = new int[selectedViewColumns.length];
 6191  
 
 6192  0
     for (int column = 0; column < selectedViewColumns.length; ++column) {
 6193  0
       selectedModelColumns[column] =
 6194  
           table.convertColumnIndexToModel(selectedViewColumns[column]);
 6195  
     }
 6196  
 
 6197  
     try {
 6198  0
       sorter = (TableSorter) table.getModel();
 6199  0
       sorter.sortByColumns(selectedModelColumns);
 6200  0
     } catch (Throwable any) {
 6201  
       // Probably table was empty
 6202  0
       if (LOGGER.isDebugEnabled()) {
 6203  0
         LOGGER.debug(
 6204  
             "Error when sorting results, probably no results in model", any);
 6205  
       }
 6206  0
     }
 6207  0
   }
 6208  
 
 6209  
   /**
 6210  
    * Run a SQL statement on its own thread. If a statement is currently being
 6211  
    * executed the user may either cancel the new request or the currently
 6212  
    * running query.
 6213  
    * 
 6214  
    * @param statementRunType
 6215  
    *          The type of query execution -- single or
 6216  
    *          multiple statement
 6217  
    */
 6218  
   private void runIt(int statementRunType) {
 6219  0
     if (runningQuery != null) {
 6220  0
       if (!runningQuery.isAlive()) {
 6221  0
         runningQuery = null;
 6222  
       } else {
 6223  0
         final int decision = JOptionPane.showConfirmDialog(this,
 6224  
             Utility.
 6225  
                 characterInsert(Resources.getString("dlgCancelQueryText"),
 6226  
                     "\n",
 6227  
                     40, 60, " ."), Resources.getString("dlgCancelQueryTitle"),
 6228  
             JOptionPane.YES_NO_OPTION,
 6229  
             JOptionPane.WARNING_MESSAGE);
 6230  0
         if (decision == JOptionPane.YES_OPTION) {
 6231  0
           runningQuery.interrupt();
 6232  0
           runningQuery = null;
 6233  0
           flashRunIndicator.interrupt();
 6234  0
           flashRunIndicator = null;
 6235  0
           timeRunIndicator.interrupt();
 6236  0
           timeRunIndicator = null;
 6237  0
           this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
 6238  
         }
 6239  
       }
 6240  
     }
 6241  
 
 6242  0
     if (runningQuery == null) {
 6243  0
       runType = statementRunType;
 6244  0
       (runningQuery = new Thread(this)).start();
 6245  
     }
 6246  0
   }
 6247  
 
 6248  
   /**
 6249  
    * Notify user if no DB drivers have been loaded. Probably no DB JARs
 6250  
    * installed.
 6251  
    */
 6252  
   private void noDBDriverWarning() {
 6253  0
     JOptionPane.showMessageDialog(
 6254  
         this,
 6255  
         Resources.getString("dlgNoDBDriversLoadedText",
 6256  
             new File(dbDriverDir).getAbsolutePath(),
 6257  
             Configuration.instance().getFile(FILENAME_DRIVERS)
 6258  
                 .getAbsolutePath()),
 6259  
         Resources.getString("dlgNoDBDriversLoadedTitle"),
 6260  
         JOptionPane.ERROR_MESSAGE);
 6261  0
   }
 6262  
 
 6263  
   /**
 6264  
    * Displays an information message in a dialog box giving details about the
 6265  
    * BasicQuery that has been executed
 6266  
    */
 6267  
   private void about() {
 6268  
     String slMessage;
 6269  
 
 6270  0
     slMessage = "Execute arbitrary SQL statements against"
 6271  
         + " any database with JDBC library.Records timing"
 6272  
         + " and memory usage information to assist in"
 6273  
         + " performance tuning of database interactions.\n\n";
 6274  
 
 6275  0
     slMessage += "David Read, www.monead.com\n\n";
 6276  
 
 6277  0
     slMessage += "Copyright (c) 2004-2014\n\n"
 6278  
         + "This program is free software; you can redistribute it and/or modify "
 6279  
         +
 6280  
         "it under the terms of the GNU General Public License as published by "
 6281  
         +
 6282  
         "the Free Software Foundation; either version 2 of the License, or "
 6283  
         + "(at your option) any later version.\n\n"
 6284  
         + "This program is distributed in the hope that it will be useful, "
 6285  
         + "but WITHOUT ANY WARRANTY; without even the implied warranty of "
 6286  
         + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the "
 6287  
         + "GNU General Public License for more details.\n\n"
 6288  
         + "You should have received a copy of the GNU General Public License "
 6289  
         + "along with this program; if not, write to the:\n"
 6290  
         + "     Free Software Foundation Inc.\n"
 6291  
         + "     59 Temple Place, Suite 330\n"
 6292  
         + "     Boston, MA  02111-1307  USA";
 6293  
 
 6294  0
     userMessage("BasicQuery SQL Execution Tool\n\n"
 6295  
         + "Version: " + VERSION + "\n\n"
 6296  
         + Utility.characterInsert(slMessage, "\n", 70, 90, " ."),
 6297  
         "About BasicQuery", JOptionPane.INFORMATION_MESSAGE, false);
 6298  0
   }
 6299  
 
 6300  
   /**
 6301  
    * Supply a brief usage summary for the parameterized SQL syntax.
 6302  
    */
 6303  
   private void helpParameterizedSQL() {
 6304  
     String messageText;
 6305  
     String[] dataTypes;
 6306  
     int loop;
 6307  
 
 6308  0
     dataTypes = SQLTypes.getKnownTypeNames();
 6309  
 
 6310  0
     messageText = Resources.getString("dlgUsingParamsTextOverview") + " ";
 6311  
 
 6312  0
     for (loop = 0; loop < dataTypes.length; ++loop) {
 6313  0
       messageText += dataTypes[loop];
 6314  0
       if (loop < dataTypes.length - 1) {
 6315  0
         messageText += ", ";
 6316  
       }
 6317  0
       if ((loop + 1) % 5 == 0) {
 6318  0
         messageText += "\n                           ";
 6319  
       }
 6320  
     }
 6321  
 
 6322  0
     messageText += Resources.getString("dlgUsingParamsTextExamples") + " ";
 6323  
 
 6324  0
     JOptionPane.showMessageDialog(this, messageText,
 6325  
         Resources.getString("dlgUsingParamsTitle"),
 6326  
         JOptionPane.INFORMATION_MESSAGE);
 6327  0
   }
 6328  
 
 6329  
   /**
 6330  
    * Advance the list of queries to the next query if the list is not
 6331  
    * already at the end.
 6332  
    */
 6333  
   private void nextQuerySelection() {
 6334  0
     if (querySelection.getSelectedIndex() + 1 < querySelection.getItemCount()) {
 6335  0
       querySelection.setSelectedIndex(querySelection.getSelectedIndex() + 1);
 6336  
     }
 6337  0
   }
 6338  
 
 6339  
   /**
 6340  
    * Select all the data in the result table
 6341  
    */
 6342  
   private void selectAllData() {
 6343  0
     table.selectAll();
 6344  0
   }
 6345  
 
 6346  
   /**
 6347  
    * Enable or disable the export menu items based on the latest query
 6348  
    * 
 6349  
    * @param available
 6350  
    *          Whether the export options should be enabled
 6351  
    */
 6352  
   private void setExportAvailable(boolean available) {
 6353  0
     fileSaveAsCSV.setEnabled(available);
 6354  0
     fileSaveAsTriples.setEnabled(available);
 6355  0
   }
 6356  
 
 6357  
   /**
 6358  
    * Copy the selected data cells to the clipboard
 6359  
    */
 6360  
   private void copySelectionToClipboard() {
 6361  
     Action objlCopy;
 6362  
 
 6363  
     try {
 6364  0
       objlCopy = TransferHandler.getCopyAction();
 6365  0
       objlCopy.actionPerformed(new ActionEvent(table,
 6366  
           ActionEvent.ACTION_PERFORMED,
 6367  
           (String) objlCopy.getValue(
 6368  
               Action.
 6369  
               NAME), EventQueue.getMostRecentEventTime(), 0));
 6370  0
     } catch (Throwable any) {
 6371  0
       LOGGER.error("Failed to copy data to clipboard", any);
 6372  0
       JOptionPane.showMessageDialog(this,
 6373  
           Resources.getString("errClipboardCopyDataText",
 6374  
               any.getClass().getName(), any.getMessage() != null
 6375  
                   ? any.getMessage() : ""),
 6376  
           Resources.getString("errClipboardCopyDataTitle"),
 6377  
           JOptionPane.ERROR_MESSAGE);
 6378  0
     }
 6379  0
   }
 6380  
 
 6381  
   /**
 6382  
    * Configure the data display based on the user-chosen row formatting.
 6383  
    */
 6384  
   private void setupResultsTableColoring() {
 6385  0
     cellRenderer.clearColors();
 6386  0
     if (configTableColoringGreenBar.isSelected()) {
 6387  0
       cellRenderer.addAlternatingRowColor(Color.black, Color.white);
 6388  0
       cellRenderer
 6389  
           .addAlternatingRowColor(Color.black, new Color(COLOR_GREEN_R_VALUE,
 6390  
               COLOR_GREEN_G_VALUE, COLOR_GREEN_B_VALUE));
 6391  0
     } else if (configTableColoringYellowBar.isSelected()) {
 6392  0
       cellRenderer.addAlternatingRowColor(Color.black, Color.white);
 6393  0
       cellRenderer
 6394  
           .addAlternatingRowColor(Color.black, new Color(COLOR_YELLOW_R_VALUE,
 6395  
               COLOR_YELLOW_G_VALUE, COLOR_YELLOW_B_VALUE));
 6396  0
     } else if (configTableColoringUserDefined.isSelected()) {
 6397  0
       setupUserDefinedColoring();
 6398  
     }
 6399  
 
 6400  0
     if (table != null) {
 6401  0
       table.repaint();
 6402  
     }
 6403  0
   }
 6404  
 
 6405  
   /**
 6406  
    * Allow the user to select a font (including size/bold/italic). This setting
 6407  
    * is used for the message area and the data table display.
 6408  
    */
 6409  
   private void chooseFont() {
 6410  
     FontChooser fontChooser;
 6411  
 
 6412  0
     fontChooser = new FontChooser(this);
 6413  0
     fontChooser.setVisible(true);
 6414  
 
 6415  
     // Font used in both table display and message display
 6416  0
     if (fontChooser.getNewFont() != null) {
 6417  0
       setupFont(fontChooser.getNewFont());
 6418  
     }
 6419  0
   }
 6420  
 
 6421  
   /**
 6422  
    * Set the font for the message area and table to match the frame's font.
 6423  
    * The frame's font will either be the default font, if the user has not
 6424  
    * configured a specific font, or it will be the user-chosen font.
 6425  
    * 
 6426  
    * @param font
 6427  
    *          Font The font to use for the message and table displays.
 6428  
    */
 6429  
   private void setupFont(Font font) {
 6430  0
     if (font != null) {
 6431  0
       this.setFont(font);
 6432  0
       message.setFont(font);
 6433  0
       cellRenderer.setText(
 6434  
           "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
 6435  0
       cellRenderer.setFont(font);
 6436  
 
 6437  
       // For some reason the cellRenderer preferred size equals the font height
 6438  
       // if no cells are rendered at the moment. Tried creating a one-row
 6439  
       // model and displaying while changing font size but it didn't help --
 6440  
       // probably because it wasn't rendered until after the setupFont method
 6441  
       // completed.
 6442  0
       if (table.getRowCount() == 0) {
 6443  0
         table.setRowHeight(cellRenderer.getPreferredSize().height + 5);
 6444  
       } else {
 6445  0
         table.setRowHeight(cellRenderer.getPreferredSize().height);
 6446  
       }
 6447  
       // table.setRowHeight(this.getGraphics().getFontMetrics(font).getHeight());
 6448  0
       table.getTableHeader().setFont(font);
 6449  
     }
 6450  0
   }
 6451  
 
 6452  
   /**
 6453  
    * Check for a new version. The checking class will notify this class if a
 6454  
    * newer version is available.
 6455  
    */
 6456  
   private void checkForNewVersion() {
 6457  0
     final CheckLatestVersion versionCheck = new CheckLatestVersion(VERSION);
 6458  0
     versionCheck.addObserver(this);
 6459  0
     new Thread(versionCheck).start();
 6460  0
   }
 6461  
 
 6462  
   /**
 6463  
    * Notify the user that a newer version of the program has been released.
 6464  
    * 
 6465  
    * @param newVersionInformation
 6466  
    *          Information about the new version of the program
 6467  
    */
 6468  
   private void notifyNewerVersion(NewVersionInformation newVersionInformation) {
 6469  0
     if (newVersionInformation.getUrlToDownloadPage() != null) {
 6470  
       int choice;
 6471  
 
 6472  0
       choice = JOptionPane.showConfirmDialog(
 6473  
           this,
 6474  
           "There is a newer version of BasicQuery Available\n"
 6475  
               + "You are running version " + VERSION
 6476  
               + " and the latest version is "
 6477  
               + newVersionInformation.getLatestVersion()
 6478  
               + "\n\n"
 6479  
               + newVersionInformation.getDownloadInformation()
 6480  
               + "\n"
 6481  
               + "New features include:\n"
 6482  
               + newVersionInformation.getNewFeaturesDescription() + "\n\n"
 6483  
               + "Would you like to download the new version now?\n\n",
 6484  
           "Newer Version Available (" + VERSION + "->"
 6485  
               + newVersionInformation.getLatestVersion() + ")",
 6486  
           JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE);
 6487  
 
 6488  0
       if (choice == JOptionPane.YES_OPTION) {
 6489  
         try {
 6490  0
           Desktop.getDesktop().browse(
 6491  
               newVersionInformation.getUrlToDownloadPage().toURI());
 6492  0
         } catch (Throwable throwable) {
 6493  0
           LOGGER.error("Cannot launch browser to access download page",
 6494  
               throwable);
 6495  0
           JOptionPane.showMessageDialog(this,
 6496  
               "Unable to launch a browser to access the download page\n"
 6497  
                   + "at "
 6498  
                   + newVersionInformation.getUrlToDownloadPage().toString()
 6499  
                   + "\n\n" + throwable.getMessage(),
 6500  
               "Unable to Access Download Page", JOptionPane.ERROR_MESSAGE);
 6501  0
         }
 6502  
       }
 6503  0
     } else {
 6504  0
       JOptionPane.showMessageDialog(
 6505  
           this,
 6506  
           "There is a newer version of BasicQuery Available\n"
 6507  
               + "You are running version " + VERSION
 6508  
               + " and the latest version is "
 6509  
               + newVersionInformation.getLatestVersion()
 6510  
               + "\n\n"
 6511  
               + "New features include:\n"
 6512  
               + newVersionInformation.getNewFeaturesDescription(),
 6513  
           "Newer Version Available (" + VERSION + "->"
 6514  
               + newVersionInformation.getLatestVersion() + ")",
 6515  
           JOptionPane.INFORMATION_MESSAGE);
 6516  
     }
 6517  0
   }
 6518  
 
 6519  
   /**
 6520  
    * Cleanup environment. Normally called before closing application.
 6521  
    */
 6522  
   private void cleanUp() {
 6523  0
     if (conn != null) {
 6524  
       try {
 6525  0
         conn.close();
 6526  0
       } catch (Throwable any) {
 6527  0
         if (LOGGER.isDebugEnabled()) {
 6528  0
           LOGGER.debug("Unable to close connection during shutdown", any);
 6529  
         }
 6530  0
       }
 6531  0
       conn = null;
 6532  
     }
 6533  0
   }
 6534  
 
 6535  
   // Begin ActionListener Interface
 6536  
 
 6537  
   /**
 6538  
    * Depending on which option the user has invoked the
 6539  
    * appropriate action is performed
 6540  
    * 
 6541  
    * @param evt
 6542  
    *          Specifies the action event that has taken place
 6543  
    */
 6544  
   public void actionPerformed(ActionEvent evt) {
 6545  
     Object source;
 6546  
 
 6547  0
     source = evt.getSource();
 6548  
 
 6549  0
     if (source == execute) {
 6550  0
       runIt(RUNTYPE_SINGLE);
 6551  0
     } else if (source == remove) {
 6552  0
       removeSelectedQuery();
 6553  0
     } else if (source == commentToggle) {
 6554  0
       commentToggle();
 6555  0
     } else if (source == nextInList) {
 6556  0
       nextQuerySelection();
 6557  0
     } else if (source == querySelection) {
 6558  0
       setupSelectedQuery();
 6559  0
     } else if (source == fileSaveBLOBs) {
 6560  0
       saveBLOBs();
 6561  0
     } else if (source == querySelectStar) {
 6562  0
       queryStar(Query.MODE_QUERY);
 6563  0
     } else if (source == queryDescribeStar) {
 6564  0
       queryStar(Query.MODE_DESCRIBE);
 6565  0
     } else if (source == queryMakeInsert) {
 6566  0
       makeInsert();
 6567  0
     } else if (source == queryMakeUpdate) {
 6568  0
       makeUpdate();
 6569  0
     } else if (source == querySetOrder) {
 6570  0
       reorderQueries();
 6571  0
     } else if (source == fileOpenSQL) {
 6572  0
       openSQLFile();
 6573  0
     } else if (source == fileSaveAsCSV) {
 6574  0
       chooseFileForSave(table.getModel(), FILE_EXPORT_CSV);
 6575  0
     } else if (source == queryMakeVerboseSelect) {
 6576  0
       makeVerboseSelect();
 6577  0
     } else if (source == queryRunAll) {
 6578  0
       runIt(RUNTYPE_ALL);
 6579  0
     } else if (source == helpAbout) {
 6580  0
       about();
 6581  0
     } else if (source == helpParameterizedSQL) {
 6582  0
       helpParameterizedSQL();
 6583  0
     } else if (source == editCopy) {
 6584  0
       copySelectionToClipboard();
 6585  0
     } else if (source == editSelectAll) {
 6586  0
       selectAllData();
 6587  0
     } else if (source == editSort) {
 6588  0
       sortSelectedColumns();
 6589  0
     } else if (source == previousQuery) {
 6590  0
       histSelectPrev();
 6591  0
     } else if (source == nextQuery) {
 6592  0
       histSelectNext();
 6593  0
     } else if (source == configTableColoringNone
 6594  
         || source == configTableColoringGreenBar
 6595  
         || source == configTableColoringYellowBar
 6596  
         || source == configTableColoringUserDefined) {
 6597  0
       setupResultsTableColoring();
 6598  0
     } else if (source == configLanguageDefault
 6599  
         || source == configLanguageEnglish
 6600  
         || source == configLanguageFrench
 6601  
         || source == configLanguageGerman
 6602  
         || source == configLanguageItalian
 6603  
         || source == configLanguagePortuguese
 6604  
         || source == configLanguageSpanish) {
 6605  0
       changeLanguage();
 6606  0
     } else if (source == configFont) {
 6607  0
       chooseFont();
 6608  0
     } else if (source == asDescribe || source == asQuery || source == asUpdate) {
 6609  0
       setExportAvailable(false);
 6610  
     }
 6611  0
   }
 6612  
 
 6613  
   // End ActionListener Interface
 6614  
 
 6615  
   // Begin WindowListener Interface
 6616  
 
 6617  
   /**
 6618  
    * Invoked when the Window is set to be the active Window.
 6619  
    * 
 6620  
    * @param evt
 6621  
    *          The event that specifies that the window is activated
 6622  
    */
 6623  
   public void windowActivated(WindowEvent evt) {
 6624  0
   }
 6625  
 
 6626  
   /**
 6627  
    * Invoked when a window has been closed as the result of calling
 6628  
    * dispose on the window.
 6629  
    * 
 6630  
    * @param evt
 6631  
    *          The Window event
 6632  
    */
 6633  
   public void windowClosed(WindowEvent evt) {
 6634  0
   }
 6635  
 
 6636  
   /**
 6637  
    * Invoked when the user attempts to close the window from the
 6638  
    * window's system menu.Exits the application once the window
 6639  
    * is closed
 6640  
    * 
 6641  
    * @param evt
 6642  
    *          The event that specifies the closing of the window
 6643  
    */
 6644  
   public void windowClosing(WindowEvent evt) {
 6645  0
     saveConfig();
 6646  0
     cleanUp();
 6647  
     try {
 6648  0
       dispose();
 6649  0
     } catch (Throwable any) {
 6650  
       // This fails periodically with a NP exception
 6651  
       // from Container.removeNotify
 6652  0
       LOGGER.warn("Error during application shutdown", any);
 6653  0
     }
 6654  
 
 6655  0
     System.exit(0);
 6656  0
   }
 6657  
 
 6658  
   /**
 6659  
    * Invoked when a Window is no longer the active Window
 6660  
    * 
 6661  
    * @param evt
 6662  
    *          The event that specifies that the window is deactivated
 6663  
    */
 6664  
   public void windowDeactivated(WindowEvent evt) {
 6665  0
   }
 6666  
 
 6667  
   /**
 6668  
    * Invoked when a window is changed from a minimized to a normal state.
 6669  
    * 
 6670  
    * @param evt
 6671  
    *          The event that specifies that the window is deiconified
 6672  
    */
 6673  
   public void windowDeiconified(WindowEvent evt) {
 6674  0
   }
 6675  
 
 6676  
   /**
 6677  
    * Invoked when a window is changed from a normal to a minimized state
 6678  
    * 
 6679  
    * @param evt
 6680  
    *          The event that specifies that the window is iconified
 6681  
    */
 6682  
   public void windowIconified(WindowEvent evt) {
 6683  0
   }
 6684  
 
 6685  
   /**
 6686  
    * Creates a new thread that attaches focus to the window that has been
 6687  
    * opened and also places the cursor on the textfield for the userid
 6688  
    * 
 6689  
    * @param evt
 6690  
    *          The event that specifies the opening of the window
 6691  
    */
 6692  
   public void windowOpened(WindowEvent evt) {
 6693  0
     new Thread(new FocusRequestor(userId)).start();
 6694  0
     if (!loadedDBDriver) {
 6695  0
       noDBDriverWarning();
 6696  
     }
 6697  0
   }
 6698  
 
 6699  
   // End WindowListener Interface
 6700  
 
 6701  
   @Override
 6702  
   public void update(Observable o, Object arg) {
 6703  0
     LOGGER.debug("Update received from " + o.getClass().getName());
 6704  
 
 6705  0
     if (o instanceof CheckLatestVersion) {
 6706  0
       notifyNewerVersion((NewVersionInformation) arg);
 6707  
     }
 6708  0
   }
 6709  
 
 6710  
   /**
 6711  
    * Handle menu selection for exporting the results to triples
 6712  
    */
 6713  
   private class ExportResultsAsTriplesListener implements ActionListener {
 6714  
     /**
 6715  
      * No operation
 6716  
      */
 6717  0
     public ExportResultsAsTriplesListener() {
 6718  
 
 6719  0
     }
 6720  
 
 6721  
     @Override
 6722  
     public void actionPerformed(ActionEvent arg0) {
 6723  0
       chooseFileForSave(table.getModel(), FILE_EXPORT_TRIPLES);
 6724  0
     }
 6725  
   }
 6726  
 
 6727  
   @Override
 6728  
   public void keyPressed(KeyEvent arg0) {
 6729  
 
 6730  0
   }
 6731  
 
 6732  
   @Override
 6733  
   public void keyReleased(KeyEvent arg0) {
 6734  0
     setExportAvailable(false);
 6735  0
   }
 6736  
 
 6737  
   @Override
 6738  
   public void keyTyped(KeyEvent arg0) {
 6739  
 
 6740  0
   }
 6741  
 
 6742  
   /**
 6743  
    * Main startup method for the BasicQuery application.
 6744  
    * Creates an object of the class BasicQuery.
 6745  
    * 
 6746  
    * @param args
 6747  
    *          Input arguments -- not currently used
 6748  
    */
 6749  
   public static final void main(String[] args) {
 6750  
     try {
 6751  0
       new BasicQuery(true);
 6752  0
     } catch (Throwable any) {
 6753  0
       LOGGER.fatal("Application failure", any);
 6754  
 
 6755  
       // In case logger isn't setup - send this fatal issue to standard out
 6756  0
       System.out.println("BasicQuery:main:Exception:" + any);
 6757  0
       any.printStackTrace();
 6758  0
     }
 6759  0
   }
 6760  
 }