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

com.darwinsys.sql.SQLRunnerGUI Maven / Gradle / Ivy

There is a newer version: 1.8.0
Show newest version
/* Copyright (c) Ian F. Darwin, http://www.darwinsys.com/, 2004-2006.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package com.darwinsys.sql;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.prefs.Preferences;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextArea;

import com.darwinsys.genericui.SuccessFailureUI;
import com.darwinsys.io.TextAreaWriter;
import com.darwinsys.swingui.SuccessFailureBarSwing;
import com.darwinsys.swingui.UtilGUI;
import com.darwinsys.util.Verbosity;

/**
 * A simple GUI to run one set of commands.
 */
@SuppressWarnings("serial")
public class SQLRunnerGUI  {

	private static final int DISPLAY_COLUMNS = 70;

	Preferences prefsNode = Preferences.userNodeForPackage(SQLRunnerGUI.class);

	final List configurations;
	final PrintWriter out;
	/** Thread to run the SQL command in */
	Thread commandRunnerThread;
	/** The active JDBC connection, or null */
	Connection currentConnection;

	ConfigurationManager configManager;

	private OutputMode mode;

	// GUI
	private final SuccessFailureUI resultsStatusBar;
	private final JFrame mainWindow;
	private final JTextArea inputTextArea, textTextArea;
	private final JTabbedPane outputPanel;
	private final JButton runButton;

	private final JComboBox connectionsList;
	private final JCheckBox passwdPromptCheckBox;
	private final JComboBox modeList;
	private final JDialog busyDialog;

	private JTable jtable;

	/** Currently-in-use Error Handler */
	private SQLRunnerErrorHandler eHandler =

		/** Default Error Handler */
		new SQLRunnerErrorHandler() {

			public void handleError(Exception e) {

				JOptionPane.showMessageDialog(mainWindow,
					"

Error: " + e, "Oops", JOptionPane.ERROR_MESSAGE); e.printStackTrace(); } }; /** * Allow a main application to provide its own error handler. * @param eHandler The error handler */ public void setErrorHandler(SQLRunnerErrorHandler eHandler) { this.eHandler = eHandler; } /** * Default main method for standalone use. * @param args You guessed it. */ public static void main(String[] args) { String config = null; if (args.length != 0) { for (int i = 0; i < args.length; i++) { String arg = args[i]; if ("-c".equals(arg) && args.length > i) { config = args[i+1]; } } } SQLRunner.setOkToExit(true); SQLRunnerGUI prog = new SQLRunnerGUI(new DefaultConfigurationManager()); if (config != null) { prog.setConfig(config); } } /** * Set the selected Configuration Object in the Connections chooser * from a given Configuration Name passed as a String. * @param config The chosen name. */ private void setConfig(String config) { if (config == null) { throw new NullPointerException("Configuration name may not be null"); } for (Configuration configListItem : configurations) { if (config.equals(configListItem.getName())) { connectionsList.setSelectedItem(configListItem); return; } } System.err.printf("Warning: Configuration %s not found", config); } /** * This is the all-important action for the Run button! Run the current SQL input * string with the given settings. Used in runAction, below. */ Runnable commandRunner = new Runnable() { public void run() { String command = inputTextArea.getText().trim(); if (command == null || command.length() == 0) { JOptionPane.showMessageDialog(mainWindow, "Command window is empty", "Out of order", JOptionPane.WARNING_MESSAGE); return; } // make busy dialog same width as main window. Dimension dlgBounds = busyDialog.getSize(); dlgBounds.width = mainWindow.getSize().width; busyDialog.setSize(dlgBounds); runButton.setEnabled(false); Configuration config = (Configuration) connectionsList.getSelectedItem(); if (passwdPromptCheckBox.isSelected() || !config.hasPassword()) { String pass = getPassword("Connection password for " + config.getName()); config.setPassword(pass); } resultsStatusBar.reset(); busyDialog.setVisible(true); try { currentConnection = configManager.getConnection(config); SQLRunner.setVerbosity(Verbosity.QUIET); SQLRunner prog = new SQLRunner(currentConnection, null, "t"); prog.setGUI(SQLRunnerGUI.this); if (mode != null) { prog.setOutputMode(mode); } prog.setOutputFile(out); // RUN THE SQL prog.runStatement(command); if (prog.isEscape()) { outputPanel.setSelectedIndex(0); } resultsStatusBar.showSuccess(); // If no exception thrown! } catch (Exception e) { resultsStatusBar.showFailure(); eHandler.handleError(e); } finally { runButton.setEnabled(true); busyDialog.setVisible(false); try { // Nested try here is deliberate, not a big deal if this call crashes if (currentConnection != null) { currentConnection.close(); } } catch (SQLException ex) { System.err.println("Warning: close caused " + ex); } } } }; Action runAction = new AbstractAction("Run") { /** Called each time the user presses the Run button * @param evt The input event */ public void actionPerformed(ActionEvent evt) { // Run this action handler under its own Thread, so we don't block the EventDispatch thread... commandRunnerThread = new Thread(commandRunner); commandRunnerThread.start(); } }; /** * Action to cancel the database if it is taking too long... Use with caution. */ Action cancelAction = new AbstractAction("Interrupt") { public void actionPerformed(ActionEvent e) { if (commandRunnerThread.isAlive()) { try { if (currentConnection != null) { currentConnection.close(); } else { // If you know a better way to interrupt a DriverManager.getConnection() // than interrupting its thread, please let me know. commandRunnerThread.interrupt(); } } catch (Exception ex) { System.err.println("Well what did you expect? I caught this exception:"); ex.printStackTrace(); } } } }; /** * Constructor for main GUI * @param configManager The configuration */ public SQLRunnerGUI(ConfigurationManager configManager) { this(configManager, "SQLRunner"); } /** * Constructor for main GUI * @param configManager The configuration * @param title The titlebar title */ public SQLRunnerGUI(ConfigurationManager configManager, String title) { this.configManager = configManager; mainWindow = new JFrame(title); // XXX DO NOT USE mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Because the GUI is intended to be embedded in other applications!! // They will call SQLRunner.setOkToExit(true) if they want. mainWindow.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { mainWindow.dispose(); SQLRunner.exit(0); } }); final Container controlsArea = new JPanel(); BoxLayout layout = new BoxLayout(controlsArea, BoxLayout.LINE_AXIS); controlsArea.setLayout(layout); mainWindow.add(controlsArea, BorderLayout.NORTH); configurations = configManager.getConfigurations(); connectionsList = new JComboBox(configurations.toArray(new Configuration[configurations.size()])); // when you change to a different database you don't want to remember the "force passwd prompt" setting connectionsList.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { passwdPromptCheckBox.setSelected(false); } }); controlsArea.add(new JLabel("Connection")); controlsArea.add(connectionsList); passwdPromptCheckBox = new JCheckBox("Ask for passwd"); controlsArea.add(passwdPromptCheckBox); JButton tb = new JButton("Test"); controlsArea.add(tb); tb.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { // XXX } }); final JComboBox inTemplateChoice = new JComboBox<>(); // XXX Of course these should be editable... inTemplateChoice.addItem("Input Template:"); for (SQLTemplate t : SQLTemplate.getList()) { inTemplateChoice.addItem(t); } controlsArea.add(inTemplateChoice); modeList = new JComboBox(); for (OutputMode mode : OutputMode.values()) { modeList.addItem(mode); } // If the mode is set to JTable, switch the // tab to 1, else reset it to 0 (which is shared // by Text, SQL, etc... // XXX should be a third tab for HTML modeList.addItemListener(new ItemListener(){ public void itemStateChanged(ItemEvent e) { mode = (OutputMode) modeList.getSelectedItem(); switch(mode) { case j: outputPanel.setSelectedIndex(1); break; default: outputPanel.setSelectedIndex(0); } } }); controlsArea.add(new JLabel("Output Format:")); controlsArea.add(modeList); runButton = new JButton(runAction); controlsArea.add(runButton); JButton clearOutput = new JButton("Clear Output"); clearOutput.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { textTextArea.setText(""); resultsStatusBar.reset(); } }); controlsArea.add(clearOutput); // END OF TOP ROW // Used by Run... busyDialog = new JDialog(mainWindow, "Running..."); JProgressBar busyIndicator = new JProgressBar(); busyIndicator.setIndeterminate(true); busyDialog.add(busyIndicator, BorderLayout.CENTER); JPanel bottomPanel = new JPanel(); bottomPanel.add(new JButton(cancelAction)); busyDialog.add(bottomPanel, BorderLayout.SOUTH); busyDialog.pack(); busyDialog.setLocationRelativeTo(mainWindow); inputTextArea = new JTextArea(6, DISPLAY_COLUMNS); // Switch to monospaced font Font msFont = new Font("SansSerif", Font.PLAIN, inputTextArea.getFont().getSize()); inputTextArea.setFont(msFont); JScrollPane inputAreaScrollPane = new JScrollPane(inputTextArea); inputAreaScrollPane.setBorder(BorderFactory.createTitledBorder("SQL Command")); outputPanel = new JTabbedPane(); textTextArea = new JTextArea(20, DISPLAY_COLUMNS); textTextArea.setFont(msFont); JScrollPane outputAreaScrollPane = new JScrollPane(textTextArea); String resultTypeName; resultTypeName = OutputMode.t.toString(); outputAreaScrollPane.setBorder(BorderFactory.createTitledBorder(resultTypeName)); outputPanel.addTab(resultTypeName, outputAreaScrollPane); jtable = new JTable(); resultTypeName = OutputMode.j.toString(); outputPanel.addTab(resultTypeName, new JScrollPane(jtable)); inTemplateChoice.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (inTemplateChoice.getSelectedIndex() == 0) { return; } final SQLTemplate selectedItem = (SQLTemplate) inTemplateChoice.getSelectedItem(); inputTextArea.setText(selectedItem.getTemplate()); } }); mainWindow.add(new JSplitPane(JSplitPane.VERTICAL_SPLIT, inputAreaScrollPane, outputPanel), BorderLayout.CENTER); out = new PrintWriter(new TextAreaWriter(textTextArea)); resultsStatusBar = new SuccessFailureBarSwing(mainWindow.getBackground(), 400, 20); resultsStatusBar.reset(); mainWindow.add((JComponent)resultsStatusBar, BorderLayout.SOUTH); mainWindow.pack(); UtilGUI.monitorWindowPosition(mainWindow, prefsNode); mainWindow.setVisible(true); inputTextArea.requestFocusInWindow(); } /** * Prompt for a password, and wait until the user enters it. * @param prompt The prompt string * @return The new password. */ private String getPassword(String prompt) { final JDialog input = new JDialog(mainWindow, "Prompt", true); input.setLayout(new FlowLayout()); input.add(new JLabel(prompt)); JPasswordField textField = new JPasswordField(10); input.add(textField); Action okAction = new AbstractAction("OK") { public void actionPerformed(ActionEvent e) { input.dispose(); } }; textField.addActionListener(okAction); JButton ok = new JButton(okAction); input.add(ok); input.pack(); input.setLocationRelativeTo(mainWindow); input.setVisible(true); // BLOCKING return new String(textField.getPassword()); } public JTable getJTable() { return jtable; } }