0001: package net.sourceforge.squirrel_sql.client.session.mainpanel;
0002:
0003: /*
0004: * Copyright (C) 2003-2004 Jason Height
0005: * jmheight@users.sourceforge.net
0006: *
0007: * This library is free software; you can redistribute it and/or
0008: * modify it under the terms of the GNU Lesser General Public
0009: * License as published by the Free Software Foundation; either
0010: * version 2.1 of the License, or (at your option) any later version.
0011: *
0012: * This library is distributed in the hope that it will be useful,
0013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0015: * Lesser General Public License for more details.
0016: *
0017: * You should have received a copy of the GNU Lesser General Public
0018: * License along with this library; if not, write to the Free Software
0019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0020: */
0021: import java.awt.BorderLayout;
0022: import java.awt.Component;
0023: import java.awt.GridBagConstraints;
0024: import java.awt.GridBagLayout;
0025: import java.awt.Insets;
0026: import java.awt.event.ActionEvent;
0027: import java.awt.event.ActionListener;
0028: import java.awt.event.MouseAdapter;
0029: import java.awt.event.MouseEvent;
0030: import java.beans.PropertyChangeEvent;
0031: import java.beans.PropertyChangeListener;
0032: import java.sql.ResultSet;
0033: import java.sql.SQLException;
0034: import java.sql.SQLWarning;
0035: import java.text.NumberFormat;
0036: import java.util.ArrayList;
0037: import java.util.HashMap;
0038: import java.util.Iterator;
0039: import java.util.List;
0040: import java.util.Map;
0041:
0042: import javax.swing.Action;
0043: import javax.swing.ImageIcon;
0044: import javax.swing.JButton;
0045: import javax.swing.JComponent;
0046: import javax.swing.JLabel;
0047: import javax.swing.JLayeredPane;
0048: import javax.swing.JMenuItem;
0049: import javax.swing.JOptionPane;
0050: import javax.swing.JPanel;
0051: import javax.swing.JPopupMenu;
0052: import javax.swing.JTabbedPane;
0053: import javax.swing.KeyStroke;
0054: import javax.swing.SwingUtilities;
0055: import javax.swing.event.EventListenerList;
0056:
0057: import net.sourceforge.squirrel_sql.client.action.ActionCollection;
0058: import net.sourceforge.squirrel_sql.client.gui.builders.UIFactory;
0059: import net.sourceforge.squirrel_sql.client.preferences.SquirrelPreferences;
0060: import net.sourceforge.squirrel_sql.client.session.ISQLEntryPanel;
0061: import net.sourceforge.squirrel_sql.client.session.ISQLExecuterHandler;
0062: import net.sourceforge.squirrel_sql.client.session.ISession;
0063: import net.sourceforge.squirrel_sql.client.session.SQLExecuterTask;
0064: import net.sourceforge.squirrel_sql.client.session.SQLExecutionInfo;
0065: import net.sourceforge.squirrel_sql.client.session.action.CloseAllSQLResultTabsAction;
0066: import net.sourceforge.squirrel_sql.client.session.action.CloseAllSQLResultTabsButCurrentAction;
0067: import net.sourceforge.squirrel_sql.client.session.action.CloseCurrentSQLResultTabAction;
0068: import net.sourceforge.squirrel_sql.client.session.action.ToggleCurrentSQLResultTabStickyAction;
0069: import net.sourceforge.squirrel_sql.client.session.event.IResultTabListener;
0070: import net.sourceforge.squirrel_sql.client.session.event.ISQLExecutionListener;
0071: import net.sourceforge.squirrel_sql.client.session.event.ResultTabEvent;
0072: import net.sourceforge.squirrel_sql.client.session.properties.SessionProperties;
0073: import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetException;
0074: import net.sourceforge.squirrel_sql.fw.datasetviewer.IDataSetUpdateableTableModel;
0075: import net.sourceforge.squirrel_sql.fw.datasetviewer.ResultSetDataSet;
0076: import net.sourceforge.squirrel_sql.fw.datasetviewer.ResultSetMetaDataDataSet;
0077: import net.sourceforge.squirrel_sql.fw.datasetviewer.cellcomponent.DataTypeClob;
0078: import net.sourceforge.squirrel_sql.fw.id.IIdentifier;
0079: import net.sourceforge.squirrel_sql.fw.id.IntegerIdentifierFactory;
0080: import net.sourceforge.squirrel_sql.fw.sql.ISQLConnection;
0081: import net.sourceforge.squirrel_sql.fw.sql.SQLExecutionException;
0082: import net.sourceforge.squirrel_sql.fw.util.Resources;
0083: import net.sourceforge.squirrel_sql.fw.util.StringManager;
0084: import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory;
0085: import net.sourceforge.squirrel_sql.fw.util.StringUtilities;
0086: import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
0087: import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;
0088:
0089: /**
0090: * This is the panel where SQL scripts are executed and results presented.
0091: *
0092: */
0093: public class SQLResultExecuterPanel extends JPanel implements
0094: ISQLResultExecuter {
0095: static final long serialVersionUID = 6961615570741567740L;
0096:
0097: /** Logger for this class. */
0098: private static final ILogger s_log = LoggerController
0099: .createLogger(SQLResultExecuterPanel.class);
0100:
0101: /** Internationalized strings for this class. */
0102: private static final StringManager s_stringMgr = StringManagerFactory
0103: .getStringManager(SQLResultExecuterPanel.class);
0104:
0105: static interface i18n {
0106: // i18n[SQLResultExecuterPanel.exec=Executing SQL]
0107: String EXEC_SQL_MSG = s_stringMgr
0108: .getString("SQLResultExecuterPanel.exec");
0109: // i18n[SQLResultExecuterPanel.cancelMsg=Press Cancel to Stop]
0110: String CANCEL_SQL_MSG = s_stringMgr
0111: .getString("SQLResultExecuterPanel.cancelMsg");
0112:
0113: }
0114:
0115: private ISession _session;
0116:
0117: private MyPropertiesListener _propsListener;
0118:
0119: /** Each tab is a <TT>ResultTab</TT> showing the results of a query. */
0120: private JTabbedPane _tabbedExecutionsPanel;
0121:
0122: /**
0123: * Collection of <TT>ResultTabInfo</TT> objects for all
0124: * <TT>ResultTab</TT> objects that have been created. Keyed
0125: * by <TT>ResultTab.getIdentifier()</TT>.
0126: */
0127: private Map<IIdentifier, ResultTabInfo> _allTabs = new HashMap<IIdentifier, ResultTabInfo>();
0128:
0129: /**
0130: * Pool of <TT>ResultTabInfo</TT> objects available for use.
0131: */
0132: private List<ResultTabInfo> _availableTabs = new ArrayList<ResultTabInfo>();
0133:
0134: /**
0135: * Pool of <TT>ResultTabInfo</TT> objects currently being used.
0136: */
0137: private ArrayList<ResultTabInfo> _usedTabs = new ArrayList<ResultTabInfo>();
0138:
0139: /** Listeners */
0140: private EventListenerList _listeners = new EventListenerList();
0141:
0142: /** Factory for generating unique IDs for new <TT>ResultTab</TT> objects. */
0143: private IntegerIdentifierFactory _idFactory = new IntegerIdentifierFactory();
0144: private IResultTab _stickyTab;
0145:
0146: private SquirrelPreferences _prefs = null;
0147:
0148: /** Reference to the executor so that it can be called from the CancelPanel*/
0149: private SQLExecuterTask _executer;
0150:
0151: private static enum SQLType {
0152: INSERT, SELECT, UPDATE, DELETE, UNKNOWN
0153: };
0154:
0155: /**
0156: * Ctor.
0157: *
0158: * @param session Current session.
0159: *
0160: * @throws IllegalArgumentException
0161: * Thrown if a <TT>null</TT> <TT>ISession</TT> passed.
0162: */
0163: public SQLResultExecuterPanel(ISession session) {
0164: super ();
0165: setSession(session);
0166: createGUI();
0167: propertiesHaveChanged(null);
0168: }
0169:
0170: public String getTitle() {
0171: // i18n[SQLResultExecuterPanel.title=Results]
0172: return s_stringMgr.getString("SQLResultExecuterPanel.title");
0173: }
0174:
0175: public JComponent getComponent() {
0176: return this ;
0177: }
0178:
0179: /**
0180: * Set the current session.
0181: *
0182: * @param session Current session.
0183: *
0184: * @throws IllegalArgumentException
0185: * Thrown if a <TT>null</TT> <TT>ISession</TT> passed.
0186: */
0187: public synchronized void setSession(ISession session) {
0188: if (session == null) {
0189: throw new IllegalArgumentException("Null ISession passed");
0190: }
0191: sessionClosing();
0192: _session = session;
0193: _prefs = _session.getApplication().getSquirrelPreferences();
0194: _propsListener = new MyPropertiesListener();
0195: _session.getProperties().addPropertyChangeListener(
0196: _propsListener);
0197: }
0198:
0199: /** Current session. */
0200: public ISession getSession() {
0201: return _session;
0202: }
0203:
0204: /**
0205: * Add a listener listening for SQL Execution.
0206: *
0207: * @param lis Listener
0208: *
0209: * @throws IllegalArgumentException
0210: * If a null <TT>ISQLExecutionListener</TT> passed.
0211: */
0212: public synchronized void addSQLExecutionListener(
0213: ISQLExecutionListener lis) {
0214: if (lis == null) {
0215: throw new IllegalArgumentException(
0216: "ISQLExecutionListener == null");
0217: }
0218: _listeners.add(ISQLExecutionListener.class, lis);
0219: }
0220:
0221: /**
0222: * Remove an SQL execution listener.
0223: *
0224: * @param lis Listener
0225: *
0226: * @throws IllegalArgumentException
0227: * If a null <TT>ISQLExecutionListener</TT> passed.
0228: */
0229: public synchronized void removeSQLExecutionListener(
0230: ISQLExecutionListener lis) {
0231: if (lis == null) {
0232: throw new IllegalArgumentException(
0233: "ISQLExecutionListener == null");
0234: }
0235: _listeners.remove(ISQLExecutionListener.class, lis);
0236: }
0237:
0238: /**
0239: * Add a listener listening for events on result tabs.
0240: *
0241: * @param lis Listener
0242: *
0243: * @throws IllegalArgumentException
0244: * If a null <TT>IResultTabListener</TT> passed.
0245: */
0246: public synchronized void addResultTabListener(IResultTabListener lis) {
0247: if (lis == null) {
0248: throw new IllegalArgumentException(
0249: "IResultTabListener == null");
0250: }
0251: _listeners.add(IResultTabListener.class, lis);
0252: }
0253:
0254: /**
0255: * Remove a listener listening for events on result tabs.
0256: *
0257: * @param lis Listener
0258: *
0259: * @throws IllegalArgumentException
0260: * If a null <TT>IResultTabListener</TT> passed.
0261: */
0262: public synchronized void removeResultTabListener(
0263: IResultTabListener lis) {
0264: if (lis == null) {
0265: throw new IllegalArgumentException(
0266: "IResultTabListener == null");
0267: }
0268: _listeners.remove(IResultTabListener.class, lis);
0269: }
0270:
0271: public void execute(ISQLEntryPanel sqlPanel) {
0272: String sql = sqlPanel.getSQLToBeExecuted();
0273: if (sql != null && sql.length() > 0) {
0274: executeSQL(sql);
0275: } else {
0276: // i18n[SQLResultExecuterPanel.nosqlselected=No SQL selected for execution.]
0277: String msg = s_stringMgr
0278: .getString("SQLResultExecuterPanel.nosqlselected");
0279: _session.showErrorMessage(msg);
0280: }
0281: }
0282:
0283: public void executeSQL(String sql) {
0284: if (sql != null && sql.trim().length() > 0) {
0285: String origSQL = sql;
0286: sql = fireSQLToBeExecutedEvent(sql);
0287:
0288: // This can happen if an impl of ISQLExecutionListener returns null
0289: // from the statementExecuting API method, to indicate that the SQL
0290: // shouldn't be executed.
0291: if (sql == null) {
0292: s_log
0293: .info("executeSQL: An ISQLExecutionListener veto'd execution of "
0294: + "the following SQL: " + origSQL);
0295: return;
0296: }
0297:
0298: ISQLExecutionListener[] executionListeners = _listeners
0299: .getListeners(ISQLExecutionListener.class);
0300: SQLExecutionHandler handler = new SQLExecutionHandler(null);
0301: _executer = new SQLExecuterTask(_session, sql, handler,
0302: executionListeners);
0303:
0304: if (_prefs.getLargeScriptStmtCount() > 0
0305: && _executer.getQueryCount() > _prefs
0306: .getLargeScriptStmtCount()) {
0307: _executer
0308: .setExecutionListeners(new ISQLExecutionListener[0]);
0309: handler.setLargeScript(true);
0310: }
0311:
0312: _session.getApplication().getThreadPool()
0313: .addTask(_executer);
0314: }
0315: }
0316:
0317: private void onRerunSQL(String sql, IResultTab resultTab) {
0318: _executer = new SQLExecuterTask(_session, sql,
0319: new SQLExecutionHandler(resultTab),
0320: new ISQLExecutionListener[0]);
0321: _session.getApplication().getThreadPool().addTask(_executer);
0322: }
0323:
0324: /**
0325: * Close all the Results frames.
0326: */
0327: public synchronized void closeAllSQLResultFrames() {
0328: List<ResultTabInfo> tabs = new ArrayList<ResultTabInfo>(
0329: _usedTabs);
0330: for (Iterator<ResultTabInfo> it = tabs.iterator(); it.hasNext();) {
0331: ResultTabInfo ti = it.next();
0332: if (ti._resultFrame != null) {
0333: ti._resultFrame.dispose();
0334: ti._resultFrame = null;
0335: }
0336: }
0337: }
0338:
0339: /**
0340: * Close all the Results tabs.
0341: */
0342: public synchronized void closeAllSQLResultTabs() {
0343: List<ResultTabInfo> tabs = new ArrayList<ResultTabInfo>(
0344: _usedTabs);
0345: for (Iterator<ResultTabInfo> it = tabs.iterator(); it.hasNext();) {
0346: ResultTabInfo ti = it.next();
0347: if (ti._resultFrame == null) {
0348: closeTab(ti._tab);
0349: }
0350: }
0351: }
0352:
0353: public synchronized void closeAllButCurrentResultTabs() {
0354: Component selectedTab = _tabbedExecutionsPanel
0355: .getSelectedComponent();
0356:
0357: List<ResultTabInfo> tabs = new ArrayList<ResultTabInfo>(
0358: _usedTabs);
0359: for (Iterator<ResultTabInfo> it = tabs.iterator(); it.hasNext();) {
0360: ResultTabInfo ti = it.next();
0361: if (false == ti._tab.equals(selectedTab)) {
0362: if (ti._resultFrame == null) {
0363: closeTab(ti._tab);
0364: }
0365: }
0366: }
0367: }
0368:
0369: public synchronized void toggleCurrentSQLResultTabSticky() {
0370: if (null != _stickyTab) {
0371: if (_stickyTab.equals(_tabbedExecutionsPanel
0372: .getSelectedComponent())) {
0373: // Sticky is turned off. Just remove sticky and return.
0374: _stickyTab = null;
0375: _tabbedExecutionsPanel.setIconAt(_tabbedExecutionsPanel
0376: .getSelectedIndex(), null);
0377: return;
0378:
0379: } else {
0380: // remove old sticky tab
0381: int indexOfStickyTab = getIndexOfTab(_stickyTab);
0382: if (-1 != indexOfStickyTab) {
0383: _tabbedExecutionsPanel.setIconAt(indexOfStickyTab,
0384: null);
0385: }
0386: _stickyTab = null;
0387: }
0388: }
0389:
0390: if (false == _tabbedExecutionsPanel.getSelectedComponent() instanceof IResultTab) {
0391: //i18n[SQLResultExecuterPanel.nonStickyPanel=Cannot make a cancel panel sticky]
0392: String msg = s_stringMgr
0393: .getString("SQLResultExecuterPanel.nonStickyPanel");
0394: JOptionPane.showMessageDialog(_session.getApplication()
0395: .getMainFrame(), msg);
0396: return;
0397: }
0398:
0399: _stickyTab = (IResultTab) _tabbedExecutionsPanel
0400: .getSelectedComponent();
0401: int selectedIndex = _tabbedExecutionsPanel.getSelectedIndex();
0402:
0403: ImageIcon icon = getStickyIcon();
0404:
0405: _tabbedExecutionsPanel.setIconAt(selectedIndex, icon);
0406: }
0407:
0408: private ImageIcon getStickyIcon() {
0409: ActionCollection actionCollection = _session.getApplication()
0410: .getActionCollection();
0411:
0412: ImageIcon icon = (ImageIcon) actionCollection.get(
0413: ToggleCurrentSQLResultTabStickyAction.class).getValue(
0414: Action.SMALL_ICON);
0415: return icon;
0416: }
0417:
0418: private int getIndexOfTab(IResultTab resultTab) {
0419: if (null == resultTab) {
0420: return -1;
0421: }
0422:
0423: for (int i = 0; i < _tabbedExecutionsPanel.getTabCount(); i++) {
0424: if (resultTab.equals(_tabbedExecutionsPanel
0425: .getComponentAt(i))) {
0426: return i;
0427: }
0428: }
0429: return -1;
0430: }
0431:
0432: public synchronized void closeCurrentResultTab() {
0433: Component selectedTab = _tabbedExecutionsPanel
0434: .getSelectedComponent();
0435:
0436: List<ResultTabInfo> tabs = new ArrayList<ResultTabInfo>(
0437: _usedTabs);
0438: for (Iterator<ResultTabInfo> it = tabs.iterator(); it.hasNext();) {
0439: ResultTabInfo ti = it.next();
0440: if (ti._tab.equals(selectedTab)) {
0441: if (ti._resultFrame == null) {
0442: closeTab(ti._tab);
0443: }
0444: }
0445: }
0446: }
0447:
0448: /**
0449: * Sesssion is ending.
0450: * Remove all listeners that this component has setup. Close all
0451: * torn off result tab windows.
0452: */
0453: void sessionClosing() {
0454: if (_propsListener != null) {
0455: _session.getProperties().removePropertyChangeListener(
0456: _propsListener);
0457: _propsListener = null;
0458: }
0459:
0460: closeAllSQLResultFrames();
0461: }
0462:
0463: /**
0464: * Close the passed <TT>ResultTab</TT>. This is done by clearing
0465: * all data from the tab, removing it from the tabbed panel
0466: * and adding it to the list of available tabs.
0467: *
0468: * @throws IllegalArgumentException
0469: * Thrown if a <TT>null</TT> <TT>ResultTab</TT> passed.
0470: */
0471: public void closeTab(ResultTab tab) {
0472: if (tab == null) {
0473: throw new IllegalArgumentException("Null ResultTab passed");
0474: }
0475: s_log.debug("SQLPanel.closeTab("
0476: + tab.getIdentifier().toString() + ")");
0477: tab.clear();
0478: _tabbedExecutionsPanel.remove(tab);
0479: ResultTabInfo tabInfo = _allTabs.get(tab.getIdentifier());
0480: _availableTabs.add(tabInfo);
0481: _usedTabs.remove(tabInfo);
0482: tabInfo._resultFrame = null;
0483: fireTabRemovedEvent(tab);
0484: }
0485:
0486: /**
0487: * Display the next tab in the SQL results.
0488: */
0489: public void gotoNextResultsTab() {
0490: final int tabCount = _tabbedExecutionsPanel.getTabCount();
0491: if (tabCount > 1) {
0492: int nextTabIdx = _tabbedExecutionsPanel.getSelectedIndex() + 1;
0493: if (nextTabIdx >= tabCount) {
0494: nextTabIdx = 0;
0495: }
0496: _tabbedExecutionsPanel.setSelectedIndex(nextTabIdx);
0497: }
0498: }
0499:
0500: /**
0501: * Display the previous tab in the SQL results.
0502: */
0503: public void gotoPreviousResultsTab() {
0504: final int tabCount = _tabbedExecutionsPanel.getTabCount();
0505: if (tabCount > 1) {
0506: int prevTabIdx = _tabbedExecutionsPanel.getSelectedIndex() - 1;
0507: if (prevTabIdx < 0) {
0508: prevTabIdx = tabCount - 1;
0509: }
0510: _tabbedExecutionsPanel.setSelectedIndex(prevTabIdx);
0511: }
0512: }
0513:
0514: protected void fireTabAddedEvent(IResultTab tab) {
0515: // Guaranteed to be non-null.
0516: Object[] listeners = _listeners.getListenerList();
0517: // Process the listeners last to first, notifying
0518: // those that are interested in this event.
0519: ResultTabEvent evt = null;
0520: for (int i = listeners.length - 2; i >= 0; i -= 2) {
0521: if (listeners[i] == IResultTabListener.class) {
0522: // Lazily create the event:
0523: if (evt == null) {
0524: evt = new ResultTabEvent(_session, tab);
0525: }
0526: ((IResultTabListener) listeners[i + 1])
0527: .resultTabAdded(evt);
0528: }
0529: }
0530: }
0531:
0532: protected void fireTabRemovedEvent(IResultTab tab) {
0533: // Guaranteed to be non-null.
0534: Object[] listeners = _listeners.getListenerList();
0535: // Process the listeners last to first, notifying
0536: // those that are interested in this event.
0537: ResultTabEvent evt = null;
0538: for (int i = listeners.length - 2; i >= 0; i -= 2) {
0539: if (listeners[i] == IResultTabListener.class) {
0540: // Lazily create the event:
0541: if (evt == null) {
0542: evt = new ResultTabEvent(_session, tab);
0543: }
0544: ((IResultTabListener) listeners[i + 1])
0545: .resultTabRemoved(evt);
0546: }
0547: }
0548: }
0549:
0550: protected void fireTabTornOffEvent(IResultTab tab) {
0551: // Guaranteed to be non-null.
0552: Object[] listeners = _listeners.getListenerList();
0553: // Process the listeners last to first, notifying
0554: // those that are interested in this event.
0555: ResultTabEvent evt = null;
0556: for (int i = listeners.length - 2; i >= 0; i -= 2) {
0557: if (listeners[i] == IResultTabListener.class) {
0558: // Lazily create the event:
0559: if (evt == null) {
0560: evt = new ResultTabEvent(_session, tab);
0561: }
0562: ((IResultTabListener) listeners[i + 1])
0563: .resultTabTornOff(evt);
0564: }
0565: }
0566: }
0567:
0568: protected void fireTornOffResultTabReturned(IResultTab tab) {
0569: // Guaranteed to be non-null.
0570: Object[] listeners = _listeners.getListenerList();
0571: // Process the listeners last to first, notifying
0572: // those that are interested in this event.
0573: ResultTabEvent evt = null;
0574: for (int i = listeners.length - 2; i >= 0; i -= 2) {
0575: if (listeners[i] == IResultTabListener.class) {
0576: // Lazily create the event:
0577: if (evt == null) {
0578: evt = new ResultTabEvent(_session, tab);
0579: }
0580: ((IResultTabListener) listeners[i + 1])
0581: .tornOffResultTabReturned(evt);
0582: }
0583: }
0584: }
0585:
0586: protected String fireSQLToBeExecutedEvent(String sql) {
0587: // Guaranteed to be non-null.
0588: Object[] listeners = _listeners.getListenerList();
0589: // Process the listeners last to first, notifying
0590: // those that are interested in this event.
0591: for (int i = listeners.length - 2; i >= 0; i -= 2) {
0592: if (listeners[i] == ISQLExecutionListener.class) {
0593: sql = ((ISQLExecutionListener) listeners[i + 1])
0594: .statementExecuting(sql);
0595: if (sql == null) {
0596: break;
0597: }
0598: }
0599: }
0600: return sql;
0601: }
0602:
0603: /**
0604: * Create an internal frame for the specified tab and
0605: * display the tab in the internal frame after removing
0606: * it from the tabbed pane.
0607: *
0608: * @param tab <TT>ResultTab</TT> to be displayed in
0609: * an internal frame.
0610: *
0611: * @throws IllegalArgumentException
0612: * Thrown if a <TT>null</TT> <TT>ResultTab</TT> passed.
0613: */
0614: public void createWindow(ResultTab tab) {
0615: if (tab == null) {
0616: throw new IllegalArgumentException("Null ResultTab passed");
0617: }
0618: s_log.debug("SQLPanel.createWindow("
0619: + tab.getIdentifier().toString() + ")");
0620: _tabbedExecutionsPanel.remove(tab);
0621: ResultFrame frame = new ResultFrame(_session, tab);
0622: ResultTabInfo tabInfo = _allTabs.get(tab.getIdentifier());
0623: tabInfo._resultFrame = frame;
0624: _session.getApplication().getMainFrame().addInternalFrame(
0625: frame, true, null, JLayeredPane.PALETTE_LAYER);
0626: fireTabTornOffEvent(tab);
0627: frame.setVisible(true);
0628:
0629: // There used to be a frame.pack() here but it resized the frame
0630: // to be very wide if text output was used.
0631:
0632: frame.toFront();
0633: frame.requestFocus();
0634:
0635: }
0636:
0637: /**
0638: * Return the passed tab back into the tabbed pane.
0639: *
0640: * @param tab <TT>Resulttab</TT> to be returned
0641: *
0642: * @throws IllegalArgumentException
0643: * Thrown if a <TT>null</TT> <TT>ResultTab</TT> passed.
0644: */
0645: public void returnToTabbedPane(ResultTab tab) {
0646: if (tab == null) {
0647: throw new IllegalArgumentException("Null ResultTab passed");
0648: }
0649:
0650: s_log.debug("SQLPanel.returnToTabbedPane("
0651: + tab.getIdentifier().toString() + ")");
0652:
0653: ResultTabInfo tabInfo = _allTabs.get(tab.getIdentifier());
0654: if (tabInfo._resultFrame != null) {
0655: addResultsTab(tab, null);
0656: fireTornOffResultTabReturned(tab);
0657: tabInfo._resultFrame = null;
0658: }
0659: }
0660:
0661: /**
0662: * @see net.sourceforge.squirrel_sql.client.session.mainpanel.ISQLResultExecuter#getSelectedResultTab()
0663: */
0664: public IResultTab getSelectedResultTab() {
0665: return (IResultTab) _tabbedExecutionsPanel
0666: .getSelectedComponent();
0667: }
0668:
0669: /**
0670: * The idea here is to allow the caller to force the result to be re-run,
0671: * potentially altering the output in the case where readFully is true and
0672: * the result previously contained data placeholders (<clob>). This will
0673: * be useful for automating export to CSV/Excel of CLOB data, where it is
0674: * most likely that the user doesn't want to see <clob> in the resultant
0675: * export file.
0676: *
0677: * @param readFully if true, then the configuration will (temporarily) be
0678: * set so that clob data is read and displayed.
0679: */
0680: public void reRunSelectedResultTab(boolean readFully) {
0681: boolean clobReadOrigVal = DataTypeClob.getReadCompleteClob();
0682: if (readFully) {
0683: DataTypeClob.setReadCompleteClob(true);
0684: }
0685: IResultTab rt = (IResultTab) _tabbedExecutionsPanel
0686: .getSelectedComponent();
0687: rt.reRunSQL();
0688: if (readFully) {
0689: DataTypeClob.setReadCompleteClob(clobReadOrigVal);
0690: }
0691: }
0692:
0693: private void addResultsTab(SQLExecutionInfo exInfo,
0694: ResultSetDataSet rsds, ResultSetMetaDataDataSet mdds,
0695: final JPanel cancelPanel,
0696: IDataSetUpdateableTableModel creator,
0697: final IResultTab resultTabToReplace) {
0698: final ResultTab tab;
0699: if (_availableTabs.size() > 0) {
0700: ResultTabInfo ti = _availableTabs.remove(0);
0701: _usedTabs.add(ti);
0702: tab = ti._tab;
0703: tab.reInit(creator, exInfo);
0704: s_log.debug("Using tab " + tab.getIdentifier().toString()
0705: + " for results.");
0706: } else {
0707: ResultTabListener resultTabListener = new ResultTabListener() {
0708: public void rerunSQL(String sql, IResultTab resultTab) {
0709: onRerunSQL(sql, resultTab);
0710: }
0711: };
0712:
0713: tab = new ResultTab(_session, this , _idFactory
0714: .createIdentifier(), exInfo, creator,
0715: resultTabListener);
0716: ResultTabInfo ti = new ResultTabInfo(tab);
0717: _allTabs.put(tab.getIdentifier(), ti);
0718: _usedTabs.add(ti);
0719: s_log.debug("Created new tab "
0720: + tab.getIdentifier().toString() + " for results.");
0721: }
0722:
0723: try {
0724: tab.showResults(rsds, mdds, exInfo);
0725: SwingUtilities.invokeLater(new Runnable() {
0726: public void run() {
0727: _tabbedExecutionsPanel.remove(cancelPanel);
0728: addResultsTab(tab, resultTabToReplace);
0729: _tabbedExecutionsPanel.setSelectedComponent(tab);
0730: fireTabAddedEvent(tab);
0731: }
0732: });
0733: } catch (DataSetException dse) {
0734: _session.showErrorMessage(dse);
0735: }
0736: }
0737:
0738: private void addResultsTab(ResultTab tab,
0739: IResultTab resultTabToReplace) {
0740: if (null == resultTabToReplace && null == _stickyTab) {
0741: _tabbedExecutionsPanel.addTab(tab.getTitle(), null, tab,
0742: tab.getViewableSqlString());
0743: checkResultTabLimit();
0744: } else {
0745: int indexToReplace = -1;
0746: ImageIcon tabIcon = null;
0747:
0748: // Either resultTabToReplace or _stickyTab must be not null here
0749: if (null != resultTabToReplace
0750: && _stickyTab != resultTabToReplace) {
0751: indexToReplace = getIndexOfTab(resultTabToReplace);
0752: } else {
0753: indexToReplace = getIndexOfTab(_stickyTab);
0754: if (-1 == indexToReplace) {
0755: // sticky tab was closed
0756: _stickyTab = null;
0757: } else {
0758: tabIcon = getStickyIcon();
0759: _stickyTab = tab;
0760: }
0761: }
0762:
0763: if (-1 == indexToReplace) {
0764: // Just add the tab
0765: addResultsTab(tab, null);
0766: return;
0767: }
0768:
0769: closeResultTabAt(indexToReplace);
0770: _tabbedExecutionsPanel.insertTab(tab.getTitle(), tabIcon,
0771: tab, tab.getViewableSqlString(), indexToReplace);
0772: }
0773: }
0774:
0775: private void checkResultTabLimit() {
0776: SessionProperties props = _session.getProperties();
0777:
0778: while (props.getLimitSQLResultTabs()
0779: && props.getSqlResultTabLimit() < _tabbedExecutionsPanel
0780: .getTabCount()) {
0781: closeResultTabAt(0);
0782: }
0783: }
0784:
0785: private void closeResultTabAt(int index) {
0786: Component selectedTab = _tabbedExecutionsPanel
0787: .getComponentAt(index);
0788:
0789: List<ResultTabInfo> tabs = new ArrayList<ResultTabInfo>(
0790: _usedTabs);
0791: for (Iterator<ResultTabInfo> it = tabs.iterator(); it.hasNext();) {
0792: ResultTabInfo ti = it.next();
0793: if (ti._tab.equals(selectedTab)) {
0794: if (ti._resultFrame == null) {
0795: closeTab(ti._tab);
0796: }
0797: }
0798: }
0799: }
0800:
0801: private void propertiesHaveChanged(String propName) {
0802: final SessionProperties props = _session.getProperties();
0803:
0804: if (propName == null
0805: || propName
0806: .equals(SessionProperties.IPropertyNames.AUTO_COMMIT)) {
0807: SetAutoCommitTask task = new SetAutoCommitTask();
0808: if (SwingUtilities.isEventDispatchThread()) {
0809: _session.getApplication().getThreadPool().addTask(task);
0810: } else {
0811: task.run();
0812: }
0813: }
0814:
0815: if (propName == null
0816: || propName
0817: .equals(SessionProperties.IPropertyNames.SQL_EXECUTION_TAB_PLACEMENT)) {
0818: _tabbedExecutionsPanel.setTabPlacement(props
0819: .getSQLExecutionTabPlacement());
0820: }
0821: }
0822:
0823: private class SetAutoCommitTask implements Runnable {
0824:
0825: public void run() {
0826: final ISQLConnection conn = _session.getSQLConnection();
0827: final SessionProperties props = _session.getProperties();
0828: if (conn != null) {
0829: boolean auto = true;
0830: try {
0831: auto = conn.getAutoCommit();
0832: } catch (SQLException ex) {
0833: s_log.error("Error with transaction control", ex);
0834: _session.showErrorMessage(ex);
0835: }
0836: try {
0837: conn.setAutoCommit(props.getAutoCommit());
0838: } catch (SQLException ex) {
0839: props.setAutoCommit(auto);
0840: _session.showErrorMessage(ex);
0841: }
0842: }
0843: }
0844: }
0845:
0846: private void createGUI() {
0847: final SessionProperties props = _session.getProperties();
0848: _tabbedExecutionsPanel = UIFactory.getInstance()
0849: .createTabbedPane(props.getSQLExecutionTabPlacement());
0850:
0851: createTabPopup();
0852:
0853: setLayout(new BorderLayout());
0854:
0855: add(_tabbedExecutionsPanel, BorderLayout.CENTER);
0856: }
0857:
0858: /**
0859: * Due to JDK 1.4 Bug 4465870 this doesn't work with JDK 1.4. when scrollable tabbed pane is used.
0860: */
0861: private void createTabPopup() {
0862: final JPopupMenu popup = new JPopupMenu();
0863:
0864: // i18n[SQLResultExecuterPanel.close=Close]
0865: String closeLabel = s_stringMgr
0866: .getString("SQLResultExecuterPanel.close");
0867: JMenuItem mnuClose = new JMenuItem(closeLabel);
0868: initAccelerator(CloseCurrentSQLResultTabAction.class, mnuClose);
0869: mnuClose.addActionListener(new ActionListener() {
0870: public void actionPerformed(ActionEvent e) {
0871: closeCurrentResultTab();
0872: }
0873: });
0874: popup.add(mnuClose);
0875:
0876: // i18n[SQLResultExecuterPanel.closeAllButThis=Close all but this]
0877: String cabtLabel = s_stringMgr
0878: .getString("SQLResultExecuterPanel.closeAllButThis");
0879: JMenuItem mnuCloseAllButThis = new JMenuItem(cabtLabel);
0880: initAccelerator(CloseAllSQLResultTabsButCurrentAction.class,
0881: mnuCloseAllButThis);
0882: mnuCloseAllButThis.addActionListener(new ActionListener() {
0883: public void actionPerformed(ActionEvent e) {
0884: closeAllButCurrentResultTabs();
0885: }
0886: });
0887: popup.add(mnuCloseAllButThis);
0888:
0889: // i18n[SQLResultExecuterPanel.closeAll=Close all]
0890: String caLabel = s_stringMgr
0891: .getString("SQLResultExecuterPanel.closeAll");
0892: JMenuItem mnuCloseAll = new JMenuItem(caLabel);
0893: initAccelerator(CloseAllSQLResultTabsAction.class, mnuCloseAll);
0894: mnuCloseAll.addActionListener(new ActionListener() {
0895: public void actionPerformed(ActionEvent e) {
0896: closeAllSQLResultTabs();
0897: }
0898: });
0899: popup.add(mnuCloseAll);
0900:
0901: // i18n[SQLResultExecuterPanel.toggleSticky=Toggle sticky]
0902: String tsLabel = s_stringMgr
0903: .getString("SQLResultExecuterPanel.toggleSticky");
0904: JMenuItem mnuToggleSticky = new JMenuItem(tsLabel);
0905: initAccelerator(ToggleCurrentSQLResultTabStickyAction.class,
0906: mnuToggleSticky);
0907: mnuToggleSticky.addActionListener(new ActionListener() {
0908: public void actionPerformed(ActionEvent e) {
0909: toggleCurrentSQLResultTabSticky();
0910: }
0911: });
0912: popup.add(mnuToggleSticky);
0913:
0914: _tabbedExecutionsPanel.addMouseListener(new MouseAdapter() {
0915: public void mousePressed(MouseEvent e) {
0916: maybeShowPopup(e, popup);
0917: }
0918:
0919: public void mouseReleased(MouseEvent e) {
0920: maybeShowPopup(e, popup);
0921: }
0922: });
0923: }
0924:
0925: private void initAccelerator(Class<? extends Action> actionClass,
0926: JMenuItem mnuItem) {
0927: Action action = _session.getApplication().getActionCollection()
0928: .get(actionClass);
0929:
0930: String accel = (String) action
0931: .getValue(Resources.ACCELERATOR_STRING);
0932: if (null != accel && 0 != accel.trim().length()) {
0933: mnuItem.setAccelerator(KeyStroke.getKeyStroke(accel));
0934: }
0935: }
0936:
0937: private void maybeShowPopup(MouseEvent e, JPopupMenu popup) {
0938: if (e.isPopupTrigger()) {
0939: int tab = _tabbedExecutionsPanel.getUI().tabForCoordinate(
0940: _tabbedExecutionsPanel, e.getX(), e.getY());
0941: if (-1 != tab) {
0942: popup.show(e.getComponent(), e.getX(), e.getY());
0943: }
0944: }
0945: }
0946:
0947: private SQLType getSQLType(String sql) {
0948: SQLType result = SQLType.UNKNOWN;
0949: if (sql.toLowerCase().startsWith("insert")) {
0950: result = SQLType.INSERT;
0951: }
0952: if (sql.toLowerCase().startsWith("update")) {
0953: result = SQLType.UPDATE;
0954: }
0955: if (sql.toLowerCase().startsWith("select")) {
0956: result = SQLType.SELECT;
0957: }
0958: if (sql.toLowerCase().startsWith("delete")) {
0959: result = SQLType.DELETE;
0960: }
0961: return result;
0962: }
0963:
0964: /** This class is the handler for the execution of sql against the SQLExecuterPanel
0965: *
0966: */
0967: private class SQLExecutionHandler implements ISQLExecuterHandler {
0968: private CancelPanel _cancelPanel = new CancelPanel();
0969:
0970: /**
0971: * Hold onto the current ResultDataSet so if the execution is
0972: * cancelled then this can be cancelled.
0973: */
0974: private ResultSetDataSet rsds = null;
0975:
0976: private String sqlToBeExecuted = null;
0977: private SQLType sqlType = null;
0978: private IResultTab _resultTabToReplace;
0979: private boolean _largeScript = false;
0980: private double _scriptTotalTime = 0;
0981: private double _scriptQueryTime = 0;
0982: private double _scriptOutptutTime = 0;
0983: private int _scriptRowsInserted = 0;
0984: private int _scriptRowsSelected = 0;
0985: private int _scriptRowsUpdated = 0;
0986: private int _scriptRowsDeleted = 0;
0987:
0988: public SQLExecutionHandler(IResultTab resultTabToReplace) {
0989: super ();
0990: _resultTabToReplace = resultTabToReplace;
0991: setCancelPanel(_cancelPanel);
0992: }
0993:
0994: /**
0995: * Set whether or not the script is large. If the script is large, then
0996: * do some performance optimizations with the GUI so that it remains
0997: * responsive. If the UI is not responsive, then the user is not able
0998: * to see what is happening, nor are they able to control it (cancelling
0999: * becomes ineffective)
1000: *
1001: * @param aBoolean whether or not the script is large.
1002: */
1003: public void setLargeScript(boolean aBoolean) {
1004: _largeScript = aBoolean;
1005: }
1006:
1007: /**
1008: * Determines whether or not the current statement SQL should be rendered.
1009: * Since too many statements can cause the UI to stop rendering the
1010: * statements, we back off rendering after many statements so that the UI
1011: * can continue to provide feedback to the user.
1012: *
1013: * @param current
1014: * @param total
1015: * @return
1016: */
1017: private boolean shouldRenderSQL(int current, int total) {
1018: if (!_largeScript) {
1019: return true;
1020: }
1021: boolean result = true;
1022: // Back-off a bit after a hundred updates to allow the UI to update
1023: if (total > 200 && current > 100 && current % 10 != 0) {
1024: result = false;
1025: }
1026: if (total > 1000 && current > 500 && current % 50 != 0) {
1027: result = false;
1028: }
1029: if (total > 2000 && current > 1000 && current % 100 != 0) {
1030: result = false;
1031: }
1032: return result;
1033: }
1034:
1035: public void sqlToBeExecuted(final String sql) {
1036: _cancelPanel.incCurrentQueryIndex();
1037: int currentStmtCount = _cancelPanel.getCurrentQueryIndex();
1038: if (!shouldRenderSQL(currentStmtCount, _cancelPanel
1039: .getTotalCount())) {
1040: return;
1041: }
1042: final String cleanSQL = StringUtilities.cleanString(sql);
1043: sqlToBeExecuted = cleanSQL;
1044: sqlType = getSQLType(cleanSQL);
1045:
1046: SwingUtilities.invokeLater(new Runnable() {
1047: public void run() {
1048: _cancelPanel.setSQL(sqlToBeExecuted);
1049:
1050: // i18n[SQLResultExecuterPanel.execStatus=Executing SQL...]
1051: String status = s_stringMgr
1052: .getString("SQLResultExecuterPanel.execStatus");
1053: _cancelPanel.setStatusLabel(status);
1054: }
1055: });
1056: }
1057:
1058: /**
1059: * This will - depending on the size of the script - print a message
1060: * indicating the time that it took to execute one or more queries.
1061: * When executing a large script (as defined by the user, but default is
1062: * > 200 statements) we don't want to keep sending messages to the
1063: * message panel, otherwise the UI will get behind and slow the execution
1064: * of the script and prevent the user from cancelling the operation. So
1065: * this method will track the total time when executing a large script,
1066: * otherwise for small scripts it puts out a message for every statement.
1067: */
1068: public void sqlExecutionComplete(SQLExecutionInfo exInfo,
1069: int processedStatementCount, int statementCount) {
1070: double executionLength = ((double) exInfo
1071: .getSQLExecutionElapsedMillis()) / 1000;
1072: double outputLength = ((double) exInfo
1073: .getResultsProcessingElapsedMillis()) / 1000;
1074: double totalLength = executionLength + outputLength;
1075:
1076: if (_largeScript) {
1077: // Track the time in aggregate for the script.
1078: _scriptQueryTime += executionLength;
1079: _scriptOutptutTime += outputLength;
1080: _scriptTotalTime += totalLength;
1081:
1082: // When we get to the last statement, if the script is large,
1083: // show the user the total execution time.
1084: if (statementCount == processedStatementCount) {
1085: printScriptExecDetails(statementCount,
1086: _scriptQueryTime, _scriptOutptutTime,
1087: _scriptTotalTime);
1088: }
1089: } else {
1090: printStatementExecTime(processedStatementCount,
1091: statementCount, executionLength, outputLength,
1092: totalLength);
1093: }
1094: }
1095:
1096: private void printScriptExecDetails(int statementCount,
1097: double executionLength, double outputLength,
1098: double totalLength) {
1099: final NumberFormat nbrFmt = NumberFormat
1100: .getNumberInstance();
1101:
1102: Object[] args = new Object[] {
1103: Integer.valueOf(statementCount),
1104: nbrFmt.format(totalLength),
1105: nbrFmt.format(executionLength),
1106: nbrFmt.format(outputLength) };
1107:
1108: //i18n[SQLResultExecuterPanel.scriptQueryStatistics=Executed {0}
1109: //queries; elapsed time (seconds) - Total: {1}, SQL query: {2},
1110: //Building output: {3}]
1111: String stats = s_stringMgr.getString(
1112: "SQLResultExecuterPanel.scriptQueryStatistics",
1113: args);
1114:
1115: String[] counts = new String[] {
1116: Integer.toString(_scriptRowsInserted),
1117: Integer.toString(_scriptRowsSelected),
1118: Integer.toString(_scriptRowsUpdated),
1119: Integer.toString(_scriptRowsDeleted) };
1120:
1121: //i18n[SQLResultExecuterPanel.scriptStmtCounts=Row update
1122: //counts: {0} Inserts, {1} Selects, {2} Updates, {3} Deletes
1123: String msg = s_stringMgr.getString(
1124: "SQLResultExecuterPanel.scriptStmtCounts", counts);
1125: getSession().showMessage(msg);
1126: getSession().showMessage(stats);
1127: }
1128:
1129: private void printStatementExecTime(
1130: int processedStatementCount, int statementCount,
1131: double executionLength, double outputLength,
1132: double totalLength) {
1133: final NumberFormat nbrFmt = NumberFormat
1134: .getNumberInstance();
1135:
1136: Object[] args = new Object[] {
1137: Integer.valueOf(processedStatementCount),
1138: Integer.valueOf(statementCount),
1139: nbrFmt.format(totalLength),
1140: nbrFmt.format(executionLength),
1141: nbrFmt.format(outputLength) };
1142:
1143: //i18n[SQLResultExecuterPanel.queryStatistics=Query {0} of {1}
1144: //elapsed time (seconds) - Total: {2}, SQL query: {3},
1145: //Building output: {4}]
1146: String stats = s_stringMgr.getString(
1147: "SQLResultExecuterPanel.queryStatistics", args);
1148:
1149: getSession().showMessage(stats);
1150: }
1151:
1152: public void sqlExecutionCancelled() {
1153: if (rsds != null) {
1154: rsds.cancelProcessing();
1155: }
1156: // i18n[SQLResultExecuterPanel.canceleRequested=Query execution cancel requested by user.]
1157: // String canc =
1158: // s_stringMgr.getString("SQLResultExecuterPanel.canceleRequested");
1159: // getSession().getMessageHandler().showMessage(canc);
1160: }
1161:
1162: public void sqlDataUpdated(int updateCount) {
1163:
1164: Integer count = Integer.valueOf(updateCount);
1165: String msg = "";
1166:
1167: switch (sqlType) {
1168: case INSERT:
1169: if (_largeScript) {
1170: _scriptRowsInserted++;
1171: } else {
1172: // i18n[SQLResultExecuterPanel.rowsUpdated={0} Row(s) Inserted]
1173: msg = s_stringMgr.getString(
1174: "SQLResultExecuterPanel.rowsInserted",
1175: count);
1176: }
1177: break;
1178: case SELECT:
1179: if (_largeScript) {
1180: _scriptRowsSelected++;
1181: } else {
1182: // i18n[SQLResultExecuterPanel.rowsSelected={0} Row(s) Selected]
1183: msg = s_stringMgr.getString(
1184: "SQLResultExecuterPanel.rowsSelected",
1185: count);
1186: }
1187: break;
1188: case UPDATE:
1189: if (_largeScript) {
1190: _scriptRowsUpdated++;
1191: } else {
1192: // i18n[SQLResultExecuterPanel.rowsUpdated={0} Row(s) Updated]
1193: msg = s_stringMgr
1194: .getString(
1195: "SQLResultExecuterPanel.rowsUpdated",
1196: count);
1197: }
1198: break;
1199: case DELETE:
1200: if (_largeScript) {
1201: _scriptRowsDeleted++;
1202: } else {
1203: // i18n[SQLResultExecuterPanel.rowsDeleted={0} Row(s) Deleted]
1204: msg = s_stringMgr
1205: .getString(
1206: "SQLResultExecuterPanel.rowsDeleted",
1207: count);
1208: }
1209: break;
1210: }
1211: if (_largeScript) {
1212: return;
1213: }
1214: getSession().showMessage(msg);
1215: }
1216:
1217: public void sqlResultSetAvailable(ResultSet rs,
1218: SQLExecutionInfo info,
1219: IDataSetUpdateableTableModel model)
1220: throws DataSetException {
1221: // i18n[SQLResultExecuterPanel.outputStatus=Building output...]
1222: String outputStatus = s_stringMgr
1223: .getString("SQLResultExecuterPanel.outputStatus");
1224: _cancelPanel.setStatusLabel(outputStatus);
1225: rsds = new ResultSetDataSet();
1226: SessionProperties props = getSession().getProperties();
1227: ResultSetMetaDataDataSet rsmdds = null;
1228: if (props.getShowResultsMetaData()) {
1229: rsmdds = new ResultSetMetaDataDataSet(rs);
1230: }
1231: rsds.setResultSet(rs);
1232:
1233: addResultsTab(info, rsds, rsmdds, _cancelPanel, model,
1234: _resultTabToReplace);
1235: rsds = null;
1236: }
1237:
1238: public void sqlExecutionWarning(SQLWarning warn) {
1239: getSession().showMessage(warn);
1240: }
1241:
1242: public void sqlStatementCount(int statementCount) {
1243: _cancelPanel.setQueryCount(statementCount);
1244: }
1245:
1246: public void sqlCloseExecutionHandler() {
1247: removeCancelPanel(_cancelPanel);
1248: _executer = null;
1249: }
1250:
1251: public void sqlExecutionException(Throwable th,
1252: String postErrorString) {
1253: SQLExecutionException ex = new SQLExecutionException(th,
1254: postErrorString);
1255:
1256: String message = getSession().formatException(ex);
1257:
1258: getSession().showErrorMessage(message);
1259:
1260: if (getSession().getProperties().getWriteSQLErrorsToLog()) {
1261: s_log.info(message);
1262: }
1263: }
1264:
1265: private void removeCancelPanel(final JPanel cancelPanel) {
1266: SwingUtilities.invokeLater(new Runnable() {
1267: public void run() {
1268: _tabbedExecutionsPanel.remove(cancelPanel);
1269:
1270: int indexToSelect = -1;
1271: if (null == _resultTabToReplace) {
1272: indexToSelect = getIndexOfTab(_stickyTab);
1273: } else {
1274: indexToSelect = getIndexOfTab(_resultTabToReplace);
1275: }
1276:
1277: if (-1 != indexToSelect) {
1278: _tabbedExecutionsPanel
1279: .setSelectedIndex(indexToSelect);
1280: }
1281:
1282: }
1283: });
1284: }
1285:
1286: private void setCancelPanel(final JPanel panel) {
1287: SwingUtilities.invokeLater(new Runnable() {
1288: public void run() {
1289: _tabbedExecutionsPanel.addTab(i18n.EXEC_SQL_MSG,
1290: null, panel, i18n.CANCEL_SQL_MSG);
1291: _tabbedExecutionsPanel.setSelectedComponent(panel);
1292: }
1293: });
1294: }
1295:
1296: private final class CancelPanel extends JPanel implements
1297: ActionListener {
1298: private static final long serialVersionUID = 1L;
1299: private JLabel _sqlLbl = new JLabel();
1300: private JLabel _currentStatusLbl = new JLabel();
1301:
1302: /** Total number of queries that will be executed. */
1303: private int _queryCount;
1304:
1305: /** Number of the query currently being executed (starts from 1). */
1306: private int _currentQueryIndex = 0;
1307:
1308: private CancelPanel() {
1309: super (new GridBagLayout());
1310:
1311: // i18n[SQLResultExecuterPanel.cancelButtonLabel=Cancel]
1312: String label = s_stringMgr
1313: .getString("SQLResultExecuterPanel.cancelButtonLabel");
1314: JButton cancelBtn = new JButton(label);
1315: cancelBtn.addActionListener(this );
1316:
1317: GridBagConstraints gbc = new GridBagConstraints();
1318:
1319: gbc.anchor = GridBagConstraints.WEST;
1320: gbc.insets = new Insets(5, 10, 5, 10);
1321:
1322: gbc.gridx = 0;
1323: gbc.gridy = 0;
1324:
1325: // i18n[SQLResultExecuterPanel.sqlLabel=SQL:]
1326: label = s_stringMgr
1327: .getString("SQLResultExecuterPanel.sqlLabel");
1328: add(new JLabel(label), gbc);
1329:
1330: gbc.weightx = 1;
1331: ++gbc.gridx;
1332: add(_sqlLbl, gbc);
1333:
1334: gbc.weightx = 0;
1335: gbc.gridx = 0;
1336: ++gbc.gridy;
1337: // i18n[SQLResultExecuterPanel.statusLabel=Status:]
1338: label = s_stringMgr
1339: .getString("SQLResultExecuterPanel.statusLabel");
1340: add(new JLabel(label), gbc);
1341:
1342: ++gbc.gridx;
1343: add(_currentStatusLbl, gbc);
1344:
1345: gbc.gridx = 0;
1346: ++gbc.gridy;
1347: gbc.fill = GridBagConstraints.NONE;
1348: add(cancelBtn, gbc);
1349: }
1350:
1351: public void incCurrentQueryIndex() {
1352: ++_currentQueryIndex;
1353: }
1354:
1355: public void setSQL(String sql) {
1356: // i18n[SQLResultExecuterPanel.currentSQLLabel={0} of {1} - {2}]
1357: String label = s_stringMgr.getString(
1358: "SQLResultExecuterPanel.currentSQLLabel",
1359: new Object[] {
1360: String.valueOf(_currentQueryIndex),
1361: String.valueOf(_queryCount), sql });
1362: _sqlLbl.setText(label);
1363: }
1364:
1365: public void setStatusLabel(String text) {
1366: _currentStatusLbl.setText(text);
1367: }
1368:
1369: public void setQueryCount(int value) {
1370: _queryCount = value;
1371: _currentQueryIndex = 0;
1372: }
1373:
1374: public int getTotalCount() {
1375: return _queryCount;
1376: }
1377:
1378: public int getCurrentQueryIndex() {
1379: return _currentQueryIndex;
1380: }
1381:
1382: public void actionPerformed(ActionEvent event) {
1383: try {
1384: if (_executer != null) {
1385: _executer.cancel();
1386: }
1387: } catch (Throwable th) {
1388: s_log.error("Error occured cancelling SQL", th);
1389: }
1390: }
1391: }
1392: }
1393:
1394: private class MyPropertiesListener implements
1395: PropertyChangeListener {
1396: private boolean _listening = true;
1397:
1398: void stopListening() {
1399: _listening = false;
1400: }
1401:
1402: void startListening() {
1403: _listening = true;
1404: }
1405:
1406: public void propertyChange(PropertyChangeEvent evt) {
1407: if (_listening) {
1408: propertiesHaveChanged(evt.getPropertyName());
1409: }
1410: }
1411: }
1412:
1413: private final static class ResultTabInfo {
1414: final ResultTab _tab;
1415: ResultFrame _resultFrame;
1416:
1417: ResultTabInfo(ResultTab tab) {
1418: if (tab == null) {
1419: throw new IllegalArgumentException(
1420: "Null ResultTab passed");
1421: }
1422: _tab = tab;
1423: }
1424: }
1425: }
|