dbeaver-corp/dbeaver-web#620 Data transfer: export + download

This commit is contained in:
serge-rider
2020-04-22 23:27:03 +03:00
parent 3858cb12fe
commit f83ab45181
14 changed files with 309 additions and 81 deletions
@@ -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
@@ -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
@@ -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");
@@ -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;
}
@@ -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");
@@ -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
}
@@ -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);
}
}
@@ -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;
}
@@ -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());
@@ -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;
}
}
@@ -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
@@ -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());
}
}
}
@@ -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);
}
}
@@ -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/*");
}
}