From bc36d306731844cb411d4e795982db3256a7d9f3 Mon Sep 17 00:00:00 2001 From: Andre Weber Date: Tue, 27 Feb 2024 13:56:36 +0100 Subject: [PATCH] chore: Create DataBrokerConnectorFactory --- .../databroker/JavaDataBrokerEngine.java | 46 +------- .../databroker/KotlinDataBrokerEngine.kt | 53 +-------- .../connection/DataBrokerConnectorFactory.kt | 101 ++++++++++++++++++ .../extension/ConnectionInfoExtension.kt | 74 ------------- 4 files changed, 111 insertions(+), 163 deletions(-) create mode 100644 app/src/main/kotlin/org/eclipse/kuksa/testapp/databroker/connection/DataBrokerConnectorFactory.kt delete mode 100644 app/src/main/kotlin/org/eclipse/kuksa/testapp/extension/ConnectionInfoExtension.kt diff --git a/app/src/main/java/org/eclipse/kuksa/testapp/databroker/JavaDataBrokerEngine.java b/app/src/main/java/org/eclipse/kuksa/testapp/databroker/JavaDataBrokerEngine.java index b4161216..6935ac91 100644 --- a/app/src/main/java/org/eclipse/kuksa/testapp/databroker/JavaDataBrokerEngine.java +++ b/app/src/main/java/org/eclipse/kuksa/testapp/databroker/JavaDataBrokerEngine.java @@ -28,35 +28,27 @@ import org.eclipse.kuksa.DataBrokerConnector; import org.eclipse.kuksa.DisconnectListener; import org.eclipse.kuksa.PropertyListener; -import org.eclipse.kuksa.TimeoutConfig; import org.eclipse.kuksa.VssSpecificationListener; -import org.eclipse.kuksa.authentication.JsonWebToken; import org.eclipse.kuksa.model.Property; import org.eclipse.kuksa.proto.v1.KuksaValV1.GetResponse; import org.eclipse.kuksa.proto.v1.KuksaValV1.SetResponse; import org.eclipse.kuksa.proto.v1.Types; import org.eclipse.kuksa.proto.v1.Types.Datapoint; +import org.eclipse.kuksa.testapp.databroker.connection.DataBrokerConnectorFactory; import org.eclipse.kuksa.testapp.databroker.model.ConnectionInfo; -import org.eclipse.kuksa.testapp.extension.ConnectionInfoExtensionKt; import org.eclipse.kuksa.vsscore.model.VssSpecification; -import org.jetbrains.annotations.NotNull; -import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.Set; -import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; -import io.grpc.ManagedChannel; - public class JavaDataBrokerEngine implements DataBrokerEngine { - private static final long TIMEOUT_CONNECTION = 5; - @Nullable private DataBrokerConnection dataBrokerConnection = null; + private final DataBrokerConnectorFactory connectorFactory = new DataBrokerConnectorFactory(); private final Set disconnectListeners = new HashSet<>(); // Too many to usefully handle: Checked Exceptions: IOE, RuntimeExceptions: UOE, ISE, IAE, ... @@ -67,45 +59,17 @@ public void connect( @NonNull CoroutineCallback callback ) { try { - if (connectionInfo.isTlsEnabled()) { - connectSecure(context, connectionInfo, callback); - } else { - connectInsecure(context, connectionInfo, callback); - } + DataBrokerConnector connector = connectorFactory.create(context, connectionInfo); + connect(connector, callback); } catch (Exception e) { callback.onError(e); } } - private void connectInsecure( - @NonNull Context context, - @NonNull ConnectionInfo connectionInfo, - @NonNull CoroutineCallback callback - ) throws IOException { - ManagedChannel insecureChannel = ConnectionInfoExtensionKt.createInsecureManagedChannel(connectionInfo); - JsonWebToken jsonWebToken = ConnectionInfoExtensionKt.loadJsonWebToken(connectionInfo, context); - - connect(insecureChannel, jsonWebToken, callback); - } - - private void connectSecure( - @NotNull Context context, - @NotNull ConnectionInfo connectionInfo, - @NotNull CoroutineCallback callback - ) throws IOException { - ManagedChannel secureChannel = ConnectionInfoExtensionKt.createSecureManagedChannel(connectionInfo, context); - JsonWebToken jsonWebToken = ConnectionInfoExtensionKt.loadJsonWebToken(connectionInfo, context); - - connect(secureChannel, jsonWebToken, callback); - } - private void connect( - @NonNull ManagedChannel managedChannel, - @Nullable JsonWebToken jsonWebToken, + @NonNull DataBrokerConnector connector, @NonNull CoroutineCallback callback ) { - DataBrokerConnector connector = new DataBrokerConnector(managedChannel, jsonWebToken); - connector.setTimeoutConfig(new TimeoutConfig(TIMEOUT_CONNECTION, TimeUnit.SECONDS)); connector.connect(new CoroutineCallback<>() { @Override public void onSuccess(@Nullable DataBrokerConnection result) { diff --git a/app/src/main/kotlin/org/eclipse/kuksa/testapp/databroker/KotlinDataBrokerEngine.kt b/app/src/main/kotlin/org/eclipse/kuksa/testapp/databroker/KotlinDataBrokerEngine.kt index 983cf00f..30731180 100644 --- a/app/src/main/kotlin/org/eclipse/kuksa/testapp/databroker/KotlinDataBrokerEngine.kt +++ b/app/src/main/kotlin/org/eclipse/kuksa/testapp/databroker/KotlinDataBrokerEngine.kt @@ -21,7 +21,6 @@ package org.eclipse.kuksa.testapp.databroker import android.content.Context import androidx.lifecycle.LifecycleCoroutineScope -import io.grpc.ManagedChannel import kotlinx.coroutines.launch import org.eclipse.kuksa.CoroutineCallback import org.eclipse.kuksa.DataBrokerConnection @@ -29,17 +28,13 @@ import org.eclipse.kuksa.DataBrokerConnector import org.eclipse.kuksa.DataBrokerException import org.eclipse.kuksa.DisconnectListener import org.eclipse.kuksa.PropertyListener -import org.eclipse.kuksa.TimeoutConfig import org.eclipse.kuksa.VssSpecificationListener -import org.eclipse.kuksa.authentication.JsonWebToken import org.eclipse.kuksa.model.Property import org.eclipse.kuksa.proto.v1.KuksaValV1.GetResponse import org.eclipse.kuksa.proto.v1.KuksaValV1.SetResponse import org.eclipse.kuksa.proto.v1.Types.Datapoint +import org.eclipse.kuksa.testapp.databroker.connection.DataBrokerConnectorFactory import org.eclipse.kuksa.testapp.databroker.model.ConnectionInfo -import org.eclipse.kuksa.testapp.extension.createInsecureManagedChannel -import org.eclipse.kuksa.testapp.extension.createSecureManagedChannel -import org.eclipse.kuksa.testapp.extension.loadJsonWebToken import org.eclipse.kuksa.vsscore.model.VssSpecification @Suppress("complexity:TooManyFunctions") @@ -48,6 +43,7 @@ class KotlinDataBrokerEngine( ) : DataBrokerEngine { override var dataBrokerConnection: DataBrokerConnection? = null + private val connectorFactory = DataBrokerConnectorFactory() private val disconnectListeners = mutableSetOf() // Too many to usefully handle: Checked Exceptions: IOE, RuntimeExceptions: UOE, ISE, IAE, ... @@ -57,46 +53,11 @@ class KotlinDataBrokerEngine( connectionInfo: ConnectionInfo, callback: CoroutineCallback, ) { - try { - if (connectionInfo.isTlsEnabled) { - connectSecure(context, connectionInfo, callback) - } else { - connectInsecure(context, connectionInfo, callback) - } + val connector: DataBrokerConnector = try { + connectorFactory.create(context, connectionInfo) } catch (e: Exception) { callback.onError(e) - } - } - - private fun connectInsecure( - context: Context, - connectionInfo: ConnectionInfo, - callback: CoroutineCallback, - ) { - val insecureManagedChannel = connectionInfo.createInsecureManagedChannel() - val jsonWebToken: JsonWebToken? = connectionInfo.loadJsonWebToken(context) - - connect(insecureManagedChannel, jsonWebToken, callback) - } - - private fun connectSecure( - context: Context, - connectionInfo: ConnectionInfo, - callback: CoroutineCallback, - ) { - val secureManagedChannel = connectionInfo.createSecureManagedChannel(context) - val jsonWebToken: JsonWebToken? = connectionInfo.loadJsonWebToken(context) - - connect(secureManagedChannel, jsonWebToken, callback) - } - - private fun connect( - managedChannel: ManagedChannel, - jsonWebToken: JsonWebToken?, - callback: CoroutineCallback, - ) { - val connector = DataBrokerConnector(managedChannel, jsonWebToken).apply { - timeoutConfig = TimeoutConfig(TIMEOUT_CONNECTION_SEC) + return } lifecycleScope.launch { @@ -184,8 +145,4 @@ class KotlinDataBrokerEngine( disconnectListeners.remove(listener) dataBrokerConnection?.disconnectListeners?.unregister(listener) } - - companion object { - const val TIMEOUT_CONNECTION_SEC = 5L - } } diff --git a/app/src/main/kotlin/org/eclipse/kuksa/testapp/databroker/connection/DataBrokerConnectorFactory.kt b/app/src/main/kotlin/org/eclipse/kuksa/testapp/databroker/connection/DataBrokerConnectorFactory.kt new file mode 100644 index 00000000..067b9162 --- /dev/null +++ b/app/src/main/kotlin/org/eclipse/kuksa/testapp/databroker/connection/DataBrokerConnectorFactory.kt @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +package org.eclipse.kuksa.testapp.databroker.connection + +import android.content.Context +import android.net.Uri +import io.grpc.ChannelCredentials +import io.grpc.Grpc +import io.grpc.ManagedChannel +import io.grpc.ManagedChannelBuilder +import io.grpc.TlsChannelCredentials +import org.eclipse.kuksa.DataBrokerConnector +import org.eclipse.kuksa.TimeoutConfig +import org.eclipse.kuksa.authentication.JsonWebToken +import org.eclipse.kuksa.testapp.databroker.model.ConnectionInfo +import org.eclipse.kuksa.testapp.extension.readAsText +import java.io.IOException +import java.util.concurrent.TimeUnit + +class DataBrokerConnectorFactory { + private val timeoutConfig = TimeoutConfig(5, TimeUnit.SECONDS) + + @Throws(IOException::class) + fun create(context: Context, connectionInfo: ConnectionInfo): DataBrokerConnector { + val managedChannel = if (connectionInfo.isTlsEnabled) { + createSecureManagedChannel(context, connectionInfo) + } else { + createInsecureManagedChannel(connectionInfo) + } + + val jsonWebToken = loadJsonWebToken(context, connectionInfo) + + return DataBrokerConnector(managedChannel, jsonWebToken).apply { + timeoutConfig = this@DataBrokerConnectorFactory.timeoutConfig + } + } + + private fun createInsecureManagedChannel(connectionInfo: ConnectionInfo): ManagedChannel { + val host = connectionInfo.host.trim() + val port = connectionInfo.port + + return ManagedChannelBuilder + .forAddress(host, port) + .usePlaintext() + .build() + } + + @Throws(IOException::class) + private fun createSecureManagedChannel(context: Context, connectionInfo: ConnectionInfo): ManagedChannel { + val certificate = connectionInfo.certificate + val rootCertFile = context.contentResolver.openInputStream(certificate.uri) + + val tlsCredentials: ChannelCredentials = TlsChannelCredentials.newBuilder() + .trustManager(rootCertFile) + .build() + + val host = connectionInfo.host.trim() + val port = connectionInfo.port + val channelBuilder = Grpc + .newChannelBuilderForAddress(host, port, tlsCredentials) + + val overrideAuthority = certificate.overrideAuthority.trim() + val hasOverrideAuthority = overrideAuthority.isNotEmpty() + if (hasOverrideAuthority) { + channelBuilder.overrideAuthority(overrideAuthority) + } + + return channelBuilder.build() + } + + @Throws(IOException::class) + private fun loadJsonWebToken(context: Context, connectionInfo: ConnectionInfo): JsonWebToken? { + val isAuthenticationDisabled = !connectionInfo.isAuthenticationEnabled + val jwtUriPath = connectionInfo.jwtUriPath + if (isAuthenticationDisabled || jwtUriPath.isNullOrEmpty()) { + return null + } + + val uri: Uri = Uri.parse(jwtUriPath) + val token = uri.readAsText(context) + + return JsonWebToken(token) + } +} diff --git a/app/src/main/kotlin/org/eclipse/kuksa/testapp/extension/ConnectionInfoExtension.kt b/app/src/main/kotlin/org/eclipse/kuksa/testapp/extension/ConnectionInfoExtension.kt deleted file mode 100644 index f5c6b380..00000000 --- a/app/src/main/kotlin/org/eclipse/kuksa/testapp/extension/ConnectionInfoExtension.kt +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2024 Contributors to the Eclipse Foundation - * - * 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. - * - * SPDX-License-Identifier: Apache-2.0 - * - */ - -package org.eclipse.kuksa.testapp.extension - -import android.content.Context -import android.net.Uri -import io.grpc.ChannelCredentials -import io.grpc.Grpc -import io.grpc.ManagedChannel -import io.grpc.ManagedChannelBuilder -import io.grpc.TlsChannelCredentials -import org.eclipse.kuksa.authentication.JsonWebToken -import org.eclipse.kuksa.testapp.databroker.model.ConnectionInfo -import java.io.IOException - -fun ConnectionInfo.createInsecureManagedChannel(): ManagedChannel { - val host = host.trim() - - return ManagedChannelBuilder - .forAddress(host, port) - .usePlaintext() - .build() -} - -@Throws(IOException::class) -fun ConnectionInfo.createSecureManagedChannel(context: Context): ManagedChannel { - val rootCertFile = context.contentResolver.openInputStream(certificate.uri) - - val tlsCredentials: ChannelCredentials = TlsChannelCredentials.newBuilder() - .trustManager(rootCertFile) - .build() - - val host = host.trim() - val port = port - val channelBuilder = Grpc - .newChannelBuilderForAddress(host, port, tlsCredentials) - - val overrideAuthority = certificate.overrideAuthority.trim() - val hasOverrideAuthority = overrideAuthority.isNotEmpty() - if (hasOverrideAuthority) { - channelBuilder.overrideAuthority(overrideAuthority) - } - - return channelBuilder.build() -} - -@Throws(IOException::class) -fun ConnectionInfo.loadJsonWebToken(context: Context): JsonWebToken? { - if (!isAuthenticationEnabled || jwtUriPath == null) { - return null - } - - val uri: Uri = Uri.parse(jwtUriPath) - val token = uri.readAsText(context) - - return JsonWebToken(token) -}