001: /*
002: * WbManager.java
003: *
004: * This file is part of SQL Workbench/J, http://www.sql-workbench.net
005: *
006: * Copyright 2002-2008, Thomas Kellerer
007: * No part of this code maybe reused without the permission of the author
008: *
009: * To contact the author please send an email to: support@sql-workbench.net
010: *
011: */
012: package workbench;
013:
014: import java.awt.BorderLayout;
015: import java.awt.Color;
016: import java.awt.EventQueue;
017: import java.awt.FlowLayout;
018: import java.awt.Font;
019: import java.awt.Toolkit;
020: import java.awt.event.ActionEvent;
021: import java.awt.event.ActionListener;
022: import java.io.File;
023: import java.io.IOException;
024: import java.lang.reflect.Constructor;
025: import java.net.URL;
026: import java.net.URLDecoder;
027: import java.util.ArrayList;
028: import java.util.Collections;
029: import java.util.List;
030:
031: import javax.swing.JButton;
032: import javax.swing.JDialog;
033: import javax.swing.JFrame;
034: import javax.swing.JLabel;
035: import javax.swing.JOptionPane;
036: import javax.swing.JPanel;
037: import javax.swing.LookAndFeel;
038: import javax.swing.SwingConstants;
039: import javax.swing.UIDefaults;
040: import javax.swing.UIManager;
041:
042: import workbench.db.ConnectionMgr;
043: import workbench.db.ConnectionProfile;
044: import workbench.gui.MainWindow;
045: import workbench.gui.WbSwingUtilities;
046: import workbench.gui.components.TabbedPaneUIFactory;
047: import workbench.gui.dbobjects.DbExplorerWindow;
048: import workbench.gui.lnf.LnFDefinition;
049: import workbench.gui.lnf.LnFLoader;
050: import workbench.gui.tools.DataPumper;
051: import workbench.interfaces.FontChangedListener;
052: import workbench.interfaces.ToolWindow;
053: import workbench.log.LogMgr;
054: import workbench.resource.ResourceMgr;
055: import workbench.resource.Settings;
056: import workbench.sql.BatchRunner;
057: import workbench.sql.MacroManager;
058: import workbench.sql.VariablePool;
059: import workbench.util.MacOSHelper;
060: import workbench.util.StringUtil;
061: import workbench.gui.dialogs.WbSplash;
062: import workbench.gui.filter.FilterDefinitionManager;
063: import workbench.gui.lnf.LnFManager;
064: import workbench.gui.profiles.ProfileKey;
065: import workbench.util.UpdateCheck;
066: import workbench.util.WbFile;
067: import workbench.util.WbThread;
068:
069: /**
070: * The main application "controller" for the SQL Workbench/J
071: *
072: * @author support@sql-workbench.net
073: */
074: public class WbManager implements FontChangedListener, Runnable,
075: Thread.UncaughtExceptionHandler {
076: private static WbManager wb;
077: private List<MainWindow> mainWindows = Collections
078: .synchronizedList(new ArrayList<MainWindow>(5));
079: private List<ToolWindow> toolWindows = Collections
080: .synchronizedList(new ArrayList<ToolWindow>(5));
081: private boolean batchMode = false;
082: private boolean writeSettings = true;
083: private boolean outOfMemoryOcurred = false;
084: private WbThread shutdownHook = new WbThread(this , "ShutdownHook");
085: private AppArguments cmdLine = new AppArguments();
086:
087: private WbManager() {
088: Runtime.getRuntime().addShutdownHook(this .shutdownHook);
089: Thread.setDefaultUncaughtExceptionHandler(this );
090: }
091:
092: public static WbManager getInstance() {
093: return wb;
094: }
095:
096: public void uncaughtException(Thread thread, Throwable error) {
097: LogMgr.logError("WbManager.uncaughtException()", "Thread + "
098: + thread.getName() + " caused an exception!", error);
099: }
100:
101: public boolean writeSettings() {
102: return this .writeSettings;
103: }
104:
105: public void showDialog(String clazz) {
106: JFrame parent = WbManager.getInstance().getCurrentWindow();
107: JDialog dialog = null;
108: try {
109: // Use reflection to load various dialogs in order to
110: // avoid unnecessary class loading during startup
111: Class cls = Class.forName(clazz);
112: Class[] types = new Class[] { java.awt.Frame.class };
113: Constructor cons = cls.getConstructor(types);
114: Object[] args = new Object[] { parent };
115: dialog = (JDialog) cons.newInstance(args);
116: dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
117: if (dialog.isModal())
118: WbSwingUtilities.center(dialog, parent);
119: dialog.setVisible(true);
120: } catch (Exception ex) {
121: LogMgr.logError("WbManager.showDialog()",
122: "Error when creating dialog " + clazz, ex);
123: } finally {
124: if (dialog != null && dialog.isModal()) {
125: dialog.dispose();
126: dialog = null;
127: }
128: }
129: }
130:
131: public boolean outOfMemoryOcurred() {
132: return this .outOfMemoryOcurred;
133: }
134:
135: public void showOutOfMemoryError() {
136: System.gc();
137: outOfMemoryOcurred = true;
138: WbSwingUtilities.showErrorMessageKey(getCurrentWindow(),
139: "MsgOutOfMemoryError");
140: }
141:
142: public MainWindow getCurrentWindow() {
143: if (this .mainWindows == null)
144: return null;
145: if (this .mainWindows.size() == 1) {
146: return this .mainWindows.get(0);
147: }
148: for (MainWindow w : mainWindows) {
149: if (w.hasFocus())
150: return w;
151: }
152: return null;
153: }
154:
155: public void registerToolWindow(ToolWindow aWindow) {
156: synchronized (toolWindows) {
157: this .toolWindows.add(aWindow);
158: }
159: }
160:
161: public void unregisterToolWindow(ToolWindow aWindow) {
162: if (aWindow == null)
163: return;
164: synchronized (toolWindows) {
165: int index = this .toolWindows.indexOf(aWindow);
166: if (index > -1) {
167: this .toolWindows.remove(index);
168: }
169: if (this .toolWindows.size() == 0
170: && this .mainWindows.size() == 0) {
171: if (aWindow instanceof JFrame) {
172: this .exitWorkbench((JFrame) aWindow);
173: } else {
174: this .exitWorkbench();
175: }
176: }
177: }
178: }
179:
180: private void closeToolWindows() {
181: synchronized (toolWindows) {
182: for (ToolWindow w : toolWindows) {
183: w.closeWindow();
184: }
185: this .toolWindows.clear();
186: }
187: }
188:
189: public void fontChanged(String aFontKey, Font newFont) {
190: if (aFontKey.equals(Settings.PROPERTY_DATA_FONT)) {
191: UIManager.put("Table.font", newFont);
192: UIManager.put("TableHeader.font", newFont);
193: }
194: }
195:
196: public boolean isWindowsClassic() {
197: return isWindowsClassic;
198: }
199:
200: private boolean isWindowsClassic = false;
201:
202: private void initializeLookAndFeel() {
203: String className = Settings.getInstance().getLookAndFeelClass();
204: try {
205: if (StringUtil.isEmptyString(className)) {
206: className = UIManager.getSystemLookAndFeelClassName();
207: }
208: LnFManager mgr = new LnFManager();
209: LnFDefinition def = mgr.findLookAndFeel(className);
210:
211: if (def == null) {
212: LogMgr.logError("WbManager.initializeLookAndFeel()",
213: "Specified Look & Feel " + className
214: + " not available!", null);
215: return;
216: }
217:
218: // JGoodies Looks settings
219: UIManager.put("jgoodies.useNarrowButtons", Boolean.FALSE);
220: UIManager.put("FileChooser.useSystemIcons", Boolean.TRUE);
221:
222: // Remove Synthetica's own window decorations
223: UIManager
224: .put("Synthetica.window.decoration", Boolean.FALSE);
225:
226: // Remove the extra icons for read only text fields and
227: // the "search bar" in the main menu for the Substance Look & Feel
228: System.setProperty("substancelaf.noExtraElements", "");
229:
230: LnFLoader loader = new LnFLoader(def);
231: LookAndFeel lnf = loader.getLookAndFeel();
232:
233: UIManager.setLookAndFeel(lnf);
234: try {
235: String clsname = lnf.getClass().getName();
236: if (clsname.indexOf("com.sun.java.swing.plaf.windows") > -1) {
237: String osVersion = System.getProperty("os.version",
238: "1.0");
239: Float version = Float.valueOf(osVersion);
240: if (version.floatValue() <= 5.0) {
241: isWindowsClassic = true;
242: } else {
243: isWindowsClassic = (clsname
244: .indexOf("WindowsClassicLookAndFeel") > -1);
245: if (!isWindowsClassic) {
246: Toolkit toolkit = Toolkit
247: .getDefaultToolkit();
248: Boolean themeActive = (Boolean) toolkit
249: .getDesktopProperty("win.xpstyle.themeActive");
250: if (themeActive != null) {
251: isWindowsClassic = !themeActive
252: .booleanValue();
253: } else {
254: isWindowsClassic = true;
255: }
256: }
257: }
258: }
259: } catch (Throwable e) {
260: isWindowsClassic = false;
261: }
262: } catch (Exception e) {
263: LogMgr.logError("Settings.initializeLookAndFeel()",
264: "Could not set look and feel", e);
265: LogMgr.logWarning("Settings.initializeLookAndFeel()",
266: "Current look and feel class [" + className
267: + "] will be removed");
268: Settings.getInstance().setLookAndFeelClass(null);
269: }
270:
271: try {
272: Toolkit.getDefaultToolkit().setDynamicLayout(
273: Settings.getInstance().getUseDynamicLayout());
274: } catch (Exception e) {
275: LogMgr.logError("WbManager.initializeLookAndFeel()",
276: "Error setting dynamic layout property", e);
277: }
278: }
279:
280: public File getJarFile() {
281: URL url = this .getClass().getProtectionDomain().getCodeSource()
282: .getLocation();
283: File f = null;
284: try {
285: // Sending the path through the URLDecoder is important
286: // because otherwise a path with %20 will be created
287: // if the directory contains spaces!
288: String p = URLDecoder.decode(url.getFile(), "UTF-8");
289: f = new File(p);
290: } catch (Exception e) {
291: // Fallback, should not happen
292: String p = url.getFile();
293: p = StringUtil.replace(p, "%20", " ");
294: f = new File(p);
295: }
296: return f;
297: }
298:
299: public String getJarPath() {
300: WbFile parent = new WbFile(getJarFile().getParentFile());
301: return parent.getFullPath();
302: }
303:
304: private void initUI() {
305: // Disable bold fonts for the Default Metal Look & Feel
306: System.setProperty("swing.boldMetal", "false");
307: UIManager.put("FileChooser.useSystemIcons", Boolean.TRUE);
308:
309: this .initializeLookAndFeel();
310:
311: Settings settings = Settings.getInstance();
312: UIDefaults def = UIManager.getDefaults();
313:
314: Font stdFont = settings.getStandardFont();
315: if (stdFont != null) {
316: def.put("Button.font", stdFont);
317: def.put("CheckBox.font", stdFont);
318: def.put("CheckBoxMenuItem.font", stdFont);
319: def.put("ColorChooser.font", stdFont);
320: def.put("ComboBox.font", stdFont);
321: def.put("EditorPane.font", stdFont);
322: def.put("FileChooser.font", stdFont);
323: def.put("Label.font", stdFont);
324: def.put("List.font", stdFont);
325: def.put("Menu.font", stdFont);
326: def.put("MenuItem.font", stdFont);
327: def.put("OptionPane.font", stdFont);
328: def.put("Panel.font", stdFont);
329: def.put("PasswordField.font", stdFont);
330: def.put("PopupMenu.font", stdFont);
331: def.put("ProgressBar.font", stdFont);
332: def.put("RadioButton.font", stdFont);
333: def.put("TabbedPane.font", stdFont);
334: def.put("TextArea.font", stdFont);
335: def.put("TextField.font", stdFont);
336: def.put("TextPane.font", stdFont);
337: def.put("TitledBorder.font", stdFont);
338: def.put("ToggleButton.font", stdFont);
339: def.put("ToolBar.font", stdFont);
340: def.put("ToolTip.font", stdFont);
341: def.put("Tree.font", stdFont);
342: def.put("ViewPort.font", stdFont);
343: }
344:
345: Font dataFont = settings.getDataFont(false);
346: if (dataFont != null) {
347: def.put("Table.font", dataFont);
348: def.put("TableHeader.font", dataFont);
349: }
350:
351: // Polish up the standard look & feel settings
352: Color c = settings.getColor("workbench.table.gridcolor",
353: new Color(215, 215, 215));
354: def.put("Table.gridColor", c);
355: def.put("Button.showMnemonics", Boolean.valueOf(settings
356: .getShowMnemonics()));
357:
358: // use our own classes for some GUI elements
359: def.put("ToolTipUI", "workbench.gui.components.WbToolTipUI");
360: def
361: .put("SplitPaneUI",
362: "workbench.gui.components.WbSplitPaneUI");
363:
364: String cls = TabbedPaneUIFactory.getTabbedPaneUIClass();
365: if (cls != null)
366: def.put("TabbedPaneUI", cls);
367:
368: settings.addFontChangedListener(this );
369: }
370:
371: private JDialog closeMessage;
372:
373: private boolean saveWindowSettings() {
374: if (!this .writeSettings)
375: return true;
376: MainWindow w = this .getCurrentWindow();
377: boolean settingsSaved = false;
378:
379: // the settings (i.e. size and position) should only be saved
380: // for the first visible window
381: if (w != null) {
382: w.saveSettings();
383: settingsSaved = true;
384: }
385:
386: if (!this .checkProfiles(w))
387: return false;
388:
389: boolean result = true;
390: for (MainWindow win : mainWindows) {
391: if (win == null)
392: continue;
393: if (!settingsSaved) {
394: win.saveSettings();
395: settingsSaved = true;
396: }
397: if (win.isBusy()) {
398: if (!this .checkAbort(win))
399: return false;
400: }
401: result = win.saveWorkspace(true);
402: if (!result)
403: return false;
404: }
405: return true;
406: }
407:
408: public boolean isTestMode() {
409: return Settings.getInstance().getBoolProperty(
410: "workbench.gui.testmode", false);
411: }
412:
413: public boolean isBatchMode() {
414: return this .batchMode;
415: }
416:
417: public boolean canExit() {
418: return this .saveWindowSettings();
419: }
420:
421: public void exitWorkbench() {
422: MainWindow w = this .getCurrentWindow();
423: this .exitWorkbench(w);
424: }
425:
426: public boolean exitWorkbench(JFrame window) {
427: // saveSettings() will also prompt if any modified
428: // files should be changed
429: boolean canExit = this .saveWindowSettings();
430: if (!canExit) {
431: LogMgr
432: .logInfo("WbManaer.exitWorkbench()",
433: "Exiting application was cancelled during saveWindowSettings()");
434: return false;
435: }
436:
437: if (window == null) {
438: ConnectionMgr.getInstance().disconnectAll();
439: this .doShutdown(0);
440: return true;
441: }
442:
443: // When disconnecting it can happen that the disconnect itself
444: // takes some time. Because of this, a small window is displayed
445: // that the disconnect takes place, and the actual disconnect is
446: // carried out in a different thread to not block the AWT thread.
447:
448: // If it takes too long the user can still abort the JVM ...
449: this .createCloseMessageWindow(window);
450: if (this .closeMessage != null)
451: this .closeMessage.setVisible(true);
452:
453: MacroManager.getInstance().saveMacros();
454: Thread t = new WbThread("WbManager disconnect") {
455: public void run() {
456: disconnectWindows();
457: ConnectionMgr.getInstance().disconnectAll();
458: disconnected();
459: }
460: };
461: t.setDaemon(false);
462: t.start();
463: return true;
464: }
465:
466: private void createCloseMessageWindow(JFrame parent) {
467: if (parent == null)
468: return;
469: this .closeMessage = new JDialog(parent, false);
470: this .closeMessage
471: .setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
472:
473: JPanel p = new JPanel();
474: p.setBorder(WbSwingUtilities.getBevelBorderRaised());
475: p.setLayout(new BorderLayout());
476: JLabel l = new JLabel(ResourceMgr
477: .getString("MsgClosingConnections"));
478: l.setFont(l.getFont().deriveFont(Font.BOLD));
479: l.setHorizontalAlignment(SwingConstants.CENTER);
480: p.add(l, BorderLayout.CENTER);
481:
482: JButton b = new JButton(ResourceMgr
483: .getString("MsgAbortImmediately"));
484: b.setToolTipText(ResourceMgr
485: .getDescription("MsgAbortImmediately"));
486: b.addActionListener(new ActionListener() {
487: public void actionPerformed(ActionEvent evt) {
488: doShutdown(0);
489: }
490: });
491:
492: JPanel p2 = new JPanel();
493: p2.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 10));
494: p2.add(b);
495: p.add(p2, BorderLayout.SOUTH);
496: this .closeMessage.getContentPane()
497: .setLayout(new BorderLayout());
498: this .closeMessage.getContentPane().add(p, BorderLayout.CENTER);
499: this .closeMessage.setUndecorated(true);
500: this .closeMessage.setSize(210, 80);
501: WbSwingUtilities.center(this .closeMessage, parent);
502: }
503:
504: protected void disconnectWindows() {
505: for (MainWindow w : mainWindows) {
506: if (w == null)
507: continue;
508: w.abortAll();
509: w.disconnect(false, true, false);
510: }
511: }
512:
513: /**
514: * this gets called from the thread that disconnects everything
515: */
516: protected void disconnected() {
517:
518: WbSwingUtilities.invoke(new Runnable() {
519: public void run() {
520: if (closeMessage != null) {
521: closeMessage.setVisible(false);
522: closeMessage.dispose();
523: closeMessage = null;
524: }
525: closeAllWindows();
526: }
527: });
528: doShutdown(0);
529: }
530:
531: protected void closeAllWindows() {
532: for (MainWindow w : mainWindows) {
533: if (w != null) {
534: try {
535: w.setVisible(false);
536: } catch (Throwable th) {
537: }
538: try {
539: w.dispose();
540: } catch (Throwable th) {
541: }
542: }
543: }
544: closeToolWindows();
545: }
546:
547: protected void saveSettings() {
548: if (this .writeSettings && !this .isBatchMode()) {
549: Settings s = Settings.getInstance();
550: FilterDefinitionManager.getInstance().saveMRUList();
551: if (s != null)
552: s.saveSettings();
553: }
554: }
555:
556: protected void doShutdown(int errorCode) {
557: Runtime.getRuntime().removeShutdownHook(this .shutdownHook);
558: this .closeAllWindows();
559: saveSettings();
560: LogMgr.logInfo("WbManager.doShutdown()", "Stopping "
561: + ResourceMgr.TXT_PRODUCT_NAME + ", Build "
562: + ResourceMgr.getString("TxtBuildNumber"));
563: LogMgr.shutdown();
564: // The property workbench.system.doexit can be used to embedd the workbench.jar
565: // in other applications and still be able to call doShutdown()
566: boolean doExit = "true".equals(System.getProperty(
567: "workbench.system.doexit", "true"));
568: if (doExit)
569: System.exit(errorCode);
570: }
571:
572: private boolean checkAbort(MainWindow win) {
573: return WbSwingUtilities.getYesNo(win, ResourceMgr
574: .getString("MsgAbortRunningSql"));
575: }
576:
577: private boolean checkProfiles(MainWindow win) {
578: if (ConnectionMgr.getInstance().profilesAreModified()) {
579: int answer = JOptionPane.showConfirmDialog(win, ResourceMgr
580: .getString("MsgConfirmUnsavedProfiles"),
581: ResourceMgr.TXT_PRODUCT_NAME,
582: JOptionPane.YES_NO_CANCEL_OPTION);
583: if (answer == JOptionPane.OK_OPTION) {
584: ConnectionMgr.getInstance().saveProfiles();
585: return true;
586: } else if (answer == JOptionPane.NO_OPTION) {
587: return true;
588: } else {
589: return false;
590: }
591: }
592: return true;
593: }
594:
595: class CloseThread extends WbThread {
596: final private MainWindow win;
597:
598: public CloseThread(String name, MainWindow w) {
599: super (name);
600: win = w;
601: }
602:
603: public void run() {
604: // First parameter tells the window to disconnect in the
605: // current thread as we are already in a background thread
606: // second parameter tells the window not to close the workspace
607: // third parameter tells the window not to save the workspace
608: WbSwingUtilities.invoke(new Runnable() {
609: public void run() {
610: win.disconnect(false, false, false);
611: win.setVisible(false);
612: win.dispose();
613: }
614: });
615: }
616: }
617:
618: public void windowClosing(final MainWindow win) {
619: if (this .mainWindows.size() == 1) {
620: // If only one window is present, shut down the application
621: this .exitWorkbench(win);
622: } else {
623: if (!win.saveWorkspace())
624: return;
625: this .mainWindows.remove(win);
626: CloseThread t = new CloseThread("WindowDisconnect", win);
627: t.start();
628: }
629:
630: }
631:
632: /**
633: * Open a new main window, but do not check any command line parameters.
634: *
635: * This method will be called from the GUI
636: * when the user requests a new window
637: */
638: public void openNewWindow() {
639: EventQueue.invokeLater(new Runnable() {
640: public void run() {
641: openNewWindow(false);
642: }
643: });
644:
645: }
646:
647: protected void openNewWindow(boolean checkCmdLine) {
648: final MainWindow main = new MainWindow();
649: this .mainWindows.add(main);
650: main.display();
651: boolean connected = false;
652:
653: if (checkCmdLine) {
654: // get profile name from commandline
655: String profilename = cmdLine
656: .getValue(AppArguments.ARG_PROFILE);
657: String group = cmdLine
658: .getValue(AppArguments.ARG_PROFILE_GROUP);
659: ConnectionProfile prof = null;
660: if (!StringUtil.isEmptyString(profilename)) {
661: ProfileKey def = new ProfileKey(profilename, group);
662: prof = ConnectionMgr.getInstance().getProfile(def);
663: } else {
664: prof = BatchRunner.createCmdLineProfile(this .cmdLine);
665: }
666:
667: if (prof != null) {
668: LogMgr.logDebug("WbManager.openNewWindow()",
669: "Connecting to " + prof.getName());
670: // try to connect to the profile passed on the
671: // command line. If this fails the connection
672: // dialog will be show to the user
673: main.connectTo(prof, true);
674:
675: // the main window will take of displaying the connection dialog
676: // if the connection to the requested profile fails.
677: connected = true;
678: }
679: }
680:
681: boolean autoSelect = Settings.getInstance().getBoolProperty(
682: "workbench.gui.autoconnect", true);
683: boolean exitOnCancel = Settings.getInstance()
684: .getExitOnFirstConnectCancel();
685:
686: // no connection? then display the connection dialog
687: if (!connected && autoSelect) {
688: main.selectConnection(exitOnCancel);
689: }
690: }
691:
692: private void readParameters(String[] args) {
693: try {
694: cmdLine.parse(args);
695: boolean needInitialize = false;
696:
697: String lang = cmdLine.getValue(AppArguments.ARG_LANG);
698: if (!StringUtil.isEmptyString(lang)) {
699: System.setProperty("workbench.gui.language", lang);
700: needInitialize = true;
701: }
702:
703: String value = cmdLine.getValue(AppArguments.ARG_CONFIGDIR);
704: if (!StringUtil.isEmptyString(value)) {
705: System.setProperty("workbench.configdir", value);
706: needInitialize = true;
707: }
708:
709: value = cmdLine.getValue(AppArguments.ARG_LIBDIR);
710: if (!StringUtil.isEmptyString(value)) {
711: System.setProperty("workbench.libdir", value);
712: needInitialize = true;
713: }
714:
715: value = cmdLine.getValue(AppArguments.ARG_LOGFILE);
716: if (!StringUtil.isEmptyString(value)) {
717: WbFile file = new WbFile(value);
718: System.setProperty("workbench.log.filename", file
719: .getFullPath());
720: needInitialize = true;
721: }
722:
723: // Make sure the Settings object is (re)initialized properly now that
724: // some system properties have been read from the commandline
725: // this is especially necessary during Junit tests to make
726: // sure a newly passed commandline overrules the previously initialized
727: // Settings instance
728: Settings.getInstance().initialize();
729:
730: String scriptname = cmdLine
731: .getValue(AppArguments.ARG_SCRIPT);
732:
733: boolean readDriverTemplates = true;
734: boolean showHelp = cmdLine.isArgPresent("help");
735:
736: if (StringUtil.isEmptyString(scriptname) && !showHelp) {
737: this .batchMode = false;
738: String url = cmdLine
739: .getValue(AppArguments.ARG_CONN_URL);
740: String jar = cmdLine
741: .getValue(AppArguments.ARG_CONN_JAR);
742: if (!StringUtil.isEmptyString(url)
743: && !StringUtil.isEmptyString(jar)) {
744: // Do not read the driver templates if a connection is specified directly
745: readDriverTemplates = false;
746: }
747: } else {
748: this .batchMode = true;
749: readDriverTemplates = false;
750: }
751:
752: value = cmdLine.getValue(AppArguments.ARG_VARDEF);
753: if (!StringUtil.isEmptyString(value)) {
754: try {
755: VariablePool.getInstance().readDefinition(
756: StringUtil.trimQuotes(value));
757: } catch (IOException e) {
758: LogMgr.logError("WbManager.initCmdLine()",
759: "Error reading variable definition from file "
760: + value, e);
761: }
762: }
763:
764: if (cmdLine.isArgPresent(AppArguments.ARG_NOTEMPLATES)) {
765: readDriverTemplates = false;
766: }
767: ConnectionMgr.getInstance().setReadTemplates(
768: readDriverTemplates);
769:
770: // Setting the profile storage should be done after initializing
771: // the configuration stuff correctly!
772: value = cmdLine.getValue(AppArguments.ARG_PROFILE_STORAGE);
773: Settings.getInstance().setProfileStorage(value);
774:
775: if (cmdLine.isArgPresent(AppArguments.ARG_NOSETTNGS)) {
776: this .writeSettings = false;
777: }
778: } catch (Exception e) {
779: e.printStackTrace(System.err);
780: LogMgr.logError("WbManager.initCdmLine()",
781: "Error initializing command line arguments!", e);
782: }
783: }
784:
785: public void startApplication() {
786: LogMgr.logInfo("WbManager.init()", "Starting "
787: + ResourceMgr.TXT_PRODUCT_NAME + ", "
788: + ResourceMgr.getBuildInfo());
789: LogMgr.logInfo("WbManager.init()", "Java version="
790: + System.getProperty("java.version") + ", java.home="
791: + System.getProperty("java.home") + ", vendor="
792: + System.getProperty("java.vendor"));
793: LogMgr.logInfo("WbManager.init()", "Operating System="
794: + System.getProperty("os.name") + ", version="
795: + System.getProperty("os.version") + ", platform="
796: + System.getProperty("os.arch"));
797:
798: // batchMode flag is set by initCmdLine()
799: if (this .batchMode) {
800: runBatch();
801: } else {
802: EventQueue.invokeLater(new Runnable() {
803: public void run() {
804: runGui();
805: }
806: });
807: }
808: }
809:
810: public void runGui() {
811: WbSplash splash = null;
812: if (Settings.getInstance().getShowSplash()) {
813: splash = new WbSplash();
814: splash.setVisible(true);
815: }
816:
817: // This will install the application listener if running under MacOS
818: MacOSHelper m = new MacOSHelper();
819: m.installApplicationHandler();
820:
821: try {
822: this .initUI();
823:
824: boolean pumper = cmdLine
825: .isArgPresent(AppArguments.ARG_SHOW_PUMPER);
826: boolean explorer = cmdLine
827: .isArgPresent(AppArguments.ARG_SHOW_DBEXP);
828:
829: if (pumper) {
830: DataPumper p = new DataPumper(null, null);
831: p.showWindow(null);
832: } else if (explorer) {
833: DbExplorerWindow.showWindow();
834: } else {
835: openNewWindow(true);
836: }
837:
838: UpdateCheck upd = new UpdateCheck();
839: upd.startUpdateCheck();
840: } finally {
841: if (splash != null) {
842: splash.setVisible(false);
843: splash.dispose();
844: }
845: }
846: }
847:
848: private void runBatch() {
849: int exitCode = 0;
850:
851: // Make sure batch mode is always using English
852: // System.setProperty("workbench.gui.language", "en");
853:
854: BatchRunner runner = BatchRunner.createBatchRunner(cmdLine);
855:
856: if (runner != null) {
857: try {
858: runner.connect();
859: } catch (Exception e) {
860: exitCode = 1;
861: // no need to log connect errors, already done by BatchRunner and ConnectionMgr
862: // runner.isSuccess() will also be false for the next step
863: }
864:
865: try {
866: // Do not check for runner.isConnected() as the in batch mode
867: // the application might be started without a profile
868: // (e.g. for a single WbCopy command)
869: if (runner.isSuccess()) {
870: runner.execute();
871: }
872:
873: // Not all exceptions will be re-thrown by the batch runner
874: // in order to be able to run the error script, so it is important
875: // to check isSuccess() in order to return the correct status
876: if (!runner.isSuccess())
877: exitCode = 2;
878: } catch (OutOfMemoryError e) {
879: LogMgr
880: .logError(
881: "WbManager.runBatch()",
882: "Not enough memory to finish the operation. Aborting execution!",
883: null);
884: System.err
885: .println("Not enough memory to finish the operation. Aborting execution!");
886: exitCode = 10;
887: } catch (Exception e) {
888: exitCode = 2;
889: } finally {
890: ConnectionMgr mgr = ConnectionMgr.getInstance();
891: if (mgr != null)
892: mgr.disconnectAll();
893: }
894: } else {
895: exitCode = 3;
896: }
897: this .doShutdown(exitCode);
898: }
899:
900: /**
901: * For testing purposes only!
902: */
903: public static void prepareForTest(String[] args) {
904: wb = new WbManager();
905: // Avoid saving the settings
906: Runtime.getRuntime().removeShutdownHook(wb.shutdownHook);
907: System.setProperty("workbench.gui.testmode", "true");
908: wb.readParameters(args);
909: }
910:
911: public static void main(String[] args) {
912: if (wb == null)
913: wb = new WbManager();
914:
915: wb.cmdLine.parse(args);
916: boolean showHelp = wb.cmdLine.isArgPresent("help");
917: if (showHelp) {
918: System.out.println(wb.cmdLine.getHelp());
919: Runtime.getRuntime().removeShutdownHook(wb.shutdownHook);
920: System.exit(0);
921: } else {
922: wb.readParameters(args);
923: wb.startApplication();
924: }
925: }
926:
927: /**
928: * this is for the shutdownhook
929: */
930: public void run() {
931: LogMgr.logDebug("WbManager.run()", "Shutdownhook called!");
932: saveSettings();
933: }
934:
935: }
|