Skip to content

Commit

Permalink
Squashable commit; refining
Browse files Browse the repository at this point in the history
Signed-off-by: Laird Nelson <laird.nelson@oracle.com>
  • Loading branch information
ljnelson committed Feb 14, 2024
1 parent 95b272a commit eef3238
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
*/
public abstract class AbstractConfigurableExtension<T> implements Extension {

private final Map<String, Properties> masterProperties;
private final Map<String, Properties> namedProperties;

private final Map<String, Properties> explicitlySetProperties;

Expand All @@ -76,7 +76,7 @@ public abstract class AbstractConfigurableExtension<T> implements Extension {
*/
protected AbstractConfigurableExtension() {
super();
this.masterProperties = new HashMap<>();
this.namedProperties = new HashMap<>();
this.explicitlySetProperties = new HashMap<>();
this.config = ConfigProvider.getConfig();
}
Expand Down Expand Up @@ -189,13 +189,13 @@ protected final Config getConfig() {
* names
*/
protected final Set<String> getNames() {
if (this.masterProperties.isEmpty()) {
if (this.namedProperties.isEmpty()) {
if (this.explicitlySetProperties.isEmpty()) {
return Set.of();
}
return Collections.unmodifiableSet(this.explicitlySetProperties.keySet());
}
return Collections.unmodifiableSet(this.masterProperties.keySet());
return Collections.unmodifiableSet(this.namedProperties.keySet());
}

/**
Expand All @@ -220,51 +220,53 @@ protected final Properties putProperties(String name, Properties properties) {
}

/**
* <strong>{@linkplain Map#clear() Clears}</strong>, and then builds or rebuilds, an internal map of properties
* <strong>{@linkplain Map#clear() Clears}</strong>, and then builds or rebuilds, an internal set of properties
* whose contents will be processed eventually by the {@link #addBean(BeanConfigurator, Named, Properties)} method.
*
* <p>If no subclass explicitly calls this method, it will be called by the {@link #addBean(BeanConfigurator, Named,
* Properties)} method just prior to its other activities.</p>
* <p>If no subclass explicitly calls this method, as is common, it will be called by the {@link
* #addBean(BeanConfigurator, Named, Properties)} method just prior to its other activities.</p>
*
* <p>Once the {@link #addBean(BeanConfigurator, Named, Properties)} method has run to completion, while this method
* may be called freely, its use is discouraged and its effects will no longer be used.</p>
*
* @see #addBean(BeanConfigurator, Named, Properties)
*/
protected final void initializeMasterProperties() {
this.masterProperties.clear();
protected final void initializeNamedProperties() {
this.namedProperties.clear();
Set<? extends String> allConfigPropertyNames = this.getConfigPropertyNames();
if (allConfigPropertyNames != null && !allConfigPropertyNames.isEmpty()) {
for (String configPropertyName : allConfigPropertyNames) {
Optional<String> propertyValue = this.config.getOptionalValue(configPropertyName, String.class);
if (propertyValue.isPresent()) {
Matcher matcher = this.getPropertyPatternMatcher(configPropertyName);
if (matcher != null && matcher.matches()) {
this.masterProperties.computeIfAbsent(this.getName(matcher), n -> new Properties())
.setProperty(this.getPropertyName(matcher), propertyValue.get());
/*
String name = this.getName(matcher);
Properties properties = this.masterProperties.computeIfAbsent(name, n -> new Properties());
properties.setProperty(this.getPropertyName(matcher), propertyValue.get());
*/
}
for (String configPropertyName : allConfigPropertyNames) {
Optional<String> propertyValue = this.config.getOptionalValue(configPropertyName, String.class);
if (propertyValue.isPresent()) {
Matcher matcher = this.getPropertyPatternMatcher(configPropertyName);
if (matcher != null && matcher.matches()) {
this.namedProperties.computeIfAbsent(this.getName(matcher), n -> new Properties())
.setProperty(this.getPropertyName(matcher), propertyValue.get());
}
}
}
this.masterProperties.putAll(this.explicitlySetProperties);
this.namedProperties.putAll(this.explicitlySetProperties);
}

/**
* Returns a {@link Set} of all known <em>configuration property names</em>.
*
* <p>This method never returns {@code null}.</p>
*
* <p>Overrides of this method must not return {@code null}.</p>
*
* <p>The {@link Set} returned by this method is {@linkplain Collections#unmodifiableSet(Set) unmodifiable}.</p>
*
* <p>Overrides of this method must ensure that the returned {@link Set} is {@linkplain
* Collections#unmodifiableSet(Set) unmodifiable}.</p>
*
* <p>The {@link Set} returned by this method is not safe for concurrent use by multiple threads.</p>
*
* <p>Any other semantics of the {@link Set} returned by this method are governed by the <a
* href="https://github.com/eclipse/microprofile-config" target="_parent">MicroProfile Config</a> specification.</p>
* <p>Overrides of this method may return {@link Set} instances that are not safe for concurrent use by multiple
* threads.</p>
*
* <p>Any other semantics of the {@link Set} returned by this method or any overrides of it are and must be governed
* by the <a href="https://github.com/eclipse/microprofile-config" target="_parent">MicroProfile Config</a>
* specification.</p>
*
* @return a non-{@code null}, {@linkplain Collections#unmodifiableSet(Set) unmodifiable <code>Set</code>} of all
* known configuration property names
Expand All @@ -273,32 +275,26 @@ protected final void initializeMasterProperties() {
*
* @see org.eclipse.microprofile.config.spi.ConfigSource#getPropertyNames()
*/
protected final Set<String> getConfigPropertyNames() {
protected Set<String> getConfigPropertyNames() {
Iterable<String> propertyNames = this.config.getPropertyNames();
if (propertyNames == null) {
if (propertyNames == null) { // MicroProfile Config specification allows this
return Set.of();
}
Set<String> set = new HashSet<>();
propertyNames.iterator().forEachRemaining(n -> set.add(n));
propertyNames.iterator().forEachRemaining(pn -> set.add(pn));
return Set.copyOf(set);
}

private void afterBeanDiscovery(@Observes AfterBeanDiscovery event) {
if (event != null) {
if (this.masterProperties.isEmpty()) {
this.initializeMasterProperties();
if (this.namedProperties.isEmpty()) {
this.initializeNamedProperties();
}
Set<? extends Entry<? extends String, ? extends Properties>> masterPropertiesEntries =
this.masterProperties.entrySet();
if (masterPropertiesEntries != null && !masterPropertiesEntries.isEmpty()) {
for (Entry<? extends String, ? extends Properties> entry : masterPropertiesEntries) {
if (entry != null) {
this.addBean(event.addBean(), NamedLiteral.of(entry.getKey()), entry.getValue());
}
}
for (Entry<? extends String, ? extends Properties> entry : this.namedProperties.entrySet()) {
this.addBean(event.addBean(), NamedLiteral.of(entry.getKey()), entry.getValue());
}
}
this.masterProperties.clear();
this.namedProperties.clear();
this.explicitlySetProperties.clear();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,40 @@
import oracle.ucp.jdbc.PoolXADataSourceImpl;

/**
* An {@link AbstractDataSourceExtension} that arranges for named {@link DataSource} injection points to be satisfied by
* the <a href="https://docs.oracle.com/en/database/oracle/oracle-database/21/jjucp/index.html">Oracle Universal
* Connection Pool</a>.
* An {@link AbstractDataSourceExtension} that arranges for {@linkplain Named named} {@link DataSource} injection points
* to be satisfied by the <a
* href="https://docs.oracle.com/en/database/oracle/oracle-database/21/jjucp/index.html">Oracle Universal Connection
* Pool</a>.
*
* <p>As with all portable extensions, to begin to make use of the features enabled by this class, ensure its containing
* artifact (normally a jar file) is on the runtime classpath of your CDI-enabled application.</p>
*
* <p>In accordance with the CDI specification, instances of this class are not necessarily safe for concurrent use by
* multiple threads.</p>
*
* <p>To support injection of a {@linkplain PoolDataSource Universal Connection Pool-backed <code>PoolDataSource</code>}
* named {@code test}, first ensure that enough MicroProfile Config configuration is present to create a valid {@link
* PoolDataSource}. For example, the following sample system properties are sufficient for a {@link PoolDataSource}
* named {@code test} to be created:</p>
*
* {@snippet lang="properties" :
* # (Note that "oracle.ucp.jdbc.PoolDataSource" below could be "javax.sql.DataSource" instead if you prefer
* # that your configuration not refer directly to Oracle-specific classnames in its keys.)
* # @link substring="oracle.ucp.jdbc.PoolDataSource" target="PoolDataSource" @link substring="oracle.jdbc.pool.OracleDataSource" target="oracle.jdbc.pool.OracleDataSource" :
* oracle.ucp.jdbc.PoolDataSource.test.connectionFactoryClassName=oracle.jdbc.pool.OracleDataSource
* oracle.ucp.jdbc.PoolDataSource.test.URL=jdbc:oracle:thin://@localhost:1521/XE
* oracle.ucp.jdbc.PoolDataSource.test.user=scott
* oracle.ucp.jdbc.PoolDataSource.test.password=tiger
* }
*
* <p>With configuration such as the above, you can now inject the implicit {@link PoolDataSource} it defines:</p>
*
* {@snippet :
* // Inject a PoolDataSource qualified with the name test into a private javax.sql.DataSource-typed field named ds:
* @jakarta.inject.Inject // @link substring="jakarta.inject.Inject" target="jakarta.inject.Inject"
* @jakarta.inject.Named("test") // @link substring="jakarta.inject.Named" target="jakarta.inject.Named"
* private javax.sql.DataSource ds; // @link substring="javax.sql.DataSource" target="DataSource"
* }
*/
public class UCPBackedDataSourceExtension extends AbstractDataSourceExtension {

Expand All @@ -63,7 +91,7 @@ public class UCPBackedDataSourceExtension extends AbstractDataSourceExtension {
static final Pattern DATASOURCE_NAME_PATTERN =
Pattern.compile("^(?:javax\\.sql\\.|oracle\\.ucp\\.jdbc\\.Pool)(XA)?DataSource\\.([^.]+)\\.(.*)$");
// Capturing groups: (1 ) (2 ) (3 )
// Are we XA? DS name DS Property
// Are we XA? DS name DS property name

private final Map<String, Boolean> xa;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,16 @@

/**
* An {@link AbstractConfigurableExtension} that provides injection support for {@link UniversalConnectionPoolManager}
* and {@link UniversalConnectionPool} instances.
* and {@linkplain Named named} {@link UniversalConnectionPool} instances.
*
* <p>As with all portable extensions, to begin to make use of the features enabled by this class, ensure its containing
* artifact (normally a jar file) is on the classpath of your CDI-enabled application.</p>
* artifact (normally a jar file) is on the runtime classpath of your CDI-enabled application.</p>
*
* <p>To support injection of the {@link UniversalConnectionPoolManager}, use normal CDI injection idioms:</p>
*
* {@snippet :
* // Inject the UniversalConnectionPoolManager into a private field named ucpManager:
* @jakarta.inject.Inject
* @jakarta.inject.Inject // @link substring="jakarta.inject.Inject" target="jakarta.inject.Inject"
* private oracle.ucp.admin.UniversalConnectionPoolManager ucpManager;
* }
*
Expand All @@ -70,8 +70,8 @@
*
* {@snippet :
* // Inject a UniversalConnectionPool whose getName() method returns test into a private field named ucp:
* @jakarta.inject.Inject
* @jakarta.inject.Named("test")
* @jakarta.inject.Inject // @link substring="jakarta.inject.Inject" target="jakarta.inject.Inject"
* @jakarta.inject.Named("test") // @link substring="jakarta.inject.Named" target="jakarta.inject.Named"
* private oracle.ucp.UniversalConnectionPool ucp; // assert "test".equals(ucp.getName());
* }
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ protected final Matcher getPropertyPatternMatcher(String configPropertyName) {
*
* <p>Implementations of this method must not return {@code null}.</p>
*
* <p>Implementations of this method must not invoke the {@link #getPropertyPatternMatcher(String)} method or an
* infinite loop may result.</p>
*
* <p>Given a {@link String} like
* <code>javax.sql.DataSource.<em>dataSourceName</em>.<em>dataSourcePropertyName</em></code>, any implementation of
* this method should return a non-{@code null} {@link Matcher} that is capable of being supplied to the {@link
Expand Down Expand Up @@ -101,6 +104,9 @@ protected final String getName(Matcher propertyPatternMatcher) {
*
* <p>Implementations of this method may return {@code null}.</p>
*
* <p>Implementations of this method must not invoke the {@link #getName(Matcher)} method or an infinite loop may
* result.</p>
*
* @param dataSourcePropertyPatternMatcher a {@link Matcher} produced by the {@link
* #getDataSourcePropertyPatternMatcher(String)} method; must not be {@code null}
*
Expand All @@ -121,6 +127,9 @@ protected final String getPropertyName(Matcher propertyPatternMatcher) {
*
* <p>Implementations of this method may return {@code null}.</p>
*
* <p>Implementations of this method must not invoke the {@link #getPropertyName(Matcher)} method or an infinite
* loop may result.</p>
*
* @param dataSourcePropertyPatternMatcher a {@link Matcher} produced by the {@link
* #getDataSourcePropertyPatternMatcher(String)} method; must not be {@code null}
*
Expand All @@ -140,7 +149,8 @@ protected final String getPropertyName(Matcher propertyPatternMatcher) {
* @return a non-{@code null}, {@linkplain Collections#unmodifiableSet(Set) unmodifiable <code>Set</code>} of known
* data source names
*
* @deprecated Please use the {@link #getNames()} method instead.
* @deprecated This method exists for backwards compatibility only. Please use the {@link #getNames()} method
* instead.
*/
@Deprecated // for backwards compatibility only
protected final Set<String> getDataSourceNames() {
Expand Down Expand Up @@ -169,4 +179,15 @@ protected final Properties putDataSourceProperties(final String dataSourceName,
return this.putProperties(dataSourceName, properties);
}

/**
* Calls the {@link #initializeNamedProperties()} method.
*
* @deprecated This method exists for backwards compatibility only. Please use the {@link
* #initializeNamedProperties()} method instead.
*/
@Deprecated // for backwards compatibility only
protected final void initializeMasterProperties() {
this.initializeNamedProperties();
}

}

0 comments on commit eef3238

Please sign in to comment.