/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.ext.import_config.wizards;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.swt.SWT;
import org.eclipse.ui.IImportWizard;
import org.eclipse.ui.IWorkbench;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.core.DBeaverCore;
import org.jkiss.dbeaver.model.connection.DBPConnectionConfiguration;
import org.jkiss.dbeaver.model.connection.DBPDriverLibrary;
import org.jkiss.dbeaver.model.exec.DBCException;
import org.jkiss.dbeaver.registry.*;
import org.jkiss.dbeaver.registry.driver.DriverDescriptor;
import org.jkiss.dbeaver.ui.UIUtils;
import org.jkiss.dbeaver.ui.dialogs.SelectObjectDialog;
import org.jkiss.utils.CommonUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class ConfigImportWizard extends Wizard implements IImportWizard {
private ConfigImportWizardPage mainPage;
private Map<String, DriverDescriptor> driverClassMap = new HashMap<>();
public ConfigImportWizard() {
super();
}
@Override
public void init(IWorkbench workbench, IStructuredSelection selection) {
setWindowTitle("Import Configuration"); //NON-NLS-1
setNeedsProgressMonitor(true);
mainPage = createMainPage(); //NON-NLS-1
}
protected abstract ConfigImportWizardPage createMainPage();
@Override
public void addPages() {
super.addPages();
addPage(mainPage);
}
@Override
public boolean performFinish() {
final ImportData importData = mainPage.getImportData();
try {
for (ImportConnectionInfo connectionInfo : importData.getConnections()) {
if (connectionInfo.isChecked() && !findOrCreateDriver(connectionInfo)) {
return false;
}
}
// Flush drivers configuration
DataSourceProviderRegistry.getInstance().saveDrivers();
} catch (DBException e) {
UIUtils.showErrorDialog(getShell(), "Import driver", null, e);
return false;
}
try {
for (ImportConnectionInfo connectionInfo : importData.getConnections()) {
if (connectionInfo.isChecked()) {
importConnection(connectionInfo);
}
}
} catch (DBException e) {
UIUtils.showErrorDialog(getShell(), "Import driver", null, e);
return false;
}
return true;
}
private boolean findOrCreateDriver(ImportConnectionInfo connectionInfo) throws DBException
{
final ImportDriverInfo driverInfo = connectionInfo.getDriverInfo();
if (CommonUtils.isEmpty(driverInfo.getDriverClass())) {
throw new DBException("Cannot create driver '" + driverInfo.getName() + "' - no driver class specified");
}
String sampleURL = driverInfo.getSampleURL();
if (CommonUtils.isEmpty(sampleURL)) {
throw new DBException("Cannot create driver '" + driverInfo.getName() + "' - no connection URL pattern specified");
}
{
DriverDescriptor driver = driverClassMap.get(driverInfo.getDriverClass());
if (driver != null) {
connectionInfo.setDriver(driver);
return true;
}
}
final DataSourceProviderRegistry registry = DataSourceProviderRegistry.getInstance();
List<DriverDescriptor> matchedDrivers = new ArrayList<>();
for (DataSourceProviderDescriptor dataSourceProvider : registry.getDataSourceProviders()) {
for (DriverDescriptor driver : dataSourceProvider.getEnabledDrivers()) {
final String driverClassName = driver.getDriverClassName();
if (driverClassName != null && driverClassName.equals(driverInfo.getDriverClass())) {
matchedDrivers.add(driver);
}
}
}
DriverDescriptor driver;
if (matchedDrivers.isEmpty()) {
// Create new driver
final DataSourceProviderDescriptor genericProvider = registry.getDataSourceProvider("generic");
if (genericProvider == null) {
throw new DBException("Generic datasource provider not found");
}
driver = genericProvider.createDriver();
driver.setName(driverInfo.getName());
driver.setDriverClassName(driverInfo.getDriverClass());
driver.setSampleURL(driverInfo.getSampleURL());
driver.setConnectionProperties(driverInfo.getProperties());
driver.setDescription(driverInfo.getDescription());
driver.setDriverDefaultPort(driverInfo.getDefaultPort());
for (String path : driverInfo.getLibraries()) {
driver.addDriverLibrary(path, DBPDriverLibrary.FileType.jar);
}
driver.setModified(true);
genericProvider.addDriver(driver);
connectionInfo.setDriver(driver);
} else if (matchedDrivers.size() == 1) {
// Use the only found driver
driver = matchedDrivers.get(0);
connectionInfo.setDriver(driver);
} else {
// Let user to choose correct driver
driver = SelectObjectDialog.selectObject(
getShell(), "Choose driver for connection '" + connectionInfo.getAlias() + "'", matchedDrivers);
if (driver == null) {
return false;
}
connectionInfo.setDriver(driver);
}
if (driver != null) {
driverClassMap.put(driver.getDriverClassName(), driver);
return true;
}
return false;
}
private void importConnection(ImportConnectionInfo connectionInfo) throws DBException
{
try {
adaptConnectionUrl(connectionInfo);
} catch (DBException e) {
UIUtils.showMessageBox(getShell(), "Extract URL parameters", e.getMessage(), SWT.ICON_WARNING);
}
final DataSourceRegistry dataSourceRegistry = DBeaverCore.getInstance().getProjectRegistry().getActiveDataSourceRegistry();
String name = connectionInfo.getAlias();
for (int i = 0; ; i++) {
if (dataSourceRegistry.findDataSourceByName(name) == null) {
break;
}
name = connectionInfo.getAlias() + " " + (i + 1);
}
DBPConnectionConfiguration config = new DBPConnectionConfiguration();
config.setProperties(connectionInfo.getProperties());
config.setProviderProperties(connectionInfo.getProviderProperties());
config.setUrl(connectionInfo.getUrl());
config.setUserName(connectionInfo.getUser());
config.setUserPassword(connectionInfo.getPassword());
config.setHostName(connectionInfo.getHost());
config.setHostPort(connectionInfo.getPort());
config.setDatabaseName(connectionInfo.getDatabase());
DataSourceDescriptor dataSource = new DataSourceDescriptor(
dataSourceRegistry,
DataSourceDescriptor.generateNewId(connectionInfo.getDriver()),
connectionInfo.getDriver(),
config);
dataSource.setName(name);
dataSource.setSavePassword(!CommonUtils.isEmpty(config.getUserPassword()));
dataSourceRegistry.addDataSource(dataSource);
}
protected void adaptConnectionUrl(ImportConnectionInfo connectionInfo) throws DBException
{
String sampleURL = connectionInfo.getDriverInfo().getSampleURL();
if (connectionInfo.getDriver() != null) {
sampleURL = connectionInfo.getDriver().getSampleURL();
}
//connectionInfo.getDriver()
String url = connectionInfo.getUrl();
if (url != null) {
// Parse url
final DriverDescriptor.MetaURL metaURL = DriverDescriptor.parseSampleURL(sampleURL);
int sourceOffset = 0;
List<String> urlComponents = metaURL.getUrlComponents();
for (int i = 0, urlComponentsSize = urlComponents.size(); i < urlComponentsSize; i++) {
String component = urlComponents.get(i);
if (component.length() > 2 && component.charAt(0) == '{' && component.charAt(component.length() - 1) == '}' &&
metaURL.getAvailableProperties().contains(component.substring(1, component.length() - 1))) {
// Property
int partEnd;
if (i < urlComponentsSize - 1) {
// Find next component
final String nextComponent = urlComponents.get(i + 1);
partEnd = url.indexOf(nextComponent, sourceOffset);
if (partEnd == -1) {
if (nextComponent.equals(":")) {
// Try to find another divider - dbvis sometimes contains bad sample URLs (e.g. for Oracle)
partEnd = url.indexOf("/", sourceOffset);
}
if (partEnd == -1) {
if (connectionInfo.getHost() == null) {
throw new DBException("Can't parse URL '" + url + "' with pattern '" + sampleURL + "'. String '" + nextComponent + "' not found after '" + component);
} else {
// We have connection properties anyway
url = null;
break;
}
}
}
} else {
partEnd = url.length();
}
String propertyValue = url.substring(sourceOffset, partEnd);
switch (component) {
case "{host}":
connectionInfo.setHost(propertyValue);
break;
case "{port}":
connectionInfo.setPort(propertyValue);
break;
case "{database}":
connectionInfo.setDatabase(propertyValue);
break;
default:
if (connectionInfo.getHost() == null) {
throw new DBException("Unsupported property " + component);
}
}
sourceOffset = partEnd;
} else {
// Static string
sourceOffset += component.length();
}
}
}
if (url == null) {
if (connectionInfo.getDriver() == null) {
throw new DBCException("Can't detect target driver for '" + connectionInfo.getAlias() + "'");
}
if (connectionInfo.getHost() == null) {
throw new DBCException("No URL and no host name - can't import connection '" + connectionInfo.getAlias() + "'");
}
// No URL - generate from props
DBPConnectionConfiguration conConfig = new DBPConnectionConfiguration();
conConfig.setHostName(connectionInfo.getHost());
conConfig.setHostPort(connectionInfo.getPort());
conConfig.setDatabaseName(connectionInfo.getDatabase());
url = connectionInfo.getDriver().getDataSourceProvider().getConnectionURL(connectionInfo.getDriver(), conConfig);
connectionInfo.setUrl(url);
}
}
}