/*******************************************************************************
* Copyright (c) 2005-2015, G. Weirich, MEDEVIT and Elexis
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* G. Weirich - initial implementation
* MEDEVIT <office@medevit.at> - re-implementation
*******************************************************************************/
package ch.elexis.core.ui.wizards;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.ui.PlatformUI;
import ch.elexis.core.constants.Preferences;
import ch.elexis.core.constants.StringConstants;
import ch.elexis.core.data.activator.CoreHub;
import ch.elexis.core.data.util.DBConnection;
import ch.elexis.core.data.util.DBConnection.DBType;
import ch.elexis.core.jdt.Nullable;
import ch.elexis.core.ui.UiDesk;
import ch.elexis.data.PersistentObject;
import ch.rgw.tools.JdbcLink;
import ch.rgw.tools.StringTool;
public class DBConnectWizard extends Wizard {
private List<DBConnection> storedConnectionList;
private DBConnection targetedConnection;
private boolean restartAfterChange = false;
private DBConnectWizardPage dbConnSelectionPage;
private DBConnectWizardPage dbConnNewConnPage;
public DBConnectWizard(){
super();
setWindowTitle(Messages.DBConnectWizard_connectDB);
dbConnSelectionPage =
new DBConnectSelectionConnectionWizardPage(Messages.DBConnectWizard_typeOfDB);
dbConnNewConnPage = new DBConnectNewOrEditConnectionWizardPage();
initStoredJDBCConnections();
targetedConnection = getCurrentConnection();
if(targetedConnection==null && storedConnectionList.size()>0) {
targetedConnection = storedConnectionList.get(0);
} else {
targetedConnection = new DBConnection();
}
}
@Override
public void addPages(){
addPage(dbConnSelectionPage);
addPage(dbConnNewConnPage);
}
public List<DBConnection> getStoredConnectionList(){
ArrayList<DBConnection> arrayList = new ArrayList<DBConnection>(storedConnectionList);
arrayList.add(0, new DBConnection());
return arrayList;
}
@Override
public boolean performFinish(){
if(testDatabaseConnection()==false) return false;
if (!storedConnectionList.contains(targetedConnection)) {
// this is a new entry
storedConnectionList.add(targetedConnection);
}
storeJDBCConnections();
setUsedConnection();
if (restartAfterChange) {
UiDesk.asyncExec(new Runnable() {
@Override
public void run(){
PlatformUI.getWorkbench().restart();
}
});
}
return true;
}
@Override
public boolean canFinish(){
return targetedConnection.allValuesSet();
}
public void setTargetedConnection(DBConnection targetedConnection){
this.targetedConnection = targetedConnection;
if(getContainer().getCurrentPage()!=null) getContainer().updateButtons();
}
public DBConnection getTargetedConnection(){
return targetedConnection;
}
public void setRestartAfterConnectionChange(boolean restartAfterChange){
this.restartAfterChange = restartAfterChange;
}
public boolean getRestartAfterConnectionChange(){
return restartAfterChange;
}
/**
* load the stored connections from the local config, initializes {@link #storedConnectionList}
* if there are not yet any connections it initializes the list starting with the current
* connection (if available)
*/
@SuppressWarnings("unchecked")
private void initStoredJDBCConnections(){
String storage = CoreHub.localCfg.get(Preferences.CFG_STORED_JDBC_CONN, null);
if (storage != null) {
storedConnectionList =
(List<DBConnection>) PersistentObject.foldObject(StringTool.dePrintable(storage));
} else {
// initialize the current connection (if available)
storedConnectionList = new ArrayList<DBConnection>();
String cnt = CoreHub.localCfg.get(Preferences.CFG_FOLDED_CONNECTION, null);
if (cnt != null) {
Hashtable<Object, Object> hConn =
PersistentObject.fold(StringTool.dePrintable(cnt));
if (hConn != null) {
String connectionString =
PersistentObject.checkNull(hConn
.get(Preferences.CFG_FOLDED_CONNECTION_CONNECTSTRING));
String user =
PersistentObject.checkNull(hConn
.get(Preferences.CFG_FOLDED_CONNECTION_USER));
String pwd =
PersistentObject.checkNull(hConn
.get(Preferences.CFG_FOLDED_CONNECTION_PASS));
DBConnection dbc = new DBConnection();
dbc.connectionString = connectionString;
dbc.rdbmsType = parseDBTyp(connectionString);
dbc.hostName = parseHostname(connectionString);
dbc.username = user;
dbc.password = pwd;
storedConnectionList.add(dbc);
storeJDBCConnections();
}
} else {
// TODO skip selection page!
}
}
}
private String parseHostname(String connectionString){
int i = connectionString.indexOf("//")+2;
if(i==-1) return "";
String woHeader = connectionString.substring(i);
int ij = woHeader.indexOf(":");
if(ij==-1) return "";
return woHeader.substring(0, ij);
}
private @Nullable DBType parseDBTyp(String connectionString){
if (connectionString.contains(StringConstants.COLON + JdbcLink.DBFLAVOR_H2
+ StringConstants.COLON)) {
return DBType.H2;
} else if (connectionString.contains(StringConstants.COLON + JdbcLink.DBFLAVOR_MYSQL
+ StringConstants.COLON)) {
return DBType.MySQL;
} else if (connectionString.contains(StringConstants.COLON + JdbcLink.DBFLAVOR_POSTGRESQL
+ StringConstants.COLON)) {
return DBType.PostgreSQL;
}
return null;
}
/**
* serialize the {@link #storedConnectionList} to the local config file
*/
void storeJDBCConnections(){
Assert.isNotNull(storedConnectionList);
byte[] flatten = PersistentObject.flattenObject(storedConnectionList);
String enPrintable = StringTool.enPrintable(flatten);
CoreHub.localCfg.set(Preferences.CFG_STORED_JDBC_CONN, enPrintable);
CoreHub.localCfg.flush();
}
/**
* retrieve the current {@link DBConnection} by parsing the value stored in the local
* configuration with key {@link Preferences#CFG_FOLDED_CONNECTION}
*
* @return the respective {@link DBConnection} from {@link #storedConnectionList} or
* <code>null</code>
*/
public @Nullable DBConnection getCurrentConnection(){
String cnt = CoreHub.localCfg.get(Preferences.CFG_FOLDED_CONNECTION, null);
if (cnt != null) {
Hashtable<Object, Object> hConn = PersistentObject.fold(StringTool.dePrintable(cnt));
if (hConn != null) {
String currConnString =
PersistentObject.checkNull(hConn
.get(Preferences.CFG_FOLDED_CONNECTION_CONNECTSTRING));
String user =
PersistentObject.checkNull(hConn.get(Preferences.CFG_FOLDED_CONNECTION_USER));
String combined = user + "@" + currConnString;
for (DBConnection dbConnection : storedConnectionList) {
if (combined.equalsIgnoreCase(dbConnection.username + "@"
+ dbConnection.connectionString)) {
return dbConnection;
}
}
}
}
return null;
}
private boolean setUsedConnection(){
Hashtable<String, String> h = new Hashtable<String, String>();
h.put(Preferences.CFG_FOLDED_CONNECTION_DRIVER, targetedConnection.rdbmsType.driverName);
h.put(Preferences.CFG_FOLDED_CONNECTION_CONNECTSTRING, targetedConnection.connectionString);
h.put(Preferences.CFG_FOLDED_CONNECTION_USER, targetedConnection.username);
h.put(Preferences.CFG_FOLDED_CONNECTION_PASS, targetedConnection.password);
h.put(Preferences.CFG_FOLDED_CONNECTION_TYPE, targetedConnection.rdbmsType.dbType);
String conn = StringTool.enPrintable(PersistentObject.flatten(h));
CoreHub.localCfg.set(Preferences.CFG_FOLDED_CONNECTION, conn);
CoreHub.localCfg.flush();
return true;
}
public void removeConnection(DBConnection connection){
storedConnectionList.remove(connection);
storeJDBCConnections();
}
/**
* test the {@link #targetedConnection} for its validity
* @return
*/
private boolean testDatabaseConnection(){
boolean error = true;
JdbcLink j = null;
String text = null;
try {
String hostname =
(targetedConnection.port != null) ? targetedConnection.hostName + ":"
+ targetedConnection.port : targetedConnection.hostName;
if (targetedConnection.databaseName == null
|| targetedConnection.databaseName.isEmpty()) {
throw new IllegalArgumentException("No database name provided.");
}
switch (targetedConnection.rdbmsType) {
case H2:
j = JdbcLink.createH2Link(targetedConnection.databaseName);
break;
case MySQL:
j = JdbcLink.createMySqlLink(hostname, targetedConnection.databaseName);
break;
case PostgreSQL:
j = JdbcLink.createPostgreSQLLink(hostname, targetedConnection.databaseName);
break;
default:
j = null;
break;
}
Assert.isNotNull(j);
j.connect(targetedConnection.username, targetedConnection.password);
text = "Verbindung hergestellt";
error = false;
} catch (Exception e) {
e.printStackTrace();
text = "Exception " + e.getMessage();
}
dbConnNewConnPage.getTdbg().setTestResult(error, text);
if(j==null) {
// thats an error situation
return true;
}
if(!error) {
targetedConnection.connectionString = j.getConnectString();
}
return !error;
}
}