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, while sub-interfaces within the
oracle.jdbc.spi package define methods to provide a particular type
of resource:
ConnectionStringProviderUsernameProviderPasswordProviderTlsConfigurationProviderAccessTokenProviderTraceEventListenerProviderJsonProviderEndUserSecurityContextProvider
OracleResourceProvider and its sub-interfaces are a Service
Provider Interface (SPI). Oracle JDBC uses ServiceLoader to locate
implementations of these interfaces.
A provider is installed by including its implementation in the class
path or module path of a JVM. Programmers who implement a provider must
meet the requirements defined by ServiceLoader for deploying service
providers on the class path or module path.
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 |
| oracle.jdbc.provider.json | Identifies a JsonProvider |
| oracle.jdbc.provider.endUserSecurityContext | Identifies an EndUserSecurityContextProvider |
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.
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
which may be identified by setting 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
.
Oracle JDBC uses ServiceLoader to locate providers each time a
Connection is created. Providers are
located using the class loader of
the thread which creates a connection.
Sub-interfaces of
OracleResourceProvider define methods that return a specific
type of resource. The JavaDoc of each method specifies the conditions under
which Oracle JDBC will invoke them.
A RuntimeException may be thrown when Oracle JDBC invokes a
resource providing method. In this case, Oracle JDBC will throw a
SQLException with the ORA-18726 error code with the
RuntimeException as its
initial cause.
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.
Interfaces in the oracle.jdbc.spi package that extend
OracleResourceProvider are intended to have user
defined implementations. A user defined implementation can allow Oracle JDBC
to integrate with specialized systems or APIs that it would not integrate
with 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 loaded by ServiceLoader 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.
A password management service is an example of a specialized system that
a provider can allow Oracle JDBC to integrate with. 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:
getName() to
identify itself by the name "example-password-provider".
getParameters()
to define the parameters that configure it.
PasswordProvider.getPassword(Map) by adapting a specialized
system to the PasswordProvider interface. In this example,
the specialized system is the password management service and the SDK
which is used to access it.
Because the example provider implements the PasswordProvider
interface, Oracle JDBC will locate this class 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. The
JavaDoc of ServiceLoader offers more detailed information about how
it will locate and instantiate providers.
Implementations of OracleResourceProvider may define parameters which
configure their behavior, and these parameters can be set as
connection properties that are recognized by Oracle JDBC. 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 must implement OracleResourceProvider.Parameter.name() to return the
name of a parameter. The parameter can be configured as a connection property
by appending its name to the
connection property which identifies the
provider. If "X" is the connection property which identifies a provider,
and "Y" is the name of a parameter, then "X.Y" will configure that parameter
as a connection property. The example provider defined parameters named
"user_id" and "is_cache_enabled". Since this provider is identified using the
"oracle.jdbc.provider.password" connection property, its parameters may be
configured as:
oracle.jdbc.provider.password = example-password-provider oracle.jdbc.provider.password.user_id = 99 oracle.jdbc.provider.password.is_cache_enabled = false
Parameter must implement OracleResourceProvider.Parameter.isSensitive() to return
true if the value of a parameter may contain security sensitive
information. Oracle JDBC will handle values of security sensitive
parameters in the same way it handles a password: The value won't appear in
log messages, error messages, or memory dumps.
Parameter may implement OracleResourceProvider.Parameter.description() to return
a human readable summary of a parameter's effect, along with a range of
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.
Parameter may implement OracleResourceProvider.Parameter.defaultValue() to
return the default value of a parameter. The default implementation of
defaultValue returns null, signifying that the parameter has
no default value. If a parameter has a default value, and that parameter is
not explicitly configured with a value, then the default value will be
populated in the Map<Parameter, CharSequence> passed to resource
providing methods, such as PasswordProvider.getPassword(Map). Oracle
JDBC will treat default values as security sensitive if isSensitive()
returns true.
OracleResourceProvider.Parameter.isRequired() to return
true if it is required by a provider. 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.
| Modifier and Type | Interface and Description |
|---|---|
static interface |
OracleResourceProvider.Parameter
A parameter that configures an
OracleResourceProvider. |
| Modifier and Type | Method and Description |
|---|---|
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.
|
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.