diff --git a/server/bundles/io.cloudbeaver.server/schema/service.core.graphqls b/server/bundles/io.cloudbeaver.server/schema/service.core.graphqls index 00e668a2fc..039ebb7ff2 100644 --- a/server/bundles/io.cloudbeaver.server/schema/service.core.graphqls +++ b/server/bundles/io.cloudbeaver.server/schema/service.core.graphqls @@ -84,6 +84,7 @@ type ServerConfig { supportsWorkspaces: Boolean configurationMode: Boolean + developmentMode: Boolean supportedLanguages: [ ServerLanguage! ]! services: [ WebServiceConfig ] diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/WebServerConfig.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/WebServerConfig.java index d88f183e9a..91ab006a5f 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/WebServerConfig.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/model/WebServerConfig.java @@ -81,6 +81,11 @@ public class WebServerConfig { return application.isConfigurationMode(); } + @Property + public boolean isDevelopmentMode() { + return application.isDevelMode(); + } + @Property public WebServerLanguage[] getSupportedLanguages() { List langs = PlatformLanguageRegistry.getInstance().getLanguages(); diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java index 8100ccd933..ef911b8694 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java @@ -18,6 +18,7 @@ package io.cloudbeaver.server; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.InstanceCreator; import io.cloudbeaver.DBWSecurityController; import io.cloudbeaver.server.jetty.CBJettyServer; import org.eclipse.core.runtime.Platform; @@ -60,7 +61,7 @@ public class CBApplication extends BaseApplicationImpl { } private int serverPort = CBConstants.DEFAULT_SERVER_PORT; - private String serverName = CBConstants.DEFAULT_SERVER_NAME; + private String serverName = null; private String contentRoot = CBConstants.DEFAULT_CONTENT_ROOT; private String rootURI = CBConstants.DEFAULT_ROOT_URI; private String servicesURI = CBConstants.DEFAULT_SERVICES_URI; @@ -69,9 +70,12 @@ public class CBApplication extends BaseApplicationImpl { private String driversLocation = CBConstants.DEFAULT_DRIVERS_LOCATION; private File homeDirectory; - private Map productConfiguration = new HashMap<>(); - private CBAppConfig appConfiguration = new CBAppConfig(); - private CBDatabaseConfig databaseConfiguration = new CBDatabaseConfig(); + // Configurations + private final Map productConfiguration = new HashMap<>(); + private final CBAppConfig appConfiguration = new CBAppConfig(); + private final CBDatabaseConfig databaseConfiguration = new CBDatabaseConfig(); + + // Persistence private CBDatabase database; private CBSecurityController securityController; @@ -155,11 +159,20 @@ public class CBApplication extends BaseApplicationImpl { } try { loadConfiguration(configPath); + + File runtimeConfigFile = new File(new File(workspaceLocation, CBConstants.RUNTIME_DATA_DIR_NAME), CBConstants.RUNTIME_CONFIG_FILE_NAME); + if (runtimeConfigFile.exists()) { + log.debug("Runtime configuration [" + runtimeConfigFile.getAbsolutePath() + "]"); + parseConfiguration(runtimeConfigFile); + } } catch (Exception e) { log.error("Error parsing configuration", e); return null; } + configurationMode = CommonUtils.isEmpty(serverName); + //|| CommonUtils.isEmpty(databaseConfiguration.getUser()) || CommonUtils.isEmpty(databaseConfiguration.getPassword()); + final Runtime runtime = Runtime.getRuntime(); Location instanceLoc = Platform.getInstanceLocation(); @@ -198,12 +211,17 @@ public class CBApplication extends BaseApplicationImpl { } else { log.debug("\tProduction mode"); } + if (configurationMode) { + log.debug("\tServer is in configuration mode!"); + } - try { - initializeDatabase(); - } catch (Exception e) { - log.error("Error initializing database", e); - return null; + { + try { + initializeDatabase(); + } catch (Exception e) { + log.error("Error initializing database", e); + return null; + } } Thread shutdownThread = new Thread(() -> { @@ -236,7 +254,7 @@ public class CBApplication extends BaseApplicationImpl { } private void loadConfiguration(String configPath) { - log.debug("Using configuration " + configPath); + log.debug("Using configuration [" + configPath + "]"); File configFile = new File(configPath); if (!configFile.exists()) { @@ -259,31 +277,41 @@ public class CBApplication extends BaseApplicationImpl { homeDirectory = new File(homeFolder); String productConfigPath = null; - Gson gson = new GsonBuilder().setLenient().create(); + // Stupid way to populate existing objects but ok google (https://github.com/google/gson/issues/431) + InstanceCreator appConfigCreator = type -> appConfiguration; + InstanceCreator dbConfigCreator = type -> databaseConfiguration; + InstanceCreator dbPoolConfigCreator = type -> databaseConfiguration.getPool(); + + Gson gson = new GsonBuilder() + .setLenient() + .registerTypeAdapter(CBAppConfig.class, appConfigCreator) + .registerTypeAdapter(CBDatabaseConfig.class, dbConfigCreator) + .registerTypeAdapter(CBDatabaseConfig.Pool.class, dbPoolConfigCreator) + .create(); try (Reader reader = new InputStreamReader(new FileInputStream(configFile), StandardCharsets.UTF_8)) { Map configProps = JSONUtils.parseMap(gson, reader); Map serverConfig = JSONUtils.getObject(configProps, "server"); - serverPort = JSONUtils.getInteger(serverConfig, CBConstants.PARAM_SERVER_PORT, CBConstants.DEFAULT_SERVER_PORT); - serverName = JSONUtils.getString(serverConfig, CBConstants.PARAM_SERVER_NAME, CBConstants.DEFAULT_SERVER_NAME); + serverPort = JSONUtils.getInteger(serverConfig, CBConstants.PARAM_SERVER_PORT, serverPort); + serverName = JSONUtils.getString(serverConfig, CBConstants.PARAM_SERVER_NAME, serverName); contentRoot = getRelativePath( - JSONUtils.getString(serverConfig, CBConstants.PARAM_CONTENT_ROOT, CBConstants.DEFAULT_CONTENT_ROOT), homeFolder); - rootURI = JSONUtils.getString(serverConfig, CBConstants.PARAM_ROOT_URI, CBConstants.DEFAULT_ROOT_URI); - servicesURI = JSONUtils.getString(serverConfig, CBConstants.PARAM_SERVICES_URI, CBConstants.DEFAULT_SERVICES_URI); + JSONUtils.getString(serverConfig, CBConstants.PARAM_CONTENT_ROOT, contentRoot), homeFolder); + rootURI = JSONUtils.getString(serverConfig, CBConstants.PARAM_ROOT_URI, rootURI); + servicesURI = JSONUtils.getString(serverConfig, CBConstants.PARAM_SERVICES_URI, servicesURI); driversLocation = getRelativePath( - JSONUtils.getString(serverConfig, CBConstants.PARAM_DRIVERS_LOCATION, CBConstants.DEFAULT_DRIVERS_LOCATION), homeFolder); + JSONUtils.getString(serverConfig, CBConstants.PARAM_DRIVERS_LOCATION, driversLocation), homeFolder); workspaceLocation = getRelativePath( - JSONUtils.getString(serverConfig, CBConstants.PARAM_WORKSPACE_LOCATION, CBConstants.DEFAULT_WORKSPACE_LOCATION), homeFolder); + JSONUtils.getString(serverConfig, CBConstants.PARAM_WORKSPACE_LOCATION, workspaceLocation), homeFolder); - maxSessionIdleTime = JSONUtils.getLong(serverConfig, CBConstants.PARAM_SESSION_EXPIRE_PERIOD, CBConstants.MAX_SESSION_IDLE_TIME); + maxSessionIdleTime = JSONUtils.getLong(serverConfig, CBConstants.PARAM_SESSION_EXPIRE_PERIOD, maxSessionIdleTime); - develMode = JSONUtils.getBoolean(serverConfig, CBConstants.PARAM_DEVEL_MODE, false); + develMode = JSONUtils.getBoolean(serverConfig, CBConstants.PARAM_DEVEL_MODE, develMode); - appConfiguration = gson.fromJson( + gson.fromJson( gson.toJsonTree(JSONUtils.getObject(configProps, "app")), CBAppConfig.class); - databaseConfiguration = gson.fromJson( + gson.fromJson( gson.toJsonTree(JSONUtils.getObject(serverConfig, "database")), CBDatabaseConfig.class); productConfigPath = getRelativePath( @@ -299,10 +327,7 @@ public class CBApplication extends BaseApplicationImpl { } else { log.debug("Load product configuration from '" + productConfigFile.getAbsolutePath() + "'"); try (Reader reader = new InputStreamReader(new FileInputStream(productConfigFile), StandardCharsets.UTF_8)) { - - //gsonBuilder.registerTypeAdapter(Object.class, new JSONBestNumberObjectDeserializer()); - - productConfiguration = JSONUtils.parseMap(gson, reader); + productConfiguration.putAll(JSONUtils.parseMap(gson, reader)); } catch (Exception e) { log.error("Error reading product configuration", e); } diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBConstants.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBConstants.java index 43b93ea727..fede3115bc 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBConstants.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBConstants.java @@ -29,6 +29,8 @@ public class CBConstants { public static final DateFormat ISO_DATE_FORMAT = new SimpleDateFormat(DBConstants.DEFAULT_ISO_TIMESTAMP_FORMAT); public static final String DEFAULT_CONFIG_FILE_PATH = "/etc/cloudbeaver.conf"; + public static final String RUNTIME_DATA_DIR_NAME = ".data"; + public static final String RUNTIME_CONFIG_FILE_NAME = ".cloudbeaver.runtime.conf"; public static final String CLI_PARAM_WEB_CONFIG = "-web-config"; @@ -46,7 +48,7 @@ public class CBConstants { public static final String PARAM_DEVEL_MODE = "develMode"; public static final int DEFAULT_SERVER_PORT = 8080; - public static final String DEFAULT_SERVER_NAME = "CloudBeaver Web Server"; + //public static final String DEFAULT_SERVER_NAME = "CloudBeaver Web Server"; public static final String DEFAULT_CONTENT_ROOT = "/var/www/cloudbeaver"; public static final String DEFAULT_ROOT_URI = "/"; public static final String DEFAULT_SERVICES_URI = "/dbeaver/"; diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBDatabase.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBDatabase.java index 76c9d14657..9b90f91d95 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBDatabase.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBDatabase.java @@ -40,6 +40,7 @@ import org.jkiss.dbeaver.registry.DataSourceProviderRegistry; import org.jkiss.dbeaver.utils.ContentUtils; import org.jkiss.dbeaver.utils.GeneralUtils; import org.jkiss.dbeaver.utils.SystemVariablesResolver; +import org.jkiss.utils.Base64; import org.jkiss.utils.CommonUtils; import org.jkiss.utils.IOUtils; @@ -100,7 +101,8 @@ public class CBDatabase { if (!CommonUtils.isEmpty(databaseConfiguration.getUser())) { dbProperties.put(DBConstants.DATA_SOURCE_PROPERTY_USER, databaseConfiguration.getUser()); if (!CommonUtils.isEmpty(databaseConfiguration.getPassword())) { - dbProperties.put(DBConstants.DATA_SOURCE_PROPERTY_PASSWORD, databaseConfiguration.getPassword()); + dbProperties.put(DBConstants.DATA_SOURCE_PROPERTY_PASSWORD, + new String(Base64.decode(databaseConfiguration.getPassword()))); } }