From 6db3c8f6cf6084aa66f391f5fe5cc67bc42e3bc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=98=BF=E7=94=B7?= Date: Sat, 28 Oct 2023 01:10:00 +0800 Subject: [PATCH] Enable Support to get DB Username/Password from enivonment variable for jberet.properties #367 --- jberet-se/pom.xml | 4 ++ .../org/jberet/se/BatchSEEnvironment.java | 55 +++++++++++++++++++ .../org/jberet/se/BatchSEEnvironmentTest.java | 41 ++++++++++++++ .../src/test/resources/jberet.properties | 4 +- 4 files changed, 102 insertions(+), 2 deletions(-) diff --git a/jberet-se/pom.xml b/jberet-se/pom.xml index 7d113d200..7e190a0e7 100644 --- a/jberet-se/pom.xml +++ b/jberet-se/pom.xml @@ -83,6 +83,10 @@ SPDX-License-Identifier: EPL-2.0 false alphabetical + + foopass + foo + diff --git a/jberet-se/src/main/java/org/jberet/se/BatchSEEnvironment.java b/jberet-se/src/main/java/org/jberet/se/BatchSEEnvironment.java index 1670d7613..7a31e2edf 100644 --- a/jberet-se/src/main/java/org/jberet/se/BatchSEEnvironment.java +++ b/jberet-se/src/main/java/org/jberet/se/BatchSEEnvironment.java @@ -22,6 +22,9 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import jakarta.transaction.TransactionManager; import org.jberet.repository.JobRepository; @@ -35,6 +38,7 @@ import org.jberet.tools.ChainedJobXmlResolver; import org.jberet.tools.MetaInfBatchJobsJobXmlResolver; import org.jberet.tx.LocalTransactionManager; +import org.wildfly.security.manager.WildFlySecurityManager; /** * Represents the Java SE batch runtime environment and its services. @@ -58,6 +62,10 @@ public final class BatchSEEnvironment implements BatchEnvironment { private final JobXmlResolver jobXmlResolver; private final JobExecutor executor; + private static final String PROP_PATTERN_STR = "\\$\\{([0-9a-zA-Z_\\-]+)(:([0-9a-zA-Z_\\-]*))?\\}"; + + private static final Pattern PROP_PATTERN = Pattern.compile(PROP_PATTERN_STR); + static final String THREAD_POOL_TYPE = "thread-pool-type"; static final String THREAD_POOL_TYPE_CACHED = "Cached"; static final String THREAD_POOL_TYPE_FIXED = "Fixed"; @@ -72,12 +80,29 @@ public final class BatchSEEnvironment implements BatchEnvironment { static final String THREAD_POOL_REJECTION_POLICY = "thread-pool-rejection-policy"; static final String THREAD_FACTORY = "thread-factory"; + static final String DB_USER_KEY = "db-user"; + static final String DB_PASSWORD_KEY = "db-password"; + public BatchSEEnvironment() { configProperties = new Properties(); final InputStream configStream = getClassLoader().getResourceAsStream(CONFIG_FILE_NAME); if (configStream != null) { try { configProperties.load(configStream); + if (configProperties.getProperty(JOB_REPOSITORY_TYPE_KEY).equals(REPOSITORY_TYPE_JDBC) || + configProperties.getProperty(JOB_REPOSITORY_TYPE_KEY).equals(REPOSITORY_TYPE_MONGODB)) { + + String dbUser = configProperties.getProperty(DB_USER_KEY); + String dbPassword = configProperties.getProperty(DB_PASSWORD_KEY); + + if (dbUser != null) { + configProperties.setProperty(DB_USER_KEY, parseProp(dbUser)); + } + + if (dbPassword != null) { + configProperties.setProperty(DB_PASSWORD_KEY, parseProp(dbPassword)); + } + } } catch (final IOException e) { throw SEBatchMessages.MESSAGES.failToLoadConfig(e, CONFIG_FILE_NAME); } finally { @@ -103,6 +128,36 @@ protected int getMaximumPoolSize() { this.jobXmlResolver = new ChainedJobXmlResolver(userJobXmlResolvers, DEFAULT_JOB_XML_RESOLVERS); } + + /** + * This method will parse the value like: {@code ${DB_PASS:xyz}}. It will try to fetch the value of the + * environment variable {@code DB_PASS} firstly, and if it does not exist, the method will return the + * default value {@code xyz}. + * + * @param propVal The property value to parse. + * @return Get the parsed value of the {@code propVal}. + */ + static String parseProp(String propVal) { + Matcher matcher = PROP_PATTERN.matcher(propVal); + if (matcher.matches()) { + matcher.reset(); + if (matcher.find()) { + String prop = matcher.group(1); + String defaultVal = matcher.group(3); + String retVal = WildFlySecurityManager.getEnvPropertyPrivileged(prop, defaultVal); + if (retVal == null && defaultVal != null) { + return defaultVal; + } else { + return retVal; + } + } else { + return propVal; + } + } else { + return propVal; + } + } + @Override public ClassLoader getClassLoader() { ClassLoader cl = Thread.currentThread().getContextClassLoader(); diff --git a/jberet-se/src/test/java/org/jberet/se/BatchSEEnvironmentTest.java b/jberet-se/src/test/java/org/jberet/se/BatchSEEnvironmentTest.java index 91a0b9535..f4fc61e4c 100644 --- a/jberet-se/src/test/java/org/jberet/se/BatchSEEnvironmentTest.java +++ b/jberet-se/src/test/java/org/jberet/se/BatchSEEnvironmentTest.java @@ -18,6 +18,7 @@ import java.util.concurrent.TimeUnit; import jakarta.batch.operations.BatchRuntimeException; +import org.jberet.repository.JdbcRepository; import org.junit.Assert; import org.junit.Test; @@ -141,6 +142,46 @@ public void testCreateThreadPoolExecutor() throws Exception { } } + @Test + public void testResolveDbProps() { + BatchSEEnvironment batchSEObject = new BatchSEEnvironment(); + Assert.assertEquals("foopass", + batchSEObject + .getBatchConfigurationProperties() + .getProperty(org.jberet.repository.JdbcRepository.DB_PASSWORD_KEY)); + + Assert.assertEquals("foouser", + batchSEObject + .getBatchConfigurationProperties() + .getProperty(JdbcRepository.DB_USER_KEY)); + } + + @Test + public void testPropParsings() { + String p1 = "${FOO:bar}"; + String p2 = "${FOO}"; + String p3 = "${BAR:defaultVal}"; + String p4 = "${INVALID"; + String p5 = "$INVALID}"; + String p6 = "${{INVALID}"; + String p7 = "${INVALID}}"; + String p8 = "${BAR:}"; + String p9 = "${}"; + String p10 = "${BAR}"; + + + Assert.assertEquals("foo", BatchSEEnvironment.parseProp(p1)); + Assert.assertEquals("foo", BatchSEEnvironment.parseProp(p2)); + Assert.assertEquals("defaultVal", BatchSEEnvironment.parseProp(p3)); + Assert.assertEquals("${INVALID", BatchSEEnvironment.parseProp(p4)); + Assert.assertEquals("$INVALID}", BatchSEEnvironment.parseProp(p5)); + Assert.assertEquals("${{INVALID}", BatchSEEnvironment.parseProp(p6)); + Assert.assertEquals("${INVALID}}", BatchSEEnvironment.parseProp(p7)); + Assert.assertEquals("", BatchSEEnvironment.parseProp(p8)); + Assert.assertEquals("${}", BatchSEEnvironment.parseProp(p9)); + Assert.assertNull(BatchSEEnvironment.parseProp(p10)); + } + private ThreadPoolExecutor verifyThreadPool(final int coreSize, final int maxSize, final long keepAliveTime, diff --git a/jberet-se/src/test/resources/jberet.properties b/jberet-se/src/test/resources/jberet.properties index c6a453725..d47646713 100644 --- a/jberet-se/src/test/resources/jberet.properties +++ b/jberet-se/src/test/resources/jberet.properties @@ -17,8 +17,8 @@ infinispan-xml = # Use the target directory to store the DB db-url = jdbc:h2:./target/jberet-repo #db-url = mongodb://localhost/testData -db-user = -db-password = +db-user = ${NONE:foouser} +db-password = ${DB_PASS} db-properties = # Optional, prefix and suffix for jdbc job repository database table names.