提交 8a9e40a8 编写于 作者: S Serge Rider

#6972 MySQL export: run in task


Former-commit-id: 567ea5bd
上级 8e096773
......@@ -223,12 +223,14 @@ public class DBeaverUI implements DBPPlatformUI {
}
@Override
public void showMessageBox(String title, String message, boolean error) {
UIUtils.showMessageBox(
UIUtils.getActiveWorkbenchShell(),
title,
message,
error ? SWT.ICON_ERROR : SWT.ICON_INFORMATION);
public void showMessageBox(@NotNull String title, String message, boolean error) {
UIUtils.syncExec(() -> {
UIUtils.showMessageBox(
UIUtils.getActiveWorkbenchShell(),
title,
message,
error ? SWT.ICON_ERROR : SWT.ICON_INFORMATION);
});
}
@Override
......
......@@ -27,6 +27,7 @@ import org.jkiss.dbeaver.tools.transfer.DataTransferJob;
import org.jkiss.dbeaver.tools.transfer.DataTransferPipe;
import org.jkiss.dbeaver.tools.transfer.DataTransferSettings;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.List;
......@@ -43,6 +44,7 @@ public class DTTaskHandlerTransfer implements DBTTaskHandler {
@NotNull DBTTask task,
@NotNull Locale locale,
@NotNull Log log,
@NotNull Writer logStream,
@NotNull DBTTaskExecutionListener listener) throws DBException
{
DataTransferSettings settings = new DataTransferSettings(runnableContext, task, log, Collections.emptyMap());
......
......@@ -77,9 +77,16 @@ class MySQLExportWizard extends AbstractImportExportWizard<MySQLExportSettings,
@Override
public void saveTaskState(DBRRunnableContext runnableContext, Map<String, Object> state) {
objectsPage.saveState();
settingsPage.updateState();
getSettings().saveSettings(runnableContext, new TaskPreferenceStore(state));
}
@Override
public boolean isRunTaskOnFinish() {
return getCurrentTask() != null;
}
@Override
public void init(IWorkbench workbench, IStructuredSelection selection) {
super.init(workbench, selection);
......@@ -177,6 +184,7 @@ class MySQLExportWizard extends AbstractImportExportWizard<MySQLExportSettings,
@Override
public boolean performFinish() {
objectsPage.saveState();
settingsPage.updateState();
return super.performFinish();
}
......@@ -189,7 +197,7 @@ class MySQLExportWizard extends AbstractImportExportWizard<MySQLExportSettings,
@Override
public List<MySQLDatabaseExportInfo> getRunInfo() {
return getSettings().getObjects();
return getSettings().getExportObjects();
}
@Override
......
......@@ -246,7 +246,7 @@ class MySQLExportWizardPageObjects extends MySQLWizardPageSettings<MySQLExportWi
}
public void saveState() {
List<MySQLDatabaseExportInfo> objects = wizard.getSettings().getObjects();
List<MySQLDatabaseExportInfo> objects = wizard.getSettings().getExportObjects();
objects.clear();
for (TableItem item : catalogTable.getItems()) {
if (item.getChecked()) {
......
......@@ -8,6 +8,7 @@ Require-Bundle: org.eclipse.core.runtime,
org.jkiss.dbeaver.model,
org.jkiss.dbeaver.model.sql,
org.jkiss.dbeaver.data.gis,
org.jkiss.dbeaver.registry,
org.jkiss.dbeaver.tasks.native,
com.google.gson
Bundle-ActivationPolicy: lazy
......
......@@ -347,7 +347,7 @@
<extension point="org.jkiss.dbeaver.task">
<category id="mysql" name="MySQL" description="MySQL database task"/>
<task id="mysqlDatabaseBackup" name="Database export" description="Database export task" icon="platform:/plugin/org.jkiss.dbeaver.ui/icons/file/export.png" type="mysql" handler="org.jkiss.dbeaver.ext.mysql.tasks.DatabaseExportHandler">
<task id="mysqlDatabaseBackup" name="Database export" description="Database export task" icon="platform:/plugin/org.jkiss.dbeaver.ui/icons/file/export.png" type="mysql" handler="org.jkiss.dbeaver.ext.mysql.tasks.MySQLDatabaseExportHandler">
<objectType name="org.jkiss.dbeaver.ext.mysql.model.MySQLCatalog"/>
<objectType name="org.jkiss.dbeaver.ext.mysql.model.MySQLTableBase"/>
</task>
......
package org.jkiss.dbeaver.ext.mysql.tasks;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.runtime.DBRRunnableContext;
import org.jkiss.dbeaver.model.task.DBTTask;
import org.jkiss.dbeaver.model.task.DBTTaskExecutionListener;
import org.jkiss.dbeaver.model.task.DBTTaskHandler;
import java.util.Locale;
public class DatabaseExportHandler implements DBTTaskHandler {
@Override
public void executeTask(
@NotNull DBRRunnableContext runnableContext,
@NotNull DBTTask task,
@NotNull Locale locale,
@NotNull Log log,
@NotNull DBTTaskExecutionListener listener) throws DBException
{
// DataTransferSettings settings = new DataTransferSettings(runnableContext, task, log, Collections.emptyMap());
// executeWithSettings(runnableContext, locale, log, listener, settings);
}
/*
public void executeWithSettings(@NotNull DBRRunnableContext runnableContext, @NotNull Locale locale, @NotNull Log log, @NotNull DBTTaskExecutionListener listener, DataTransferSettings settings) throws DBException {
// Start consumers
listener.taskStarted(settings);
log.debug("Data transfer initiated");
List<DataTransferPipe> dataPipes = settings.getDataPipes();
try {
runnableContext.run(true, false, monitor -> {
log.debug("Initialize data transfer sources");
monitor.beginTask("Initialize pipes", dataPipes.size());
try {
for (int i = 0; i < dataPipes.size(); i++) {
DataTransferPipe pipe = dataPipes.get(i);
pipe.initPipe(settings, i, dataPipes.size());
pipe.getConsumer().startTransfer(monitor);
monitor.worked(1);
}
} catch (DBException e) {
throw new InvocationTargetException(e);
} finally {
monitor.done();
}
});
} catch (InvocationTargetException e) {
throw new DBException("Error starting data transfer", e.getTargetException());
} catch (InterruptedException e) {
return;
}
// Schedule jobs for data providers
int totalJobs = settings.getDataPipes().size();
if (totalJobs > settings.getMaxJobCount()) {
totalJobs = settings.getMaxJobCount();
}
Throwable error = null;
for (int i = 0; i < totalJobs; i++) {
DataTransferJob job = new DataTransferJob(settings, locale, log, listener);
try {
runnableContext.run(true, true, job);
} catch (InvocationTargetException e) {
error = e.getTargetException();
} catch (InterruptedException e) {
break;
}
listener.subTaskFinished(error);
}
listener.taskFinished(settings, error);
log.debug("Data transfer completed");
}
*/
}
package org.jkiss.dbeaver.ext.mysql.tasks;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.ext.mysql.MySQLConstants;
import org.jkiss.dbeaver.ext.mysql.model.MySQLTableBase;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.DBRRunnableContext;
import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.model.task.DBTTask;
import org.jkiss.dbeaver.registry.task.TaskPreferenceStore;
import org.jkiss.dbeaver.utils.GeneralUtils;
import org.jkiss.dbeaver.utils.RuntimeUtils;
import org.jkiss.utils.CommonUtils;
import java.io.*;
import java.text.NumberFormat;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MySQLDatabaseExportHandler extends MySQLNativeToolHandler<MySQLExportSettings, DBSObject, MySQLDatabaseExportInfo> {
@Override
public Collection<MySQLDatabaseExportInfo> getRunInfo(MySQLExportSettings settings) {
return settings.getExportObjects();
}
@Override
protected MySQLExportSettings createTaskSettings(DBRRunnableContext context, DBTTask task) {
MySQLExportSettings settings = new MySQLExportSettings();
settings.loadSettings(context, new TaskPreferenceStore(task));
return settings;
}
@Override
protected boolean validateTaskParameters(DBTTask task, MySQLExportSettings settings, Log log) {
if (task.getType().getId().equals(MySQLTasks.TASK_DATABASE_BACKUP)) {
final File dir = settings.getOutputFolder();
if (!dir.exists()) {
if (!dir.mkdirs()) {
log.error("Can't create directory '" + dir.getAbsolutePath() + "'");
return false;
}
}
}
return true;
}
@Override
protected List<String> getCommandLine(MySQLExportSettings settings, MySQLDatabaseExportInfo arg) throws IOException {
List<String> cmd = getMySQLToolCommandLine(this, settings, arg);
if (!CommonUtils.isEmpty(arg.getTables())) {
cmd.add(arg.getDatabase().getName());
for (MySQLTableBase table : arg.getTables()) {
cmd.add(table.getName());
}
} else {
cmd.add(arg.getDatabase().getName());
}
return cmd;
}
@Override
public void fillProcessParameters(MySQLExportSettings settings, MySQLDatabaseExportInfo arg, List<String> cmd) throws IOException {
File dumpBinary = RuntimeUtils.getNativeClientBinary(settings.getClientHome(), MySQLConstants.BIN_FOLDER, "mysqldump"); //$NON-NLS-1$
String dumpPath = dumpBinary.getAbsolutePath();
cmd.add(dumpPath);
switch (settings.getMethod()) {
case LOCK_ALL_TABLES:
cmd.add("--lock-all-tables"); //$NON-NLS-1$
break;
case ONLINE:
cmd.add("--single-transaction"); //$NON-NLS-1$
break;
}
if (settings.isNoCreateStatements()) {
cmd.add("--no-create-info"); //$NON-NLS-1$
} else {
if (CommonUtils.isEmpty(arg.getTables())) {
cmd.add("--routines"); //$NON-NLS-1$
}
}
if (settings.isAddDropStatements()) {
cmd.add("--add-drop-table"); //$NON-NLS-1$
} else {
cmd.add("--skip-add-drop-table"); //$NON-NLS-1$
}
if (settings.isDisableKeys()) cmd.add("--disable-keys"); //$NON-NLS-1$
if (settings.isExtendedInserts()) {
cmd.add("--extended-insert"); //$NON-NLS-1$
} else {
cmd.add("--skip-extended-insert"); //$NON-NLS-1$
}
if (settings.isBinariesInHex()) {
cmd.add("--hex-blob"); //$NON-NLS-1$
}
if (settings.isNoData()) {
cmd.add("--no-data"); //$NON-NLS-1$
}
if (settings.isDumpEvents()) cmd.add("--events"); //$NON-NLS-1$
if (settings.isComments()) cmd.add("--comments"); //$NON-NLS-1$
settings.addExtraCommandArgs(cmd);
}
@Override
public boolean isVerbose() {
return true;
}
@Override
protected void startProcessHandler(DBRProgressMonitor monitor, DBTTask task, MySQLExportSettings settings, final MySQLDatabaseExportInfo arg, ProcessBuilder processBuilder, Process process, Log log) {
super.startProcessHandler(monitor, task, settings, arg, processBuilder, process, log);
String outFileName = GeneralUtils.replaceVariables(settings.getOutputFilePattern(), name -> {
switch (name) {
case VARIABLE_DATABASE:
return arg.getDatabase().getName();
case VARIABLE_HOST:
return arg.getDatabase().getDataSource().getContainer().getConnectionConfiguration().getHostName();
case VARIABLE_TABLE:
final Iterator<MySQLTableBase> iterator = arg.getTables() == null ? null : arg.getTables().iterator();
if (iterator != null && iterator.hasNext()) {
return iterator.next().getName();
} else {
return "null";
}
case VARIABLE_TIMESTAMP:
return RuntimeUtils.getCurrentTimeStamp();
case VARIABLE_DATE:
return RuntimeUtils.getCurrentDate();
default:
System.getProperty(name);
}
return null;
});
File outFile = new File(settings.getOutputFolder(), outFileName);
boolean isFiltering = settings.isRemoveDefiner();
Thread job = isFiltering ?
new DumpFilterJob(monitor, process.getInputStream(), outFile, log) :
new DumpCopierJob(monitor, "Dump database", process.getInputStream(), outFile, log);
job.start();
}
static class DumpFilterJob extends DumpJob {
private Pattern DEFINER_PATTER = Pattern.compile("DEFINER\\s*=\\s*`[^*]*`@`[0-9a-z\\-_\\.%]*`", Pattern.CASE_INSENSITIVE);
DumpFilterJob(DBRProgressMonitor monitor, InputStream stream, File outFile, Log log) {
super("MySQL databasse dump filter", monitor, stream, outFile, log);
}
@Override
public void runDump() throws IOException {
monitor.beginTask("Export database", 100);
long prevStatusUpdateTime = 0;
try {
NumberFormat numberFormat = NumberFormat.getInstance();
LineNumberReader reader = new LineNumberReader(new InputStreamReader(input, GeneralUtils.DEFAULT_ENCODING));
try (OutputStream output = new FileOutputStream(outFile)) {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output, GeneralUtils.DEFAULT_ENCODING));
for (; ; ) {
String line = reader.readLine();
if (line == null) {
break;
}
final Matcher matcher = DEFINER_PATTER.matcher(line);
if (matcher.find()) {
line = matcher.replaceFirst("");
}
long currentTime = System.currentTimeMillis();
if (currentTime - prevStatusUpdateTime > 300) {
monitor.subTask("Saved " + numberFormat.format(reader.getLineNumber()) + " lines");
prevStatusUpdateTime = currentTime;
}
line = filterLine(line);
writer.write(line);
writer.newLine();
}
writer.flush();
}
} finally {
monitor.done();
}
}
@NotNull
private String filterLine(@NotNull String line) {
return line;
}
}
}
......@@ -17,17 +17,30 @@
*/
package org.jkiss.dbeaver.ext.mysql.tasks;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.ext.mysql.MySQLDataSourceProvider;
import org.jkiss.dbeaver.ext.mysql.MySQLServerHome;
import org.jkiss.dbeaver.ext.mysql.model.MySQLCatalog;
import org.jkiss.dbeaver.ext.mysql.model.MySQLTableBase;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.preferences.DBPPreferenceMap;
import org.jkiss.dbeaver.model.preferences.DBPPreferenceStore;
import org.jkiss.dbeaver.model.runtime.DBRRunnableContext;
import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.tasks.nativetool.AbstractImportExportSettings;
import org.jkiss.utils.CommonUtils;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class MySQLExportSettings extends AbstractImportExportSettings<DBSObject> {
private static final Log log = Log.getLog(MySQLExportSettings.class);
public enum DumpMethod {
ONLINE,
LOCK_ALL_TABLES,
......@@ -46,7 +59,7 @@ public class MySQLExportSettings extends AbstractImportExportSettings<DBSObject>
private boolean noData;
private boolean showViews;
public List<MySQLDatabaseExportInfo> objects = new ArrayList<>();
public List<MySQLDatabaseExportInfo> exportObjects = new ArrayList<>();
public DumpMethod getMethod() {
return method;
......@@ -136,12 +149,17 @@ public class MySQLExportSettings extends AbstractImportExportSettings<DBSObject>
this.showViews = showViews;
}
public void setObjects(List<MySQLDatabaseExportInfo> objects) {
this.objects = objects;
public void setExportObjects(List<MySQLDatabaseExportInfo> exportObjects) {
this.exportObjects = exportObjects;
}
public List<MySQLDatabaseExportInfo> getExportObjects() {
return exportObjects;
}
public List<MySQLDatabaseExportInfo> getObjects() {
return objects;
@Override
public MySQLServerHome findNativeClientHome(String clientHomeId) {
return MySQLDataSourceProvider.getServerHome(clientHomeId);
}
@Override
......@@ -161,6 +179,55 @@ public class MySQLExportSettings extends AbstractImportExportSettings<DBSObject>
// Backward compatibility
setExtraCommandArgs(store.getString("MySQL.export.extraArgs"));
}
if (store instanceof DBPPreferenceMap) {
// Save input objects to task properties
List<Map<String, Object>> objectList = ((DBPPreferenceMap) store).getObject("exportObjects");
if (!CommonUtils.isEmpty(objectList)) {
for (Map<String, Object> object : objectList) {
String catalogId = CommonUtils.toString(object.get("catalog"));
if (!CommonUtils.isEmpty(catalogId)) {
List<String> tableNames = (List<String>) object.get("tables");
MySQLDatabaseExportInfo exportInfo = loadDatabaseExportInfo(runnableContext, catalogId, tableNames);
if (exportInfo != null) {
exportObjects.add(exportInfo);
}
}
}
}
}
}
private MySQLDatabaseExportInfo loadDatabaseExportInfo(DBRRunnableContext runnableContext, String catalogId, List<String> tableNames) {
MySQLDatabaseExportInfo[] exportInfo = new MySQLDatabaseExportInfo[1];
try {
runnableContext.run(false, true, monitor -> {
try {
MySQLCatalog catalog = (MySQLCatalog) DBUtils.findObjectById(monitor, getProject(), catalogId);
if (catalog == null) {
throw new DBException("Catalog " + catalogId + " not found");
}
List<MySQLTableBase> tables = null;
if (!CommonUtils.isEmpty(tableNames)) {
tables = new ArrayList<>();
for (String tableName : tableNames) {
MySQLTableBase table = catalog.getTableCache().getObject(monitor, catalog, tableName);
if (table != null) {
tables.add(table);
}
}
}
exportInfo[0] = new MySQLDatabaseExportInfo(catalog, tables);
} catch (Throwable e) {
throw new InvocationTargetException(e);
}
});
} catch (InvocationTargetException e) {
log.error("Error loading objects configuration", e);
} catch (InterruptedException e) {
// Ignore
}
return exportInfo[0];
}
@Override
......@@ -176,6 +243,25 @@ public class MySQLExportSettings extends AbstractImportExportSettings<DBSObject>
store.setValue("MySQL.export.binariesInHex", binariesInHex);
store.setValue("MySQL.export.noData", noData);
store.setValue("MySQL.export.showViews", showViews);
if (store instanceof DBPPreferenceMap && !CommonUtils.isEmpty(exportObjects)) {
// Save input objects to task properties
List<Map<String, Object>> objectList = new ArrayList<>();
for (MySQLDatabaseExportInfo object : exportObjects) {
Map<String, Object> objInfo = new LinkedHashMap<>();
objInfo.put("catalog", DBUtils.getObjectFullId(object.getDatabase()));
if (!CommonUtils.isEmpty(object.getTables())) {
List<String> tableList = new ArrayList<>();
for (MySQLTableBase table : object.getTables()) {
tableList.add(table.getName());
}
objInfo.put("tables", tableList);
}
objectList.add(objInfo);
}
((DBPPreferenceMap) store).getPropertyMap().put("exportObjects", objectList);
}
}
}
package org.jkiss.dbeaver.ext.mysql.tasks;
import org.jkiss.dbeaver.ext.mysql.MySQLConstants;
import org.jkiss.dbeaver.model.connection.DBPConnectionConfiguration;
import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.tasks.nativetool.AbstractNativeToolHandler;
import org.jkiss.dbeaver.tasks.nativetool.AbstractNativeToolSettings;
import org.jkiss.utils.CommonUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public abstract class MySQLNativeToolHandler<SETTINGS extends AbstractNativeToolSettings<BASE_OBJECT>, BASE_OBJECT extends DBSObject, PROCESS_ARG> extends AbstractNativeToolHandler<SETTINGS, BASE_OBJECT, PROCESS_ARG> {
@Override
protected void setupProcessParameters(SETTINGS settings, PROCESS_ARG arg, ProcessBuilder process) {
String userPassword = settings.getToolUserPassword();
if (CommonUtils.isEmpty(userPassword)) {
userPassword = settings.getDataSourceContainer().getActualConnectionConfiguration().getUserPassword();
}
if (!CommonUtils.isEmpty(userPassword)) {
process.environment().put(MySQLConstants.ENV_VARIABLE_MYSQL_PWD, userPassword);
}/* else {
// Empty password?
process.environment().put(MySQLConstants.ENV_VARIABLE_MYSQL_PWD, "");
}*/
}
protected List<String> getMySQLToolCommandLine(AbstractNativeToolHandler<SETTINGS, BASE_OBJECT, PROCESS_ARG> handler, SETTINGS settings, PROCESS_ARG arg) throws IOException {
java.util.List<String> cmd = new ArrayList<>();
handler.fillProcessParameters(settings, arg, cmd);
if (handler.isVerbose()) {
cmd.add("-v");
}
DBPConnectionConfiguration connectionInfo = settings.getDataSourceContainer().getActualConnectionConfiguration();
cmd.add("--host=" + connectionInfo.getHostName());
if (!CommonUtils.isEmpty(connectionInfo.getHostPort())) {
cmd.add("--port=" + connectionInfo.getHostPort());
}
cmd.add("-u");
cmd.add(settings.getToolUserName());
// Password is passed in env variable (#1004)
// if (!CommonUtils.isEmpty(toolWizard.getToolUserPassword())) {
// cmd.add("--password=" + toolWizard.getToolUserPassword());
// }
return cmd;
}
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2019 Serge Rider (serge@jkiss.org)
* Copyright (C) 2011-2012 Eugene Fradkin (eugene.fradkin@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -14,57 +15,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.tasks.nativetool;
package org.jkiss.dbeaver.ext.mysql.tasks;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.model.task.DBTTask;
import org.jkiss.utils.CommonUtils;
import org.jkiss.dbeaver.tasks.nativetool.AbstractImportExportSettings;
import java.io.File;
/**
* TaskHandlerNativeToolExport
*/
public abstract class TaskHandlerNativeToolExport<BASE_OBJECT extends DBSObject, PROCESS_ARG> extends TaskHandlerNativeToolBase<BASE_OBJECT, PROCESS_ARG> {
protected File outputFolder;
protected String outputFilePattern;
public File getOutputFolder() {
return outputFolder;
}
public String getOutputFilePattern() {
return outputFilePattern;
}
@Override
protected boolean prepareTaskRun(DBRProgressMonitor monitor, DBTTask task, Log log) {
if (outputFolder != null) {
if (!outputFolder.exists()) {
if (!outputFolder.mkdirs()) {
log.error("Can't create directory '" + outputFolder.getAbsolutePath() + "'");
return false;
}
}
}
return true;
}
@Override
protected void loadToolSettings(@NotNull DBRProgressMonitor monitor, @NotNull DBTTask task, Log log) {
super.loadToolSettings(monitor, task, log);
String outputFolderName = CommonUtils.toString(task.getProperties().get("outputFolder"));
if (!CommonUtils.isEmpty(outputFolderName)) {
outputFolder = new File(outputFolderName);
}
outputFilePattern = CommonUtils.toString(task.getProperties().get("outputFilePattern"));
}
public abstract class MySQLNativeToolSettings extends AbstractImportExportSettings<DBSObject> {
}
......@@ -42,13 +42,13 @@ public class JDBCSQLDialect extends BasicSQLDialect {
private static final Log log = Log.getLog(JDBCSQLDialect.class);
private String name;
private String[][] identifierQuoteString;
private String[][] identifierQuoteString = new String[][]{{SQLConstants.DEFAULT_IDENTIFIER_QUOTE, SQLConstants.DEFAULT_IDENTIFIER_QUOTE}};
private SQLStateType sqlStateType;
private String searchStringEscape;
private String catalogSeparator;
private String catalogSeparator = String.valueOf(SQLConstants.STRUCT_SEPARATOR);
private boolean isCatalogAtStart;
private int catalogUsage;
protected int schemaUsage;
private int catalogUsage = SQLDialect.USAGE_ALL;
protected int schemaUsage = SQLDialect.USAGE_ALL;
protected String validCharacters = "";
private boolean supportsUnquotedMixedCase;
private boolean supportsQuotedMixedCase;
......
......@@ -21,6 +21,7 @@ import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.runtime.DBRRunnableContext;
import java.io.Writer;
import java.util.Locale;
/**
......@@ -33,6 +34,7 @@ public interface DBTTaskHandler {
@NotNull DBTTask task,
@NotNull Locale locale,
@NotNull Log log,
@NotNull Writer logStream,
@NotNull DBTTaskExecutionListener listener)
throws DBException;
......
......@@ -117,7 +117,7 @@ public class RuntimeUtils {
if (!dumpBinary.exists()) {
dumpBinary = new File(home.getPath(), binName);
if (!dumpBinary.exists()) {
throw new IOException("Utility '" + binName + "' not found in client home '" + home.getDisplayName() + "'");
throw new IOException("Utility '" + binName + "' not found in client home '" + home.getDisplayName() + "' (" + home.getPath().getAbsolutePath() + ")");
}
}
return dumpBinary;
......
......@@ -84,7 +84,7 @@ public class TaskRunJob extends AbstractJob implements DBRRunnableContext {
Log.setLogWriter(logStream);
try {
monitor.beginTask("Run task '" + task.getName() + " (" + task.getType().getName() + ")", 1);
executeTask(new LoggingProgressMonitor(monitor));
executeTask(new LoggingProgressMonitor(monitor), new PrintWriter(logStream, true));
} catch (Throwable e) {
taskError = e;
taskLog.error("Task fatal error", e);
......@@ -115,10 +115,10 @@ public class TaskRunJob extends AbstractJob implements DBRRunnableContext {
return Status.OK_STATUS;
}
private void executeTask(DBRProgressMonitor monitor) throws DBException {
private void executeTask(DBRProgressMonitor monitor, Writer logWriter) throws DBException {
activeMonitor = monitor;
DBTTaskHandler taskHandler = task.getType().createHandler();
taskHandler.executeTask(this, task, locale, taskLog, executionListener);
taskHandler.executeTask(this, task, locale, taskLog, logWriter, executionListener);
}
@Override
......
......@@ -38,12 +38,14 @@ import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.DBRRunnableWithProgress;
import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.model.task.DBTTask;
import org.jkiss.dbeaver.model.task.DBTTaskHandler;
import org.jkiss.dbeaver.registry.task.TaskPreferenceStore;
import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.dbeaver.runtime.ProgressStreamReader;
import org.jkiss.dbeaver.tasks.nativetool.AbstractNativeToolSettings;
import org.jkiss.dbeaver.tasks.ui.nativetool.internal.TaskNativeUIMessages;
import org.jkiss.dbeaver.tasks.ui.wizard.TaskConfigurationWizard;
import org.jkiss.dbeaver.tasks.ui.wizard.TaskWizardExecutor;
import org.jkiss.dbeaver.ui.UIUtils;
import org.jkiss.utils.CommonUtils;
import org.jkiss.utils.IOUtils;
......@@ -257,12 +259,39 @@ public abstract class AbstractToolWizard<SETTINGS extends AbstractNativeToolSett
// Save settings
settings.saveSettings(getRunnableContext(), getPreferenceStore());
if (!validateClientFiles()) {
return false;
}
if (isRunTaskOnFinish()) {
return super.performFinish();
}
if (getContainer().getCurrentPage() != logPage) {
getContainer().showPage(logPage);
}
if (!validateClientFiles()) {
return false;
if (getCurrentTask() == null) {
try {
DBTTaskHandler handler = null;
try {
handler = getTaskType().createHandler();
} catch (Throwable e) {
// No handler
}
if (handler != null) {
// Execute directly - without task serialize/deserialize
// We need it because some data producers cannot be serialized properly (e.g. ResultSetDatacontainer - see #7342)
DBTTask temporaryTask = getProject().getTaskManager().createTemporaryTask(getTaskType(), getTaskType().getName());
saveConfigurationToTask(temporaryTask);
TaskWizardExecutor executor = new TaskWizardExecutor(getRunnableContext(), temporaryTask, log, logPage.getLogWriter());
executor.executeTask();
return false;
}
} catch (Exception e) {
DBWorkbench.getPlatformUI().showError(e.getMessage(), "Error running task", e);
return false;
}
}
long startTime = System.currentTimeMillis();
......
......@@ -28,10 +28,7 @@ import org.jkiss.dbeaver.tasks.ui.nativetool.internal.TaskNativeUIMessages;
import org.jkiss.dbeaver.ui.UIUtils;
import org.jkiss.dbeaver.utils.GeneralUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.*;
import java.util.Date;
import java.util.List;
......@@ -67,6 +64,25 @@ public class ToolWizardPageLog extends WizardPage {
setControl(composite);
}
public Writer getLogWriter() {
return new Writer() {
@Override
public void write(char[] cbuf, int off, int len) {
appendLog(new String(cbuf, off, len));
}
@Override
public void flush() {
}
@Override
public void close() {
}
};
}
public void appendLog(final String line)
{
appendLog(line, false);
......@@ -77,23 +93,20 @@ public class ToolWizardPageLog extends WizardPage {
if (getShell().isDisposed()) {
return;
}
UIUtils.syncExec(new Runnable() {
@Override
public void run() {
synchronized (ToolWizardPageLog.this) {
if (!dumpLogText.isDisposed()) {
int caretOffset = dumpLogText.getCaretOffset();
dumpLogText.append(line);
//dumpLogText.append(ContentUtils.getDefaultLineSeparator());
dumpLogText.setCaretOffset(dumpLogText.getCharCount());
dumpLogText.showSelection();
if (error) {
StyleRange style1Range = new StyleRange();
style1Range.start = caretOffset;
style1Range.length = line.length();
style1Range.foreground = dumpLogText.getDisplay().getSystemColor(SWT.COLOR_RED);
dumpLogText.setStyleRange(style1Range);
}
UIUtils.syncExec(() -> {
synchronized (ToolWizardPageLog.this) {
if (!dumpLogText.isDisposed()) {
int caretOffset = dumpLogText.getCaretOffset();
dumpLogText.append(line);
//dumpLogText.append(ContentUtils.getDefaultLineSeparator());
dumpLogText.setCaretOffset(dumpLogText.getCharCount());
dumpLogText.showSelection();
if (error) {
StyleRange style1Range = new StyleRange();
style1Range.start = caretOffset;
style1Range.length = line.length();
style1Range.foreground = dumpLogText.getDisplay().getSystemColor(SWT.COLOR_RED);
dumpLogText.setStyleRange(style1Range);
}
}
}
......@@ -105,13 +118,10 @@ public class ToolWizardPageLog extends WizardPage {
if (getShell().isDisposed()) {
return;
}
UIUtils.syncExec(new Runnable() {
@Override
public void run() {
synchronized (ToolWizardPageLog.this) {
if (!dumpLogText.isDisposed()) {
dumpLogText.setText(""); //$NON-NLS-1$
}
UIUtils.syncExec(() -> {
synchronized (ToolWizardPageLog.this) {
if (!dumpLogText.isDisposed()) {
dumpLogText.setText(""); //$NON-NLS-1$
}
}
});
......@@ -162,15 +172,6 @@ public class ToolWizardPageLog extends WizardPage {
try {
InputStream in = input;
// if (in instanceof FilterInputStream) {
// try {
// final Field inField = FilterInputStream.class.getDeclaredField("in");
// inField.setAccessible(true);
// in = (InputStream) inField.get(in);
// } catch (Exception e) {
// appendLog(e.getMessage() + lf);
// }
// }
try (Reader reader = new InputStreamReader(in, GeneralUtils.getDefaultConsoleEncoding())) {
StringBuilder buf = new StringBuilder();
for (; ; ) {
......
......@@ -17,35 +17,53 @@
*/
package org.jkiss.dbeaver.tasks.nativetool;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.connection.DBPConnectionConfiguration;
import org.jkiss.dbeaver.model.connection.DBPNativeClientLocation;
import org.jkiss.dbeaver.model.preferences.DBPPreferenceStore;
import org.jkiss.dbeaver.model.runtime.DBRRunnableContext;
import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.utils.CommonUtils;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Collections;
import java.util.List;
public abstract class AbstractNativeToolSettings<BASE_OBJECT extends DBSObject> extends AbstractToolSettings<BASE_OBJECT> {
private static final Log log = Log.getLog(AbstractNativeToolSettings.class);
private final String PROP_NAME_EXTRA_ARGS = "tools.wizard." + getClass().getSimpleName() + ".extraArgs";
private DBPNativeClientLocation clientHome;
private DBPConnectionConfiguration connectionInfo;
private Writer logWriter = new PrintWriter(System.out, true);
private String clientHomeName;
private String toolUserName;
private String toolUserPassword;
private String extraCommandArgs;
protected DBPNativeClientLocation findNativeClientHome(String clientHomeId) {
return null;
}
public Writer getLogWriter() {
return logWriter;
}
public void setLogWriter(Writer logWriter) {
this.logWriter = logWriter;
}
public String getClientHomeName() {
return clientHomeName;
}
public DBPNativeClientLocation getClientHome() {
return clientHome;
}
public void setClientHome(DBPNativeClientLocation clientHome) {
this.clientHome = clientHome;
this.clientHomeName = clientHome == null ? null : clientHome.getName();
}
public String getToolUserName() {
......@@ -81,15 +99,26 @@ public abstract class AbstractNativeToolSettings<BASE_OBJECT extends DBSObject>
@Override
public void loadSettings(DBRRunnableContext runnableContext, DBPPreferenceStore preferenceStore) {
super.loadSettings(runnableContext, preferenceStore);
connectionInfo = getDataSourceContainer() == null ? null : getDataSourceContainer().getActualConnectionConfiguration();
extraCommandArgs = preferenceStore.getString(PROP_NAME_EXTRA_ARGS);
clientHomeName = preferenceStore.getString("clientHomeName");
toolUserName = preferenceStore.getString("toolUserName");
toolUserPassword = preferenceStore.getString("toolUserPassword");
}
@Override
public void saveSettings(DBRRunnableContext runnableContext, DBPPreferenceStore preferenceStore) {
super.saveSettings(runnableContext, preferenceStore);
preferenceStore.setValue(PROP_NAME_EXTRA_ARGS, extraCommandArgs);
if (clientHomeName != null) {
preferenceStore.setValue("clientHomeName", clientHomeName);
}
if (!CommonUtils.isEmpty(toolUserName)) {
preferenceStore.setValue("toolUserName", toolUserName);
}
if (!CommonUtils.isEmpty(toolUserPassword)) {
preferenceStore.setValue("toolUserPassword", toolUserPassword);
}
}
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2019 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.tasks.nativetool;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.app.DBPProject;
import org.jkiss.dbeaver.model.connection.DBPConnectionConfiguration;
import org.jkiss.dbeaver.model.connection.DBPNativeClientLocation;
import org.jkiss.dbeaver.model.navigator.DBNDatabaseNode;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.DBRRunnableContext;
import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.model.task.DBTTask;
import org.jkiss.dbeaver.model.task.DBTTaskExecutionListener;
import org.jkiss.dbeaver.model.task.DBTTaskHandler;
import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.utils.CommonUtils;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
/**
* TaskHandlerNativeToolBase
*/
public abstract class TaskHandlerNativeToolBase<BASE_OBJECT extends DBSObject, PROCESS_ARG> implements DBTTaskHandler {
private List<BASE_OBJECT> databaseObjects;
private DBPNativeClientLocation clientHome;
private DBPDataSourceContainer dataSourceContainer;
private DBPConnectionConfiguration connectionInfo;
private String toolUserName;
private String toolUserPassword;
private String extraCommandArgs;
private boolean refreshObjects;
private boolean isSuccess;
////////////////////////////////////
// Methods to implement in real handlers
public abstract Collection<PROCESS_ARG> getRunInfo(DBTTask task);
protected abstract List<String> getCommandLine(PROCESS_ARG arg) throws IOException;
protected void setupProcessParameters(ProcessBuilder process) {
}
protected abstract void startProcessHandler(DBRProgressMonitor monitor, PROCESS_ARG arg, ProcessBuilder processBuilder, Process process);
protected boolean isNativeClientHomeRequired() {
return true;
}
protected boolean isMergeProcessStreams() {
return false;
}
public boolean isVerbose() {
return false;
}
protected boolean needsModelRefresh() {
return true;
}
protected void onSuccess(long workTime) {
}
////////////////////////////////////
// Helpers
public List<BASE_OBJECT> getDatabaseObjects() {
return databaseObjects;
}
public DBPConnectionConfiguration getConnectionInfo() {
return connectionInfo;
}
public DBPNativeClientLocation getClientHome() {
return clientHome;
}
public String getToolUserName() {
return toolUserName;
}
public void setToolUserName(String toolUserName) {
this.toolUserName = toolUserName;
}
public String getToolUserPassword() {
return toolUserPassword;
}
public void setToolUserPassword(String toolUserPassword) {
this.toolUserPassword = toolUserPassword;
}
public String getExtraCommandArgs() {
return extraCommandArgs;
}
public void setExtraCommandArgs(String extraCommandArgs) {
this.extraCommandArgs = extraCommandArgs;
}
protected void addExtraCommandArgs(List<String> cmd) {
if (!CommonUtils.isEmptyTrimmed(extraCommandArgs)) {
Collections.addAll(cmd, extraCommandArgs.split(" "));
}
}
public DBPDataSourceContainer getDataSourceContainer() {
return dataSourceContainer;
}
public DBPNativeClientLocation findNativeClientHome(String clientHomeId) {
return null;
}
////////////////////////////////////
// Native tool executor
@Override
public void executeTask(
@NotNull DBRRunnableContext runnableContext,
@NotNull DBTTask task,
@NotNull Locale locale,
@NotNull Log log,
@NotNull DBTTaskExecutionListener listener) throws DBException
{
log.debug(task.getType().getName() + " initiated");
try {
runnableContext.run(true, true, monitor -> {
loadToolSettings(monitor, task, log);
if (!prepareTaskRun(monitor, task, log)) {
isSuccess = false;
return;
}
Collection<PROCESS_ARG> runList = getRunInfo(task);
try {
isSuccess = true;
for (PROCESS_ARG arg : runList) {
if (monitor.isCanceled()) break;
if (!executeProcess(monitor, task, log, arg)) {
isSuccess = false;
}
}
} catch (Exception e){
throw new InvocationTargetException(e);
}
refreshObjects = isSuccess && !monitor.isCanceled();
if (refreshObjects && !CommonUtils.isEmpty(databaseObjects) && needsModelRefresh()) {
// Refresh navigator node (script execution can change everything inside)
for (BASE_OBJECT object : databaseObjects) {
final DBNDatabaseNode node = DBWorkbench.getPlatform().getNavigatorModel().findNode(object);
if (node != null) {
try {
node.refreshNode(monitor, TaskHandlerNativeToolBase.this);
} catch (DBException e) {
log.debug("Error refreshing node '" + node.getNodeItemPath() + "' after native tool execution", e);
}
}
}
}
});
} catch (InvocationTargetException e) {
throw new DBException("Error executing native tool", e.getTargetException());
} catch (InterruptedException e) {
// ignore
log.debug("Canceled");
}
log.debug(task.getType().getName() + " completed");
}
protected boolean prepareTaskRun(DBRProgressMonitor monitor, DBTTask task, Log log) {
return true;
}
private boolean executeProcess(DBRProgressMonitor monitor, DBTTask task, Log log, PROCESS_ARG arg) throws IOException, DBException, InterruptedException {
monitor.beginTask(task.getName(), 1);
try {
final List<String> commandLine = getCommandLine(arg);
final File execPath = new File(commandLine.get(0));
ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
processBuilder.directory(execPath.getParentFile());
if (this.isMergeProcessStreams()) {
processBuilder.redirectErrorStream(true);
}
setupProcessParameters(processBuilder);
Process process = processBuilder.start();
startProcessHandler(monitor, arg, processBuilder, process);
Thread.sleep(100);
for (; ; ) {
Thread.sleep(100);
if (monitor.isCanceled()) {
process.destroy();
}
try {
final int exitCode = process.exitValue();
if (exitCode != 0) {
log.error("Process exit code: " + exitCode);
return false;
}
} catch (IllegalThreadStateException e) {
// Still running
continue;
}
break;
}
//process.waitFor();
} catch (IOException e) {
monitor.done();
log.error(e);
//logPage.appendLog(NLS.bind(TaskNativeUIMessages.tools_wizard_log_io_error, e.getMessage()) + "\n", true);
return false;
}
return true;
}
protected void loadToolSettings(@NotNull DBRProgressMonitor monitor, @NotNull DBTTask task, Log log) {
String projectName = CommonUtils.toString(task.getProperties().get("project"));
DBPProject project = CommonUtils.isEmpty(projectName) ? null : DBWorkbench.getPlatform().getWorkspace().getProject(projectName);
if (project == null) {
if (!CommonUtils.isEmpty(projectName)) {
log.error("Can't find project '" + projectName + "' for tool configuration");
}
project = DBWorkbench.getPlatform().getWorkspace().getActiveProject();
}
String dsID = CommonUtils.toString(task.getProperties().get("dataSource"));
if (!CommonUtils.isEmpty(dsID)) {
dataSourceContainer = project.getDataSourceRegistry().getDataSource(dsID);
if (dataSourceContainer == null) {
log.error("Can't find datasource '" + dsID+ "' in project '" + project.getName() + "' for tool configuration");
}
}
{
List<String> databaseObjectList = (List<String>) task.getProperties().get("databaseObjects");
if (!CommonUtils.isEmpty(databaseObjectList)) {
DBPProject finalProject = project;
for (String objectId : databaseObjectList) {
try {
DBSObject object = DBUtils.findObjectById(monitor, finalProject, objectId);
if (object != null) {
databaseObjects.add((BASE_OBJECT) object);
}
} catch (Throwable e) {
log.error("Can't find database object '" + objectId + "' in project '" + finalProject.getName() + "' for task configuration");
}
}
}
}
connectionInfo = dataSourceContainer == null ? null : dataSourceContainer.getActualConnectionConfiguration();
toolUserName = CommonUtils.toString(task.getProperties().get("toolUserName"));
toolUserPassword = CommonUtils.toString(task.getProperties().get("toolUserPassword"));
extraCommandArgs = CommonUtils.toString(task.getProperties().get("extraArgs"));
}
}
......@@ -32,6 +32,7 @@ import org.eclipse.ui.IWorkbenchWizard;
import org.eclipse.ui.PartInitException;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.app.DBPProject;
import org.jkiss.dbeaver.model.runtime.DBRRunnableContext;
import org.jkiss.dbeaver.model.task.DBTTask;
......@@ -43,12 +44,15 @@ import org.jkiss.dbeaver.ui.UIUtils;
import org.jkiss.dbeaver.ui.dialogs.BaseWizard;
import org.jkiss.dbeaver.ui.navigator.NavigatorUtils;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
public abstract class TaskConfigurationWizard extends BaseWizard implements IWorkbenchWizard {
private static final Log log = Log.getLog(TaskConfigurationWizard.class);
private DBTTask currentTask;
private IStructuredSelection currentSelection;
private Button saveAsTaskButton;
......@@ -176,7 +180,7 @@ public abstract class TaskConfigurationWizard extends BaseWizard implements IWor
}
// Run task thru task manager
// Pass executor to visualize task progress in UI
TaskWizardExecutor executor = new TaskWizardExecutor(getRunnableContext(), task);
TaskWizardExecutor executor = new TaskWizardExecutor(getRunnableContext(), task, log, new PrintWriter(System.out));
if (getCurrentTask() == null) {
// Execute directly in wizard
executor.executeTask();
......
......@@ -24,13 +24,18 @@ import org.jkiss.dbeaver.model.task.DBTTask;
import org.jkiss.dbeaver.model.task.DBTTaskHandler;
import org.jkiss.utils.CommonUtils;
import java.io.Writer;
import java.util.Locale;
public class TaskWizardExecutor extends TaskProcessorUI {
private static final Log log = Log.getLog(TaskWizardExecutor.class);
public TaskWizardExecutor(@NotNull DBRRunnableContext staticContext, @NotNull DBTTask task) {
private final Log log;
private Writer logWriter;
public TaskWizardExecutor(@NotNull DBRRunnableContext staticContext, @NotNull DBTTask task, @NotNull Log log, @NotNull Writer logWriter) {
super(staticContext, task);
this.log = log;
this.logWriter = logWriter;
}
@Override
......@@ -41,7 +46,7 @@ public class TaskWizardExecutor extends TaskProcessorUI {
@Override
protected void runTask() throws DBException {
DBTTaskHandler handlerTransfer = getTask().getType().createHandler();
handlerTransfer.executeTask(this, getTask(), Locale.getDefault(), log, this);
handlerTransfer.executeTask(this, getTask(), Locale.getDefault(), log, logWriter, this);
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册