From c6e0ef5c9b3fd61df4d41a87373c7eee3c7d5727 Mon Sep 17 00:00:00 2001 From: Loes Immens Date: Mon, 28 Oct 2024 12:35:14 +0100 Subject: [PATCH] FDP-2728: formatted --- README.md | 2 +- .../kotlin/org/gxf/soapbridge/EndToEndTest.kt | 68 +++++++++---------- .../factories/HostnameVerifierFactory.java | 8 +-- .../gxf/soapbridge/SoapBridgeApplication.kt | 7 +- .../configuration/SecurityConfiguration.kt | 28 +++----- .../configuration/kafka/KafkaConfiguration.kt | 9 +-- .../SecurityConfigurationProperties.kt | 18 ++--- .../properties/SoapConfigurationProperties.kt | 23 +++---- .../exceptions/ProxyMessageException.kt | 2 - .../listeners/ProxyRequestKafkaListener.kt | 3 +- .../listeners/ProxyResponseKafkaListener.kt | 3 +- .../TopicsConfigurationProperties.kt | 10 +-- .../kafka/senders/ProxyRequestKafkaSender.kt | 1 - .../kafka/senders/ProxyResponseKafkaSender.kt | 1 - .../monitoring/MonitoringService.kt | 17 ++--- .../valueobjects/ProxyServerBaseMessage.kt | 10 +-- .../valueobjects/ProxyServerRequestMessage.kt | 21 ++---- .../ProxyServerResponseMessage.kt | 17 ++--- .../monitoring/MonitoringServiceTest.kt | 56 +++++++-------- build.gradle.kts | 39 +++++++++-- docker-compose.yaml | 4 +- license-template.kt | 3 + scripts/pre-commit | 40 +++++++++++ settings.gradle.kts | 13 ++-- 24 files changed, 200 insertions(+), 203 deletions(-) create mode 100644 license-template.kt create mode 100755 scripts/pre-commit diff --git a/README.md b/README.md index ce192a8..7df9dc1 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ and re-issue the SOAP request over there. ![](docs/proxy.svg) -- `Servce X` will try to call Service Y. You've configured X to make the request to the proxy instead +- `Service X` will try to call Service Y. You've configured X to make the request to the proxy instead - `Proxy A` will - store the HTTP connection used to receive the request and keep it open - receive the SOAP body and some meta data diff --git a/application/src/integrationTest/kotlin/org/gxf/soapbridge/EndToEndTest.kt b/application/src/integrationTest/kotlin/org/gxf/soapbridge/EndToEndTest.kt index c21e78e..2ee77b8 100644 --- a/application/src/integrationTest/kotlin/org/gxf/soapbridge/EndToEndTest.kt +++ b/application/src/integrationTest/kotlin/org/gxf/soapbridge/EndToEndTest.kt @@ -1,12 +1,13 @@ // SPDX-FileCopyrightText: Copyright Contributors to the GXF project // // SPDX-License-Identifier: Apache-2.0 - package org.gxf.soapbridge import com.github.tomakehurst.wiremock.client.WireMock.* import com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig import com.github.tomakehurst.wiremock.junit5.WireMockExtension +import java.net.http.HttpClient +import java.time.Duration import org.assertj.core.api.Assertions.assertThat import org.gxf.soapbridge.application.factories.SslContextFactory import org.junit.jupiter.api.BeforeEach @@ -15,14 +16,9 @@ import org.junit.jupiter.api.extension.RegisterExtension import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.web.server.LocalServerPort -import org.springframework.context.ApplicationContext -import org.springframework.context.annotation.ComponentScan import org.springframework.http.client.reactive.JdkClientHttpConnector import org.springframework.kafka.test.context.EmbeddedKafka import org.springframework.web.reactive.function.client.WebClient -import java.net.http.HttpClient -import java.time.Duration - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @EmbeddedKafka(topics = ["requests", "responses"]) @@ -37,11 +33,7 @@ class EndToEndTest( @BeforeEach fun setUp() { wireMockExtension.stubFor( - post(methodPath) - .withRequestBody(equalToXml(soapBody)) - .willReturn( - ok().withBody(soapResponse) - ) + post(methodPath).withRequestBody(equalToXml(soapBody)).willReturn(ok().withBody(soapResponse)) ) } @@ -49,25 +41,25 @@ class EndToEndTest( fun testRequestResponse() { // Arrange an SSL context for organisation "testClient" using its client certificate val sslContextForOrganisation = sslContextFactory.createSslContext("testClient") - val httpClient = HttpClient.newBuilder() - .sslContext(sslContextForOrganisation) - .build() - val webClient = WebClient.builder() - .clientConnector(JdkClientHttpConnector(httpClient)) - .build() + val httpClient = HttpClient.newBuilder().sslContext(sslContextForOrganisation).build() + val webClient = WebClient.builder().clientConnector(JdkClientHttpConnector(httpClient)).build() // Act: send SOAP request and get the answer - val responseBody = webClient.post().uri(callUrl) - .bodyValue(soapBody) - .exchangeToMono { it.bodyToMono(String::class.java) } - .timeout(Duration.ofSeconds(10)) - .block() + val responseBody = + webClient + .post() + .uri(callUrl) + .bodyValue(soapBody) + .exchangeToMono { it.bodyToMono(String::class.java) } + .timeout(Duration.ofSeconds(10)) + .block() // Assert assertThat(responseBody).isEqualTo(soapResponse) } - val soapBody = """ + val soapBody = + """ @@ -77,7 +69,8 @@ class EndToEndTest( - """.trimIndent() + """ + .trimIndent() val soapResponse = "Read This Fine Message" @@ -85,17 +78,20 @@ class EndToEndTest( @JvmField @RegisterExtension val wireMockExtension: WireMockExtension = - WireMockExtension.newInstance().options( - wireMockConfig() - .httpDisabled(true).httpsPort(8888) - .keystorePath("src/integrationTest/resources/proxy.keystore.jks") - .keystorePassword("123456") - .keyManagerPassword("123456") - .keystoreType("PKCS12") - .trustStorePath("src/integrationTest/resources/proxy.truststore.jks") - .trustStorePassword("123456") - .trustStoreType("PKCS12") - .needClientAuth(true) - ).build() + WireMockExtension.newInstance() + .options( + wireMockConfig() + .httpDisabled(true) + .httpsPort(8888) + .keystorePath("src/integrationTest/resources/proxy.keystore.jks") + .keystorePassword("123456") + .keyManagerPassword("123456") + .keystoreType("PKCS12") + .trustStorePath("src/integrationTest/resources/proxy.truststore.jks") + .trustStorePassword("123456") + .trustStoreType("PKCS12") + .needClientAuth(true) + ) + .build() } } diff --git a/application/src/main/java/org/gxf/soapbridge/application/factories/HostnameVerifierFactory.java b/application/src/main/java/org/gxf/soapbridge/application/factories/HostnameVerifierFactory.java index c40078d..36bdb2d 100644 --- a/application/src/main/java/org/gxf/soapbridge/application/factories/HostnameVerifierFactory.java +++ b/application/src/main/java/org/gxf/soapbridge/application/factories/HostnameVerifierFactory.java @@ -8,8 +8,8 @@ import static org.gxf.soapbridge.configuration.properties.HostnameVerificationStrategy.BROWSER_COMPATIBLE_HOSTNAMES; import javax.net.ssl.HostnameVerifier; -import org.apache.http.conn.ssl.DefaultHostnameVerifier; -import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.hc.client5.http.ssl.DefaultHostnameVerifier; +import org.apache.hc.client5.http.ssl.NoopHostnameVerifier; import org.gxf.soapbridge.configuration.properties.SoapConfigurationProperties; import org.gxf.soapbridge.soap.exceptions.ProxyServerException; import org.springframework.stereotype.Component; @@ -23,9 +23,9 @@ public HostnameVerifierFactory(final SoapConfigurationProperties soapConfigurati } public HostnameVerifier getHostnameVerifier() throws ProxyServerException { - if (soapConfiguration.getHostnameVerificationStrategy() == ALLOW_ALL_HOSTNAMES) { + if (this.soapConfiguration.getHostnameVerificationStrategy() == ALLOW_ALL_HOSTNAMES) { return new NoopHostnameVerifier(); - } else if (soapConfiguration.getHostnameVerificationStrategy() + } else if (this.soapConfiguration.getHostnameVerificationStrategy() == BROWSER_COMPATIBLE_HOSTNAMES) { return new DefaultHostnameVerifier(); } else { diff --git a/application/src/main/kotlin/org/gxf/soapbridge/SoapBridgeApplication.kt b/application/src/main/kotlin/org/gxf/soapbridge/SoapBridgeApplication.kt index b2f354d..c1d47d1 100644 --- a/application/src/main/kotlin/org/gxf/soapbridge/SoapBridgeApplication.kt +++ b/application/src/main/kotlin/org/gxf/soapbridge/SoapBridgeApplication.kt @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright Contributors to the GXF project // // SPDX-License-Identifier: Apache-2.0 - package org.gxf.soapbridge import org.springframework.boot.autoconfigure.SpringBootApplication @@ -10,11 +9,7 @@ import org.springframework.boot.runApplication import org.springframework.scheduling.annotation.EnableAsync import org.springframework.web.servlet.config.annotation.EnableWebMvc -@SpringBootApplication -@EnableWebMvc -@EnableAsync -@ConfigurationPropertiesScan -class SoapBridgeApplication +@SpringBootApplication @EnableWebMvc @EnableAsync @ConfigurationPropertiesScan class SoapBridgeApplication fun main(args: Array) { runApplication(*args) diff --git a/application/src/main/kotlin/org/gxf/soapbridge/configuration/SecurityConfiguration.kt b/application/src/main/kotlin/org/gxf/soapbridge/configuration/SecurityConfiguration.kt index 4f4eab4..ad2aae4 100644 --- a/application/src/main/kotlin/org/gxf/soapbridge/configuration/SecurityConfiguration.kt +++ b/application/src/main/kotlin/org/gxf/soapbridge/configuration/SecurityConfiguration.kt @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright Contributors to the GXF project // // SPDX-License-Identifier: Apache-2.0 - package org.gxf.soapbridge.configuration import org.springframework.context.annotation.Bean @@ -16,26 +15,15 @@ class SecurityConfiguration { @Bean fun filterChain(http: HttpSecurity): SecurityFilterChain = - http.authorizeHttpRequests { - it - .requestMatchers("/actuator/**").permitAll() - .anyRequest().authenticated() - }.x509 { - it - .subjectPrincipalRegex("CN=(.*?)(?:,|$)") - .userDetailsService(userDetailsService()) - }.csrf { it.disable() } + http + .authorizeHttpRequests { it.requestMatchers("/actuator/**").permitAll().anyRequest().authenticated() } + .x509 { it.subjectPrincipalRegex("CN=(.*?)(?:,|$)").userDetailsService(userDetailsService()) } + .csrf { it.disable() } .build() - - /** - * Uses the CN of the client certificate as the username for Springs Principal object - */ + /** Uses the CN of the client certificate as the username for Springs Principal object */ @Bean - fun userDetailsService(): UserDetailsService = - UserDetailsService { username -> - return@UserDetailsService User( - username, "", emptyList() - ) - } + fun userDetailsService(): UserDetailsService = UserDetailsService { username -> + return@UserDetailsService User(username, "", emptyList()) + } } diff --git a/application/src/main/kotlin/org/gxf/soapbridge/configuration/kafka/KafkaConfiguration.kt b/application/src/main/kotlin/org/gxf/soapbridge/configuration/kafka/KafkaConfiguration.kt index 8075fd1..74f025b 100644 --- a/application/src/main/kotlin/org/gxf/soapbridge/configuration/kafka/KafkaConfiguration.kt +++ b/application/src/main/kotlin/org/gxf/soapbridge/configuration/kafka/KafkaConfiguration.kt @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright Contributors to the GXF project +// +// SPDX-License-Identifier: Apache-2.0 package org.gxf.soapbridge.configuration.kafka import org.springframework.context.annotation.Bean @@ -8,11 +11,9 @@ import org.springframework.util.backoff.FixedBackOff @Configuration class KafkaConfiguration { - /** - * Retry messages two times before giving up on the message - */ + /** Retry messages two times before giving up on the message */ @Bean fun errorHandler(): DefaultErrorHandler { return DefaultErrorHandler(FixedBackOff(0, 2L)) } -} \ No newline at end of file +} diff --git a/application/src/main/kotlin/org/gxf/soapbridge/configuration/properties/SecurityConfigurationProperties.kt b/application/src/main/kotlin/org/gxf/soapbridge/configuration/properties/SecurityConfigurationProperties.kt index a9bb8d3..5536359 100644 --- a/application/src/main/kotlin/org/gxf/soapbridge/configuration/properties/SecurityConfigurationProperties.kt +++ b/application/src/main/kotlin/org/gxf/soapbridge/configuration/properties/SecurityConfigurationProperties.kt @@ -1,11 +1,9 @@ // SPDX-FileCopyrightText: Copyright Contributors to the GXF project // // SPDX-License-Identifier: Apache-2.0 - package org.gxf.soapbridge.configuration.properties import io.github.oshai.kotlinlogging.KotlinLogging -import org.springframework.boot.context.properties.ConfigurationProperties import java.io.IOException import java.nio.file.Files import java.nio.file.Paths @@ -14,6 +12,7 @@ import java.security.PrivateKey import java.security.PublicKey import java.security.spec.PKCS8EncodedKeySpec import java.security.spec.X509EncodedKeySpec +import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties("security") class SecurityConfigurationProperties( @@ -22,12 +21,7 @@ class SecurityConfigurationProperties( val signing: SigningConfigurationProperties ) -class StoreConfigurationProperties( - val location: String, - val password: String, - val type: String -) - +class StoreConfigurationProperties(val location: String, val password: String, val type: String) class SigningConfigurationProperties( keyType: String, @@ -46,9 +40,7 @@ class SigningConfigurationProperties( /** Public key used for verification. */ val verifyKey = createPublicKey(verifyKeyFile, keyType, provider) - private fun createPrivateKey( - keyPath: String, keyType: String, provider: String - ): PrivateKey? { + private fun createPrivateKey(keyPath: String, keyType: String, provider: String): PrivateKey? { return try { val key = readKeyFromDisk(keyPath) val privateKeySpec = PKCS8EncodedKeySpec(key) @@ -60,9 +52,7 @@ class SigningConfigurationProperties( } } - private fun createPublicKey( - keyPath: String, keyType: String, provider: String - ): PublicKey? { + private fun createPublicKey(keyPath: String, keyType: String, provider: String): PublicKey? { return try { val key = readKeyFromDisk(keyPath) val publicKeySpec = X509EncodedKeySpec(key) diff --git a/application/src/main/kotlin/org/gxf/soapbridge/configuration/properties/SoapConfigurationProperties.kt b/application/src/main/kotlin/org/gxf/soapbridge/configuration/properties/SoapConfigurationProperties.kt index 60e1968..6317222 100644 --- a/application/src/main/kotlin/org/gxf/soapbridge/configuration/properties/SoapConfigurationProperties.kt +++ b/application/src/main/kotlin/org/gxf/soapbridge/configuration/properties/SoapConfigurationProperties.kt @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright Contributors to the GXF project // // SPDX-License-Identifier: Apache-2.0 - package org.gxf.soapbridge.configuration.properties import org.springframework.boot.context.properties.ConfigurationProperties @@ -10,35 +9,31 @@ import org.springframework.boot.context.properties.ConfigurationProperties class SoapConfigurationProperties( val hostnameVerificationStrategy: HostnameVerificationStrategy, /** - * Maximum number of seconds this {@link SoapEndpoint} will wait for a response from the other end - * before terminating the connection with the client application. + * Maximum number of seconds this {@link SoapEndpoint} will wait for a response from the other end before + * terminating the connection with the client application. */ val timeout: Int, - /** - * Timeouts for specific functions. - */ + /** Timeouts for specific functions. */ val customTimeouts: Map = emptyMap(), /** * TODO Can we search for certificates on both sides * * Property to set common name based on the organisation on requests published to Kafka. * - * If set to false the other listening proxy doesn't search for certificates by [org.gxf.soapbridge.valueobjects.ProxyServerRequestMessage.commonName]. - * Instead, the other proxy will generate a new ssl context. + * If set to false the other listening proxy doesn't search for certificates by + * [org.gxf.soapbridge.valueobjects.ProxyServerRequestMessage.commonName]. Instead, the other proxy will generate a + * new ssl context. */ val useOrganisationFromRequest: Boolean = true, val callEndpoint: SoapEndpointConfiguration, ) enum class HostnameVerificationStrategy { - ALLOW_ALL_HOSTNAMES, BROWSER_COMPATIBLE_HOSTNAMES + ALLOW_ALL_HOSTNAMES, + BROWSER_COMPATIBLE_HOSTNAMES } -class SoapEndpointConfiguration( - host: String, - port: Int, - protocol: String -) { +class SoapEndpointConfiguration(host: String, port: Int, protocol: String) { // TODO Use java.net.URI class val hostAndPort = "$host:$port" val uri = "$protocol://${hostAndPort}" diff --git a/application/src/main/kotlin/org/gxf/soapbridge/exceptions/ProxyMessageException.kt b/application/src/main/kotlin/org/gxf/soapbridge/exceptions/ProxyMessageException.kt index 6a70b37..16c8108 100644 --- a/application/src/main/kotlin/org/gxf/soapbridge/exceptions/ProxyMessageException.kt +++ b/application/src/main/kotlin/org/gxf/soapbridge/exceptions/ProxyMessageException.kt @@ -1,8 +1,6 @@ // SPDX-FileCopyrightText: Copyright Contributors to the GXF project // // SPDX-License-Identifier: Apache-2.0 - package org.gxf.soapbridge.exceptions - class ProxyMessageException(message: String?) : Exception(message) diff --git a/application/src/main/kotlin/org/gxf/soapbridge/kafka/listeners/ProxyRequestKafkaListener.kt b/application/src/main/kotlin/org/gxf/soapbridge/kafka/listeners/ProxyRequestKafkaListener.kt index 39f0162..f3055d9 100644 --- a/application/src/main/kotlin/org/gxf/soapbridge/kafka/listeners/ProxyRequestKafkaListener.kt +++ b/application/src/main/kotlin/org/gxf/soapbridge/kafka/listeners/ProxyRequestKafkaListener.kt @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright Contributors to the GXF project // // SPDX-License-Identifier: Apache-2.0 - package org.gxf.soapbridge.kafka.listeners import io.github.oshai.kotlinlogging.KotlinLogging @@ -13,7 +12,7 @@ import org.springframework.stereotype.Component @Component class ProxyRequestKafkaListener(private val platformCommunicationService: PlatformCommunicationService) { - private val logger = KotlinLogging.logger { } + private val logger = KotlinLogging.logger {} @KafkaListener( id = "gxf-request-consumer", diff --git a/application/src/main/kotlin/org/gxf/soapbridge/kafka/listeners/ProxyResponseKafkaListener.kt b/application/src/main/kotlin/org/gxf/soapbridge/kafka/listeners/ProxyResponseKafkaListener.kt index 12aef09..1a13ca8 100644 --- a/application/src/main/kotlin/org/gxf/soapbridge/kafka/listeners/ProxyResponseKafkaListener.kt +++ b/application/src/main/kotlin/org/gxf/soapbridge/kafka/listeners/ProxyResponseKafkaListener.kt @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright Contributors to the GXF project // // SPDX-License-Identifier: Apache-2.0 - package org.gxf.soapbridge.kafka.listeners import io.github.oshai.kotlinlogging.KotlinLogging @@ -13,7 +12,7 @@ import org.springframework.stereotype.Component @Component class ProxyResponseKafkaListener(private val clientCommunicationService: ClientCommunicationService) { - private val logger = KotlinLogging.logger { } + private val logger = KotlinLogging.logger {} @KafkaListener( id = "gxf-response-consumer", diff --git a/application/src/main/kotlin/org/gxf/soapbridge/kafka/properties/TopicsConfigurationProperties.kt b/application/src/main/kotlin/org/gxf/soapbridge/kafka/properties/TopicsConfigurationProperties.kt index 1561a83..19ea033 100644 --- a/application/src/main/kotlin/org/gxf/soapbridge/kafka/properties/TopicsConfigurationProperties.kt +++ b/application/src/main/kotlin/org/gxf/soapbridge/kafka/properties/TopicsConfigurationProperties.kt @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright Contributors to the GXF project // // SPDX-License-Identifier: Apache-2.0 - package org.gxf.soapbridge.kafka.properties import org.springframework.boot.context.properties.ConfigurationProperties @@ -11,11 +10,6 @@ class TopicsConfigurationProperties( val outgoing: OutgoingTopicsConfiguration, ) -class OutgoingTopicsConfiguration( - val requests: OutgoingTopic, - val responses: OutgoingTopic -) +class OutgoingTopicsConfiguration(val requests: OutgoingTopic, val responses: OutgoingTopic) -class OutgoingTopic( - val topic: String -) \ No newline at end of file +class OutgoingTopic(val topic: String) diff --git a/application/src/main/kotlin/org/gxf/soapbridge/kafka/senders/ProxyRequestKafkaSender.kt b/application/src/main/kotlin/org/gxf/soapbridge/kafka/senders/ProxyRequestKafkaSender.kt index e2a3c99..3ca2e6c 100644 --- a/application/src/main/kotlin/org/gxf/soapbridge/kafka/senders/ProxyRequestKafkaSender.kt +++ b/application/src/main/kotlin/org/gxf/soapbridge/kafka/senders/ProxyRequestKafkaSender.kt @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright Contributors to the GXF project // // SPDX-License-Identifier: Apache-2.0 - package org.gxf.soapbridge.kafka.senders import io.github.oshai.kotlinlogging.KotlinLogging diff --git a/application/src/main/kotlin/org/gxf/soapbridge/kafka/senders/ProxyResponseKafkaSender.kt b/application/src/main/kotlin/org/gxf/soapbridge/kafka/senders/ProxyResponseKafkaSender.kt index 15492c4..191d033 100644 --- a/application/src/main/kotlin/org/gxf/soapbridge/kafka/senders/ProxyResponseKafkaSender.kt +++ b/application/src/main/kotlin/org/gxf/soapbridge/kafka/senders/ProxyResponseKafkaSender.kt @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright Contributors to the GXF project // // SPDX-License-Identifier: Apache-2.0 - package org.gxf.soapbridge.kafka.senders import io.github.oshai.kotlinlogging.KotlinLogging diff --git a/application/src/main/kotlin/org/gxf/soapbridge/monitoring/MonitoringService.kt b/application/src/main/kotlin/org/gxf/soapbridge/monitoring/MonitoringService.kt index 0a4f5ec..a56f327 100644 --- a/application/src/main/kotlin/org/gxf/soapbridge/monitoring/MonitoringService.kt +++ b/application/src/main/kotlin/org/gxf/soapbridge/monitoring/MonitoringService.kt @@ -1,16 +1,17 @@ +// SPDX-FileCopyrightText: Copyright Contributors to the GXF project +// +// SPDX-License-Identifier: Apache-2.0 package org.gxf.soapbridge.monitoring import io.micrometer.core.instrument.Gauge import io.micrometer.core.instrument.MeterRegistry import io.micrometer.core.instrument.Timer -import org.springframework.stereotype.Service import java.time.Duration import java.time.Instant +import org.springframework.stereotype.Service @Service -class MonitoringService( - private val registry: MeterRegistry -) { +class MonitoringService(private val registry: MeterRegistry) { companion object { private const val METRIC_PREFIX = "gxf.soap.bridge" @@ -19,7 +20,6 @@ class MonitoringService( const val CONNECTION_TIMER_CONTEXT_TAG = "context" const val CONNECTION_TIMER_SUCCESSFUL_TAG = "successful" - } /** @@ -29,9 +29,7 @@ class MonitoringService( * @return A Gauge object that measures the size of the cache. */ fun monitorCacheSize(cache: Map<*, *>) = - Gauge - .builder(CACHE_SIZE_METRIC, cache) { it.size.toDouble() } - .register(registry) + Gauge.builder(CACHE_SIZE_METRIC, cache) { it.size.toDouble() }.register(registry) /** * Records the connection time for a request. @@ -45,8 +43,7 @@ class MonitoringService( fun recordConnectionTime(startTime: Instant, context: String, successful: Boolean) { val duration = Duration.between(startTime, Instant.now()) - Timer - .builder(CONNECTION_TIMER_METRIC) + Timer.builder(CONNECTION_TIMER_METRIC) .description("The time it takes to handle an incoming soap request") .tag(CONNECTION_TIMER_CONTEXT_TAG, context) .tag(CONNECTION_TIMER_SUCCESSFUL_TAG, successful.toString()) diff --git a/application/src/main/kotlin/org/gxf/soapbridge/valueobjects/ProxyServerBaseMessage.kt b/application/src/main/kotlin/org/gxf/soapbridge/valueobjects/ProxyServerBaseMessage.kt index 364de6a..fec231f 100644 --- a/application/src/main/kotlin/org/gxf/soapbridge/valueobjects/ProxyServerBaseMessage.kt +++ b/application/src/main/kotlin/org/gxf/soapbridge/valueobjects/ProxyServerBaseMessage.kt @@ -1,28 +1,28 @@ // SPDX-FileCopyrightText: Copyright Contributors to the GXF project // // SPDX-License-Identifier: Apache-2.0 - package org.gxf.soapbridge.valueobjects import java.util.Base64 - -/** Base class for proxy-server messages. */ +/** Base class for proxy-server messages. */ abstract class ProxyServerBaseMessage(val connectionId: String) { var signature: String? = null protected abstract fun getFieldsForMessage(): List - /** Constructs a string separated by '~' from the fields of this instance. */ + /** Constructs a string separated by '~' from the fields of this instance. */ fun constructString() = getFieldsForMessage().joinToString(SEPARATOR, postfix = SEPARATOR) // TODO possibly convert to jackson mapping - /** Constructs a string separated by '~' from the fields of this instance followed by the signature. */ + /** Constructs a string separated by '~' from the fields of this instance followed by the signature. */ fun constructSignedString() = constructString() + signature companion object { const val SEPARATOR = "~" + fun encode(input: String): String = Base64.getEncoder().encodeToString(input.toByteArray()) + fun decode(input: String?): String = String(Base64.getDecoder().decode(input)) } } diff --git a/application/src/main/kotlin/org/gxf/soapbridge/valueobjects/ProxyServerRequestMessage.kt b/application/src/main/kotlin/org/gxf/soapbridge/valueobjects/ProxyServerRequestMessage.kt index 5c8761d..bf06df9 100644 --- a/application/src/main/kotlin/org/gxf/soapbridge/valueobjects/ProxyServerRequestMessage.kt +++ b/application/src/main/kotlin/org/gxf/soapbridge/valueobjects/ProxyServerRequestMessage.kt @@ -1,13 +1,11 @@ // SPDX-FileCopyrightText: Copyright Contributors to the GXF project // // SPDX-License-Identifier: Apache-2.0 - package org.gxf.soapbridge.valueobjects import io.github.oshai.kotlinlogging.KotlinLogging -import org.gxf.soapbridge.exceptions.ProxyMessageException import java.util.* - +import org.gxf.soapbridge.exceptions.ProxyMessageException class ProxyServerRequestMessage( connectionId: String, @@ -16,15 +14,11 @@ class ProxyServerRequestMessage( val soapPayload: String ) : ProxyServerBaseMessage(connectionId) { - override fun getFieldsForMessage(): List = listOf( - connectionId, - encode(context), - encode(soapPayload), - encode(commonName) - ) + override fun getFieldsForMessage(): List = + listOf(connectionId, encode(context), encode(soapPayload), encode(commonName)) companion object { - private val LOGGER = KotlinLogging.logger { } + private val LOGGER = KotlinLogging.logger {} /** * Constructs a ProxyServerRequestMessage instance from a string separated by '~'. @@ -39,9 +33,7 @@ class ProxyServerRequestMessage( val numTokens = split.size LOGGER.debug { "split.length: ${numTokens}" } if (numTokens < 4 || numTokens > 5) { - throw ProxyMessageException( - "Invalid number of tokens, not trying to create ProxyServerRequestMessage." - ) + throw ProxyMessageException("Invalid number of tokens, not trying to create ProxyServerRequestMessage.") } if (LOGGER.isDebugEnabled()) { printValues(numTokens, split) @@ -60,8 +52,7 @@ class ProxyServerRequestMessage( commonName = decode(split[3]) signature = split[4] } - val proxyServerRequestMessage = - ProxyServerRequestMessage(connectionId, commonName, context, soapRequest) + val proxyServerRequestMessage = ProxyServerRequestMessage(connectionId, commonName, context, soapRequest) proxyServerRequestMessage.signature = signature return proxyServerRequestMessage } diff --git a/application/src/main/kotlin/org/gxf/soapbridge/valueobjects/ProxyServerResponseMessage.kt b/application/src/main/kotlin/org/gxf/soapbridge/valueobjects/ProxyServerResponseMessage.kt index 58a0bd9..6f78929 100644 --- a/application/src/main/kotlin/org/gxf/soapbridge/valueobjects/ProxyServerResponseMessage.kt +++ b/application/src/main/kotlin/org/gxf/soapbridge/valueobjects/ProxyServerResponseMessage.kt @@ -1,25 +1,20 @@ // SPDX-FileCopyrightText: Copyright Contributors to the GXF project // // SPDX-License-Identifier: Apache-2.0 - package org.gxf.soapbridge.valueobjects import io.github.oshai.kotlinlogging.KotlinLogging -import org.gxf.soapbridge.exceptions.ProxyMessageException import java.util.* +import org.gxf.soapbridge.exceptions.ProxyMessageException class ProxyServerResponseMessage(connectionId: String, val soapResponse: String) : ProxyServerBaseMessage(connectionId) { - - /** Constructs a string separated by '~' from the fields of this instance. */ - override fun getFieldsForMessage(): List = listOf( - connectionId, - encode(soapResponse) - ) + /** Constructs a string separated by '~' from the fields of this instance. */ + override fun getFieldsForMessage(): List = listOf(connectionId, encode(soapResponse)) companion object { - val logger = KotlinLogging.logger { } + val logger = KotlinLogging.logger {} /** * Constructs a ProxyServerResponseMessage instance from a string separated by '~'. @@ -34,9 +29,7 @@ class ProxyServerResponseMessage(connectionId: String, val soapResponse: String) val numTokens = split.size logger.debug { "split.length: ${numTokens}" } if (numTokens < 3) { - throw ProxyMessageException( - "Invalid number of tokens, don't try to create ProxyServerResponseMessage" - ) + throw ProxyMessageException("Invalid number of tokens, don't try to create ProxyServerResponseMessage") } if (logger.isDebugEnabled()) { logger.debug { "split[0] connection-id: ${split[0]}" } diff --git a/application/src/test/kotlin/org/gxf/soapbridge/monitoring/MonitoringServiceTest.kt b/application/src/test/kotlin/org/gxf/soapbridge/monitoring/MonitoringServiceTest.kt index 9f540f0..749a0e7 100644 --- a/application/src/test/kotlin/org/gxf/soapbridge/monitoring/MonitoringServiceTest.kt +++ b/application/src/test/kotlin/org/gxf/soapbridge/monitoring/MonitoringServiceTest.kt @@ -1,9 +1,14 @@ +// SPDX-FileCopyrightText: Copyright Contributors to the GXF project +// +// SPDX-License-Identifier: Apache-2.0 package org.gxf.soapbridge.monitoring import io.micrometer.core.instrument.ImmutableTag import io.micrometer.core.instrument.MeterRegistry import io.micrometer.core.instrument.search.Search import io.micrometer.core.instrument.simple.SimpleMeterRegistry +import java.time.Instant +import java.util.concurrent.TimeUnit import org.assertj.core.api.Assertions.assertThat import org.gxf.soapbridge.monitoring.MonitoringService.Companion.CACHE_SIZE_METRIC import org.gxf.soapbridge.monitoring.MonitoringService.Companion.CONNECTION_TIMER_CONTEXT_TAG @@ -13,9 +18,6 @@ import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test -import java.time.Instant -import java.util.concurrent.TimeUnit - class MonitoringServiceTest { @@ -65,35 +67,28 @@ class MonitoringServiceTest { val contextOne = "test-context-one" val successfulOne = true - val expectedTagsOne = listOf( - ImmutableTag(CONNECTION_TIMER_CONTEXT_TAG, contextOne), - ImmutableTag(CONNECTION_TIMER_SUCCESSFUL_TAG, successfulOne.toString()) - ) + val expectedTagsOne = + listOf( + ImmutableTag(CONNECTION_TIMER_CONTEXT_TAG, contextOne), + ImmutableTag(CONNECTION_TIMER_SUCCESSFUL_TAG, successfulOne.toString()) + ) val contextTwo = "test-context-two" val successfulTwo = false - val expectedTagsTwo = listOf( - ImmutableTag(CONNECTION_TIMER_CONTEXT_TAG, contextTwo), - ImmutableTag(CONNECTION_TIMER_SUCCESSFUL_TAG, successfulTwo.toString()) - ) + val expectedTagsTwo = + listOf( + ImmutableTag(CONNECTION_TIMER_CONTEXT_TAG, contextTwo), + ImmutableTag(CONNECTION_TIMER_SUCCESSFUL_TAG, successfulTwo.toString()) + ) monitoringService.recordConnectionTime(startTime, contextOne, successfulOne) monitoringService.recordConnectionTime(startTime, contextTwo, successfulTwo) - val timerOne = - Search.`in`(meterRegistry) - .name(CONNECTION_TIMER_METRIC) - .tags(expectedTagsOne) - .timer() + val timerOne = Search.`in`(meterRegistry).name(CONNECTION_TIMER_METRIC).tags(expectedTagsOne).timer() assertThat(timerOne).isNotNull() - val timerTwo = - Search.`in`(meterRegistry) - .name(CONNECTION_TIMER_METRIC) - .tags(expectedTagsTwo) - .timer() + val timerTwo = Search.`in`(meterRegistry).name(CONNECTION_TIMER_METRIC).tags(expectedTagsTwo).timer() assertThat(timerTwo).isNotNull() - } @Test @@ -105,18 +100,15 @@ class MonitoringServiceTest { monitoringService.recordConnectionTime(startTime, context, successful) // Find the timer by name and tags - val expectedTags = listOf( - ImmutableTag(CONNECTION_TIMER_CONTEXT_TAG, context), - ImmutableTag(CONNECTION_TIMER_SUCCESSFUL_TAG, successful.toString()) - ) - val timer = Search.`in`(meterRegistry) - .name(CONNECTION_TIMER_METRIC) - .tags(expectedTags) - .timer() + val expectedTags = + listOf( + ImmutableTag(CONNECTION_TIMER_CONTEXT_TAG, context), + ImmutableTag(CONNECTION_TIMER_SUCCESSFUL_TAG, successful.toString()) + ) + val timer = Search.`in`(meterRegistry).name(CONNECTION_TIMER_METRIC).tags(expectedTags).timer() assertNotNull(timer) check(timer != null) - assertThat(timer.count()).isEqualTo(1) assertThat(timer.totalTime(TimeUnit.NANOSECONDS)).isNotEqualTo(0) assertThat(timer.max(TimeUnit.NANOSECONDS)).isNotEqualTo(0) @@ -128,7 +120,5 @@ class MonitoringServiceTest { assertThat(timer.totalTime(TimeUnit.NANOSECONDS)).isNotEqualTo(0) assertThat(timer.max(TimeUnit.NANOSECONDS)).isNotEqualTo(0) assertThat(timer.mean(TimeUnit.NANOSECONDS)).isNotEqualTo(0) - } - } diff --git a/build.gradle.kts b/build.gradle.kts index 5cd8d76..58ff4d3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,18 +1,21 @@ -// Copyright 2023 Alliander N.V. - +// SPDX-FileCopyrightText: Copyright Contributors to the GXF project +// +// SPDX-License-Identifier: Apache-2.0 +import com.diffplug.gradle.spotless.SpotlessExtension import com.github.davidmc24.gradle.plugin.avro.GenerateAvroJavaTask import io.spring.gradle.dependencymanagement.internal.dsl.StandardDependencyManagementExtension import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - id("org.springframework.boot") version "3.3.1" apply false - id("io.spring.dependency-management") version "1.1.5" apply false + id("org.springframework.boot") version "3.3.5" apply false + id("io.spring.dependency-management") version "1.1.6" apply false kotlin("jvm") version "2.0.0" apply false kotlin("plugin.spring") version "2.0.0" apply false kotlin("plugin.jpa") version "2.0.0" apply false id("com.github.davidmc24.gradle.plugin.avro") version "1.9.1" apply false - id("org.sonarqube") version "5.0.0.4638" + id("com.diffplug.spotless") version("6.25.0") + id("org.sonarqube") version "5.1.0.4882" id("eclipse") } @@ -30,6 +33,7 @@ subprojects { apply(plugin = "org.jetbrains.kotlin.jvm") apply(plugin = "org.jetbrains.kotlin.plugin.spring") apply(plugin = "io.spring.dependency-management") + apply(plugin = "com.diffplug.spotless") apply(plugin = "eclipse") apply(plugin = "org.jetbrains.kotlin.plugin.jpa") apply(plugin = "jacoco") @@ -50,6 +54,19 @@ subprojects { } } + extensions.configure { + kotlin { + // by default the target is every '.kt' and '.kts' file in the java source sets + ktfmt().kotlinlangStyle().configure { + it.setMaxWidth(120) + } + licenseHeaderFile( + "${project.rootDir}/license-template.kt", + "package") + .updateYearWithLatest(false) + } + } + extensions.configure { imports { mavenBom(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES) @@ -65,8 +82,18 @@ subprojects { } } + tasks.register("updateGitHooks") { + description = "Copies the pre-commit Git Hook to the .git/hooks folder." + group = "verification" + from("${project.rootDir}/scripts/pre-commit") + into("${project.rootDir}/.git/hooks") + } + tasks.withType { - dependsOn(tasks.withType()) + dependsOn( + tasks.withType(), + tasks.named("updateGitHooks") + ) } tasks.withType { diff --git a/docker-compose.yaml b/docker-compose.yaml index 3c98f55..31f2484 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,4 +1,6 @@ -# Copyright 2023 Alliander N.V. +#SPDX-FileCopyrightText: Copyright Contributors to the GXF project +# +#SPDX-License-Identifier: Apache-2.0 version: '2' services: zookeeper: diff --git a/license-template.kt b/license-template.kt new file mode 100644 index 0000000..21caf6f --- /dev/null +++ b/license-template.kt @@ -0,0 +1,3 @@ +// SPDX-FileCopyrightText: Copyright Contributors to the GXF project +// +// SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/pre-commit b/scripts/pre-commit new file mode 100755 index 0000000..69d6506 --- /dev/null +++ b/scripts/pre-commit @@ -0,0 +1,40 @@ +#!/bin/bash + +# SPDX-FileCopyrightText: Copyright Contributors to the GXF project +# +# SPDX-License-Identifier: Apache-2.0 + +echo "*********************************************************" +echo "Running git pre-commit hook. Running Spotless Apply... " +echo "*********************************************************" + +[[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh" + +# Gather the staged files - to make sure changes are saved only for these files. +stagedFiles=$(git diff --staged --name-only) + +# run spotless apply +./gradlew spotlessApply + +status=$? + +if [ "$status" = 0 ] ; then + echo "Static analysis found no problems." + # Add staged file changes to git + for file in $stagedFiles; do + if test -f "$file"; then + git add $file + fi + done + #Exit + exit 0 +else + echo "*********************************************************" + echo " ******************************************** " + echo 1>&2 "Spotless Apply found violations it could not fix." + echo "Run spotless apply in your terminal and fix the issues before trying to commit again." + echo " ******************************************** " + echo "*********************************************************" + #Exit + exit 1 +fi diff --git a/settings.gradle.kts b/settings.gradle.kts index cd30151..d7e1d90 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,5 +1,6 @@ -// Copyright 2023 Alliander N.V. - +// SPDX-FileCopyrightText: Copyright Contributors to the GXF project +// +// SPDX-License-Identifier: Apache-2.0 rootProject.name = "gxf-soap-bridge" include("application") @@ -8,17 +9,17 @@ dependencyResolutionManagement { versionCatalogs { create("libs") { version("kotlinLogging", "7.0.0") - version("gxfUtils", "0.3.7") - version("apacheHttpClient", "4.5.14") + version("gxfUtils", "2.1") + version("apacheHttpClient", "5.4") library("logging", "io.github.oshai", "kotlin-logging-jvm").versionRef("kotlinLogging") library("kafkaAzureOAuth", "com.gxf.utilities", "kafka-azure-oauth").versionRef("gxfUtils") - library("apacheHttpClient", "org.apache.httpcomponents", "httpclient").versionRef("apacheHttpClient") + library("apacheHttpClient", "org.apache.httpcomponents.client5", "httpclient5").versionRef("apacheHttpClient") } create("testLibs") { - version("wiremock", "3.6.0") + version("wiremock", "3.9.2") library("mockServer", "org.wiremock", "wiremock-standalone").versionRef("wiremock") }