001: package net.sourceforge.squirrel_sql.plugins.mssql;
002:
003: /*
004: * Copyright (C) 2004 Ryan Walberg <generalpf@yahoo.com>
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020:
021: import javax.swing.Action;
022: import javax.swing.JMenu;
023: import javax.swing.event.MenuEvent;
024: import javax.swing.event.MenuListener;
025:
026: import net.sourceforge.squirrel_sql.client.IApplication;
027: import net.sourceforge.squirrel_sql.client.action.ActionCollection;
028: import net.sourceforge.squirrel_sql.client.gui.session.ObjectTreeInternalFrame;
029: import net.sourceforge.squirrel_sql.client.gui.session.SQLInternalFrame;
030: import net.sourceforge.squirrel_sql.client.plugin.PluginQueryTokenizerPreferencesManager;
031: import net.sourceforge.squirrel_sql.client.plugin.PluginResources;
032: import net.sourceforge.squirrel_sql.client.plugin.PluginSessionCallback;
033: import net.sourceforge.squirrel_sql.client.plugin.gui.PluginGlobalPreferencesTab;
034: import net.sourceforge.squirrel_sql.client.plugin.gui.PluginQueryTokenizerPreferencesPanel;
035: import net.sourceforge.squirrel_sql.client.preferences.IGlobalPreferencesPanel;
036: import net.sourceforge.squirrel_sql.client.session.IObjectTreeAPI;
037: import net.sourceforge.squirrel_sql.client.session.ISession;
038: import net.sourceforge.squirrel_sql.client.session.mainpanel.objecttree.ObjectTreeNode;
039: import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetException;
040: import net.sourceforge.squirrel_sql.fw.datasetviewer.ResultSetDataSet;
041: import net.sourceforge.squirrel_sql.fw.dialects.DialectFactory;
042: import net.sourceforge.squirrel_sql.fw.gui.GUIUtils;
043: import net.sourceforge.squirrel_sql.fw.preferences.IQueryTokenizerPreferenceBean;
044: import net.sourceforge.squirrel_sql.fw.sql.DatabaseObjectType;
045: import net.sourceforge.squirrel_sql.fw.sql.IDatabaseObjectInfo;
046: import net.sourceforge.squirrel_sql.fw.sql.ISQLConnection;
047: import net.sourceforge.squirrel_sql.fw.sql.ITableInfo;
048: import net.sourceforge.squirrel_sql.fw.sql.SQLDatabaseMetaData;
049: import net.sourceforge.squirrel_sql.fw.util.StringManager;
050: import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory;
051: import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
052: import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;
053: import net.sourceforge.squirrel_sql.plugins.mssql.action.GenerateSqlAction;
054: import net.sourceforge.squirrel_sql.plugins.mssql.action.IndexDefragAction;
055: import net.sourceforge.squirrel_sql.plugins.mssql.action.ScriptProcedureAction;
056: import net.sourceforge.squirrel_sql.plugins.mssql.action.ScriptProcedureExecAction;
057: import net.sourceforge.squirrel_sql.plugins.mssql.action.ShowStatisticsAction;
058: import net.sourceforge.squirrel_sql.plugins.mssql.action.ShrinkDatabaseAction;
059: import net.sourceforge.squirrel_sql.plugins.mssql.action.ShrinkDatabaseFileAction;
060: import net.sourceforge.squirrel_sql.plugins.mssql.action.TruncateLogAction;
061: import net.sourceforge.squirrel_sql.plugins.mssql.action.UpdateStatisticsAction;
062: import net.sourceforge.squirrel_sql.plugins.mssql.event.IndexIterationListener;
063: import net.sourceforge.squirrel_sql.plugins.mssql.gui.MonitorPanel;
064: import net.sourceforge.squirrel_sql.plugins.mssql.prefs.MSSQLPreferenceBean;
065: import net.sourceforge.squirrel_sql.plugins.mssql.prefs.PreferencesManager;
066: import net.sourceforge.squirrel_sql.plugins.mssql.sql.dbfile.DatabaseFile;
067: import net.sourceforge.squirrel_sql.plugins.mssql.sql.dbfile.DatabaseFileInfo;
068: import net.sourceforge.squirrel_sql.plugins.mssql.tab.ViewSourceTab;
069: import net.sourceforge.squirrel_sql.plugins.mssql.tokenizer.MSSQLQueryTokenizer;
070: import net.sourceforge.squirrel_sql.plugins.mssql.util.MssqlIntrospector;
071:
072: public class MssqlPlugin extends
073: net.sourceforge.squirrel_sql.client.plugin.DefaultSessionPlugin {
074: private final static ILogger s_log = LoggerController
075: .createLogger(MssqlPlugin.class);
076: private PluginResources _resources;
077: private IObjectTreeAPI _treeAPI;
078: private JMenu _mssqlMenu;
079: private ISession _session;
080: private int[] indexColumnIndices = new int[] { 6 };
081:
082: /** manages our query tokenizing preferences */
083: private PluginQueryTokenizerPreferencesManager _prefsManager = null;
084:
085: /** The database name that appears in the border label of the pref panel */
086: private static final String SCRIPT_SETTINGS_BORDER_LABEL_DBNAME = "MS SQL-Server";
087:
088: /**
089: * Internationalized strings for this class.
090: */
091: private static final StringManager s_stringMgr = StringManagerFactory
092: .getStringManager(MssqlPlugin.class);
093:
094: interface i18n {
095: // i18n[SybaseASEPlugin.title=SybaseASE]
096: String title = s_stringMgr.getString("MssqlPlugin.title");
097:
098: // i18n[SybaseASEPlugin.hint=Preferences for SybaseASE]
099: String hint = s_stringMgr.getString("MssqlPlugin.hint");
100: }
101:
102: public MssqlPlugin() {
103: super ();
104: }
105:
106: public String getChangeLogFileName() {
107: return "changes.txt";
108: }
109:
110: public String getContributors() {
111: return "Rob Manning";
112: }
113:
114: public net.sourceforge.squirrel_sql.client.preferences.IGlobalPreferencesPanel[] getGlobalPreferencePanels() {
115: boolean includeProcSepPref = false;
116:
117: PluginQueryTokenizerPreferencesPanel _prefsPanel = new PluginQueryTokenizerPreferencesPanel(
118: _prefsManager, SCRIPT_SETTINGS_BORDER_LABEL_DBNAME,
119: includeProcSepPref);
120:
121: PluginGlobalPreferencesTab tab = new PluginGlobalPreferencesTab(
122: _prefsPanel);
123:
124: tab.setHint(i18n.hint);
125: tab.setTitle(i18n.title);
126:
127: return new IGlobalPreferencesPanel[] { tab };
128: }
129:
130: public String getHelpFileName() {
131: return "readme.html";
132: }
133:
134: public String getLicenceFileName() {
135: return "licence.txt";
136: }
137:
138: public net.sourceforge.squirrel_sql.client.preferences.INewSessionPropertiesPanel[] getNewSessionPropertiesPanels() {
139: net.sourceforge.squirrel_sql.client.preferences.INewSessionPropertiesPanel[] retValue;
140:
141: retValue = super .getNewSessionPropertiesPanels();
142: return retValue;
143: }
144:
145: public net.sourceforge.squirrel_sql.client.plugin.IPluginDatabaseObjectType[] getObjectTypes(
146: net.sourceforge.squirrel_sql.client.session.ISession iSession) {
147: net.sourceforge.squirrel_sql.client.plugin.IPluginDatabaseObjectType[] retValue;
148:
149: retValue = super .getObjectTypes(iSession);
150: return retValue;
151: }
152:
153: public java.io.File getPluginAppSettingsFolder()
154: throws java.io.IOException {
155: java.io.File retValue;
156:
157: retValue = super .getPluginAppSettingsFolder();
158: return retValue;
159: }
160:
161: public java.io.File getPluginUserSettingsFolder()
162: throws java.io.IOException {
163: java.io.File retValue;
164:
165: retValue = super .getPluginUserSettingsFolder();
166: return retValue;
167: }
168:
169: public net.sourceforge.squirrel_sql.client.session.properties.ISessionPropertiesPanel[] getSessionPropertiesPanels(
170: net.sourceforge.squirrel_sql.client.session.ISession iSession) {
171: net.sourceforge.squirrel_sql.client.session.properties.ISessionPropertiesPanel[] retValue;
172:
173: retValue = super .getSessionPropertiesPanels(iSession);
174: return retValue;
175: }
176:
177: public String getWebSite() {
178: String retValue;
179:
180: retValue = super .getWebSite();
181: return retValue;
182: }
183:
184: public void initialize()
185: throws net.sourceforge.squirrel_sql.client.plugin.PluginException {
186: super .initialize();
187: PreferencesManager.initialize(this );
188: final IApplication app = getApplication();
189: final ActionCollection coll = app.getActionCollection();
190:
191: coll.add(new GenerateSqlAction(app, _resources, this ));
192: coll.add(new ScriptProcedureAction(app, _resources, this ));
193: coll.add(new ScriptProcedureExecAction(app, _resources, this ));
194: coll.add(new ShrinkDatabaseAction(app, _resources, this ));
195: coll.add(new TruncateLogAction(app, _resources, this ));
196: coll.add(new UpdateStatisticsAction(app, _resources, this ));
197:
198: _mssqlMenu = createFullMssqlMenu();
199:
200: app.addToMenu(IApplication.IMenuIDs.SESSION_MENU, _mssqlMenu);
201: super .registerSessionMenu(_mssqlMenu);
202:
203: _prefsManager = new PluginQueryTokenizerPreferencesManager();
204: _prefsManager.initialize(this , new MSSQLPreferenceBean());
205: }
206:
207: public void load(
208: net.sourceforge.squirrel_sql.client.IApplication iApplication)
209: throws net.sourceforge.squirrel_sql.client.plugin.PluginException {
210: super .load(iApplication);
211:
212: _resources = new MssqlResources(getClass().getName(), this );
213: }
214:
215: public void sessionCreated(
216: net.sourceforge.squirrel_sql.client.session.ISession iSession) {
217: super .sessionCreated(iSession);
218: }
219:
220: public void sessionEnding(
221: net.sourceforge.squirrel_sql.client.session.ISession iSession) {
222: super .sessionEnding(iSession);
223: }
224:
225: public boolean allowsSessionStartedInBackground() {
226: return true;
227: }
228:
229: public PluginSessionCallback sessionStarted(final ISession iSession) {
230: if (!isPluginSession(iSession)) {
231: return null;
232: }
233: installMssqlQueryTokenizer(iSession);
234: GUIUtils.processOnSwingEventThread(new Runnable() {
235: public void run() {
236: updateTreeApi(iSession);
237: }
238: });
239:
240: return new MssqlPluginSessionCallback();
241: }
242:
243: @Override
244: protected boolean isPluginSession(ISession session) {
245: return DialectFactory.isMSSQLServer(session.getMetaData());
246: }
247:
248: /**
249: * Determines from the user's preference whether or not to install the
250: * custom query tokenizer, and if so configure installs it.
251: *
252: * @param session the session to install the custom query tokenizer in.
253: */
254: private void installMssqlQueryTokenizer(ISession session) {
255: IQueryTokenizerPreferenceBean _prefs = _prefsManager
256: .getPreferences();
257:
258: if (_prefs.isInstallCustomQueryTokenizer()) {
259: session.setQueryTokenizer(new MSSQLQueryTokenizer(_prefs));
260: }
261: }
262:
263: private void updateTreeApi(ISession iSession) {
264: _treeAPI = iSession.getSessionInternalFrame()
265: .getObjectTreeAPI();
266:
267: _treeAPI.addToPopup(DatabaseObjectType.CATALOG,
268: addToMssqlCatalogMenu(null));
269: _treeAPI.addToPopup(DatabaseObjectType.TABLE,
270: addToMssqlTableMenu(null));
271: _treeAPI.addToPopup(DatabaseObjectType.PROCEDURE,
272: addToMssqlProcedureMenu(null));
273:
274: _treeAPI.addDetailTab(DatabaseObjectType.VIEW,
275: new ViewSourceTab());
276: _session = iSession;
277:
278: MonitorPanel monitorPanel = new MonitorPanel();
279: iSession.addMainTab(monitorPanel);
280: }
281:
282: public void unload() {
283: super .unload();
284: }
285:
286: public String getAuthor() {
287: return "Ryan Walberg";
288: }
289:
290: public String getDescriptiveName() {
291: return "Microsoft SQL Server Assistant";
292: }
293:
294: public String getInternalName() {
295: return "mssql";
296: }
297:
298: public String getVersion() {
299: return "0.3";
300: }
301:
302: @SuppressWarnings("unchecked")
303: private void removeActionsOfType(ActionCollection coll,
304: java.lang.Class classType) {
305: java.lang.Object obj;
306: java.util.Iterator<Action> iter = coll.actions();
307: while (iter.hasNext()) {
308: obj = iter.next();
309: if (obj.getClass() == classType)
310: iter.remove();
311: }
312: }
313:
314: private JMenu addToMssqlTableMenu(JMenu menu) {
315: final IApplication app = getApplication();
316: final ActionCollection coll = app.getActionCollection();
317: final MssqlPlugin plugin = this ;
318:
319: final JMenu mssqlMenu;
320: if (menu == null)
321: mssqlMenu = _resources
322: .createMenu(MssqlResources.IMenuResourceKeys.MSSQL);
323: else
324: mssqlMenu = menu;
325:
326: _resources.addToMenu(coll.get(UpdateStatisticsAction.class),
327: mssqlMenu);
328:
329: final JMenu showStatisticsMenu = _resources
330: .createMenu(MssqlResources.IMenuResourceKeys.SHOW_STATISTICS);
331: showStatisticsMenu.addMenuListener(new MenuListener() {
332: public void menuSelected(MenuEvent e) {
333: final JMenu menu = (JMenu) e.getSource();
334: menu.removeAll();
335: removeActionsOfType(coll, ShowStatisticsAction.class);
336: iterateIndexes(new IndexIterationListener() {
337: public void indexSpotted(
338: final ITableInfo tableInfo,
339: final String indexName) {
340: final ShowStatisticsAction showStatisticsAction = new ShowStatisticsAction(
341: app, _resources, plugin, tableInfo,
342: indexName);
343: showStatisticsAction.setSession(_session);
344: coll.add(showStatisticsAction);
345: _resources
346: .addToMenu(showStatisticsAction, menu);
347: }
348: });
349: }
350:
351: public void menuDeselected(MenuEvent e) {
352: }
353:
354: public void menuCanceled(MenuEvent e) {
355: }
356: });
357:
358: final JMenu indexDefragMenu = _resources
359: .createMenu(MssqlResources.IMenuResourceKeys.INDEXDEFRAG);
360: indexDefragMenu.addMenuListener(new MenuListener() {
361: public void menuSelected(MenuEvent e) {
362: final JMenu menu = (JMenu) e.getSource();
363: menu.removeAll();
364: removeActionsOfType(coll, IndexDefragAction.class);
365: app.getThreadPool().addTask(
366: new IteratorIndexesTask(menu));
367: }
368:
369: public void menuDeselected(MenuEvent e) {
370: }
371:
372: public void menuCanceled(MenuEvent e) {
373: }
374: });
375:
376: mssqlMenu.add(showStatisticsMenu);
377: mssqlMenu.add(indexDefragMenu);
378:
379: return mssqlMenu;
380: }
381:
382: private class IteratorIndexesTask implements Runnable {
383:
384: JMenu _menu = null;
385: final IApplication app = getApplication();
386: final ActionCollection coll = app.getActionCollection();
387: final MssqlPlugin plugin = MssqlPlugin.this ;
388:
389: public IteratorIndexesTask(JMenu menu) {
390: _menu = menu;
391: }
392:
393: public void run() {
394: iterateIndexes(new IndexIterationListener() {
395: public void indexSpotted(final ITableInfo tableInfo,
396: final String indexName) {
397: final IndexDefragAction indexDefragAction = new IndexDefragAction(
398: app, _resources, plugin, tableInfo,
399: indexName);
400: indexDefragAction.setSession(_session);
401: GUIUtils.processOnSwingEventThread(new Runnable() {
402: public void run() {
403: coll.add(indexDefragAction);
404: _resources.addToMenu(indexDefragAction,
405: _menu);
406: }
407: });
408: }
409: });
410: }
411: }
412:
413: private void iterateIndexes(IndexIterationListener listener) {
414: /* this should just bring back one table, i hope. */
415: final IDatabaseObjectInfo[] dbObjs = _treeAPI
416: .getSelectedDatabaseObjects();
417:
418: if (dbObjs.length != 1) {
419: s_log
420: .error("iterateIndexes: more than one item is selected");
421: return;
422: }
423: if (dbObjs[0].getDatabaseObjectType() != DatabaseObjectType.TABLE) {
424: s_log.error("iterateIndexes: selected item isn't a table");
425: return;
426: }
427:
428: ITableInfo tableInfo = (ITableInfo) dbObjs[0];
429:
430: ISQLConnection conn = _session.getSQLConnection();
431: SQLDatabaseMetaData metaData = conn.getSQLMetaData();
432:
433: try {
434: ResultSetDataSet rsds = metaData.getIndexInfo(tableInfo,
435: indexColumnIndices, false);
436: String indexName = "";
437: while (rsds.next(null)) {
438: String this IndexName = (String) rsds.get(0);
439: if (this IndexName != null) {
440: if (!indexName.equals(this IndexName)) {
441: listener.indexSpotted(tableInfo, this IndexName);
442: indexName = this IndexName;
443: }
444: }
445: }
446: } catch (DataSetException ex) {
447: s_log.error("Unable to show indices for table "
448: + tableInfo.getSimpleName(), ex);
449: // fine, don't show any indexes.
450: //throw new WrappedSQLException(ex);
451: }
452: }
453:
454: private JMenu createFullMssqlMenu() {
455: final IApplication app = getApplication();
456: final ActionCollection coll = app.getActionCollection();
457:
458: final JMenu mssqlMenu = _resources
459: .createMenu(MssqlResources.IMenuResourceKeys.MSSQL);
460:
461: _resources.addToMenu(coll.get(GenerateSqlAction.class),
462: mssqlMenu);
463:
464: addToMssqlCatalogMenu(mssqlMenu);
465: addToMssqlTableMenu(mssqlMenu);
466: addToMssqlProcedureMenu(mssqlMenu);
467:
468: return mssqlMenu;
469: }
470:
471: private JMenu addToMssqlCatalogMenu(JMenu menu) {
472: final IApplication app = getApplication();
473: final ActionCollection coll = app.getActionCollection();
474: final MssqlPlugin plugin = this ;
475:
476: final JMenu mssqlMenu;
477: if (menu == null)
478: mssqlMenu = _resources
479: .createMenu(MssqlResources.IMenuResourceKeys.MSSQL);
480: else
481: mssqlMenu = menu;
482:
483: _resources.addToMenu(coll.get(ShrinkDatabaseAction.class),
484: mssqlMenu);
485: _resources.addToMenu(coll.get(TruncateLogAction.class),
486: mssqlMenu);
487:
488: final JMenu shrinkDBFileMenu = _resources
489: .createMenu(MssqlResources.IMenuResourceKeys.SHRINKDBFILE);
490: shrinkDBFileMenu.addMenuListener(new MenuListener() {
491: public void menuSelected(MenuEvent e) {
492: final JMenu menu = (JMenu) e.getSource();
493: menu.removeAll();
494: removeActionsOfType(coll,
495: ShrinkDatabaseFileAction.class);
496:
497: final ObjectTreeNode[] nodes = _treeAPI
498: .getSelectedNodes();
499: if (nodes.length != 1)
500: return;
501:
502: try {
503: if (nodes[0].getDatabaseObjectType() != DatabaseObjectType.CATALOG)
504: return;
505:
506: DatabaseFileInfo info = MssqlIntrospector
507: .getDatabaseFileInfo(nodes[0].toString(),
508: _session.getSQLConnection());
509: Object[] files = info.getDataFiles();
510: for (int i = 0; i < files.length; i++) {
511: DatabaseFile file = (DatabaseFile) files[i];
512: final ShrinkDatabaseFileAction shrinkDatabaseFileAction = new ShrinkDatabaseFileAction(
513: app, _resources, plugin, nodes[0]
514: .toString(), file);
515: shrinkDatabaseFileAction.setSession(_session);
516: coll.add(shrinkDatabaseFileAction);
517: _resources.addToMenu(shrinkDatabaseFileAction,
518: menu);
519: }
520: menu.addSeparator();
521: files = info.getLogFiles();
522: for (int i = 0; i < files.length; i++) {
523: DatabaseFile file = (DatabaseFile) files[i];
524: final ShrinkDatabaseFileAction shrinkDatabaseFileAction = new ShrinkDatabaseFileAction(
525: app, _resources, plugin, nodes[0]
526: .toString(), file);
527: shrinkDatabaseFileAction.setSession(_session);
528: coll.add(shrinkDatabaseFileAction);
529: _resources.addToMenu(shrinkDatabaseFileAction,
530: menu);
531: }
532: } catch (java.sql.SQLException ex) {
533: s_log
534: .error(
535: "Exception while attempting to shrink database file",
536: ex);
537: // fine, don't add any data files.
538: //throw new WrappedSQLException(ex);
539: }
540: }
541:
542: public void menuDeselected(MenuEvent e) {
543: }
544:
545: public void menuCanceled(MenuEvent e) {
546: }
547: });
548: mssqlMenu.add(shrinkDBFileMenu);
549:
550: return mssqlMenu;
551: }
552:
553: private JMenu addToMssqlProcedureMenu(JMenu menu) {
554: final IApplication app = getApplication();
555: final ActionCollection coll = app.getActionCollection();
556:
557: final JMenu mssqlMenu;
558: if (menu == null)
559: mssqlMenu = _resources
560: .createMenu(MssqlResources.IMenuResourceKeys.MSSQL);
561: else
562: mssqlMenu = menu;
563:
564: _resources.addToMenu(coll.get(ScriptProcedureAction.class),
565: mssqlMenu);
566: _resources.addToMenu(coll.get(ScriptProcedureExecAction.class),
567: mssqlMenu);
568:
569: return mssqlMenu;
570: }
571:
572: private class MssqlPluginSessionCallback implements
573: PluginSessionCallback {
574: public void sqlInternalFrameOpened(
575: SQLInternalFrame sqlInternalFrame, ISession sess) {
576: // TODO
577: // Plugin supports only the main session window
578: }
579:
580: public void objectTreeInternalFrameOpened(
581: ObjectTreeInternalFrame objectTreeInternalFrame,
582: ISession sess) {
583: // TODO
584: // Plugin supports only the main session window
585: }
586: }
587: }
|