Class JDBCPairwiseIdStore
- java.lang.Object
-
- net.shibboleth.utilities.java.support.component.AbstractInitializableComponent
-
- net.shibboleth.idp.attribute.impl.JDBCPairwiseIdStore
-
- All Implemented Interfaces:
DurablePairwiseIdStore,PairwiseIdStore,Component,DestructableComponent,InitializableComponent
public class JDBCPairwiseIdStore extends AbstractInitializableComponent implements DurablePairwiseIdStore
JDBC-based storage management for pairwise IDs.The general DDL for the database, which is unchanged for compatibility, is:
CREATE TABLE shibpid ( localEntity VARCHAR(255) NOT NULL, peerEntity VARCHAR(255) NOT NULL, persistentId VARCHAR(50) NOT NULL, principalName VARCHAR(50) NOT NULL, localId VARCHAR(50) NOT NULL, peerProvidedId VARCHAR(50) NULL, creationDate TIMESTAMP NOT NULL, deactivationDate TIMESTAMP NULL, PRIMARY KEY (localEntity, peerEntity, persistentId) );.The first three columns should be defined as the primary key of the table, and the other columns should be indexed.
- Since:
- 4.0.0
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description protected classJDBCPairwiseIdStore.ConnectionWithLockA Class to encapsulate aConnectionprotected by an optional read/write lock.
-
Field Summary
Fields Modifier and Type Field Description private StringattachSQLParameterized update statement used to attach an alias to an ID.private StringcreationTimeColumnName of the creation time column.private DataSourcedataSourceJDBC data source for retrieving connections.private StringdeactivateSQLParameterized update statement used to deactivate an ID.private StringdeactivationTimeColumnName of the deactivation time column.private StringdeleteSQLParameterized delete statement used to clear dummy rows after verification.private StringgetByIssuedSelectSQLParameterized select query for lookup by issued value.private StringgetBySourceSelectSQLParameterized select query for lookup by source ID.private PairwiseIdStoreinitialValueStoreOptional hook for obtaining initial values from a primary store, usually a computed algorithm.private StringinsertSQLParameterized insert statement used to insert a new record.private StringissuerColumnName of the issuer entityID column.private org.slf4j.LoggerlogClass logger.private StringpeerProvidedIdColumnName of recipient-attached alias column.private StringpersistentIdColumnName of the persistent ID column.private StringprincipalNameColumnName of the principal name column.private DurationqueryTimeoutTimeout of SQL queries.private ReadWriteLockreadWriteLockIf non-null we doing local locking.private StringrecipientColumnName of the recipient entityID column.private Collection<String>retryableErrorsError messages that signal a transaction should be retried.private StringsourceIdColumnName of the source ID column.private StringtableNameName of the database table.private inttransactionIsolationWhat transaction isolation do we want?private inttransactionRetryNumber of times to retry a transaction if it rolls back.private booleanverifyDatabaseWhether to fail if the database cannot be verified.
-
Constructor Summary
Constructors Constructor Description JDBCPairwiseIdStore()Constructor.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description voidattach(PairwiseId pid)Attach a peer-supplied alias to a pairwise ID.private List<PairwiseId>buildIdentifierEntries(ResultSet resultSet)Build a list ofPairwiseIdobjects from a result set.voiddeactivate(PairwiseId pid)Deactivate/revoke a pairwise ID.protected voiddoInitialize()PairwiseIdgetByIssuedValue(PairwiseId pid)Populate the underlying principal/source fields for the input object based on the supplied values.PairwiseIdgetBySourceValue(PairwiseId pid, boolean allowCreate)Populate the pairwise ID field for the input object based on the supplied values.DataSourcegetDataSource()Get the source datasource used to communicate with the database.PairwiseIdStoregetInitialValueStore()Get a store to use to produce the first value for a given issuer/recipient pair.DurationgetQueryTimeout()Get the SQL query timeout.Collection<String>getRetryableErrors()Get the error messages to check for classifying a driver error as retryable, generally indicating a lock violation or duplicate insert that signifies a broken database.StringgetTableName()Gets the table name.intgetTransactionRetries()Get the number of retries to attempt for a failed transaction.booleangetVerifyDatabase()Get whether to allow startup if the database cannot be verified.booleanisLocalLocking()Do we do thread level locking or delegate to the Database?voidsetAttachSQL(String sql)Set the UPDATE statement used to attach an SPProvidedID to an issued value.voidsetCreateTimeColumn(String name)Set the name of the creation time column.voidsetDataSource(DataSource source)Get the source datasource used to communicate with the database.voidsetDeactivateSQL(String sql)Set the UPDATE statement used to deactivate issued values.voidsetDeactivationTimeColumn(String name)Set the name of the deactivation time column.voidsetDeleteSQL(String sql)Set the DELETE statement used to clear dummy row(s) created during verification.voidsetGetByIssuedSelectSQL(String sql)Set the SELECT statement used to lookup records by issued value.voidsetGetBySourceSelectSQL(String sql)Set the SELECT statement used to lookup records by source ID.voidsetInitialValueStore(PairwiseIdStore store)Set a store to use to produce the first value for a given issuer/recipient pair.voidsetInsertSQL(String sql)Set the INSERT statement used to insert new records.voidsetLocalEntityColumn(String name)Set the name of the issuer entityID column.voidsetLocalLocking(boolean what)Will we do thread level locking or delegate to the Database?voidsetPeerEntityColumn(String name)Set the name of the recipient entityID column.voidsetPeerProvidedIdColumn(String name)Set the name of the peer-provided ID column.voidsetPersistentIdColumn(String name)Set the name of the persistent ID column.voidsetPrincipalNameColumn(String name)Set the name of the principal name column.voidsetQueryTimeout(Duration timeout)Set the SQL query timeout.voidsetRetryableErrors(Collection<String> errors)Set the error messages to check for classifying a driver error as retryable, generally indicating a lock violation or duplicate insert that signifies a broken database.voidsetSourceIdColumn(String name)Set the name of the source ID column.voidsetTableName(String name)Set the table name.voidsetTransactionIsolation(int what)Set the parameter that will be passed toConnection.setTransactionIsolation(int).voidsetTransactionRetries(int retries)Set the number of retries to attempt for a failed transaction.voidsetVerifyDatabase(boolean flag)Set whether to allow startup if the database cannot be verified.(package private) voidstore(PairwiseId entry, JDBCPairwiseIdStore.ConnectionWithLock dbConn)Store a record containing the values from the input object.private voidverifyDatabase()Check the database and the presence of a uniqueness constraint.-
Methods inherited from class net.shibboleth.utilities.java.support.component.AbstractInitializableComponent
destroy, doDestroy, initialize, isDestroyed, isInitialized
-
-
-
-
Field Detail
-
log
@Nonnull private final org.slf4j.Logger log
Class logger.
-
dataSource
@NonnullAfterInit private DataSource dataSource
JDBC data source for retrieving connections.
-
queryTimeout
@Nonnull private Duration queryTimeout
Timeout of SQL queries.
-
transactionRetry
@NonNegative private int transactionRetry
Number of times to retry a transaction if it rolls back.
-
transactionIsolation
private int transactionIsolation
What transaction isolation do we want?
-
retryableErrors
@Nonnull @NonnullElements private Collection<String> retryableErrors
Error messages that signal a transaction should be retried.
-
readWriteLock
private ReadWriteLock readWriteLock
If non-null we doing local locking.
-
verifyDatabase
private boolean verifyDatabase
Whether to fail if the database cannot be verified.
-
recipientColumn
@Nonnull @NotEmpty private String recipientColumn
Name of the recipient entityID column.
-
principalNameColumn
@Nonnull @NotEmpty private String principalNameColumn
Name of the principal name column.
-
persistentIdColumn
@Nonnull @NotEmpty private String persistentIdColumn
Name of the persistent ID column.
-
peerProvidedIdColumn
@Nonnull @NotEmpty private String peerProvidedIdColumn
Name of recipient-attached alias column.
-
creationTimeColumn
@Nonnull @NotEmpty private String creationTimeColumn
Name of the creation time column.
-
deactivationTimeColumn
@Nonnull @NotEmpty private String deactivationTimeColumn
Name of the deactivation time column.
-
getByIssuedSelectSQL
@NonnullAfterInit private String getByIssuedSelectSQL
Parameterized select query for lookup by issued value.
-
getBySourceSelectSQL
@NonnullAfterInit private String getBySourceSelectSQL
Parameterized select query for lookup by source ID.
-
insertSQL
@NonnullAfterInit private String insertSQL
Parameterized insert statement used to insert a new record.
-
deactivateSQL
@NonnullAfterInit private String deactivateSQL
Parameterized update statement used to deactivate an ID.
-
attachSQL
@NonnullAfterInit private String attachSQL
Parameterized update statement used to attach an alias to an ID.
-
deleteSQL
@NonnullAfterInit private String deleteSQL
Parameterized delete statement used to clear dummy rows after verification.
-
initialValueStore
@Nullable private PairwiseIdStore initialValueStore
Optional hook for obtaining initial values from a primary store, usually a computed algorithm.
-
-
Method Detail
-
getDataSource
@NonnullAfterInit public DataSource getDataSource()
Get the source datasource used to communicate with the database.- Returns:
- the data source;
-
setDataSource
public void setDataSource(@Nonnull DataSource source)Get the source datasource used to communicate with the database.- Parameters:
source- the data source;
-
setLocalLocking
public void setLocalLocking(boolean what)
Will we do thread level locking or delegate to the Database?- Parameters:
what- do we want to lock locally?
-
isLocalLocking
public boolean isLocalLocking()
Do we do thread level locking or delegate to the Database?- Returns:
- do we lock locally?
-
setTransactionIsolation
public void setTransactionIsolation(int what)
Set the parameter that will be passed toConnection.setTransactionIsolation(int).- Parameters:
what- the value to set
-
getQueryTimeout
@Nonnull public Duration getQueryTimeout()
Get the SQL query timeout.- Returns:
- the timeout
-
setQueryTimeout
public void setQueryTimeout(@Nonnull Duration timeout)Set the SQL query timeout. Defaults to 5s.- Parameters:
timeout- the timeout to set
-
getTransactionRetries
public int getTransactionRetries()
Get the number of retries to attempt for a failed transaction.- Returns:
- number of retries
-
setTransactionRetries
public void setTransactionRetries(@NonNegative int retries)
Set the number of retries to attempt for a failed transaction. Defaults to 3.- Parameters:
retries- the number of retries
-
getRetryableErrors
@Nonnull @NonnullElements @NotLive @Unmodifiable public Collection<String> getRetryableErrors()
Get the error messages to check for classifying a driver error as retryable, generally indicating a lock violation or duplicate insert that signifies a broken database.- Returns:
- retryable messages
-
setRetryableErrors
public void setRetryableErrors(@Nullable @NonnullElements Collection<String> errors)
Set the error messages to check for classifying a driver error as retryable, generally indicating a lock violation or duplicate insert that signifies a broken database.- Parameters:
errors- retryable messages
-
getVerifyDatabase
public boolean getVerifyDatabase()
Get whether to allow startup if the database cannot be verified.- Returns:
- whether to allow startup if the database cannot be verified
-
setVerifyDatabase
public void setVerifyDatabase(boolean flag)
Set whether to allow startup if the database cannot be verified.Verification consists not only of a liveness check, but the successful insertion of a dummy row, a failure to insert a duplicate, and then deletion of the row.
- Parameters:
flag- flag to set
-
getTableName
@Nonnull @NotEmpty public String getTableName()
Gets the table name.- Returns:
- table name
- Since:
- 4.1.0
-
setTableName
public void setTableName(@Nonnull @NotEmpty String name)
Set the table name.- Parameters:
name- table name
-
setLocalEntityColumn
public void setLocalEntityColumn(@Nonnull @NotEmpty String name)
Set the name of the issuer entityID column.- Parameters:
name- name of issuer column
-
setPeerEntityColumn
public void setPeerEntityColumn(@Nonnull @NotEmpty String name)
Set the name of the recipient entityID column.- Parameters:
name- name of recipient column
-
setPrincipalNameColumn
public void setPrincipalNameColumn(@Nonnull @NotEmpty String name)
Set the name of the principal name column.- Parameters:
name- name of principal name column
-
setSourceIdColumn
public void setSourceIdColumn(@Nonnull @NotEmpty String name)
Set the name of the source ID column.- Parameters:
name- name of source ID column
-
setPersistentIdColumn
public void setPersistentIdColumn(@Nonnull @NotEmpty String name)
Set the name of the persistent ID column.- Parameters:
name- name of the persistent ID column
-
setPeerProvidedIdColumn
public void setPeerProvidedIdColumn(@Nonnull @NotEmpty String name)
Set the name of the peer-provided ID column.- Parameters:
name- name of peer-provided ID column
-
setCreateTimeColumn
public void setCreateTimeColumn(@Nonnull @NotEmpty String name)
Set the name of the creation time column.- Parameters:
name- name of creation time column
-
setDeactivationTimeColumn
public void setDeactivationTimeColumn(@Nonnull @NotEmpty String name)
Set the name of the deactivation time column.- Parameters:
name- name of deactivation time column
-
setGetByIssuedSelectSQL
public void setGetByIssuedSelectSQL(@Nonnull @NotEmpty String sql)
Set the SELECT statement used to lookup records by issued value.- Parameters:
sql- statement text, which must contain three parameters (NameQualifier, SPNameQualifier, value)
-
setGetBySourceSelectSQL
public void setGetBySourceSelectSQL(@Nonnull @NotEmpty String sql)
Set the SELECT statement used to lookup records by source ID.- Parameters:
sql- statement text, which must contain six parameters (NameQualifier, SPNameQualifier, source ID, NameQualifier, SPNameQualifier, source ID)
-
setInsertSQL
public void setInsertSQL(@Nonnull @NotEmpty String sql)
Set the INSERT statement used to insert new records.- Parameters:
sql- statement text, which must contain 8 parameters (NameQualifier, SPNameQualifier, value, principal, source ID, SPProvidedID, creation time, deactivation time)
-
setDeactivateSQL
public void setDeactivateSQL(@Nonnull @NotEmpty String sql)
Set the UPDATE statement used to deactivate issued values.- Parameters:
sql- statement text, which must contain four parameters (deactivation TS, NameQualifier, SPNameQualifier, value)
-
setAttachSQL
public void setAttachSQL(@Nonnull @NotEmpty String sql)
Set the UPDATE statement used to attach an SPProvidedID to an issued value.- Parameters:
sql- statement text, which must contain four parameters (SPProvidedID, NameQualifier, SPNameQualifier, value)
-
setDeleteSQL
public void setDeleteSQL(@Nonnull @NotEmpty String sql)
Set the DELETE statement used to clear dummy row(s) created during verification.- Parameters:
sql- statement text, which must contain one parameter (NameQualifier)
-
getInitialValueStore
@Nullable public PairwiseIdStore getInitialValueStore()
Get a store to use to produce the first value for a given issuer/recipient pair.- Returns:
- initial value source
-
setInitialValueStore
public void setInitialValueStore(@Nullable PairwiseIdStore store)Set a store to use to produce the first value for a given issuer/recipient pair.This is typically used to draw the "first" (often only) value for a given pairwise relationship from an algorithm instead of a random value requiring storage to know.
- Parameters:
store- initial value source
-
doInitialize
protected void doInitialize() throws ComponentInitializationException- Overrides:
doInitializein classAbstractInitializableComponent- Throws:
ComponentInitializationException
-
getBySourceValue
@Nullable public PairwiseId getBySourceValue(@Nonnull PairwiseId pid, boolean allowCreate) throws IOException
Populate the pairwise ID field for the input object based on the supplied values.The input object must contain values for issuer and recipient entityIDs and the principal name, and the pairwise ID will be populated as applicable on output.
The object returned, if non-null, may be, but does not have to be, the same physical object used as input. The original input object should not be referenced further.
- Specified by:
getBySourceValuein interfacePairwiseIdStore- Parameters:
pid- object to populateallowCreate- true iff the caller is authorizing the issuance of a new identifier- Returns:
- object for the given inputs or null if none exists
- Throws:
IOException- if an error occurs accessing the store
-
getByIssuedValue
@Nullable public PairwiseId getByIssuedValue(@Nonnull PairwiseId pid) throws IOException
Populate the underlying principal/source fields for the input object based on the supplied values.The input object must contain values for issuer and recipient entityIDs and the pairwiseId itself, and the rest of the fields will be populated as applicable on output.
The object returned, if non-null, will at least contain the principal name and source system ID. It may be, but does not have to be, the same physical object used as input. The original input object should not be referenced further.
- Specified by:
getByIssuedValuein interfaceDurablePairwiseIdStore- Parameters:
pid- object to populate- Returns:
- object for the given inputs or null if none exists
- Throws:
IOException- if an error occurs accessing the store
-
deactivate
public void deactivate(@Nonnull PairwiseId pid) throws IOExceptionDeactivate/revoke a pairwise ID.If the object's deactivation time field is null, then the current time is used.
- Specified by:
deactivatein interfaceDurablePairwiseIdStore- Parameters:
pid- the object to deactivate/revoke- Throws:
IOException- if there is an error updating the store
-
attach
public void attach(@Nonnull PairwiseId pid) throws IOExceptionAttach a peer-supplied alias to a pairwise ID.- Specified by:
attachin interfaceDurablePairwiseIdStore- Parameters:
pid- the object to update in storage- Throws:
IOException- if there is an error updating the store
-
store
void store(@Nonnull PairwiseId entry, @Nonnull JDBCPairwiseIdStore.ConnectionWithLock dbConn) throws SQLExceptionStore a record containing the values from the input object.- Parameters:
entry- new object to storedbConn- connection to obtain a statement from.- Throws:
SQLException- if an error occurs
-
verifyDatabase
private void verifyDatabase() throws SQLExceptionCheck the database and the presence of a uniqueness constraint.- Throws:
SQLException- if the database cannot be verified
-
buildIdentifierEntries
@Nonnull @NonnullElements @Live private List<PairwiseId> buildIdentifierEntries(@Nonnull ResultSet resultSet) throws SQLException
Build a list ofPairwiseIdobjects from a result set.- Parameters:
resultSet- the result set- Returns:
- list of
PairwiseIdobjects - Throws:
SQLException- thrown if there is a problem reading the information from the database
-
-