diff --git a/integrations/oci/sdk/cdi/pom.xml b/integrations/oci/sdk/cdi/pom.xml
index a724f824f51..7ab71fa16db 100644
--- a/integrations/oci/sdk/cdi/pom.xml
+++ b/integrations/oci/sdk/cdi/pom.xml
@@ -61,6 +61,14 @@
+
+ io.helidon.config
+ helidon-config-mp
+
+
+ io.helidon.integrations.oci.sdk
+ helidon-integrations-oci-sdk-runtime
+
org.glassfish.jersey.connectors
diff --git a/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/AdpSelectionStrategy.java b/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/AdpSelectionStrategy.java
deleted file mode 100644
index 329de31120a..00000000000
--- a/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/AdpSelectionStrategy.java
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
- * Copyright (c) 2022, 2023 Oracle and/or its affiliates.
- *
- * 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 io.helidon.integrations.oci.sdk.cdi;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.lang.annotation.Annotation;
-import java.net.ConnectException;
-import java.net.InetAddress;
-import java.net.URI;
-import java.net.UnknownHostException;
-import java.nio.file.NoSuchFileException;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.Supplier;
-import java.util.logging.Logger;
-
-import com.oracle.bmc.Region;
-import com.oracle.bmc.auth.AbstractAuthenticationDetailsProvider;
-import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider;
-import com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider;
-import com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider.InstancePrincipalsAuthenticationDetailsProviderBuilder;
-import com.oracle.bmc.auth.ResourcePrincipalAuthenticationDetailsProvider;
-import com.oracle.bmc.auth.ResourcePrincipalAuthenticationDetailsProvider.ResourcePrincipalAuthenticationDetailsProviderBuilder;
-import com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider;
-import com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider.SimpleAuthenticationDetailsProviderBuilder;
-import com.oracle.bmc.auth.SimplePrivateKeySupplier;
-import com.oracle.bmc.auth.StringPrivateKeySupplier;
-
-import static com.oracle.bmc.auth.AbstractFederationClientAuthenticationDetailsProviderBuilder.METADATA_SERVICE_BASE_URL;
-
-/**
- * A strategy for finding and building various well-known kinds of
- * {@link AbstractAuthenticationDetailsProvider} instances.
- */
-enum AdpSelectionStrategy {
-
-
- //
- // ------------
- // PLEASE READ:
- // ------------
- //
- // The ordering of the constants in this enum is *extremely*
- // important! It governs the default "auto" case order
- // (EnumSets always traverse their members in declaration
- // order)! Do not reorder the constants unless you have a good
- // reason!
- //
-
-
- /*
- * Enum constants.
- */
-
-
- /**
- * An {@link AdpSelectionStrategy} that works with {@link
- * SimpleAuthenticationDetailsProvider} instances configured from
- * configuration.
- */
- CONFIG(SimpleAuthenticationDetailsProvider.class,
- SimpleAuthenticationDetailsProviderBuilder.class) {
-
- private static final String OCI_AUTH_FINGERPRINT = "oci.auth.fingerprint";
-
- private static final String OCI_AUTH_PASSPHRASE = "oci.auth.passphrase";
-
- private static final String OCI_AUTH_PRIVATE_KEY = "oci.auth.private-key";
-
- private static final String OCI_AUTH_REGION = "oci.auth.region";
-
- private static final String OCI_AUTH_TENANT_ID = "oci.auth.tenant-id";
-
- private static final String OCI_AUTH_USER_ID = "oci.auth.user-id";
-
- @Override // AdpSelectionStrategy
- boolean isAvailable(Selector selector, Config c, Annotation[] qualifiersArray) {
- // See
- // https://docs.oracle.com/en-us/iaas/tools/java/latest/com/oracle/bmc/auth/SimpleAuthenticationDetailsProvider.SimpleAuthenticationDetailsProviderBuilder.html#method.summary
- //
- // Some fallback logic is for backwards compatibility with
- // a prior OCI-related extension.
- return
- super.isAvailable(selector, c, qualifiersArray)
- && c.get(OCI_AUTH_FINGERPRINT, String.class).isPresent()
- && c.get(OCI_AUTH_REGION, String.class).isPresent()
- && (c.get(OCI_AUTH_TENANT_ID, String.class).isPresent() || c.get("oci.auth.tenancy", String.class).isPresent())
- && (c.get(OCI_AUTH_USER_ID, String.class).isPresent() || c.get("oci.auth.user", String.class).isPresent());
- }
-
- @Override // AdpSelectionStrategy
- @SuppressWarnings("checkstyle:LineLength")
- SimpleAuthenticationDetailsProviderBuilder produceBuilder(Selector selector, Config c, Annotation[] qualifiersArray) {
- SimpleAuthenticationDetailsProviderBuilder b = SimpleAuthenticationDetailsProvider.builder();
- // See
- // https://docs.oracle.com/en-us/iaas/tools/java/latest/com/oracle/bmc/auth/SimpleAuthenticationDetailsProvider.SimpleAuthenticationDetailsProviderBuilder.html#method.summary
- //
- // See
- // https://docs.oracle.com/en-us/iaas/Content/API/Concepts/apisigningkey.htm#apisigningkey_topic_How_to_Generate_an_API_Signing_Key_Mac_Linux__ol_t5v_lwz_zmb
- // for default private key file naming rationale used in a
- // fallback case below.
- //
- // Some fallback logic is for backwards compatibility with
- // a prior OCI-related extension.
- c.get(OCI_AUTH_FINGERPRINT, String.class)
- .ifPresent(b::fingerprint);
- c.get(OCI_AUTH_PASSPHRASE, String.class).or(() -> c.get(OCI_AUTH_PASSPHRASE + "Characters", String.class))
- .ifPresent(b::passPhrase);
- c.get(OCI_AUTH_PRIVATE_KEY, String.class).or(() -> c.get("oci.auth.privateKey", String.class))
- .ifPresentOrElse(pk -> b.privateKeySupplier(new StringPrivateKeySupplier(pk)),
- () -> b.privateKeySupplier(new SimplePrivateKeySupplier(c.get(OCI_AUTH_PRIVATE_KEY + "-path", String.class)
- .orElse(c.get("oci.auth.keyFile", String.class)
- .orElse(Paths.get(System.getProperty("user.home"), ".oci", "oci_api_key.pem").toString())))));
- c.get(OCI_AUTH_REGION, Region.class)
- .ifPresent(b::region);
- c.get(OCI_AUTH_TENANT_ID, String.class).or(() -> c.get("oci.auth.tenancy", String.class))
- .ifPresent(b::tenantId);
- c.get(OCI_AUTH_USER_ID, String.class).or(() -> c.get("oci.auth.user", String.class))
- .ifPresent(b::userId);
- return b;
- }
-
- @Override // AdpSelectionStrategy
- SimpleAuthenticationDetailsProvider produce(Selector selector, Config c, Annotation[] qualifiersArray) {
- return selector.select(SimpleAuthenticationDetailsProviderBuilder.class, qualifiersArray).get().build();
- }
-
- },
-
- /**
- * An {@link AdpSelectionStrategy} that works with {@link
- * ConfigFileAuthenticationDetailsProvider} instances.
- */
- CONFIG_FILE(ConfigFileAuthenticationDetailsProvider.class) {
-
- @Override // AdpSelectionStrategy
- boolean isAvailable(Selector selector, Config c, Annotation[] qualifiersArray) {
- if (super.isAvailable(selector, c, qualifiersArray)) {
- try {
- this.get(selector, c, qualifiersArray);
- } catch (UncheckedIOException uncheckedIoException) {
- Object cause = uncheckedIoException.getCause();
- if (cause instanceof FileNotFoundException || cause instanceof NoSuchFileException) {
- return false;
- }
- throw uncheckedIoException;
- }
- return true;
- }
- return false;
- }
-
- @Override // AdpSelectionStrategy
- Void produceBuilder(Selector selector, Config c, Annotation[] qualifiersArray) {
- throw new UnsupportedOperationException();
- }
-
- @Override // AdpSelectionStrategy
- ConfigFileAuthenticationDetailsProvider produce(Selector selector, Config c, Annotation[] qualifiersArray) {
- return
- this.produce(c.get("oci.config.path", String.class).orElse(null), // null on purpose; use OCI defaulting logic
- c.get("oci.config.profile", String.class)
- .orElse(c.get("oci.auth.profile", String.class)
- .orElse("DEFAULT")));
- }
-
- private ConfigFileAuthenticationDetailsProvider produce(String ociConfigPath, String ociAuthProfile) {
- try {
- if (ociConfigPath == null) {
- // Don't get clever and try to use ~/.oci/config
- // as a default value; there is OCI-managed logic
- // to figure out the proper default; we want to
- // make sure it's used
- return new ConfigFileAuthenticationDetailsProvider(ociAuthProfile);
- } else {
- return new ConfigFileAuthenticationDetailsProvider(ociConfigPath, ociAuthProfile);
- }
- } catch (FileNotFoundException fileNotFoundException) {
- throw new UncheckedIOException(fileNotFoundException.getMessage(), fileNotFoundException);
- } catch (NoSuchFileException noSuchFileException) {
- throw new UncheckedIOException(noSuchFileException.getMessage(), noSuchFileException);
- } catch (IOException ioException) {
- // The underlying ConfigFileReader that does the real
- // work does not throw a FileNotFoundException in this
- // case (as it probably should). We have no choice
- // but to parse the error message. See
- // https://github.com/oracle/oci-java-sdk/blob/2.19.0/bmc-common/src/main/java/com/oracle/bmc/ConfigFileReader.java#L94-L98.
- String message = ioException.getMessage();
- if (message != null
- && message.startsWith("Can't load the default config from ")
- && message.endsWith(" because it does not exist or it is not a file.")) {
- throw new UncheckedIOException(message,
- (IOException) new FileNotFoundException(message).initCause(ioException));
- }
- throw new UncheckedIOException(message, ioException);
- }
- }
- },
-
- /**
- * An {@link AdpSelectionStrategy} that works with {@link
- * InstancePrincipalsAuthenticationDetailsProvider} instances.
- */
- INSTANCE_PRINCIPALS(InstancePrincipalsAuthenticationDetailsProvider.class,
- InstancePrincipalsAuthenticationDetailsProviderBuilder.class) {
-
- private final String defaultImdsHostname = URI.create(METADATA_SERVICE_BASE_URL).getHost();
-
- @Override // AdpSelectionStrategy
- boolean isAvailable(Selector selector, Config c, Annotation[] qualifiersArray) {
- if (super.isAvailable(selector, c, qualifiersArray)) {
- InetAddress imds = null;
- try {
- imds = InetAddress.getByName(c.get("oci.imds.hostname", String.class).orElse(this.defaultImdsHostname));
- } catch (UnknownHostException unknownHostException) {
- throw new UncheckedIOException(unknownHostException.getMessage(), unknownHostException);
- }
- int ociImdsTimeoutMillis = 0;
- try {
- ociImdsTimeoutMillis =
- Math.max(0, c.get("oci.imds.timeout.milliseconds", Integer.class).orElse(Integer.valueOf(100)));
- } catch (IllegalArgumentException conversionException) {
- ociImdsTimeoutMillis = 100;
- }
- try {
- return imds.isReachable(ociImdsTimeoutMillis);
- } catch (ConnectException connectException) {
- return false;
- } catch (IOException ioException) {
- throw new UncheckedIOException(ioException.getMessage(), ioException);
- }
- }
- return false;
- }
-
- @Override // AdpSelectionStrategy
- InstancePrincipalsAuthenticationDetailsProviderBuilder produceBuilder(Selector s, Config c, Annotation[] qs) {
- return InstancePrincipalsAuthenticationDetailsProvider.builder();
- }
-
- @Override // AdpSelectionStrategy
- InstancePrincipalsAuthenticationDetailsProvider produce(Selector selector, Config c, Annotation[] qualifiersArray) {
- return selector.select(InstancePrincipalsAuthenticationDetailsProviderBuilder.class, qualifiersArray).get().build();
- }
- },
-
- /**
- * An {@link AdpSelectionStrategy} that works with {@link
- * ResourcePrincipalAuthenticationDetailsProvider} instances.
- */
- RESOURCE_PRINCIPAL(ResourcePrincipalAuthenticationDetailsProvider.class,
- ResourcePrincipalAuthenticationDetailsProviderBuilder.class) {
-
- @Override // AdpSelectionStrategy
- boolean isAvailable(Selector selector, Config c, Annotation[] qualifiersArray) {
- return
- super.isAvailable(selector, c, qualifiersArray)
- // https://github.com/oracle/oci-java-sdk/blob/v2.19.0/bmc-common/src/main/java/com/oracle/bmc/auth/ResourcePrincipalAuthenticationDetailsProvider.java#L246-L251
- && System.getenv("OCI_RESOURCE_PRINCIPAL_VERSION") != null;
- }
-
- @Override // AdpSelectionStrategy
- ResourcePrincipalAuthenticationDetailsProviderBuilder produceBuilder(Selector s, Config c, Annotation[] qualifiersArray) {
- return ResourcePrincipalAuthenticationDetailsProvider.builder();
- }
-
- @Override // AdpSelectionStrategy
- ResourcePrincipalAuthenticationDetailsProvider produce(Selector selector, Config c, Annotation[] qualifiersArray) {
- return selector.select(ResourcePrincipalAuthenticationDetailsProviderBuilder.class, qualifiersArray).get().build();
- }
- },
-
- /**
- * An {@linkplain #isAbstract() abstract} {@link
- * AdpSelectionStrategy} that selects the most appropriate
- * concrete {@link AdpSelectionStrategy} by consulting
- * configuration.
- */
- AUTO(AbstractAuthenticationDetailsProvider.class, true) {
-
- private final transient Logger logger = Logger.getLogger(this.getClass().getName());
-
- @Override // AdpSelectionStrategy
- Void produceBuilder(Selector selector, Config c, Annotation[] qualifiersArray) {
- throw new UnsupportedOperationException();
- }
-
- @Override // AdpSelectionStrategy
- AbstractAuthenticationDetailsProvider produce(Selector selector, Config c, Annotation[] qualifiersArray) {
- Collection extends AdpSelectionStrategy> strategies =
- concreteStrategies(c.get("oci.auth-strategies", String[].class)
- .or(() -> c.get("oci.auth-strategy", String[].class))
- .orElse(null));
- for (AdpSelectionStrategy s : strategies) {
- if (s == this) {
- // concreteStrategies(String[]) bug
- throw new IllegalStateException("concreteStrategies(String[]) returned " + this.name());
- } else if (s.isAvailable(selector, c, qualifiersArray)) {
- logger.config(() -> "Using authentication strategy " + s.configName()
- + "; selected AbstractAuthenticationDetailsProvider " + s.type().getTypeName());
- return s.get(selector, c, qualifiersArray);
- } else {
- logger.fine(() -> "Skipping authentication strategy " + s.configName() + " because it is not available");
- }
- }
- throw new NoSuchElementException("No instances of "
- + AbstractAuthenticationDetailsProvider.class.getName()
- + " available for use");
- }
-
- };
-
-
- /*
- * Static fields.
- */
-
-
- private static final Collection CONCRETE_STRATEGIES;
-
- private static final Set> BUILDER_CLASSES;
-
- static {
- EnumSet set = EnumSet.allOf(AdpSelectionStrategy.class);
- set.removeIf(AdpSelectionStrategy::isAbstract);
- CONCRETE_STRATEGIES = Collections.unmodifiableCollection(set);
- Set> builderClasses = new HashSet<>(7);
- for (AdpSelectionStrategy s : set) {
- Class> builderType = s.builderType();
- if (builderType != null) {
- builderClasses.add(builderType);
- }
- }
- BUILDER_CLASSES = Collections.unmodifiableSet(builderClasses);
- }
-
-
- /*
- * Instance fields.
- */
-
-
- private final Class extends AbstractAuthenticationDetailsProvider> type;
-
- private final Class> builderType;
-
- private final boolean isAbstract;
-
-
- /*
- * Constructors.
- */
-
-
- AdpSelectionStrategy(Class extends AbstractAuthenticationDetailsProvider> type) {
- this(type, null, false);
- }
-
- AdpSelectionStrategy(Class extends AbstractAuthenticationDetailsProvider> type, boolean isAbstract) {
- this(type, null, isAbstract);
- }
-
- AdpSelectionStrategy(Class extends AbstractAuthenticationDetailsProvider> type, Class> builderType) {
- this(type, builderType, false);
- }
-
- AdpSelectionStrategy(Class extends AbstractAuthenticationDetailsProvider> type, Class> builderType, boolean isAbstract) {
- this.type = Objects.requireNonNull(type, "type");
- this.builderType = builderType;
- this.isAbstract = isAbstract;
- }
-
-
- /*
- * Instance methods.
- */
-
-
- final String configName() {
- return this.name().replace('_', '-').toLowerCase();
- }
-
- final Class extends AbstractAuthenticationDetailsProvider> type() {
- return this.type;
- }
-
- final Class> builderType() {
- return this.builderType;
- }
-
- final AbstractAuthenticationDetailsProvider get(Selector selector, Config c, Annotation[] qualifiersArray) {
- return selector.select(this.type(), qualifiersArray).get();
- }
-
- final boolean isAbstract() {
- return this.isAbstract;
- }
-
- boolean isAvailable(Selector selector, Config c, Annotation[] qualifiersArray) {
- return !this.isAbstract();
- }
-
- abstract Object produceBuilder(Selector selector, Config c, Annotation[] qualifiersArray);
-
- abstract AbstractAuthenticationDetailsProvider produce(Selector selector, Config c, Annotation[] qualifiersArray);
-
-
- /*
- * Static methods.
- */
-
-
- static Set> builderClasses() {
- return BUILDER_CLASSES;
- }
-
- private static AdpSelectionStrategy of(String name) {
- return valueOf(name.replace('-', '_').toUpperCase());
- }
-
- private static AdpSelectionStrategy ofConfigString(String strategyString) {
- if (strategyString == null) {
- return AUTO;
- } else {
- strategyString = strategyString.strip();
- return strategyString.isBlank() ? AUTO : of(strategyString);
- }
- }
-
- private static Collection concreteStrategies() {
- return CONCRETE_STRATEGIES;
- }
-
- private static Collection concreteStrategies(String[] strategyStringsArray) {
- Collection strategies;
- AdpSelectionStrategy strategy;
- switch (strategyStringsArray == null ? 0 : strategyStringsArray.length) {
- case 0:
- strategies = List.of();
- break;
- case 1:
- strategy = ofConfigString(strategyStringsArray[0]);
- strategies = strategy.isAbstract() ? List.of() : EnumSet.of(strategy);
- break;
- default:
- Set strategyStrings = new LinkedHashSet<>(Arrays.asList(strategyStringsArray));
- switch (strategyStrings.size()) {
- case 0:
- throw new AssertionError();
- case 1:
- strategy = ofConfigString(strategyStrings.iterator().next());
- strategies = strategy.isAbstract() ? List.of() : EnumSet.of(strategy);
- break;
- default:
- strategies = new ArrayList<>(strategyStrings.size());
- for (String s : strategyStrings) {
- strategy = ofConfigString(s);
- if (!strategy.isAbstract()) {
- strategies.add(strategy);
- }
- }
- }
- break;
- }
- if (strategies.isEmpty()) {
- return concreteStrategies();
- }
- return Collections.unmodifiableCollection(strategies);
- }
-
-
- /*
- * Inner and nested classes.
- */
-
-
- interface Selector {
-
- Supplier select(Class type, Annotation... qualifiers);
-
- }
-
- interface Config {
-
- Optional get(String name, Class type);
-
- }
-
-}
diff --git a/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/OciExtension.java b/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/OciExtension.java
index f40888e2fea..2882f1e15bd 100644
--- a/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/OciExtension.java
+++ b/integrations/oci/sdk/cdi/src/main/java/io/helidon/integrations/oci/sdk/cdi/OciExtension.java
@@ -27,10 +27,8 @@
import java.security.ProtectionDomain;
import java.util.Arrays;
import java.util.Collection;
-import java.util.EnumSet;
import java.util.HashSet;
import java.util.Objects;
-import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -40,6 +38,13 @@
import com.oracle.bmc.Service;
import com.oracle.bmc.auth.AbstractAuthenticationDetailsProvider;
+import com.oracle.bmc.auth.BasicAuthenticationDetailsProvider;
+import com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider;
+import com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider.InstancePrincipalsAuthenticationDetailsProviderBuilder;
+import com.oracle.bmc.auth.ResourcePrincipalAuthenticationDetailsProvider;
+import com.oracle.bmc.auth.ResourcePrincipalAuthenticationDetailsProvider.ResourcePrincipalAuthenticationDetailsProviderBuilder;
+import com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider;
+import com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider.SimpleAuthenticationDetailsProviderBuilder;
import com.oracle.bmc.common.ClientBuilderBase;
import jakarta.enterprise.event.Event;
import jakarta.enterprise.event.Observes;
@@ -58,6 +63,9 @@
import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.ConfigProvider;
+import static io.helidon.config.mp.MpConfig.toHelidonConfig;
+import static io.helidon.integrations.oci.sdk.runtime.OciExtension.fallbackConfigSupplier;
+import static io.helidon.integrations.oci.sdk.runtime.OciExtension.ociAuthenticationProvider;
import static java.lang.invoke.MethodType.methodType;
/**
@@ -559,6 +567,11 @@ public final class OciExtension implements Extension {
private static final Lookup PUBLIC_LOOKUP = MethodHandles.publicLookup();
+ private static final Set> ADP_BUILDER_CLASSES =
+ Set.of(InstancePrincipalsAuthenticationDetailsProviderBuilder.class,
+ ResourcePrincipalAuthenticationDetailsProviderBuilder.class,
+ SimpleAuthenticationDetailsProviderBuilder.class);
+
private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
@@ -634,7 +647,7 @@ private void processInjectionPoint(@Observes ProcessInjectionPoint, ?> event)
}
Set qualifiers = ip.getQualifiers();
if (AbstractAuthenticationDetailsProvider.class.isAssignableFrom(baseClass)
- || AdpSelectionStrategy.builderClasses().contains(baseClass)) {
+ || ADP_BUILDER_CLASSES.contains(baseClass)) {
// Use an "empty" ServiceTaqs as an indicator of demand
// for some kind of AbstractAuthenticationDetailsProvider
// (or a relevant builder).
@@ -652,14 +665,17 @@ private void processInjectionPoint(@Observes ProcessInjectionPoint, ?> event)
}
private void afterBeanDiscovery(@Observes AfterBeanDiscovery event, BeanManager bm) {
- for (ServiceTaqs serviceTaqs : this.serviceTaqs) {
- if (serviceTaqs.isEmpty()) {
- installAdps(event, bm, serviceTaqs.qualifiers());
- } else {
- TypeAndQualifiers serviceClientBuilder = serviceTaqs.serviceClientBuilder();
- TypeAndQualifiers serviceClient = serviceTaqs.serviceClient();
- installServiceClientBuilder(event, bm, serviceClientBuilder, serviceClient, this.lenientClassloading);
- installServiceClient(event, bm, serviceClient, serviceTaqs.serviceInterface(), serviceClientBuilder);
+ if (!this.serviceTaqs.isEmpty()) {
+ fallbackConfigSupplier(() -> toHelidonConfig(ConfigProvider.getConfig()));
+ for (ServiceTaqs serviceTaqs : this.serviceTaqs) {
+ if (serviceTaqs.isEmpty()) {
+ installAdps(event, bm, serviceTaqs.qualifiers());
+ } else {
+ TypeAndQualifiers serviceClientBuilder = serviceTaqs.serviceClientBuilder();
+ TypeAndQualifiers serviceClient = serviceTaqs.serviceClient();
+ installServiceClientBuilder(event, bm, serviceClientBuilder, serviceClient, this.lenientClassloading);
+ installServiceClient(event, bm, serviceClient, serviceTaqs.serviceInterface(), serviceClientBuilder);
+ }
}
}
}
@@ -823,43 +839,88 @@ private Class> toClassUnresolved(Consumer super ClassNotFoundException> erro
private static void installAdps(AfterBeanDiscovery event, BeanManager bm, Annotation[] qualifiersArray) {
Set qualifiers = Set.of(qualifiersArray);
- for (AdpSelectionStrategy s : EnumSet.allOf(AdpSelectionStrategy.class)) {
- Type builderType = s.builderType();
- if (builderType != null) {
- TypeAndQualifiers builderTaq = new TypeAndQualifiers(builderType, qualifiersArray);
- if (isUnsatisfied(bm, builderTaq)) {
- event.addBean()
- .types(builderType)
- .qualifiers(qualifiers)
- .scope(Singleton.class)
- .produceWith(i -> produceAdpBuilder(s, i, qualifiersArray));
- }
- }
- Type type = s.type();
- TypeAndQualifiers taq = new TypeAndQualifiers(type, qualifiersArray);
- if (isUnsatisfied(bm, taq)) {
- event.addBean()
- .types(type)
- .qualifiers(qualifiers)
- .scope(Singleton.class)
- .produceWith(i -> produceAdp(s, i, qualifiersArray));
- }
+
+ // AbstractAuthenticationDetailsProvider
+ if (isUnsatisfied(bm, AbstractAuthenticationDetailsProvider.class, qualifiersArray)) {
+ Supplier extends AbstractAuthenticationDetailsProvider> s = ociAuthenticationProvider();
+ event.addBean()
+ .types(AbstractAuthenticationDetailsProvider.class)
+ .qualifiers(qualifiers)
+ .scope(Singleton.class)
+ .produceWith(i ->
+ s.get());
}
- }
- private static Object produceAdpBuilder(AdpSelectionStrategy s,
- Instance super Object> instance,
- Annotation[] qualifiersArray) {
- Object builder = s.produceBuilder(SelectorShim.of(instance), ConfigShim.of(instance), qualifiersArray);
- // Permit arbitrary customization.
- fire(instance, builder, qualifiersArray);
- return builder;
- }
+ // BasicAuthenticationDetailsProvider
+ if (isUnsatisfied(bm, BasicAuthenticationDetailsProvider.class, qualifiersArray)) {
+ Supplier extends AbstractAuthenticationDetailsProvider> s = ociAuthenticationProvider();
+ event.addBean()
+ .types(BasicAuthenticationDetailsProvider.class)
+ .qualifiers(qualifiers)
+ .scope(Singleton.class)
+ .produceWith(i ->
+ (BasicAuthenticationDetailsProvider) s.get());
+ }
- private static AbstractAuthenticationDetailsProvider produceAdp(AdpSelectionStrategy s,
- Instance super Object> instance,
- Annotation[] qualifiersArray) {
- return s.produce(SelectorShim.of(instance), ConfigShim.of(instance), qualifiersArray);
+ // InstancePrincipalsAuthenticationDetailsProvider
+ if (isUnsatisfied(bm, InstancePrincipalsAuthenticationDetailsProviderBuilder.class, qualifiersArray)) {
+ event.addBean()
+ .types(InstancePrincipalsAuthenticationDetailsProviderBuilder.class)
+ .qualifiers(qualifiers)
+ .scope(Singleton.class)
+ .produceWith(i -> fire(i, InstancePrincipalsAuthenticationDetailsProvider.builder(), qualifiersArray));
+ }
+ if (isUnsatisfied(bm, InstancePrincipalsAuthenticationDetailsProvider.class, qualifiersArray)) {
+ event.addBean()
+ .types(InstancePrincipalsAuthenticationDetailsProvider.class)
+ .qualifiers(qualifiers)
+ .scope(Singleton.class)
+ .produceWith(i ->
+ i.select(InstancePrincipalsAuthenticationDetailsProviderBuilder.class,
+ qualifiersArray)
+ .get()
+ .build());
+ }
+
+ // ResourcePrincipalAuthenticationDetailsProvider
+ if (isUnsatisfied(bm, ResourcePrincipalAuthenticationDetailsProviderBuilder.class, qualifiersArray)) {
+ event.addBean()
+ .types(ResourcePrincipalAuthenticationDetailsProviderBuilder.class)
+ .qualifiers(qualifiers)
+ .scope(Singleton.class)
+ .produceWith(i -> fire(i, ResourcePrincipalAuthenticationDetailsProvider.builder(), qualifiersArray));
+ }
+ if (isUnsatisfied(bm, ResourcePrincipalAuthenticationDetailsProvider.class, qualifiersArray)) {
+ event.addBean()
+ .types(ResourcePrincipalAuthenticationDetailsProvider.class)
+ .qualifiers(qualifiers)
+ .scope(Singleton.class)
+ .produceWith(i ->
+ i.select(ResourcePrincipalAuthenticationDetailsProviderBuilder.class,
+ qualifiersArray)
+ .get()
+ .build());
+ }
+
+ // SimpleAuthenticationDetailsProvider
+ if (isUnsatisfied(bm, SimpleAuthenticationDetailsProviderBuilder.class, qualifiersArray)) {
+ event.addBean()
+ .types(SimpleAuthenticationDetailsProviderBuilder.class)
+ .qualifiers(qualifiers)
+ .scope(Singleton.class)
+ .produceWith(i -> fire(i, SimpleAuthenticationDetailsProvider.builder(), qualifiersArray));
+ }
+ if (isUnsatisfied(bm, SimpleAuthenticationDetailsProvider.class, qualifiersArray)) {
+ event.addBean()
+ .types(SimpleAuthenticationDetailsProvider.class)
+ .qualifiers(qualifiers)
+ .scope(Singleton.class)
+ .produceWith(i ->
+ i.select(SimpleAuthenticationDetailsProviderBuilder.class,
+ qualifiersArray)
+ .get()
+ .build());
+ }
}
private static boolean installServiceClientBuilder(AfterBeanDiscovery event,
@@ -963,8 +1024,7 @@ private static Object produceClientBuilder(Instance super Object> instance,
throw new AssertionError(impossible.getMessage(), impossible);
}
// Permit arbitrary customization.
- fire(instance, builderInstance, qualifiers);
- return builderInstance;
+ return fire(instance, builderInstance, qualifiers);
}
private static Object produceClient(Instance super Object> instance, Class> builderClass, Annotation[] qualifiersArray) {
@@ -995,8 +1055,9 @@ private static void close(AutoCloseable autoCloseable) {
}
@SuppressWarnings("unchecked")
- private static void fire(Instance super Object> instance, T payload, Annotation[] qualifiers) {
+ private static T fire(Instance super Object> instance, T payload, Annotation[] qualifiers) {
instance.select(EVENT_OBJECT_TYPE_LITERAL).get().select((Class) payload.getClass(), qualifiers).fire(payload);
+ return payload;
}
private static boolean isUnsatisfied(BeanManager bm, TypeAndQualifiers taq) {
@@ -1301,96 +1362,4 @@ public final boolean equals(Object other) {
}
- private static class SelectorShim implements AdpSelectionStrategy.Selector {
-
-
- /*
- * Instance fields.
- */
-
-
- private final Instance super Object> instance;
-
-
- /*
- * Constructors.
- */
-
-
- private SelectorShim(Instance super Object> instance) {
- super();
- this.instance = Objects.requireNonNull(instance, "instance");
- }
-
-
- /*
- * Instance methods.
- */
-
-
- @Override // AdpSelectionStrategy.Selector
- public final Supplier select(Class type, Annotation... qualifiers) {
- return this.instance.select(type, qualifiers)::get;
- }
-
-
- /*
- * Static methods.
- */
-
-
- private static SelectorShim of(Instance super Object> instance) {
- return new SelectorShim(instance);
- }
-
- }
-
- private static class ConfigShim implements AdpSelectionStrategy.Config {
-
-
- /*
- * Instance fields.
- */
-
-
- private final Config config;
-
-
- /*
- * Constructors.
- */
-
-
- private ConfigShim(Config config) {
- super();
- this.config = Objects.requireNonNull(config, "config");
- }
-
-
- /*
- * Instance methods.
- */
-
-
- @Override // AdpSelectionStrategy.Config
- public final Optional get(String propertyName, Class propertyType) {
- return config.getOptionalValue(propertyName, propertyType);
- }
-
-
- /*
- * Static methods.
- */
-
-
- private static ConfigShim of(Config config) {
- return new ConfigShim(config);
- }
-
- private static ConfigShim of(Instance super Object> instance) {
- return of(instance.select(Config.class).get());
- }
-
- }
-
}
diff --git a/integrations/oci/sdk/cdi/src/main/java/module-info.java b/integrations/oci/sdk/cdi/src/main/java/module-info.java
index 95961df80cc..3336a5ea06e 100644
--- a/integrations/oci/sdk/cdi/src/main/java/module-info.java
+++ b/integrations/oci/sdk/cdi/src/main/java/module-info.java
@@ -30,10 +30,12 @@
requires transitive jakarta.cdi;
requires jakarta.inject;
requires jakarta.ws.rs;
+ requires io.helidon.config.mp;
+ requires io.helidon.integrations.oci.sdk.runtime;
requires microprofile.config.api;
requires oci.java.sdk.common;
requires oci.java.sdk.common.httpclient;
-
+
exports io.helidon.integrations.oci.sdk.cdi;
provides jakarta.enterprise.inject.spi.Extension
diff --git a/integrations/oci/sdk/cdi/src/test/java/io/helidon/integrations/oci/sdk/cdi/TestOciSdkRuntimeOciExtension.java b/integrations/oci/sdk/cdi/src/test/java/io/helidon/integrations/oci/sdk/cdi/TestOciSdkRuntimeOciExtension.java
new file mode 100644
index 00000000000..f0d17bcb079
--- /dev/null
+++ b/integrations/oci/sdk/cdi/src/test/java/io/helidon/integrations/oci/sdk/cdi/TestOciSdkRuntimeOciExtension.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2023 Oracle and/or its affiliates.
+ *
+ * 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 io.helidon.integrations.oci.sdk.cdi;
+
+import java.util.Map;
+import java.util.Set;
+
+import io.helidon.config.Config;
+
+import com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider;
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
+import org.eclipse.microprofile.config.spi.ConfigSource;
+import org.junit.jupiter.api.Test;
+
+import static io.helidon.config.mp.MpConfig.toHelidonConfig;
+import static io.helidon.integrations.oci.sdk.runtime.OciExtension.configSupplier;
+import static io.helidon.integrations.oci.sdk.runtime.OciExtension.configuredAuthenticationDetailsProvider;
+import static io.helidon.integrations.oci.sdk.runtime.OciExtension.fallbackConfigSupplier;
+import static io.helidon.integrations.oci.sdk.runtime.OciExtension.isSufficientlyConfigured;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+class TestOciSdkRuntimeOciExtension {
+
+ @Test
+ void testOciSdkRuntimeOciExtensionUsesEmptyMicroProfileConfigProperly() {
+ // Create a MicroProfile Config Config object that is almost entirely empty, save for a single property used to
+ // test that this creation worked.
+ org.eclipse.microprofile.config.Config emptyMicroProfileConfig = ConfigProviderResolver.instance().getBuilder()
+ .withSources(new MinimalConfigSource(Map.of("valid", "true")))
+ .build();
+
+ // (Sanity check.)
+ assertThat(emptyMicroProfileConfig.getValue("valid", String.class), is(equalTo("true")));
+
+ // Convert the MicroProfile Config Config into a Helidon Config.
+ Config hc = toHelidonConfig(emptyMicroProfileConfig);
+ assertThat(hc, not(equalTo(nullValue())));
+
+ // Pass it to the io.helidon.integrations.oci.sdk.runtime.OciExtension class as its "fallback config supplier".
+ fallbackConfigSupplier(() -> hc);
+
+ // Assert that this method call worked.
+ assertThat(configSupplier().get(), is(equalTo(hc)));
+
+ // Assert that the Helidon Config is not "sufficiently configured", for the purposes of the
+ // io.helidon.integrations.oci.sdk.runtime.OciExtension class, since it does not specify an explicit
+ // authentication strategy. This effectively tests whether "auto" is
+ // io.helidon.integrations.oci.sdk.runtime.OciExtension's effective authentication strategy.
+ assertThat(isSufficientlyConfigured(hc), is(equalTo(false)));
+ }
+
+ @Test
+ void testOciSdkRuntimeOciExtensionUsesNonEmptyMicroProfileConfigProperly() {
+ // Create a MicroProfile Config Config object that contains "oci.auth-strategies" set to "config" only. Note
+ // that, deliberately, although its value is "config", there are deliberately no other properties. The
+ // io.helidon.integrations.oci.sdk.runtime.OciExtension class will indicate that this is a valid strategy, but
+ // (correctly) that it is not available since we didn't set any other properties.
+ org.eclipse.microprofile.config.Config c = ConfigProviderResolver.instance().getBuilder()
+ .withSources(new MinimalConfigSource(Map.of("oci.auth-strategies", "config")))
+ .build();
+
+ // (Sanity check.)
+ assertThat(c.getValue("oci.auth-strategies", String.class), is(equalTo("config")));
+
+ // Convert the MicroProfile Config Config into a Helidon Config.
+ Config hc = toHelidonConfig(c);
+ assertThat(hc, not(equalTo(nullValue())));
+
+ // Pass it to the io.helidon.integrations.oci.sdk.runtime.OciExtension class as its "fallback config supplier".
+ fallbackConfigSupplier(() -> hc);
+
+ // Assert that this method call worked.
+ assertThat(configSupplier().get(), is(equalTo(hc)));
+
+ // Assert that the selected strategy is not, in fact, available, since we didn't supply enough information for
+ // it to be so. We have to pass "false" for "verifyIsAvailable" because otherwise, despite the fact we have
+ // specified an unavailable but explicit strategy, it will try to fall back to a different one.
+ assertThat(configuredAuthenticationDetailsProvider(false), is(equalTo(SimpleAuthenticationDetailsProvider.class)));
+ }
+
+ private static class MinimalConfigSource implements ConfigSource {
+
+ private final Map properties;
+
+ private MinimalConfigSource(Map properties) {
+ super();
+ this.properties = Map.copyOf(properties);
+ }
+
+ @Override
+ public String getName() {
+ return this.getClass().getName();
+ }
+
+ @Override
+ public Map getProperties() {
+ return this.properties;
+ }
+
+ @Override
+ public Set getPropertyNames() {
+ return this.getProperties().keySet();
+ }
+
+ @Override
+ public String getValue(String propertyName) {
+ return propertyName == null ? null : this.getProperties().get(propertyName);
+ }
+
+ }
+
+}