package org.reldb.dbrowser.ui; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CBanner; import org.eclipse.swt.custom.CTabFolder2Adapter; import org.eclipse.swt.custom.CTabFolderEvent; import org.eclipse.swt.custom.CTabItem; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; import org.reldb.dbrowser.DBrowser; import org.reldb.dbrowser.ui.backup.Backup; import org.reldb.dbrowser.ui.content.cmd.DbTabContentCmd; import org.reldb.dbrowser.ui.content.conversion.DbTabContentConversion; import org.reldb.dbrowser.ui.content.rel.DbTabContentRel; import org.reldb.dbrowser.ui.content.rev.DbTabContentRev; import org.reldb.dbrowser.ui.crash.CrashTrap; import org.reldb.dbrowser.ui.preferences.PreferenceChangeAdapter; import org.reldb.dbrowser.ui.preferences.PreferenceChangeEvent; import org.reldb.dbrowser.ui.preferences.PreferenceChangeListener; import org.reldb.dbrowser.ui.preferences.PreferencePageGeneral; import org.reldb.dbrowser.ui.preferences.Preferences; import org.reldb.dbrowser.ui.version.Version; import org.reldb.rel.client.connection.CrashHandler; import org.reldb.rel.exceptions.DatabaseFormatVersionException; public class DbTab extends CTabItem { private Text textDbLocation; private String status = ""; private AttemptConnectionResult connection = null; private String lastURI = ""; private String oldText = ""; private CrashTrap crashTrap; private DbTabContentCmd contentCmd = null; private DbTabContentRel contentRel = null; private DbTabContentRev contentRev = null; private DbTabContentConversion contentConversion = null; private ToolBar toolBarMode; private ToolItem tltmOpenRemoteDb; private ToolItem tltmOpenLocalDb; private ToolItem tltmNewLocalDb; private ToolItem tltmModeRel; private ToolItem tltmModeRev; private ToolItem tltmModeCmd; private Composite modeContent; private StackLayout contentStack; private PreferenceChangeListener preferenceChangeListener; public DbTab() { super(DBrowser.getTabFolder(), SWT.None); crashTrap = new CrashTrap(this.getParent().getShell(), Version.getVersion()); setImage(IconLoader.loadIcon("plusIcon")); Composite core = new Composite(DBrowser.getTabFolder(), SWT.None); core.setLayout(new FormLayout()); CBanner bannerDbLocationMode = new CBanner(core, SWT.NONE); FormData fd_bannerDbLocationMode = new FormData(); fd_bannerDbLocationMode.right = new FormAttachment(100); fd_bannerDbLocationMode.top = new FormAttachment(0); fd_bannerDbLocationMode.left = new FormAttachment(0); bannerDbLocationMode.setLayoutData(fd_bannerDbLocationMode); Composite compDbLocation = new Composite(bannerDbLocationMode, SWT.NONE); bannerDbLocationMode.setLeft(compDbLocation); GridLayout gl_compDbLocation = new GridLayout(2, false); gl_compDbLocation.verticalSpacing = 0; gl_compDbLocation.marginWidth = 0; gl_compDbLocation.marginHeight = 0; compDbLocation.setLayout(gl_compDbLocation); ToolBar toolBarDatabase = new ToolBar(compDbLocation, SWT.None); tltmNewLocalDb = new ToolItem(toolBarDatabase, SWT.NONE); tltmNewLocalDb.setToolTipText("Create or open local database"); tltmNewLocalDb.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { DBrowser.newDatabase(); } }); tltmOpenLocalDb = new ToolItem(toolBarDatabase, SWT.NONE); tltmOpenLocalDb.setToolTipText("Open local database"); tltmOpenLocalDb.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { DBrowser.openLocalDatabase(); } }); tltmOpenRemoteDb = new ToolItem(toolBarDatabase, SWT.NONE); tltmOpenRemoteDb.setToolTipText("Open remote database"); tltmOpenRemoteDb.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { DBrowser.openRemoteDatabase(); } }); textDbLocation = new Text(compDbLocation, SWT.BORDER); textDbLocation.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1)); textDbLocation.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { if (e.character == 0xD && !textDbLocation.getText().trim().equals(oldText)) { oldText = textDbLocation.getText().trim(); if (textDbLocation.getText().trim().length() == 0) textDbLocation.setText(lastURI); else { openDatabaseAtURI(textDbLocation.getText(), false); } } } }); toolBarMode = new ToolBar(bannerDbLocationMode, SWT.None); toolBarMode.setEnabled(false); bannerDbLocationMode.setRight(toolBarMode); modeContent = new Composite(core, SWT.NONE); contentStack = new StackLayout(); modeContent.setLayout(contentStack); FormData fd_modeContent = new FormData(); fd_modeContent.bottom = new FormAttachment(100); fd_modeContent.top = new FormAttachment(bannerDbLocationMode); fd_modeContent.right = new FormAttachment(100); fd_modeContent.left = new FormAttachment(0); modeContent.setLayoutData(fd_modeContent); tltmModeRel = new ToolItem(toolBarMode, SWT.RADIO); tltmModeRel.setToolTipText("Rel"); tltmModeRel.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { showRel(); } }); tltmModeRev = new ToolItem(toolBarMode, SWT.RADIO); tltmModeRev.setToolTipText("Rev"); tltmModeRev.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { showRev(); } }); tltmModeCmd = new ToolItem(toolBarMode, SWT.RADIO); tltmModeCmd.setToolTipText("Command line"); tltmModeCmd.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { showCmd(); } }); setControl(core); setupIcons(); preferenceChangeListener = new PreferenceChangeAdapter("DbTab") { @Override public void preferenceChange(PreferenceChangeEvent evt) { setupIcons(); if (connection != null && connection.client != null) setImage(IconLoader.loadIcon("DatabaseIcon")); else setImage(IconLoader.loadIcon("plusIcon")); } }; Preferences.addPreferenceChangeListener(PreferencePageGeneral.LARGE_ICONS, preferenceChangeListener); core.pack(); } private void setupIcons() { tltmNewLocalDb.setImage(IconLoader.loadIcon("NewDBIcon")); tltmOpenLocalDb.setImage(IconLoader.loadIcon("OpenDBLocalIcon")); tltmOpenRemoteDb.setImage(IconLoader.loadIcon("OpenDBRemoteIcon")); tltmModeRel.setImage(IconLoader.loadIcon("ModeRelIcon")); tltmModeRev.setImage(IconLoader.loadIcon("ModeRevIcon")); tltmModeCmd.setImage(IconLoader.loadIcon("ModeCmdIcon")); } private void showRel() { boolean existing = true; if (contentRel == null) { existing = false; Cursor oldCursor = getParent().getCursor(); getParent().setCursor(new Cursor(getParent().getDisplay(), SWT.CURSOR_WAIT)); try { contentRel = new DbTabContentRel(DbTab.this, modeContent); } finally { getParent().getCursor().dispose(); getParent().setCursor(oldCursor); } } contentStack.topControl = contentRel; modeContent.layout(); if (existing) contentRel.redisplayed(); } private void showRev() { boolean existing = true; if (contentRev == null) { existing = false; Cursor oldCursor = getParent().getCursor(); getParent().setCursor(new Cursor(getParent().getDisplay(), SWT.CURSOR_WAIT)); try { contentRev = new DbTabContentRev(DbTab.this, modeContent); } finally { getParent().getCursor().dispose(); getParent().setCursor(oldCursor); } } contentStack.topControl = contentRev; modeContent.layout(); if (existing) contentRev.redisplayed(); } private void showCmd() { boolean existing = true; if (contentCmd == null) { existing = false; Cursor oldCursor = getParent().getCursor(); getParent().setCursor(new Cursor(getParent().getDisplay(), SWT.CURSOR_WAIT)); try { contentCmd = new DbTabContentCmd(DbTab.this, modeContent); getParent().getCursor().dispose(); getParent().setCursor(oldCursor); } catch (Exception e) { getParent().getCursor().dispose(); getParent().setCursor(oldCursor); e.printStackTrace(); MessageDialog.openError(DBrowser.getShell(), "Unable to open local database", wrapped("Unable to open command line due to error: " + e.toString())); return; } } contentStack.topControl = contentCmd; modeContent.layout(); if (existing) contentCmd.redisplayed(); } private void showConversion(String message, String dbURL) { Cursor oldCursor = getParent().getCursor(); getParent().setCursor(new Cursor(getParent().getDisplay(), SWT.CURSOR_WAIT)); try { contentConversion = new DbTabContentConversion(DbTab.this, message, dbURL, modeContent); } finally { getParent().getCursor().dispose(); getParent().setCursor(oldCursor); } contentStack.topControl = contentConversion; modeContent.layout(); } private static class AttemptConnectionResult { Throwable exception; DbConnection client; String dbURL; public AttemptConnectionResult(Throwable exception) { this.exception = exception; this.client = null; this.dbURL = null; } public AttemptConnectionResult(String dbURL, DbConnection client) { this.exception = null; this.client = client; this.dbURL = dbURL; } } private void clearModes() { if (contentCmd != null) { contentCmd.dispose(); contentCmd = null; } if (contentRel != null) { contentRel.dispose(); contentRel = null; } if (contentRev != null) { contentRev.dispose(); contentRev = null; } if (contentConversion != null) { contentConversion.dispose(); contentConversion = null; } toolBarMode.setEnabled(false); } static String wrapped(String s) { if (s.length() < 80) return s; return s.replace(": ",":\n"); } private void doConnectionResultConversion(String message, String dbURL) { setImage(IconLoader.loadIcon("DatabaseIcon")); setStatus("Requires conversion to the current database format."); showConversion(message, dbURL.substring("db:".length())); DBrowser.getTabFolder().addCTabFolder2Listener(new CTabFolder2Adapter() { public void close(CTabFolderEvent event) { if (event.item == DbTab.this) DbTab.this.close(); } }); DBrowser.createNewTabIfNeeded(); } private void doConnectionResultSuccess(DbConnection client, String dbURL, boolean permanent) { setImage(IconLoader.loadIcon("DatabaseIcon")); setStatus("Ok"); toolBarMode.setEnabled(true); refresh(); if (tltmModeRel.getSelection()) showRel(); else if (tltmModeRev.getSelection()) showRev(); else if (tltmModeCmd.getSelection()) showCmd(); else { // default mode if (Preferences.getPreferenceBoolean(PreferencePageGeneral.DEFAULT_CMD_MODE)) { tltmModeCmd.setSelection(true); showCmd(); } else { tltmModeRel.setSelection(true); showRel(); } } DBrowser.getTabFolder().addCTabFolder2Listener(new CTabFolder2Adapter() { public void close(CTabFolderEvent event) { if (event.item == DbTab.this) DbTab.this.close(); } }); DBrowser.createNewTabIfNeeded(); DBrowser.updateRecentlyUsedDatabaseList(dbURL); } public void refresh() { tltmModeRev.setEnabled(connection.client.hasRevExtensions() >= 0); } public void switchToCmdMode() { tltmModeRev.setSelection(false); tltmModeRel.setSelection(false); tltmModeCmd.setSelection(true); showCmd(); } public void setAndDisplayCmdContent(String content) { switchToCmdMode(); contentCmd.setContent(content); } public String getStatus() { return status; } public void setStatus(String s) { status = s; DBrowser.setStatus(status); } private void doConnectionResultFailed(Throwable reason, String dbURL) { String shortMsg = "Unable to establish connection to " + dbURL; setStatus(shortMsg); String msg = shortMsg + " - " + reason; msg = wrapped(msg); if (msg.contains("The environment cannot be locked for single writer access. ENV_LOCKED")) { MessageDialog.openError(DBrowser.getShell(), "Unable to open local database", "A copy of Rel is already accessing the database you're trying to open at " + dbURL); } else if (msg.contains("Connection refused")) { MessageDialog.openError(DBrowser.getShell(), "Unable to open remote database", "A Rel server doesn't appear to be running or available at " + dbURL); } else if (msg.contains("RS0406:")) { MessageDialog.openError(DBrowser.getShell(), "Unable to open local database", dbURL + " either doesn't exist or doesn't contain a Rel database."); } else if (msg.contains("RS0307:")) { MessageDialog.openError(DBrowser.getShell(), "Unable to open local database", dbURL + " doesn't exist."); } else if (msg.contains("RS0410:")) { if (reason instanceof DatabaseFormatVersionException) { DatabaseFormatVersionException dfve = (DatabaseFormatVersionException)reason; if (dfve.getOldVersion() >= 0) doConnectionResultConversion("Database " + dbURL + " needs to be converted to the current format.", dbURL); else MessageDialog.openError(DBrowser.getShell(), "Unable to open local database", "The database at " + dbURL + " appears to be a newer format than that supported by this version of Rel."); } else MessageDialog.openError(DBrowser.getShell(), "Unable to open local database", "You'll need to open " + dbURL + " in the version of Rel last used to access it, back it up, and import the backup into a new database."); } else MessageDialog.openError(DBrowser.getShell(), "Unable to open database", msg); } private AttemptConnectionResult openConnection(String dbURL, boolean createAllowed) { try { DbConnection client = new DbConnection(dbURL, createAllowed, crashTrap); return new AttemptConnectionResult(dbURL, client); } catch (Throwable exception) { return new AttemptConnectionResult(exception); } } /** Attempt to open a connection. */ private AttemptConnectionResult attemptConnectionOpen(String dbURL, boolean createAllowed) { setStatus("Opening connection to " + dbURL); return openConnection(dbURL, createAllowed); } /** Open a connection and associated panel. */ private boolean openConnection(String dbURL, boolean permanent, boolean canCreate) { Cursor oldCursor = getParent().getCursor(); getParent().setCursor(new Cursor(getParent().getDisplay(), SWT.CURSOR_WAIT)); try { setText(dbURL); if (DBrowser.isNoLocalRel() && dbURL.startsWith("db:")) { doConnectionResultFailed(new Throwable("Local Rel server is not installed."), dbURL); return false; } connection = attemptConnectionOpen(dbURL, canCreate); if (connection.client != null) { doConnectionResultSuccess(connection.client, dbURL, permanent); return true; } else { doConnectionResultFailed(connection.exception, dbURL); return false; } } finally { getParent().getCursor().dispose(); getParent().setCursor(oldCursor); } } public void dispose() { clearModes(); Preferences.removePreferenceChangeListener(PreferencePageGeneral.LARGE_ICONS, preferenceChangeListener); super.dispose(); } public boolean openDatabaseAtURI(String uri, boolean canCreate) { close(); textDbLocation.setText(uri); lastURI = uri; if (openConnection(uri, true, canCreate)) { setShowClose(true); return true; } return false; } public boolean isOpenOnADatabase() { if (connection == null) return false; return (connection.client != null || (connection.exception != null && connection.exception instanceof DatabaseFormatVersionException)); } public String getURL() { if (isOpenOnADatabase()) return connection.dbURL; return null; } public DbConnection getConnection() { if (!isOpenOnADatabase()) return null; return connection.client; } public void close() { if (connection != null && connection.client != null) { clearModes(); setImage(IconLoader.loadIcon("plusIcon")); } } public boolean newDatabase(String string) { return openDatabaseAtURI("db:" + string, true); } public boolean openLocalDatabase(String string) { return openDatabaseAtURI("db:" + string, false); } public boolean openRemoteDatabase(String string) { return openDatabaseAtURI(string, false); } public boolean openDefaultDatabase(String string) { return openDatabaseAtURI("db:" + string, true); } public void makeBackup() { Backup.makeBackup(connection.client); } public CrashHandler getCrashHandler() { return crashTrap; } public void openFile(String fname) { showCmd(); contentCmd.load(fname); } }