Package oracle.jdbc.spi

## Interface OracleResourceProvider

All Known Subinterfaces:
  `AccessTokenProvider`, `ConnectionStringProvider`, `PasswordProvider`, `TlsConfigurationProvider`, `TraceEventListenerProvider`, `UsernameProvider`

All Known Implementing Classes:
  `DefaultTraceEventListenerProvider`

    public interface OracleResourceProvider

A provider of resources that are consumed by the Oracle JDBC Driver.

The `OracleResourceProvider` interface defines methods that are common to all resource providers. Interfaces in the `oracle.jdbc.spi` package extend `OracleResourceProvider` to provide a particular type of resource:

`ConnectionStringProvider`
  Provides a connection string for establishing a network connection with Oracle Database.
`UsernameProvider`
  Provides a username for authentication with Oracle Database.
`PasswordProvider`
  Provides a password for authentication with Oracle Database.
`TlsConfigurationProvider`
  Provides keys and certificates for TLS communication with Oracle Database.
`AccessTokenProvider`
  Provides an OAUTH access token that authorizes logins to Oracle Database.
`TraceEventListenerProvider`
  Provides a listener for receiving application and system tracing events.

### Installing a Provider

Interfaces that extend `OracleResourceProvider` define a Service Provider Interface (SPI). Oracle JDBC locates implementations of these interfaces using `ServiceLoader`.

A provider is installed by including its implementation in the class path or module path of a JVM. Programmers who implement a provider must met the requirements defined by `ServiceLoader` for deploying service providers on the class path or module path.

### Identifying a Provider

A provider is identified by setting one of the following connection properties to the name of a provider:

Connection Property | Provider Type
--- | ---
oracle.jdbc.provider.connectionString | Identifies a `ConnectionStringProvider`
oracle.jdbc.provider.username | Identifies a `UsernameProvider`
oracle.jdbc.provider.password | Identifies a `PasswordProvider`
oracle.jdbc.provider.accessToken | Identifies an `AccessTokenProvider`
oracle.jdbc.provider.tlsConfiguration | Identifies a `TlsConfigurationProvider`
oracle.jdbc.provider.traceEventListener | Identifies a `TraceEventListenerProvider`

### Configuring a Provider

A provider may support one or more parameters that configure its behavior. Each individual implementation of `OracleResourceProvider` defines the set of parameters it supports, if any. These parameters may be queried by calling `getParameters()`.

A parameter is configured as a connection property by appending its name to the name of a connection property that identifies a provider. For example, the following connection properties would configure the "user_id" parameter of a password provider:

        oracle.jdbc.provider.password=example-password-provider
        oracle.jdbc.provider.password.user_id=99

The names of parameters are case-insensitive. In the example above, changing "user_id" to "USER_ID" would configure the same parameter.

Connection properties in the `oracle.jdbc.provider` namespace may be configured using any programmatic API that accepts connection properties, or using an connection properties file . These properties can not be set as JVM system properties.

### Querying Installed Providers

Tools and applications may call `OracleDriver.getPropertyInfo(String, Properties)` to retrieve information about installed providers at runtime.

The `getPropertyInfo` method returns a `DriverPropertyInfo` object for each connection property that identifies a provider . The `DriverPropertyInfo.choices` field of these objects contains the name of each provider that is installed and that may be identified by the property. If the `Properties` argument to `getPropertyInfo` already contains an entry that identifies a provider, a `DriverPropertyInfo` object is returned for each connection property that configures a parameter of that provider .

### How Oracle JDBC Interacts with a Provider

Oracle JDBC locates providers and requests resources from them each time a `Connection` is created. Providers are located using the class loader of the thread which creates a connection.

Oracle JDBC does not cache resources. Providers may implement their own caching strategy when it makes sense to do so.

If the request for a resource fails, Oracle JDBC throws a `SQLException` with the ORA-18726 error code. The cause of the `SQLException` may convey additional information about the failure.

Oracle JDBC will often support alternative methods for configuring a provided resource. For instance, a password may be configured with the "oracle.jdbc.password" property, or may be passed as an argument to `DataSource.getConnection(String, String)`. A resource is only requested from a provider if no alternative method has configured it. The JavaDoc of each connection property that identifies a provider specifies any alternative configuration methods that will override a provider.

### Implementing a Provider

Interfaces in the `oracle.jdbc.spi` package that extend `OracleResourceProvider` with methods that provide a particular type of resource to Oracle JDBC. These interfaces are intended to have user defined implementations that provide resources from a specialized process that Oracle JDBC would not support otherwise.

Programmers who implement these interfaces must adhere to their specification. The specification is defined by the class level and method level JavaDocs of these interfaces. Oracle JDBC will raise a error if a provider is not implemented according to this specification.

Thread safety is not strictly required. Oracle JDBC uses `ServiceLoader.load(Class)` to obtain an instance of a provider each time a new `Connection` is created. The instance that `ServiceLoader` locates is not shared with any other thread that creates a `Connection`. If each call to `ServiceLoader.load(Class)` returns a new instance, then concurrent access to the same instance is not possible.

### Example Implementation

An example of a specialized process that a provider might implement is to request a password from a password management service. In the following code example, the `PasswordProvider` interface is implemented using the SDK of a fictional password management service:

      import com.example.PasswordRequest;
      import com.example.PasswordService;
      import oracle.jdbc.spi.PasswordProvider;

      import java.util.Arrays;
      import java.util.Collection;
      import java.util.Map;
      import java.util.Objects;

      public class ExamplePasswordProvider implements PasswordProvider {

        @Override
        public String getName() {
          return "example-password-provider";
        }

        @Override
        public Collection<Parameter> getParameters() {
          return Arrays.asList(ProviderParameter.values());
        }

        @Override
        public char[] getPassword(Map<Parameter, CharSequence> parameters) {

          Objects.requireNonNull(parameters, "parameters is null");

          PasswordRequest request = createRequest(parameters);
          char[] password = PasswordService.requestPassword(request);

          return password;
        }

        private PasswordRequest createRequest(Map<Parameter, CharSequence> parameters) {

          PasswordRequest.Builder requestBuilder = PasswordRequest.builder();

          for (Map.Entry<Parameter, CharSequence> entry : parameters.entrySet()) {

            Parameter parameter = entry.getKey();

            if (!(parameter instanceof ProviderParameter)) {
              throw new IllegalArgumentException(
                "Unrecognized parameter: " + parameter);
            }

            ProviderParameter providerParameter = (ProviderParameter)parameter;
            providerParameter.configureBuilder(requestBuilder, entry.getValue());
          }

          return requestBuilder.build();
        }

        private enum ProviderParameter implements Parameter {

          USER_ID {

            @Override
            public String description() {
              return "The ID of a user that accesses the password management service.";
            }

            @Override
            public boolean isSensitive() {
              return false;
            }

            @Override
            public boolean isRequired() {
              return true;
            }

            @Override
            void configureBuilder(
              PasswordRequest.Builder builder, CharSequence value) {
              String userId = value.toString();
              builder.userId(userId);
            }

          },

          IS_CACHE_ENABLED {

            @Override
            public String description() {
              return "Set to a value other than \"true\" to disable caching of passwords";
            }

            @Override
            public boolean isSensitive() {
              return false;
            }

            @Override
            public String defaultValue() {
              return "true";
            }

            @Override
            void configureBuilder(PasswordRequest.Builder builder, CharSequence value) {
              boolean isCacheEnabled = Boolean.parseBoolean(value.toString());
              builder.isCacheEnabled(isCacheEnabled);
            }

          };

          abstract void configureBuilder(
            PasswordRequest.Builder builder, CharSequence value);

        }

      }

The example above demonstrates the key functions of an `OracleResourceProvider`:

1. Identification: The provider implements `getName()` to identify itself by the name "example-password-provider".
2. Configuration: The provider implements `getParameters()` to define the parameters that configure it.
3. Adaptation: The provider implements `PasswordProvider.getPassword(Map)` by adapting a specialized process to the `PasswordProvider` interface. In this example, the specialized process is the usage of an SDK for the password management service.

The example provider implements the `PasswordProvider` interface. Oracle JDBC locates implementations of this interface by calling ServiceLoader.load(PasswordProvider.class). `ServiceLoader` instantiates `ExamplePasswordProvider` if the class name is declared with a `META-INF/services/oracle.jdbc.spi.PasswordProvider` file, or with a `module-info.java` file having the "`provides oracle.jdbc.spi.PasswordProvider`" directive. A full specification of how providers are located and instantiated can be found in the JavaDoc of the `ServiceLoader` class.

### Defining Parameters

Implementations of `OracleResourceProvider` may define parameters that can be configured as connection properties. Defining parameters is optional. A provider may implement `getParameters()` to return an empty `Collection` if it does not support any parameters.

If a provider defines parameters, then it must implement the `Parameter` interface to describe the attributes of each parameter. These attributes effect how Oracle JDBC will process the parameter, and may also be utilized by database tools.

Parameter Names
  A `Parameter` must implement `OracleResourceProvider.Parameter.name()` to identify the parameter. The name may be used to configure the parameter as a connection property. Where a connection property named "X" identifies a provider, and the provider defines a parameter named "Y", a connection property named "X.Y" configures that parameter. To illustrate, the example provider implementation defines parameters named "user_id" and "is_cache_enabled". When this provider is identified by the "oracle.jdbc.provider.password" connection property, its parameters may be configured as shown below:

        oracle.jdbc.provider.password=example-password-provider
        oracle.jdbc.provider.password.user_id=99
        oracle.jdbc.provider.password.is_cache_enabled=false

Security Sensitivity
  A `Parameter` must implement `OracleResourceProvider.Parameter.isSensitive()` to return `true` if the value of that parameter contains security sensitive information. Oracle JDBC will handle the value of a security sensitive parameter in the same way it handles a password: The value won't appear in log messages, error messages, or memory dumps.
Descriptions
  A `Parameter` may implement `OracleResourceProvider.Parameter.description()` to return a human readable summary of the parameter's effect, and the range of values it may be set to. A database tool may display this description to a user.
Default Values
  A parameter may implement `OracleResourceProvider.Parameter.defaultValue()` to return its default value. The default implementation of `defaultValue` returns `null`, signifying that there is no default value for that parameter. Oracle JDBC populates the `Map<Parameter, CharSequence>` it passes to a provider with the default value of any parameter that is not configured by a connection property. Oracle JDBC will treat default values as security sensitive if `isSensitive()` returns `true`.
Required Parameters
  A parameter may implement `OracleResourceProvider.Parameter.isRequired()` to return `true` if a provider requires that parameter to be set. The default implementation of `isRequired()` returns `false`. Oracle JDBC throws a `SQLException` if no value is configured for a required parameter, and that parameter has no default value.

Since:
  23

### Nested Class Summary

Nested Classes
`static interface` `OracleResourceProvider.Parameter` A parameter that configures an `OracleResourceProvider`.

### Method Summary

All Methods Instance Methods Abstract Methods Default Methods
`java.lang.String` `getName()` Returns the name of this provider.
`default java.util.Collection<? extends OracleResourceProvider.Parameter>` `getParameters()` Returns a collection of parameters that configure this provider, if any.

### Method Detail

#### getName

    java.lang.String getName()

Returns the name of this provider.

Returns:
  The name of this provider. Not null.

#### getParameters

    default java.util.Collection<? extends OracleResourceProvider.Parameter> getParameters()

Returns a collection of parameters that configure this provider, if any.

Returns:
  A collection of parameters supported by this provider. Not null. May be empty if this provider does not support any parameters.