mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
dbeaver-corp/dbeaver-web#620 Data transfer: export + download
This commit is contained in:
+9
-25
@@ -49,13 +49,9 @@ import org.jkiss.dbeaver.runtime.qm.QMControllerImpl;
|
||||
import org.jkiss.dbeaver.runtime.qm.QMLogFileWriter;
|
||||
import org.jkiss.dbeaver.utils.ContentUtils;
|
||||
import org.jkiss.dbeaver.utils.GeneralUtils;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
import org.jkiss.utils.StandardConstants;
|
||||
import org.osgi.framework.Bundle;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -69,7 +65,7 @@ public class CloudbeaverPlatform extends BasePlatformImpl {
|
||||
|
||||
private static final Log log = Log.getLog(CloudbeaverPlatform.class);
|
||||
|
||||
private static final String TEMP_PROJECT_NAME = "cloudbeaver-temp";
|
||||
public static final String WORK_DATA_FOLDER_NAME = ".work-data";
|
||||
|
||||
static CloudbeaverPlatform instance;
|
||||
|
||||
@@ -285,30 +281,18 @@ public class CloudbeaverPlatform extends BasePlatformImpl {
|
||||
if (tempFolder == null) {
|
||||
// Make temp folder
|
||||
monitor.subTask("Create temp folder");
|
||||
try {
|
||||
final java.nio.file.Path tempDirectory = Files.createTempDirectory(TEMP_PROJECT_NAME);
|
||||
tempFolder = tempDirectory.toFile();
|
||||
} catch (IOException e) {
|
||||
final String sysTempFolder = System.getProperty(StandardConstants.ENV_TMP_DIR);
|
||||
if (!CommonUtils.isEmpty(sysTempFolder)) {
|
||||
tempFolder = new File(sysTempFolder, TEMP_PROJECT_NAME);
|
||||
if (!tempFolder.mkdirs()) {
|
||||
final String sysUserFolder = System.getProperty(StandardConstants.ENV_USER_HOME);
|
||||
if (!CommonUtils.isEmpty(sysUserFolder)) {
|
||||
tempFolder = new File(sysUserFolder, TEMP_PROJECT_NAME);
|
||||
if (!tempFolder.mkdirs()) {
|
||||
tempFolder = new File(TEMP_PROJECT_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
tempFolder = new File(workspace.getAbsolutePath(), WORK_DATA_FOLDER_NAME);
|
||||
}
|
||||
if (!tempFolder.exists() && !tempFolder.mkdirs()) {
|
||||
log.error("Can't create temp directory!");
|
||||
}
|
||||
return tempFolder;
|
||||
File folder = new File(tempFolder, name);
|
||||
if (folder.exists()) {
|
||||
if (!folder.mkdirs()) {
|
||||
log.error("Error creating temp folder '" + folder.getAbsolutePath() + "'");
|
||||
}
|
||||
}
|
||||
return folder;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+4
-3
@@ -13,6 +13,7 @@ import org.eclipse.jetty.server.session.FileSessionDataStore;
|
||||
import org.eclipse.jetty.server.session.SessionHandler;
|
||||
import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.servlet.ServletMapping;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.runtime.DBWorkbench;
|
||||
@@ -39,9 +40,9 @@ public class CloudbeaverJettyServer {
|
||||
ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||
servletContextHandler.setResourceBase(application.getContentRoot());
|
||||
servletContextHandler.setContextPath(application.getRootURI());
|
||||
servletContextHandler.addServlet(CloudbeaverStaticServlet.class, application.getRootURI());
|
||||
servletContextHandler.addServlet(CloudbeaverImageServlet.class, application.getServicesURI() + "images/*");
|
||||
servletContextHandler.addServlet(GraphQLEndpoint.class, application.getServicesURI() + "gql/*");
|
||||
servletContextHandler.addServlet(new ServletHolder("static", new CloudbeaverStaticServlet()), application.getRootURI());
|
||||
servletContextHandler.addServlet(new ServletHolder("images", new CloudbeaverImageServlet()), application.getServicesURI() + "images/*");
|
||||
servletContextHandler.addServlet(new ServletHolder("graphql", new GraphQLEndpoint()), application.getServicesURI() + "gql/*");
|
||||
servletContextHandler.addEventListener(new CloudbeaverServerContextListener());
|
||||
|
||||
// Add extensions from services
|
||||
|
||||
+1
-2
@@ -18,7 +18,6 @@ package io.cloudbeaver.server.model;
|
||||
|
||||
import org.jkiss.dbeaver.model.data.json.JSONUtils;
|
||||
import org.jkiss.dbeaver.model.meta.Property;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -46,7 +45,7 @@ public class WebConnectionConfig {
|
||||
}
|
||||
|
||||
public WebConnectionConfig(Map<String, Object> params) {
|
||||
dataSourceId = CommonUtils.toString(params.get("dataSourceId"));
|
||||
dataSourceId = JSONUtils.getString(params, "dataSourceId");
|
||||
|
||||
driverId = JSONUtils.getString(params, "driverId");
|
||||
host = JSONUtils.getString(params, "host");
|
||||
|
||||
+20
-3
@@ -49,6 +49,7 @@ import javax.servlet.http.HttpSession;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Web session.
|
||||
@@ -75,6 +76,7 @@ public class WebSession {
|
||||
|
||||
private final Map<String, WebAsyncTaskInfo> asyncTasks = new HashMap<>();
|
||||
private final Map<String, Object> attributes = new HashMap<>();
|
||||
private final Map<String, Function<Object,Object>> attributeDisposers = new HashMap<>();
|
||||
|
||||
private DBNModel navigatorModel;
|
||||
private DBNProjectDatabases databases;
|
||||
@@ -318,6 +320,16 @@ public class WebSession {
|
||||
|
||||
void close() {
|
||||
try {
|
||||
// Clear attributes
|
||||
synchronized (attributes) {
|
||||
for (Map.Entry<String, Function<Object,Object>> attrDisposer : attributeDisposers.entrySet()) {
|
||||
Object attrValue = attributes.get(attrDisposer.getKey());
|
||||
attrDisposer.getValue().apply(attrValue);
|
||||
}
|
||||
attributeDisposers.clear();
|
||||
attributes.clear();
|
||||
}
|
||||
|
||||
List<WebConnectionInfo> conCopy;
|
||||
synchronized (this.connections) {
|
||||
conCopy = new ArrayList<>(this.connections);
|
||||
@@ -522,12 +534,17 @@ public class WebSession {
|
||||
}
|
||||
}
|
||||
|
||||
public <T> T getAttribute(String name, DBRCreator<T, T> creator) {
|
||||
public <T> T getAttribute(String name, Function<T, T> creator, Function<T, T> disposer) {
|
||||
synchronized (attributes) {
|
||||
T value = (T) attributes.get(name);
|
||||
if (value == null) {
|
||||
value = creator.createObject(null);
|
||||
attributes.put(name, value);
|
||||
value = creator.apply(null);
|
||||
if (value != null) {
|
||||
attributes.put(name, value);
|
||||
if (disposer != null) {
|
||||
attributeDisposers.put(name, (Function<Object, Object>) disposer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
+2
-2
@@ -79,7 +79,7 @@ public class WebSQLProcessor {
|
||||
return connection;
|
||||
}
|
||||
|
||||
WebSession getWebSession() {
|
||||
public WebSession getWebSession() {
|
||||
return webSession;
|
||||
}
|
||||
|
||||
@@ -328,7 +328,7 @@ public class WebSQLProcessor {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private <T> T getDataContainerByNodePath(DBRProgressMonitor monitor, @NotNull String containerPath, Class<T> type) throws DBException {
|
||||
public <T> T getDataContainerByNodePath(DBRProgressMonitor monitor, @NotNull String containerPath, Class<T> type) throws DBException {
|
||||
DBNNode node = webSession.getNavigatorModel().getNodeByPath(monitor, containerPath);
|
||||
if (node == null) {
|
||||
throw new DBWebException("Container node '" + containerPath + "' not found");
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ input DataTransferParameters {
|
||||
# - openNewConnection: opens new database connection for data transfer task
|
||||
settings: Object
|
||||
# Processor properties. See DataTransferProcessorInfo.properties
|
||||
processorProperties: Object
|
||||
processorProperties: Object!
|
||||
# Data filter settings
|
||||
filter: SQLDataFilter
|
||||
}
|
||||
|
||||
+131
-20
@@ -16,18 +16,38 @@
|
||||
*/
|
||||
package io.cloudbeaver.service.data.transfer;
|
||||
|
||||
import io.cloudbeaver.api.DBWModel;
|
||||
import io.cloudbeaver.DBWebException;
|
||||
import io.cloudbeaver.server.CloudbeaverPlatform;
|
||||
import io.cloudbeaver.server.model.WebAsyncTaskInfo;
|
||||
import io.cloudbeaver.server.model.session.WebSession;
|
||||
import io.cloudbeaver.server.model.sql.WebSQLContextInfo;
|
||||
import io.cloudbeaver.server.model.sql.WebSQLProcessor;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.meta.RuntimeAction;
|
||||
import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor;
|
||||
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
|
||||
import org.jkiss.dbeaver.model.runtime.DBRRunnableWithResult;
|
||||
import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
|
||||
import org.jkiss.dbeaver.model.struct.DBSDataContainer;
|
||||
import org.jkiss.dbeaver.model.struct.DBSEntity;
|
||||
import org.jkiss.dbeaver.tools.transfer.IDataTransferConsumer;
|
||||
import org.jkiss.dbeaver.tools.transfer.IDataTransferProcessor;
|
||||
import org.jkiss.dbeaver.tools.transfer.database.DatabaseProducerSettings;
|
||||
import org.jkiss.dbeaver.tools.transfer.database.DatabaseTransferProducer;
|
||||
import org.jkiss.dbeaver.tools.transfer.registry.DataTransferProcessorDescriptor;
|
||||
import org.jkiss.dbeaver.tools.transfer.registry.DataTransferRegistry;
|
||||
import org.jkiss.dbeaver.tools.transfer.stream.IStreamDataExporter;
|
||||
import org.jkiss.dbeaver.tools.transfer.stream.StreamConsumerSettings;
|
||||
import org.jkiss.dbeaver.tools.transfer.stream.StreamTransferConsumer;
|
||||
import org.jkiss.dbeaver.utils.ContentUtils;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -35,10 +55,21 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
public class WebDataTransferManager {
|
||||
|
||||
private final DBWModel model;
|
||||
private static final Log log = Log.getLog(WebDataTransferManager.class);
|
||||
|
||||
public WebDataTransferManager(DBWModel model) {
|
||||
this.model = model;
|
||||
private final File dataExportFolder;
|
||||
|
||||
public WebDataTransferManager() {
|
||||
dataExportFolder = CloudbeaverPlatform.getInstance().getTempFolder(new VoidProgressMonitor(), "data-transfer");
|
||||
|
||||
ContentUtils.deleteFileRecursive(dataExportFolder);
|
||||
if (!dataExportFolder.mkdirs()) {
|
||||
log.error("Error re-creating temporary folder");
|
||||
}
|
||||
}
|
||||
|
||||
public File getDataExportFolder() {
|
||||
return dataExportFolder;
|
||||
}
|
||||
|
||||
@RuntimeAction
|
||||
@@ -53,32 +84,112 @@ public class WebDataTransferManager {
|
||||
|
||||
@RuntimeAction
|
||||
public WebAsyncTaskInfo dataTransferExportDataFromContainer(
|
||||
WebSession session,
|
||||
String connectionId,
|
||||
WebSQLProcessor sqlProcessor,
|
||||
String containerNodePath,
|
||||
WebDataTransferParameters parameters)
|
||||
{
|
||||
WebDataTransferParameters parameters) throws DBWebException {
|
||||
DataTransferProcessorDescriptor processor = DataTransferRegistry.getInstance().getProcessor(parameters.getProcessorId());
|
||||
|
||||
return null;
|
||||
DBSDataContainer dataContainer;
|
||||
try {
|
||||
dataContainer = sqlProcessor.getDataContainerByNodePath(sqlProcessor.getWebSession().getProgressMonitor(), containerNodePath, DBSDataContainer.class);
|
||||
} catch (DBException e) {
|
||||
throw new DBWebException("Invalid node path: " + containerNodePath, e);
|
||||
}
|
||||
|
||||
DBRRunnableWithResult<String> runnable = new DBRRunnableWithResult<String>() {
|
||||
@Override
|
||||
public void run(DBRProgressMonitor monitor) throws InvocationTargetException {
|
||||
try {
|
||||
File exportFile = new File(dataExportFolder, makeUniqueFileName(sqlProcessor, processor));
|
||||
try {
|
||||
exportData(monitor, processor, dataContainer, parameters, exportFile);
|
||||
} catch (Exception e) {
|
||||
if (exportFile.exists()) {
|
||||
if (!exportFile.delete()) {
|
||||
log.error("Error deleting export file " + exportFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
throw new DBException("Error exporting data", e);
|
||||
}
|
||||
WebDataTransferTaskConfig taskConfig = new WebDataTransferTaskConfig(exportFile, parameters);
|
||||
String exportFileName = CommonUtils.escapeFileName(CommonUtils.truncateString(dataContainer.getName(), 32));
|
||||
taskConfig.setExportFileName(exportFileName);
|
||||
WebDataTransferUtils.getSessionDataTransferConfig(sqlProcessor.getWebSession()).addTask(taskConfig);
|
||||
|
||||
result = exportFile.getName();
|
||||
} catch (Throwable e) {
|
||||
throw new InvocationTargetException(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
return sqlProcessor.getWebSession().createAndRunAsyncTask("Data export", runnable);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String makeUniqueFileName(WebSQLProcessor sqlProcessor, DataTransferProcessorDescriptor processor) {
|
||||
return sqlProcessor.getWebSession().getId() + "_" + UUID.randomUUID() + "." + WebDataTransferUtils.getProcessorFileExtension(processor);
|
||||
}
|
||||
|
||||
@RuntimeAction
|
||||
public WebAsyncTaskInfo dataTransferExportDataFromResults(
|
||||
WebSession session,
|
||||
String connectionId,
|
||||
String contextId,
|
||||
WebSQLContextInfo sqlContextInfo,
|
||||
String resultsId,
|
||||
WebDataTransferParameters parameters)
|
||||
{
|
||||
return null;
|
||||
WebDataTransferParameters parameters) throws DBWebException {
|
||||
throw new DBWebException("Not supported");
|
||||
}
|
||||
|
||||
@RuntimeAction
|
||||
public Boolean dataTransferRemoveDataFile(WebSession session, String dataFileId) {
|
||||
public Boolean dataTransferRemoveDataFile(WebSQLProcessor sqlProcessor, String dataFileId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private WebDataTransferSessionConfig getConfig(WebSession session) {
|
||||
return session.getAttribute("dataTransfer", x -> new WebDataTransferSessionConfig());
|
||||
private void exportData(
|
||||
DBRProgressMonitor monitor,
|
||||
DataTransferProcessorDescriptor processor,
|
||||
DBSDataContainer dataContainer,
|
||||
WebDataTransferParameters parameters,
|
||||
File exportFile) throws DBException, IOException
|
||||
{
|
||||
IDataTransferProcessor processorInstance = processor.getInstance();
|
||||
if (!(processorInstance instanceof IStreamDataExporter)) {
|
||||
throw new DBException("Invalid processor. " + IStreamDataExporter.class.getSimpleName() + " expected");
|
||||
}
|
||||
IStreamDataExporter exporter = (IStreamDataExporter) processorInstance;
|
||||
|
||||
StreamTransferConsumer consumer = new StreamTransferConsumer();
|
||||
StreamConsumerSettings settings = new StreamConsumerSettings();
|
||||
|
||||
settings.setOutputEncodingBOM(false);
|
||||
settings.setOpenFolderOnFinish(false);
|
||||
settings.setOutputFolder(exportFile.getParentFile().getAbsolutePath());
|
||||
settings.setOutputFilePattern(exportFile.getName());
|
||||
|
||||
Map<Object, Object> properties = new HashMap<>();
|
||||
|
||||
Map<String, Object> processorProperties = parameters.getProcessorProperties();
|
||||
if (processorProperties == null) processorProperties = Collections.emptyMap();
|
||||
for (DBPPropertyDescriptor prop : processor.getProperties()) {
|
||||
Object propValue = processorProperties.get(CommonUtils.toString(prop.getId()));
|
||||
properties.put(prop.getId(), propValue != null ? propValue : prop.getDefaultValue());
|
||||
}
|
||||
// Remove extension property (we specify file name directly)
|
||||
properties.remove(StreamConsumerSettings.PROP_FILE_EXTENSION);
|
||||
|
||||
consumer.initTransfer(
|
||||
dataContainer,
|
||||
settings,
|
||||
new IDataTransferConsumer.TransferParameters(processor.isBinaryFormat(), processor.isHTMLFormat()),
|
||||
exporter,
|
||||
properties);
|
||||
|
||||
DatabaseTransferProducer producer = new DatabaseTransferProducer(dataContainer, parameters.getFilter() == null ? null : parameters.getFilter().makeDataFilter());
|
||||
DatabaseProducerSettings producerSettings = new DatabaseProducerSettings();
|
||||
producerSettings.setExtractType(DatabaseProducerSettings.ExtractType.SINGLE_QUERY);
|
||||
producerSettings.setQueryRowCount(false);
|
||||
producerSettings.setOpenNewConnections(CommonUtils.getOption(parameters.getSettings(), "openNewConnection"));
|
||||
|
||||
producer.transferData(monitor, consumer, null, producerSettings, null);
|
||||
|
||||
consumer.finishTransfer(monitor, false);
|
||||
}
|
||||
}
|
||||
|
||||
+11
@@ -1,6 +1,7 @@
|
||||
package io.cloudbeaver.service.data.transfer;
|
||||
|
||||
import io.cloudbeaver.server.model.sql.WebSQLDataFilter;
|
||||
import org.jkiss.dbeaver.model.data.json.JSONUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -11,6 +12,16 @@ public class WebDataTransferParameters {
|
||||
private Map<String, Object> processorProperties;
|
||||
private WebSQLDataFilter filter;
|
||||
|
||||
public WebDataTransferParameters() {
|
||||
}
|
||||
|
||||
public WebDataTransferParameters(Map<String, Object> params) {
|
||||
this.processorId = JSONUtils.getString(params, "processorId");
|
||||
this.settings = JSONUtils.getObject(params, "settings");
|
||||
this.processorProperties = JSONUtils.getObject(params, "processorProperties");
|
||||
this.filter = new WebSQLDataFilter(JSONUtils.getObject(params, "filter"));
|
||||
}
|
||||
|
||||
public String getProcessorId() {
|
||||
return processorId;
|
||||
}
|
||||
|
||||
+38
-2
@@ -5,21 +5,30 @@ import io.cloudbeaver.server.CloudbeaverApplication;
|
||||
import io.cloudbeaver.server.CloudbeaverPlatform;
|
||||
import io.cloudbeaver.server.model.session.WebSession;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.tools.transfer.registry.DataTransferProcessorDescriptor;
|
||||
import org.jkiss.dbeaver.tools.transfer.registry.DataTransferRegistry;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
import org.jkiss.utils.IOUtils;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class WebDataTransferServlet extends HttpServlet {
|
||||
|
||||
private static final Log log = Log.getLog(WebDataTransferServlet.class);
|
||||
|
||||
private final CloudbeaverApplication application;
|
||||
private final WebDataTransferManager dtManager;
|
||||
|
||||
public WebDataTransferServlet(CloudbeaverApplication application) {
|
||||
public WebDataTransferServlet(CloudbeaverApplication application, WebDataTransferManager dtManager) {
|
||||
this.application = application;
|
||||
this.dtManager = dtManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -34,8 +43,35 @@ public class WebDataTransferServlet extends HttpServlet {
|
||||
if (webSession == null) {
|
||||
throw new DBWebException("No active session");
|
||||
}
|
||||
WebDataTransferSessionConfig dtConfig = WebDataTransferUtils.getSessionDataTransferConfig(webSession);
|
||||
WebDataTransferTaskConfig taskInfo = dtConfig.getTask(dataFileId);
|
||||
if (taskInfo == null) {
|
||||
throw new DBWebException("Session task '" + dataFileId + "' not found");
|
||||
}
|
||||
DataTransferProcessorDescriptor processor = DataTransferRegistry.getInstance().getProcessor(taskInfo.getParameters().getProcessorId());
|
||||
if (processor == null) {
|
||||
throw new DBWebException("Wrong data processor '" + taskInfo.getParameters().getProcessorId() + "'");
|
||||
}
|
||||
String fileName = taskInfo.getExportFileName();
|
||||
if (!CommonUtils.isEmpty(fileName)) {
|
||||
fileName += "." + WebDataTransferUtils.getProcessorFileExtension(processor);
|
||||
} else {
|
||||
fileName = taskInfo.getDataFileId();
|
||||
}
|
||||
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Not implemented");
|
||||
File dataFile = taskInfo.getDataFile();
|
||||
|
||||
response.setHeader("Content-Type", processor.getContentType());
|
||||
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
|
||||
response.setHeader("Content-Length", String.valueOf(dataFile.length()));
|
||||
|
||||
try (InputStream is = new FileInputStream(dataFile)) {
|
||||
IOUtils.copyStream(is, response.getOutputStream());
|
||||
}
|
||||
|
||||
dtConfig.removeTask(taskInfo);
|
||||
|
||||
//response.ok(HttpServletResponse.SC_BAD_REQUEST, "Not implemented");
|
||||
} catch (Exception e) {
|
||||
log.error(e);
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Error reading data: " + e.getMessage());
|
||||
|
||||
+27
-1
@@ -5,8 +5,34 @@ import java.util.Map;
|
||||
|
||||
public class WebDataTransferSessionConfig {
|
||||
|
||||
private Map<String, WebDataTransferTaskConfig> tasks = new HashMap<>();
|
||||
private final Map<String, WebDataTransferTaskConfig> tasks = new HashMap<>();
|
||||
|
||||
public WebDataTransferSessionConfig() {
|
||||
}
|
||||
|
||||
public WebDataTransferTaskConfig getTask(String dataFileId) {
|
||||
return tasks.get(dataFileId);
|
||||
}
|
||||
|
||||
public void addTask(WebDataTransferTaskConfig taskConfig) {
|
||||
synchronized (tasks) {
|
||||
tasks.put(taskConfig.getDataFileId(), taskConfig);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeTask(WebDataTransferTaskConfig taskConfig) {
|
||||
synchronized (tasks) {
|
||||
tasks.remove(taskConfig.getDataFileId());
|
||||
taskConfig.deleteFile();
|
||||
}
|
||||
}
|
||||
|
||||
public WebDataTransferSessionConfig deleteExportFiles() {
|
||||
synchronized (tasks) {
|
||||
tasks.values().forEach(WebDataTransferTaskConfig::deleteFile);
|
||||
tasks.clear();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
+2
-5
@@ -4,9 +4,7 @@ import io.cloudbeaver.server.model.WebPropertyInfo;
|
||||
import io.cloudbeaver.server.model.session.WebSession;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.dbeaver.model.meta.Property;
|
||||
import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor;
|
||||
import org.jkiss.dbeaver.tools.transfer.registry.DataTransferProcessorDescriptor;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -24,7 +22,7 @@ public class WebDataTransferStreamProcessor {
|
||||
|
||||
@Property
|
||||
public String getId() {
|
||||
return processor.getId();
|
||||
return processor.getFullId();
|
||||
}
|
||||
|
||||
@Property
|
||||
@@ -39,8 +37,7 @@ public class WebDataTransferStreamProcessor {
|
||||
|
||||
@Property
|
||||
public String getFileExtension() {
|
||||
DBPPropertyDescriptor extProperty = processor.getProperty("extension");
|
||||
return extProperty == null ? getAppFileExtension() : CommonUtils.toString(extProperty.getDefaultValue(), null);
|
||||
return WebDataTransferUtils.getProcessorFileExtension(processor);
|
||||
}
|
||||
|
||||
@Property
|
||||
|
||||
+37
-6
@@ -1,14 +1,45 @@
|
||||
package io.cloudbeaver.service.data.transfer;
|
||||
|
||||
import org.jkiss.dbeaver.tools.transfer.registry.DataTransferProcessorDescriptor;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
|
||||
import java.util.Map;
|
||||
import java.io.File;
|
||||
|
||||
public class WebDataTransferTaskConfig {
|
||||
|
||||
private String dataFileId;
|
||||
private DataTransferProcessorDescriptor processor;
|
||||
private Map<String, Object> settings;
|
||||
private Map<String, Object> processorProperties;
|
||||
private static final Log log = Log.getLog(WebDataTransferTaskConfig.class);
|
||||
|
||||
private File dataFile;
|
||||
private WebDataTransferParameters parameters;
|
||||
private String exportFileName;
|
||||
|
||||
public WebDataTransferTaskConfig(File dataFile, WebDataTransferParameters parameters) {
|
||||
this.dataFile = dataFile;
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public File getDataFile() {
|
||||
return dataFile;
|
||||
}
|
||||
|
||||
public String getDataFileId() {
|
||||
return dataFile.getName();
|
||||
}
|
||||
|
||||
public WebDataTransferParameters getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public String getExportFileName() {
|
||||
return exportFileName;
|
||||
}
|
||||
|
||||
public void setExportFileName(String exportFileName) {
|
||||
this.exportFileName = exportFileName;
|
||||
}
|
||||
|
||||
public void deleteFile() {
|
||||
if (!dataFile.delete()) {
|
||||
log.error("Error deleting export file " + dataFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -1,6 +1,10 @@
|
||||
package io.cloudbeaver.service.data.transfer;
|
||||
|
||||
import io.cloudbeaver.server.model.session.WebSession;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor;
|
||||
import org.jkiss.dbeaver.tools.transfer.registry.DataTransferProcessorDescriptor;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
|
||||
@@ -9,4 +13,13 @@ public class WebDataTransferUtils extends HttpServlet {
|
||||
private static final Log log = Log.getLog(WebDataTransferUtils.class);
|
||||
|
||||
|
||||
public static String getProcessorFileExtension(DataTransferProcessorDescriptor processor) {
|
||||
DBPPropertyDescriptor extProperty = processor.getProperty("extension");
|
||||
String ext = extProperty == null ? processor.getAppFileExtension() : CommonUtils.toString(extProperty.getDefaultValue(), null);
|
||||
return CommonUtils.isEmpty(ext) ? "data" : ext;
|
||||
}
|
||||
|
||||
public static WebDataTransferSessionConfig getSessionDataTransferConfig(WebSession session) {
|
||||
return session.getAttribute("dataTransfer", x -> new WebDataTransferSessionConfig(), WebDataTransferSessionConfig::deleteExportFiles);
|
||||
}
|
||||
}
|
||||
+13
-11
@@ -38,6 +38,11 @@ public class WebServiceDataTransfer implements DBWServiceGraphQL, DBWServiceServ
|
||||
|
||||
private WebDataTransferManager dtManager;
|
||||
|
||||
public WebServiceDataTransfer() {
|
||||
dtManager = new WebDataTransferManager();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeDefinitionRegistry getTypeDefinition() throws DBWebException {
|
||||
return WebServiceUtils.loadSchemaDefinition(getClass(), DT_SCHEMA_FILE_NAME);
|
||||
@@ -45,25 +50,21 @@ public class WebServiceDataTransfer implements DBWServiceGraphQL, DBWServiceServ
|
||||
|
||||
@Override
|
||||
public void bindWiring(DBWModel model) {
|
||||
dtManager = new WebDataTransferManager(model);
|
||||
model.getQueryType()
|
||||
.dataFetcher("dataTransferAvailableStreamProcessors",
|
||||
env -> dtManager.getAvailableStreamProcessors(getWebSession(model, env)))
|
||||
.dataFetcher("dataTransferExportDataFromContainer", env -> dtManager.dataTransferExportDataFromContainer(
|
||||
getWebSession(model, env),
|
||||
env.getArgument("connectionId"),
|
||||
DBWUtils.getSQLProcessor(model.getSessionManager(), env),
|
||||
env.getArgument("containerNodePath"),
|
||||
env.getArgument("parameters")
|
||||
new WebDataTransferParameters(env.getArgument("parameters"))
|
||||
))
|
||||
.dataFetcher("dataTransferExportDataFromResults", env -> dtManager.dataTransferExportDataFromResults(
|
||||
getWebSession(model, env),
|
||||
env.getArgument("connectionId"),
|
||||
env.getArgument("contextId"),
|
||||
DBWUtils.getSQLContext(model.getSessionManager(), env),
|
||||
env.getArgument("resultsId"),
|
||||
env.getArgument("parameters")
|
||||
new WebDataTransferParameters(env.getArgument("parameters"))
|
||||
))
|
||||
.dataFetcher("dataTransferRemoveDataFile", env -> dtManager.dataTransferRemoveDataFile(
|
||||
getWebSession(model, env),
|
||||
DBWUtils.getSQLProcessor(model.getSessionManager(), env),
|
||||
env.getArgument("dataFileId")
|
||||
))
|
||||
;
|
||||
@@ -76,7 +77,8 @@ public class WebServiceDataTransfer implements DBWServiceGraphQL, DBWServiceServ
|
||||
|
||||
@Override
|
||||
public void addServlets(CloudbeaverApplication application, ServletContextHandler servletContextHandler) {
|
||||
ServletHolder servletHolder = new ServletHolder("dataTransfer", new WebDataTransferServlet(application));
|
||||
servletContextHandler.addServlet(servletHolder, application.getServicesURI() + "data/*");
|
||||
servletContextHandler.addServlet(
|
||||
new ServletHolder("dataTransfer", new WebDataTransferServlet(application, dtManager)),
|
||||
application.getServicesURI() + "data/*");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user