Skip to content

Commit

Permalink
Added configuration provider
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikita-Smirnov-Exactpro committed Oct 6, 2023
1 parent 665af82 commit c2b86df
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 21 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,7 @@ dependencies {
### 5.6.0-dev
#### Feature:
+ Added common microservice entry point
+ Added configuration provider to common factory

### 5.5.0-dev

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import com.exactpro.th2.common.metrics.PrometheusConfiguration;
import com.exactpro.th2.common.schema.box.configuration.BoxConfiguration;
import com.exactpro.th2.common.schema.configuration.ConfigurationManager;
import com.exactpro.th2.common.schema.configuration.impl.JsonConfigurationProvider;
import com.exactpro.th2.common.schema.cradle.CradleConfidentialConfiguration;
import com.exactpro.th2.common.schema.cradle.CradleNonConfidentialConfiguration;
import com.exactpro.th2.common.schema.dictionary.DictionaryType;
Expand All @@ -56,12 +57,8 @@
import com.exactpro.th2.common.schema.message.impl.rabbitmq.custom.RabbitCustomRouter;
import com.exactpro.th2.common.schema.message.impl.rabbitmq.transport.GroupBatch;
import com.exactpro.th2.common.schema.message.impl.rabbitmq.transport.TransportGroupBatchRouter;
import com.exactpro.th2.common.schema.strategy.route.json.RoutingStrategyModule;
import com.exactpro.th2.common.schema.util.Log4jConfigUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.kotlin.KotlinFeature;
import com.fasterxml.jackson.module.kotlin.KotlinModule;
import io.prometheus.client.exporter.HTTPServer;
import io.prometheus.client.hotspot.DefaultExports;
import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -108,23 +105,7 @@ public abstract class AbstractCommonFactory implements AutoCloseable {
protected static final Path LOG4J_PROPERTIES_DEFAULT_PATH = Path.of("/var/th2/config");
protected static final String LOG4J2_PROPERTIES_NAME = "log4j2.properties";

public static final ObjectMapper MAPPER = new ObjectMapper();

static {
MAPPER.registerModules(
new KotlinModule.Builder()
.withReflectionCacheSize(512)
.configure(KotlinFeature.NullToEmptyCollection, false)
.configure(KotlinFeature.NullToEmptyMap, false)
.configure(KotlinFeature.NullIsSameAsDefault, false)
.configure(KotlinFeature.SingletonSupport, false)
.configure(KotlinFeature.StrictNullChecks, false)
.build(),
new RoutingStrategyModule(MAPPER),
new JavaTimeModule()
);
}

public static final ObjectMapper MAPPER = JsonConfigurationProvider.MAPPER;
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractCommonFactory.class);
private final StringSubstitutor stringSubstitutor;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright 2023 Exactpro (Exactpro Systems Limited)
* 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.exactpro.th2.common.schema.configuration

interface IConfigurationProvider {
fun <T : Any> load(configClass: Class<T>, alias: String, default: () -> T): T
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright 2023 Exactpro (Exactpro Systems Limited)
* 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.exactpro.th2.common.schema.configuration.impl

import com.exactpro.th2.common.schema.configuration.IConfigurationProvider
import com.exactpro.th2.common.schema.strategy.route.json.RoutingStrategyModule
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import com.fasterxml.jackson.module.kotlin.KotlinFeature
import com.fasterxml.jackson.module.kotlin.KotlinModule
import mu.KotlinLogging
import org.apache.commons.text.StringSubstitutor
import java.nio.file.Files
import java.nio.file.Path
import java.util.concurrent.ConcurrentHashMap
import kotlin.io.path.exists
import kotlin.io.path.isDirectory

class JsonConfigurationProvider(
private val baseDir: Path
) : IConfigurationProvider {

init {
require(baseDir.isDirectory()) {
"The '$baseDir' base directory doesn't exist or isn't directory"
}
}

private val cache = ConcurrentHashMap<String, Any>()

@Suppress("UNCHECKED_CAST")
override fun <T : Any> load(configClass: Class<T>, alias: String, default: () -> T): T =
cache.computeIfAbsent(alias) {
val configPath = baseDir.resolve("${alias}.${EXTENSION}")
if (!configPath.exists()) {
K_LOGGER.debug { "'$configPath' file related to the '$alias' config alias doesn't exist" }
return@computeIfAbsent default()
}

val sourceContent = String(Files.readAllBytes(configPath))
K_LOGGER.info { "'$configPath' file related to the '$alias' config alias has source content $sourceContent" }
val content = SUBSTITUTOR.get().replace(sourceContent)
requireNotNull(MAPPER.readValue(content, configClass)) {
"Parsed format of the '$alias' config alias content can't be null"
}
}.also { value ->
check(configClass.isInstance(value)) {
"Stored configuration instance of $alias config alias mismatches, " +
"expected: ${configClass.canonicalName}, actual: ${value::class.java.canonicalName}"
}
} as T

companion object {
private const val EXTENSION = "json"

private val K_LOGGER = KotlinLogging.logger {}
private val SUBSTITUTOR: ThreadLocal<StringSubstitutor> = object : ThreadLocal<StringSubstitutor>() {
override fun initialValue(): StringSubstitutor = StringSubstitutor(System.getenv())
}

@JvmField
val MAPPER = ObjectMapper().apply {
registerModules(
KotlinModule.Builder()
.withReflectionCacheSize(512)
.configure(KotlinFeature.NullToEmptyCollection, false)
.configure(KotlinFeature.NullToEmptyMap, false)
.configure(KotlinFeature.NullIsSameAsDefault, false)
.configure(KotlinFeature.SingletonSupport, false)
.configure(KotlinFeature.StrictNullChecks, false)
.build(),
RoutingStrategyModule(this),
JavaTimeModule()
)
}
}
}

0 comments on commit c2b86df

Please sign in to comment.