diff --git a/components/xnwh/pools/DefaultConnectionPoolTypes/build.xml b/components/xnwh/pools/DefaultConnectionPoolTypes/build.xml index bf73f7be4..564282399 100644 --- a/components/xnwh/pools/DefaultConnectionPoolTypes/build.xml +++ b/components/xnwh/pools/DefaultConnectionPoolTypes/build.xml @@ -23,7 +23,7 @@ - + diff --git a/components/xnwh/pools/DefaultConnectionPoolTypes/pom.xml b/components/xnwh/pools/DefaultConnectionPoolTypes/pom.xml index 642e69c0f..57af5ea71 100644 --- a/components/xnwh/pools/DefaultConnectionPoolTypes/pom.xml +++ b/components/xnwh/pools/DefaultConnectionPoolTypes/pom.xml @@ -27,7 +27,7 @@ 4.0.0 com.gip.xyna DefaultConnectionPoolTypes - 1.0.0 + 1.0.1 jar UTF-8 diff --git a/components/xnwh/pools/DefaultConnectionPoolTypes/src/com/gip/xyna/xnwh/pools/MySQLPoolType.java b/components/xnwh/pools/DefaultConnectionPoolTypes/src/com/gip/xyna/xnwh/pools/MySQLPoolType.java index 43beb6880..f2ec92017 100644 --- a/components/xnwh/pools/DefaultConnectionPoolTypes/src/com/gip/xyna/xnwh/pools/MySQLPoolType.java +++ b/components/xnwh/pools/DefaultConnectionPoolTypes/src/com/gip/xyna/xnwh/pools/MySQLPoolType.java @@ -1,6 +1,6 @@ /* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * Copyright 2022 Xyna GmbH, Germany + * Copyright 2024 Xyna GmbH, Germany * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,7 @@ import java.sql.Connection; import java.sql.SQLException; import java.util.List; +import java.util.Optional; import java.util.concurrent.CountDownLatch; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.SynchronousQueue; @@ -38,11 +39,13 @@ import com.gip.xyna.utils.db.ConnectionPool.NoConnectionAvailableException.Reason; import com.gip.xyna.utils.db.ConnectionPool.NoConnectionAvailableReasonDetector; import com.gip.xyna.utils.db.DBConnectionData; +import com.gip.xyna.utils.db.DBConnectionData.DBConnectionDataBuilder; import com.gip.xyna.utils.db.pool.ConnectionBuildStrategy; import com.gip.xyna.utils.db.pool.DefaultValidationStrategy; import com.gip.xyna.utils.db.pool.ValidationStrategy; import com.gip.xyna.utils.misc.Documentation; import com.gip.xyna.utils.misc.StringParameter; +import com.gip.xyna.utils.misc.EnvironmentVariable.StringEnvironmentVariable; import com.gip.xyna.utils.timing.Duration; import com.gip.xyna.xmcp.PluginDescription; import com.gip.xyna.xmcp.PluginDescription.ParameterUsage; @@ -87,8 +90,29 @@ public class MySQLPoolType extends ConnectionPoolType { defaultValue(Duration.valueOf("10 s")). build(); - public static final List> additionalParameters = - StringParameter.asList( CONNECT_TIMEOUT, SOCKET_TIMEOUT, VALIDATION_TIMEOUT ); + public static final StringParameter USERNAME_ENV = StringParameter + .typeEnvironmentVariable(StringEnvironmentVariable.class, "usernameEnv") + .label("Username environment variable.") + .documentation(Documentation.en("Name of the environment variable containing the db username.") + .de("Name der Umgebungsvariable, die den DB Nutzernamen enthält.").build()) + .optional().build(); + + public static final StringParameter PASSWORD_ENV = StringParameter + .typeEnvironmentVariable(StringEnvironmentVariable.class, "passwordEnv") + .label("Password environment variable.") + .documentation(Documentation.en("Name of the environment variable containing the db password.") + .de("Name der Umgebungsvariable, die das DB Passwort enthält.").build()) + .optional().build(); + + public static final StringParameter CONNECT_ENV = StringParameter + .typeEnvironmentVariable(StringEnvironmentVariable.class, "connectStringEnv") + .label("Connectstring environment variable.") + .documentation(Documentation.en("Name of the environment variable containing the JDBC connect string.") + .de("Name der Umgebungsvariable mit den JDBC Verbindungsdaten.").build()) + .optional().build(); + + public static final List> additionalParameters = StringParameter.asList(CONNECT_TIMEOUT, + SOCKET_TIMEOUT, VALIDATION_TIMEOUT, USERNAME_ENV, PASSWORD_ENV, CONNECT_ENV); private PluginDescription pluginDescription; @@ -168,16 +192,7 @@ public PluginDescription getPluginDescription() { public ConnectionBuildStrategy createConnectionBuildStrategy(TypedConnectionPoolParameter cpp) { Duration connectTimeout = CONNECT_TIMEOUT.getFromMap(cpp.getAdditionalParams()); Duration socketTimeout = SOCKET_TIMEOUT.getFromMap(cpp.getAdditionalParams()); - DBConnectionData dbdata = - DBConnectionData.newDBConnectionData(). - user(cpp.getUser()).password(cpp.getPassword()).url(cpp.getConnectString()) - .connectTimeoutInSeconds((int)connectTimeout.getDuration(TimeUnit.SECONDS)) - .socketTimeoutInSeconds((int)socketTimeout.getDuration(TimeUnit.SECONDS)) - .classLoaderToLoadDriver(MySQLPoolType.class.getClassLoader()) // enforcing the connector jar to be stored in userlib - .property("rewriteBatchedStatements", "true") - .build(); - - return new MySQLConnectionBuildStrategy(dbdata, (int)connectTimeout.getDuration(TimeUnit.SECONDS) ); + return new MySQLConnectionBuildStrategy(cpp, (int)connectTimeout.getDuration(TimeUnit.SECONDS), (int)socketTimeout.getDuration(TimeUnit.SECONDS) ); } @@ -191,16 +206,55 @@ public ValidationStrategy createValidationStrategy(TypedConnectionPoolParameter public static class MySQLConnectionBuildStrategy implements ConnectionBuildStrategy { private static ThreadPoolExecutor threadpool = new ThreadPoolExecutor(1, 1000, 10, TimeUnit.SECONDS, new SynchronousQueue()); + private TypedConnectionPoolParameter tcpp; private DBConnectionData dbdata; private int connectTimeout; + private int socketTimeout; private String poolId; - public MySQLConnectionBuildStrategy(DBConnectionData dbdata, int connectTimeout) { - this.dbdata = dbdata; + private final Optional userEnv; + private final Optional pwdEnv; + private final Optional connectStringEnv; + + public MySQLConnectionBuildStrategy(TypedConnectionPoolParameter tcpp, int connectTimeout, int socketTimeout) { + this.tcpp = tcpp; + this.dbdata = null; this.connectTimeout = connectTimeout; + this.socketTimeout = socketTimeout; + + userEnv = Optional + .ofNullable(USERNAME_ENV.getFromMap(tcpp.getAdditionalParams())); + pwdEnv = Optional + .ofNullable(PASSWORD_ENV.getFromMap(tcpp.getAdditionalParams())); + connectStringEnv = Optional + .ofNullable(CONNECT_ENV.getFromMap(tcpp.getAdditionalParams())); + } + + private void updateDBConnectData() { + String user = userEnv.flatMap(u -> u.getValue()).filter(s -> !s.isEmpty()).orElse(tcpp.getUser()).trim(); + String pwd = pwdEnv.flatMap(p -> p.getValue()).filter(s -> !s.isEmpty()).orElse(tcpp.getPassword()).trim(); + String connString = connectStringEnv.flatMap(c -> c.getValue()).filter(s -> !s.isEmpty()) + .orElse(tcpp.getConnectString()).trim(); + + if (dbdata == null) { + dbdata = DBConnectionData.newDBConnectionData().user(user).password(pwd).url(connString) + .connectTimeoutInSeconds(connectTimeout) + .socketTimeoutInSeconds(socketTimeout) + .classLoaderToLoadDriver(MySQLPoolType.class.getClassLoader()) // enforcing the connector jar to be stored + // in userlib + .property("rewriteBatchedStatements", "true") + .build(); + } else { + if (dbdata.getUrl().equals(connString) && dbdata.getUser().equals(user) && dbdata.getPassword().equals(pwd)) + return; + + dbdata = (new DBConnectionDataBuilder(dbdata)).user(user).password(pwd).url(connString).build(); + } } public Connection createNewConnection() { + updateDBConnectData(); + Connection con = createNewConnectionInternal(); if (con == null) { throw new RuntimeException("Could not create connection but returned null."); diff --git a/components/xnwh/pools/DefaultConnectionPoolTypes/src/com/gip/xyna/xnwh/pools/OraclePoolType.java b/components/xnwh/pools/DefaultConnectionPoolTypes/src/com/gip/xyna/xnwh/pools/OraclePoolType.java index 98c36010d..61aac4739 100644 --- a/components/xnwh/pools/DefaultConnectionPoolTypes/src/com/gip/xyna/xnwh/pools/OraclePoolType.java +++ b/components/xnwh/pools/DefaultConnectionPoolTypes/src/com/gip/xyna/xnwh/pools/OraclePoolType.java @@ -21,6 +21,7 @@ import java.sql.Connection; import java.sql.SQLException; import java.util.List; +import java.util.Optional; import java.util.concurrent.TimeUnit; import org.apache.log4j.Logger; @@ -30,11 +31,13 @@ import com.gip.xyna.utils.db.ConnectionPool.NoConnectionAvailableException.Reason; import com.gip.xyna.utils.db.ConnectionPool.NoConnectionAvailableReasonDetector; import com.gip.xyna.utils.db.DBConnectionData; +import com.gip.xyna.utils.db.DBConnectionData.DBConnectionDataBuilder; import com.gip.xyna.utils.db.pool.ConnectionBuildStrategy; import com.gip.xyna.utils.db.pool.FastValidationStrategy; import com.gip.xyna.utils.db.pool.ValidationStrategy; import com.gip.xyna.utils.misc.Documentation; import com.gip.xyna.utils.misc.StringParameter; +import com.gip.xyna.utils.misc.EnvironmentVariable.StringEnvironmentVariable; import com.gip.xyna.utils.timing.Duration; import com.gip.xyna.xmcp.PluginDescription; import com.gip.xyna.xmcp.PluginDescription.ParameterUsage; @@ -87,9 +90,30 @@ public class OraclePoolType extends ConnectionPoolType { build()). defaultValue(false). build(); - - public static final List> additionalParameters = - StringParameter.asList( CONNECT_TIMEOUT, SOCKET_TIMEOUT, VALIDATION_TIMEOUT, DURABLE_STATEMENT_CACHE ); + + public static final StringParameter USERNAME_ENV = StringParameter + .typeEnvironmentVariable(StringEnvironmentVariable.class, "usernameEnv") + .label("Username environment variable.") + .documentation(Documentation.en("Name of the environment variable containing the db username.") + .de("Name der Umgebungsvariable, die den DB Nutzernamen enthält.").build()) + .optional().build(); + + public static final StringParameter PASSWORD_ENV = StringParameter + .typeEnvironmentVariable(StringEnvironmentVariable.class, "passwordEnv") + .label("Password environment variable.") + .documentation(Documentation.en("Name of the environment variable containing the db password.") + .de("Name der Umgebungsvariable, die das DB Passwort enthält.").build()) + .optional().build(); + + public static final StringParameter CONNECT_ENV = StringParameter + .typeEnvironmentVariable(StringEnvironmentVariable.class, "connectStringEnv") + .label("Connectstring environment variable.") + .documentation(Documentation.en("Name of the environment variable containing the JDBC connect string.") + .de("Name der Umgebungsvariable mit den JDBC Verbindungsdaten.").build()) + .optional().build(); + + public static final List> additionalParameters = StringParameter.asList(CONNECT_TIMEOUT, + SOCKET_TIMEOUT, VALIDATION_TIMEOUT, DURABLE_STATEMENT_CACHE, USERNAME_ENV, PASSWORD_ENV, CONNECT_ENV); private PluginDescription pluginDescription; @@ -121,32 +145,65 @@ public ConnectionBuildStrategy createConnectionBuildStrategy(TypedConnectionPool Duration connectTimeout = CONNECT_TIMEOUT.getFromMap(cpp.getAdditionalParams()); Duration socketTimeout = SOCKET_TIMEOUT.getFromMap(cpp.getAdditionalParams()); Boolean useDurableStatementCache = DURABLE_STATEMENT_CACHE.getFromMap(cpp.getAdditionalParams()); - - DBConnectionData dbdata = - DBConnectionData.newDBConnectionData(). - user(cpp.getUser()).password(cpp.getPassword()).url(cpp.getConnectString()) - .connectTimeoutInSeconds((int)connectTimeout.getDuration(TimeUnit.SECONDS)) - .socketTimeoutInSeconds((int)socketTimeout.getDuration(TimeUnit.SECONDS)) - .classLoaderToLoadDriver(OraclePoolType.class.getClassLoader()) // enforcing the connector jar to be stored in userlib - .property("rewriteBatchedStatements", "true") - .build(); - - return new OracleConnectionBuildStrategy(dbdata, useDurableStatementCache); + + return new OracleConnectionBuildStrategy(cpp, useDurableStatementCache, + (int) connectTimeout.getDuration(TimeUnit.SECONDS), (int) socketTimeout.getDuration(TimeUnit.SECONDS)); } public static class OracleConnectionBuildStrategy implements ConnectionBuildStrategy { + private TypedConnectionPoolParameter tcpp; private DBConnectionData dbdata; + private int connectTimeout; + private int socketTimeout; private boolean useDurableStatementCache; private String poolId; - public OracleConnectionBuildStrategy(DBConnectionData dbdata, boolean useDurableStatementCache) { - this.dbdata = dbdata; + private final Optional userEnv; + private final Optional pwdEnv; + private final Optional connectStringEnv; + + public OracleConnectionBuildStrategy(TypedConnectionPoolParameter tcpp, boolean useDurableStatementCache, int connectTimeout, int socketTimeout) { + this.tcpp = tcpp; + this.socketTimeout = socketTimeout; + this.connectTimeout = connectTimeout; + this.dbdata = null; this.useDurableStatementCache = useDurableStatementCache; + + userEnv = Optional + .ofNullable(USERNAME_ENV.getFromMap(tcpp.getAdditionalParams())); + pwdEnv = Optional + .ofNullable(PASSWORD_ENV.getFromMap(tcpp.getAdditionalParams())); + connectStringEnv = Optional + .ofNullable(CONNECT_ENV.getFromMap(tcpp.getAdditionalParams())); + } + + private void updateDBConnectData() { + String user = userEnv.flatMap(u -> u.getValue()).filter(s -> !s.isEmpty()).orElse(tcpp.getUser()).trim(); + String pwd = pwdEnv.flatMap(p -> p.getValue()).filter(s -> !s.isEmpty()).orElse(tcpp.getPassword()).trim(); + String connString = connectStringEnv.flatMap(c -> c.getValue()).filter(s -> !s.isEmpty()) + .orElse(tcpp.getConnectString()).trim(); + + if (dbdata == null) { + dbdata = DBConnectionData.newDBConnectionData().user(user).password(pwd).url(connString) + .connectTimeoutInSeconds(connectTimeout) + .socketTimeoutInSeconds(socketTimeout) + .classLoaderToLoadDriver(OraclePoolType.class.getClassLoader()) // enforcing the connector jar to be stored + // in userlib + .property("rewriteBatchedStatements", "true") + .build(); + } else { + if (dbdata.getUrl().equals(connString) && dbdata.getUser().equals(user) && dbdata.getPassword().equals(pwd)) + return; + + dbdata = (new DBConnectionDataBuilder(dbdata)).user(user).password(pwd).url(connString).build(); + } } public Connection createNewConnection() { + updateDBConnectData(); + try { Connection con = dbdata.createConnection(); if (useDurableStatementCache) { diff --git a/components/xnwh/pools/MockConnectionPoolTypes/build.xml b/components/xnwh/pools/MockConnectionPoolTypes/build.xml index 3e164463e..55af5fab3 100644 --- a/components/xnwh/pools/MockConnectionPoolTypes/build.xml +++ b/components/xnwh/pools/MockConnectionPoolTypes/build.xml @@ -23,7 +23,7 @@ - + diff --git a/components/xnwh/pools/MockConnectionPoolTypes/pom.xml b/components/xnwh/pools/MockConnectionPoolTypes/pom.xml index d649f6867..92f47ed33 100644 --- a/components/xnwh/pools/MockConnectionPoolTypes/pom.xml +++ b/components/xnwh/pools/MockConnectionPoolTypes/pom.xml @@ -27,7 +27,7 @@ 4.0.0 com.gip.xyna MockConnectionPoolTypes - 1.0.0 + 1.0.1 jar UTF-8 diff --git a/components/xnwh/pools/MockConnectionPoolTypes/src/com/gip/xyna/xnwh/pools/mock/MockMySQLPoolType.java b/components/xnwh/pools/MockConnectionPoolTypes/src/com/gip/xyna/xnwh/pools/mock/MockMySQLPoolType.java index abac69806..44fba5618 100644 --- a/components/xnwh/pools/MockConnectionPoolTypes/src/com/gip/xyna/xnwh/pools/mock/MockMySQLPoolType.java +++ b/components/xnwh/pools/MockConnectionPoolTypes/src/com/gip/xyna/xnwh/pools/mock/MockMySQLPoolType.java @@ -28,6 +28,7 @@ import com.gip.xyna.utils.db.pool.ValidationStrategy; import com.gip.xyna.utils.misc.Documentation; import com.gip.xyna.utils.misc.StringParameter; +import com.gip.xyna.utils.misc.EnvironmentVariable.StringEnvironmentVariable; import com.gip.xyna.utils.timing.Duration; import com.gip.xyna.xmcp.PluginDescription; import com.gip.xyna.xmcp.PluginDescription.ParameterUsage; @@ -70,8 +71,29 @@ public class MockMySQLPoolType extends ConnectionPoolType { defaultValue(Duration.valueOf("10 s")). build(); - public static final List> additionalParameters = - StringParameter.asList( CONNECT_TIMEOUT, SOCKET_TIMEOUT, VALIDATION_TIMEOUT ); + public static final StringParameter USERNAME_ENV = StringParameter + .typeEnvironmentVariable(StringEnvironmentVariable.class, "usernameEnv") + .label("Username environment variable.") + .documentation(Documentation.en("Name of the environment variable containing the db username.") + .de("Name der Umgebungsvariable, die den DB Nutzernamen enthält.").build()) + .optional().build(); + + public static final StringParameter PASSWORD_ENV = StringParameter + .typeEnvironmentVariable(StringEnvironmentVariable.class, "passwordEnv") + .label("Password environment variable.") + .documentation(Documentation.en("Name of the environment variable containing the db password.") + .de("Name der Umgebungsvariable, die das DB Passwort enthält.").build()) + .optional().build(); + + public static final StringParameter CONNECT_ENV = StringParameter + .typeEnvironmentVariable(StringEnvironmentVariable.class, "connectStringEnv") + .label("Connectstring environment variable.") + .documentation(Documentation.en("Name of the environment variable containing the JDBC connect string.") + .de("Name der Umgebungsvariable mit den JDBC Verbindungsdaten.").build()) + .optional().build(); + + public static final List> additionalParameters = StringParameter.asList(CONNECT_TIMEOUT, + SOCKET_TIMEOUT, VALIDATION_TIMEOUT, USERNAME_ENV, PASSWORD_ENV, CONNECT_ENV); private PluginDescription pluginDescription; diff --git a/installation/build.sh b/installation/build.sh index 5c9c438cb..9b6291c53 100755 --- a/installation/build.sh +++ b/installation/build.sh @@ -152,7 +152,7 @@ build_conpooltypes() { echo "building connectionpooltypes..." cd $SCRIPT_DIR/build ant -Doracle.home=/tmp conpooltypes - mvn install:install-file -Dfile=../../common/lib/xyna/DefaultConnectionPoolTypes-1.0.0.jar -DpomFile=../../components/xnwh/pools/DefaultConnectionPoolTypes/pom.xml + mvn install:install-file -Dfile=../../common/lib/xyna/DefaultConnectionPoolTypes-1.0.1.jar -DpomFile=../../components/xnwh/pools/DefaultConnectionPoolTypes/pom.xml } build_persistencelayers() { diff --git a/installation/build/pom.xml b/installation/build/pom.xml index 16d39d94b..5cb1fc8e4 100644 --- a/installation/build/pom.xml +++ b/installation/build/pom.xml @@ -71,7 +71,7 @@ com.gip.xyna DefaultConnectionPoolTypes - 1.0.0 + 1.0.1 com.gip.xyna diff --git a/server/src/com/gip/xyna/utils/misc/EnvironmentVariable.java b/server/src/com/gip/xyna/utils/misc/EnvironmentVariable.java new file mode 100644 index 000000000..67947304b --- /dev/null +++ b/server/src/com/gip/xyna/utils/misc/EnvironmentVariable.java @@ -0,0 +1,176 @@ +/* + * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Copyright 2024 Xyna GmbH, Germany + * + * 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 com.gip.xyna.utils.misc; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Optional; + +import org.apache.log4j.Logger; +import com.gip.xyna.CentralFactoryLogging; + +public abstract class EnvironmentVariable { + + protected final static Logger logger = CentralFactoryLogging.getLogger(EnvironmentVariable.class); + + private final String varName; + private boolean isFile; + + public EnvironmentVariable(String varName) { + this.varName = varName; + this.isFile = false; + } + + public EnvironmentVariable(String varName, boolean isFilePath) { + this.varName = varName; + this.isFile = isFilePath; + } + + public abstract Optional getValue(); + + public void setIsFile() { + this.isFile = true; + } + + protected Optional readValue() { + try { + if (isFilePath()) { + return Optional.of(readValueFromFile(readValueFromEnv())); + } else { + return Optional.ofNullable(readValueFromEnv()); + } + } catch (IOException e) { + logger.error("Error reading from file in environment variable '" + varName + "'': " + e.getMessage()); + return Optional.empty(); + } + } + + protected String readValueFromFile(String filePath) throws IOException { + if (filePath == null) + throw new IOException("no filePath available."); + + return Files.readString(Paths.get(filePath)); + } + + protected String readValueFromEnv() { + return System.getenv(varName); + } + + protected boolean isFilePath() { + return isFile || varName.toLowerCase().endsWith("_file"); + } + + public String toString() { + return "EnvironmentVariale '" + varName + "' isFile: " + isFilePath(); + } + + public String getVarName() { + return varName; + } + + public static class StringEnvironmentVariable extends EnvironmentVariable { + + StringEnvironmentVariable(String varName) { + super(varName); + } + + StringEnvironmentVariable(String varName, boolean isFilePath) { + super(varName, isFilePath); + } + + @Override + public Optional getValue() { + return readValue(); + } + } + + public static class IntegerEnvironmentVariable extends EnvironmentVariable { + IntegerEnvironmentVariable(String varName) { + super(varName); + } + + IntegerEnvironmentVariable(String varName, boolean isFilePath) { + super(varName, isFilePath); + } + + @Override + public Optional getValue() { + return readValue().flatMap(value -> { + try { + return Optional.of(Integer.parseInt(value)); + } catch (NumberFormatException e) { + if (isFilePath()) + logger.error( + "Error parsing integer value from file from variable: '" + getVarName() + "'" + + e.getMessage()); + else + logger.error( + "Error parsing integer value from variable: '" + getVarName() + "'" + e.getMessage()); + return Optional.empty(); + } + }); + } + } + + public static class DoubleEnvironmentVariable extends EnvironmentVariable { + DoubleEnvironmentVariable(String varName) { + super(varName); + } + + DoubleEnvironmentVariable(String varName, boolean isFilePath) { + super(varName, isFilePath); + } + + @Override + public Optional getValue() { + return readValue().flatMap(value -> { + try { + return Optional.of(Double.parseDouble(value)); + } catch (NumberFormatException e) { + if (isFilePath()) + logger.error( + "Error parsing double value from file from variable: '" + getVarName() + "'" + + e.getMessage()); + else + logger.error( + "Error parsing double value from variable: '" + getVarName() + "'" + e.getMessage()); + return Optional.empty(); + } + }); + } + } + + public static class BooleanEnvironmentVariable extends EnvironmentVariable { + BooleanEnvironmentVariable(String varName) { + super(varName); + } + + BooleanEnvironmentVariable(String varName, boolean isFilePath) { + super(varName, isFilePath); + } + + @Override + public Optional getValue() { + return readValue().flatMap(value -> { + return Optional.of(Boolean.parseBoolean(value)); + }); + } + } + +} \ No newline at end of file diff --git a/server/src/com/gip/xyna/utils/misc/StringParameter.java b/server/src/com/gip/xyna/utils/misc/StringParameter.java index ef40842a8..2adfb0bc2 100644 --- a/server/src/com/gip/xyna/utils/misc/StringParameter.java +++ b/server/src/com/gip/xyna/utils/misc/StringParameter.java @@ -649,6 +649,11 @@ public static StringParameterBuilder typeString(String name) { return spb.name(name); } + public static > StringParameterBuilder typeEnvironmentVariable(Class type, String name) { + StringParameterBuilder spb = new StringParameterBuilder( new StringParameterEnvironmentVariable(type) ); + return spb.name(name); + } + public static > StringParameterBuilder typeEnum(Class enumClass, String name) { StringParameterBuilder spb = new StringParameterBuilder( new StringParameterEnum(enumClass) ); return spb.name(name); @@ -1097,6 +1102,36 @@ public Class getTypeClass() { return Boolean.class; } } + + public static class StringParameterEnvironmentVariable> extends StringParameter { + private static final long serialVersionUID = 1L; + + private final Class baseType; + + StringParameterEnvironmentVariable(Class baseType) { + this.baseType = baseType; + } + + public E parseString(String string) { + try { + return baseType.getDeclaredConstructor(String.class).newInstance(string); + } catch (ReflectiveOperationException e) { + throw new RuntimeException("Error creating instance of " + baseType.getName(), e); + } + } + + public E parseObject(Object object) { + return (E) object; + } + + public String asString(E value) { + return value.getVarName(); + } + + public Class getTypeClass() { + return baseType; + } + } public static abstract class StringParameterWithEnum> extends StringParameter {