Class 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
  • Field Details

    • 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.
    • tableName

      @Nonnull @NotEmpty private String tableName
      Name of the database table.
    • issuerColumn

      @Nonnull @NotEmpty private String issuerColumn
      Name of the issuer entityID column.
    • recipientColumn

      @Nonnull @NotEmpty private String recipientColumn
      Name of the recipient entityID column.
    • principalNameColumn

      @Nonnull @NotEmpty private String principalNameColumn
      Name of the principal name column.
    • sourceIdColumn

      @Nonnull @NotEmpty private String sourceIdColumn
      Name of the source ID 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.
  • Constructor Details

    • JDBCPairwiseIdStore

      public JDBCPairwiseIdStore()
      Constructor.
  • Method Details

    • 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 to Connection.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:
      doInitialize in class AbstractInitializableComponent
      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:
      getBySourceValue in interface PairwiseIdStore
      Parameters:
      pid - object to populate
      allowCreate - 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:
      getByIssuedValue in interface DurablePairwiseIdStore
      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 IOException
      Deactivate/revoke a pairwise ID.

      If the object's deactivation time field is null, then the current time is used.

      Specified by:
      deactivate in interface DurablePairwiseIdStore
      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 IOException
      Attach a peer-supplied alias to a pairwise ID.
      Specified by:
      attach in interface DurablePairwiseIdStore
      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 SQLException
      Store a record containing the values from the input object.
      Parameters:
      entry - new object to store
      dbConn - connection to obtain a statement from.
      Throws:
      SQLException - if an error occurs
    • verifyDatabase

      private void verifyDatabase() throws SQLException
      Check 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 of PairwiseId objects from a result set.
      Parameters:
      resultSet - the result set
      Returns:
      list of PairwiseId objects
      Throws:
      SQLException - thrown if there is a problem reading the information from the database