/* * 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.core.application; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.*; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.jkiss.dbeaver.model.DBConstants; import org.jkiss.dbeaver.model.runtime.BaseProgressMonitor; import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; import org.jkiss.dbeaver.utils.GeneralUtils; import org.jkiss.utils.ArrayUtils; import org.jkiss.utils.IOUtils; import org.jkiss.utils.StandardConstants; import java.io.*; import java.util.Properties; /** * This class controls all aspects of the application's execution */ class DBeaverSettingsImporter { private static final String[] COPY_PLUGINS = { "org.eclipse.compare", "org.eclipse.core.resources", "org.eclipse.core.runtime", "org.eclipse.e4.ui.workbench.swt", "org.eclipse.equinox.p2.ui", "org.eclipse.equinox.security.ui", "org.eclipse.help.ui", "org.eclipse.search", "org.eclipse.ui.ide", "org.eclipse.ui.views.log", "org.eclipse.ui.workbench", "org.eclipse.ui.workbench.texteditor", "org.jkiss.dbeaver.core", "org.jkiss.dbeaver.model", }; private final DBeaverApplication application; private final Display display; private Shell windowShell; private Label progressLabel; private ProgressBar progressBar; private File driversFolder; private File oldWorkspacePath; private int shellResult = SWT.NONE; public DBeaverSettingsImporter(DBeaverApplication application, Display display) { this.application = application; this.display = display; } boolean migrateFromPreviousVersion(final File oldDir, final File newDir) { final Properties oldProps = application.readWorkspaceInfo(GeneralUtils.getMetadataFolder(oldDir)); String oldVersion = oldProps.getProperty(DBeaverApplication.VERSION_PROP_PRODUCT_VERSION); if (oldVersion == null) { oldVersion = "3.x"; } oldWorkspacePath = oldDir; driversFolder = new File( System.getProperty(StandardConstants.ENV_USER_HOME), DBConstants.DEFAULT_DRIVERS_FOLDER); /* int msgResult = application.showMessageBox( "DBeaver - Import settings", "Settings of previous version (" + oldVersion + ") of " + GeneralUtils.getProductName() + " was found at\n" + oldDir.getAbsolutePath() + "\n" + "Do you want to import previous version settings? (Recommended).\n\n" + "Make sure previous version of " + GeneralUtils.getProductName() + " isn't running", SWT.ICON_QUESTION | SWT.NO | SWT.YES); if (msgResult != SWT.YES) { return; } if (!newDir.exists()) { if (!newDir.mkdirs()) { application.showMessageBox("Error", "Can't create workspace folder '" + newDir.getAbsolutePath() + "'", SWT.ICON_ERROR | SWT.OK); return; } } */ Image dbeaverIcon = AbstractUIPlugin.imageDescriptorFromPlugin(DBeaverApplication.APPLICATION_PLUGIN_ID, "icons/dbeaver32.png").createImage(); Image dbeaverLogo = AbstractUIPlugin.imageDescriptorFromPlugin(DBeaverApplication.APPLICATION_PLUGIN_ID, "icons/dbeaver64.png").createImage(); windowShell = new Shell(display); windowShell.setImage(dbeaverIcon); windowShell.setText("Import " + GeneralUtils.getProductName() + " configuration"); windowShell.setLayout(new GridLayout(1, false)); { Group infoGroup = new Group(windowShell, SWT.NONE); infoGroup.setText("Import workspace"); infoGroup.setLayoutData(new GridData(GridData.FILL_BOTH)); GridLayout gl = new GridLayout(2, false); gl.horizontalSpacing = 10; infoGroup.setLayout(gl); Label iconLabel = new Label(infoGroup, SWT.NONE); iconLabel.setImage(dbeaverLogo); iconLabel.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); Label confirmLabel = new Label(infoGroup, SWT.NONE); //confirmLabel.setImage(JFaceResources.getImage(org.eclipse.jface.dialogs.Dialog.DLG_IMG_MESSAGE_INFO)); confirmLabel.setText("Previous version (" + GeneralUtils.getProductName() + " " + oldVersion + ") settings were found:\n" + oldDir.getAbsolutePath() + "\n" + "Do you want to import these settings? (Recommended).\n\n" + "Make sure previous version of " + GeneralUtils.getProductName() + " isn't running"); confirmLabel.setLayoutData(new GridData(GridData.FILL_BOTH)); } { Composite buttonsPanel = new Composite(windowShell, SWT.NONE); buttonsPanel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); buttonsPanel.setLayout(new GridLayout(2, true)); final Button migrateButton = new Button(buttonsPanel, SWT.PUSH); migrateButton.setText("Import workspace"); final Button skipButton = new Button(buttonsPanel, SWT.PUSH); skipButton.setText("Skip"); migrateButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); migrateButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { migrateButton.setEnabled(false); skipButton.setEnabled(false); progressBar.setVisible(true); ((GridData)progressBar.getLayoutData()).exclude = false; windowShell.pack(); migrateWorkspace(oldDir, newDir); } }); skipButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); skipButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { MessageBox messageBox = new MessageBox(windowShell, SWT.ICON_WARNING | SWT.YES | SWT.NO); messageBox.setText("Skip workspace migration"); messageBox.setMessage("Skipping workspace migration you will loose all previous workspace data.\n\nAre you sure?"); int response = messageBox.open(); if (response == SWT.YES) { shellResult = SWT.IGNORE; windowShell.dispose(); } } }); } progressLabel = new Label(windowShell, SWT.NONE); progressLabel.setLayoutData(new GridData(GridData.FILL_BOTH)); progressBar = new ProgressBar(windowShell, SWT.SMOOTH); progressBar.setVisible(false); final GridData gd = new GridData(GridData.FILL_BOTH); gd.heightHint = 30; gd.widthHint = 300; gd.exclude = true; progressBar.setLayoutData(gd); windowShell.pack(); Rectangle screenSize = display.getPrimaryMonitor().getBounds(); windowShell.setLocation((screenSize.width - windowShell.getBounds().width) / 2, (screenSize.height - windowShell.getBounds().height) / 2); windowShell.open(); while (!windowShell.isDisposed ()) { if (!display.readAndDispatch ()) display.sleep (); } return (shellResult != SWT.NONE); } private void migrateWorkspace(final File oldDir, final File newDir) { progressLabel.setText("Counting workspace files..."); final int totalFiles = countWorkspaceFiles(oldDir); progressBar.setMinimum(0); progressBar.setMaximum(totalFiles); final DBRProgressMonitor monitor = new BaseProgressMonitor() { int filesProcessed = 0; @Override public void subTask(final String name) { display.syncExec(new Runnable() { @Override public void run() { progressLabel.setText(name); } }); } @Override public void worked(final int work) { display.syncExec(new Runnable() { @Override public void run() { filesProcessed += work; progressBar.setSelection(filesProcessed); } }); } }; new Thread() { @Override public void run() { try { if (!newDir.exists()) { if (!newDir.mkdirs()) { System.err.println("Can't create target workspace directory '" + newDir.getAbsolutePath() + "'"); return; } } copyWorkspaceFiles(monitor, DIR_TYPE.WORKSPACE, oldDir, newDir); } finally { DBeaverApplication.WORKSPACE_MIGRATED = true; display.syncExec(new Runnable() { @Override public void run() { showMessageBox("Import completed", "Configuration was imported to '" + newDir.getAbsolutePath() + "'", SWT.ICON_INFORMATION | SWT.OK); shellResult = SWT.OK; windowShell.dispose(); } }); } } }.start(); } private int countWorkspaceFiles(File dir) { int count = 1; final File[] files = dir.listFiles(); if (files == null) { return count; } for (File file : files) { if (file.isDirectory()) { count += countWorkspaceFiles(file); } else { count++; } } return count; } enum DIR_TYPE { WORKSPACE, NORMAL, METADATA, PLUGINS, CORE } private void copyWorkspaceFiles(DBRProgressMonitor monitor, DIR_TYPE parentDirType, File fromDir, File toDir) { final File[] files = fromDir.listFiles(); if (files == null) { return; } int skippedFiles = 0; for (File file : files) { DIR_TYPE dirType = DIR_TYPE.NORMAL; switch (file.getName()) { case ".metadata": if (parentDirType == DIR_TYPE.WORKSPACE) { dirType = DIR_TYPE.METADATA; } break; case ".plugins": if (parentDirType == DIR_TYPE.METADATA) { dirType = DIR_TYPE.PLUGINS; } break; case "org.jkiss.dbeaver.core": if (parentDirType == DIR_TYPE.PLUGINS) { dirType = DIR_TYPE.CORE; } break; } String relPath = file.getAbsolutePath().substring(oldWorkspacePath.getAbsolutePath().length()); monitor.subTask(relPath); if (file.isDirectory()) { if (parentDirType == DIR_TYPE.METADATA && !file.getName().equals(".plugins")) { // Skip all dirs but plugins skippedFiles += countWorkspaceFiles(file); continue; } if (parentDirType == DIR_TYPE.PLUGINS) { if (!ArrayUtils.contains(COPY_PLUGINS, file.getName())) { skippedFiles += countWorkspaceFiles(file); continue; } } if (parentDirType == DIR_TYPE.CORE) { // Copy drivers in the separate location switch (file.getName()) { case "drivers": case "maven": case "remote": File targetDir = new File(driversFolder, file.getName()); if (!targetDir.exists()) { if (!targetDir.mkdirs()) { System.err.println("Can't create drivers folder " + targetDir.getAbsolutePath()); skippedFiles += countWorkspaceFiles(file); continue; } } copyWorkspaceFiles(monitor, DIR_TYPE.NORMAL, file, targetDir); continue; } } File newDir = new File(toDir, file.getName()); if (newDir.exists() || newDir.mkdir()) { copyWorkspaceFiles(monitor, dirType, file, newDir); } else { System.err.println("Can't create folder " + newDir.getAbsolutePath()); } } else { if (parentDirType == DIR_TYPE.METADATA && file.getName().startsWith(".")) { // Skip ALL hidden files in .metadata skippedFiles++; continue; } File newFile = new File(toDir, file.getName()); if (file.getName().equals("org.jkiss.dbeaver.core.prefs")) { // Patch configuration Properties coreProps = new Properties(); try (FileInputStream is = new FileInputStream(file)) { coreProps.load(is); } catch (IOException e) { e.printStackTrace(System.err); } final String driversHomeProp = coreProps.getProperty("ui.drivers.home"); if (driversHomeProp != null && !driversHomeProp.isEmpty()) { File oldDriversPath = new File(driversHomeProp); if (oldDriversPath.equals(new File(oldWorkspacePath, ".metadata/.plugins/org.jkiss.dbeaver.core"))) { // Set new drivers path coreProps.setProperty("ui.drivers.home", driversFolder.getAbsolutePath()); } } try (FileOutputStream os = new FileOutputStream(newFile)) { coreProps.store(os, null); } catch (IOException e) { e.printStackTrace(System.err); } } else if (parentDirType == DIR_TYPE.CORE && file.getName().equals("drivers.xml")) { // Patch drivers cache path String driversText = null; try (Reader r = new InputStreamReader(new FileInputStream(file), GeneralUtils.UTF8_CHARSET)) { driversText = IOUtils.readToString(r); driversText = driversText.replace("${workspace}\\.metadata\\.plugins\\org.jkiss.dbeaver.core", "${drivers_home}"); driversText = driversText.replace("${workspace}/.metadata/.plugins/org.jkiss.dbeaver.core", "${drivers_home}"); } catch (IOException e) { e.printStackTrace(System.err); } if (driversText != null) { try (Writer w = new OutputStreamWriter(new FileOutputStream(newFile), GeneralUtils.UTF8_CHARSET)) { w.write(driversText); } catch (IOException e) { e.printStackTrace(System.err); } } } else { copyFileContents(file, newFile); } } monitor.worked(1 + skippedFiles); } } private void copyFileContents(File file, File newFile) { // Just copy the file if (newFile.exists() && newFile.length() == file.length()) { // It is already there } else { try (FileInputStream is = new FileInputStream(file)) { try (FileOutputStream os = new FileOutputStream(newFile)) { IOUtils.fastCopy(is, os); } } catch (IOException e) { // Error e.printStackTrace(System.err); } } } int showMessageBox(String title, String message, int style) { // Can't lock specified path MessageBox messageBox = new MessageBox(windowShell, style); messageBox.setText(title); messageBox.setMessage(message); return messageBox.open(); } }