SAML2CTSPersistentStore.java revision 20f5623265019e171eea2c55da2cd32688877506
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2012-2014 ForgeRock AS.
*
* The contents of this file are subject to the terms of the Common Development and
* Distribution License (the License). You may not use this file except in compliance with the
* License.
*
* You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
* specific language governing permission and limitations under the License.
*
* When distributing Covered Software, include this CDDL Header Notice in each file and include
* the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
* Header, with the fields enclosed by brackets [] replaced by your own identifying
* information:
*
* "Portions copyright [year] [name of copyright owner]".
*/
/**
*
* This class acts as a Proxy to perform distinct SAML2
* operations and allow the CTSPersistentStore implementation
* to handle the actual CRUD for Tokens.
*
*/
public class SAML2CTSPersistentStore extends GeneralTaskRunnable
implements AMTokenSAML2Repository {
/**
* This Instances Server ID.
*/
/**
* Indicator for Persistence Store.
*/
private static boolean isDatabaseUp = false;
private static boolean lastLoggedDBStatusIsUp = false;
/**
* Provides a Reference the AMTokenSAML2Repository Implementation Class for our
* persistence operations.
*
* This instance is this classes Singleton.
*/
/**
* OpenAM CTS Repository.
*
* This instance actually brings in the implementation for all CRUD
* Operations and main implementation. @see CTSPersistentStore.
*/
/**
* grace period before expired session records are removed from the
* repository
*/
private static final String CLEANUP_GRACE_PERIOD =
"com.sun.identity.session.repository.cleanupGracePeriod";
private static final String BRIEF_DB_ERROR_MSG =
"SAML2 failover service is not functional due to Token Persistent Store unavailability.";
private static final String DB_ERROR_MSG =
"SAML2 Token Persistent Store is not available at this moment."
+ "Please check with the system administrator " +
"for appropriate actions";
private static final String LOG_MSG_DB_BACK_ONLINE =
"SESSION_DATABASE_BACK_ONLINE";
private static final String LOG_MSG_DB_UNAVAILABLE =
"SESSION_DATABASE_UNAVAILABLE";
public static final String CLEANUP_RUN_PERIOD =
"com.sun.identity.saml2.repository.cleanupRunPeriod";
/**
* Time period between two successive runs of DBHealthChecker thread which
* checks for Database availability.
*/
public static final String HEALTH_CHECK_RUN_PERIOD =
"com.sun.identity.saml2.repository.healthCheckRunPeriod";
/**
* This period is actual one that is used by the thread. The value is set to
* the smallest value of cleanUPPeriod and healthCheckPeriod.
*/
/**
* Static Initialization Stanza.
*/
static {
try {
} catch (Exception e) {
+ ", using default");
}
try {
} catch (Exception e) {
+ ", using default");
}
// Instantiate the Singleton Instance.
try {
initialize();
} catch(Exception e) {
debug.error("Unable to Instantiate "+SAML2CTSPersistentStore.class.getName()+" for SAML2 Persistence",e);
}
}
/**
* Package Protected from instantiation.
*/
private SAML2CTSPersistentStore() {
}
/**
*
* Constructs new SAML2CTSPersistentStore
* @exception Exception when cannot create a new SAML2 repository
*
*/
private static void initialize() throws SessionException {
// Obtain OpenAM Instance Configuration Properties.
if (thisSessionServerProtocol == null
|| thisSessionServer == null) {
"propertyMustBeSet", null);
}
try {
// Obtain our Server ID for this OpenAM Instance.
} catch (ServerEntryNotFoundException serverNotFoundException) {
}
// Initialize our Persistence Layer.
// Schedule our Runnable Background Thread Task. @see run() method for associated Task.
}
/**
*
* Initialize the Reference to our CTS Persistent Store.
*/
private static void initPersistSession() {
try {
// Obtain our AM Token Repository Instance to provide the Backend CRUD for Tokens.
if (persistentStore != null) {
isDatabaseUp = true;
} else {
// This Throw will be caught below.
throw new Exception("Unable to acquire AMTokenSAML2Repository Implementation Reference from Factory!");
}
} catch (Exception e) {
isDatabaseUp = false;
if (debug.messageEnabled()) {
}
}
}
/**
* Provide Service Instance Access to our Singleton
*
* @return AMTokenSAML2Repository Singleton Instance.
*/
public static AMTokenSAML2Repository getInstance() {
return instance;
}
/**
* Retrives existing SAML2 object from persistent Repository.
*
* @param samlKey primary key
* @return Object - SAML2 unMarshaled Object, if failed, return null.
*/
if (!isDatabaseUp) {
return null;
}
try {
// Retrieve the SAML2 Token from the Repository using the SAML2 Primary Key.
} catch (CoreTokenException e) {
isDatabaseUp = false;
logDBStatus();
if (debug.messageEnabled()) {
}
return null;
} catch (Exception e) {
+ "SAML2 object", e);
return null;
}
}
/**
* Retrives a list of existing SAML2 object from persistent datastore with
* secodaryKey
*
* @param secKey Secondary Key
* @return SAML2 object, if failed, return null.
*/
if (!isDatabaseUp) {
return null;
}
try {
// Perform a query against the token store with the secondary key.
}
return results;
} catch (CoreTokenException e) {
isDatabaseUp = false;
logDBStatus();
if (debug.messageEnabled()) {
}
return null;
} catch (Exception e) {
+ "SAML2 object", e);
return null;
}
}
/**
* Deletes the SAML2 object by given primary key from the repository
* @param samlKey primary key
*/
if (!isDatabaseUp) {
return;
}
try {
} catch (CoreTokenException e) {
isDatabaseUp = false;
logDBStatus();
if (debug.messageEnabled()) {
}
+ "SAML2 object", e);
}
}
/**
* Deletes expired SAML2 object from the repository
* @exception Exception When Unable to delete the expired SAML2 objects
*/
public void deleteExpiredSAML2Tokens() {
}
/**
* {@inheritDoc}
*/
// Is our Token Repository Available?
if (!isDatabaseUp) {
return;
}
// Save the SAML2 Token.
try {
// Perform the Save of the Token to the Token Repository.
} catch (CoreTokenException e) {
isDatabaseUp = false;
logDBStatus();
if (debug.messageEnabled()) {
}
+ "to save SAML2 object", e);
}
}
/**
* This method is invoked to log a message in the following two cases:
*
* (1) the DB is detected down by either the user requests
* Log message: HA_DATABASE_UNAVAILABLE (2) the DB is detected
* available again by the background health checker thread => Log message:
* HA_DATABASE_BACK_ONLINE
*
* The flag "lastLoggedDBStatusIsUp" is used to avoid logging the same DB
* status again and again if the status actually doesn't change over time.
*
* Please also note that if the DB is already down in the very beginning
* when starting the AM instance, there will be no message being logged
* since at this time the session service is not fully initialized yet
* therefore no sso token can be generated and used for the logging purpose.
* Nevertheless, the appropriate logging will be done later when the
* background thread kicks in.
*
*/
private void logDBStatus() {
if (!isDatabaseUp && lastLoggedDBStatusIsUp) {
lastLoggedDBStatusIsUp = false;
}
if (isDatabaseUp && !lastLoggedDBStatusIsUp) {
lastLoggedDBStatusIsUp = true;
}
}
/**
* Return Service Run Period.
*
* @return long current run period.
*/
public long getRunPeriod() {
return runPeriod;
}
/**
* Service Method.
*
* @param obj
* @return
*/
return false;
}
/**
* Service Method.
*
* @param obj
* @return
*/
return false;
}
/**
* Service Method.
*
* @return
*/
public boolean isEmpty() {
return true;
}
/**
* Monitoring logic used by background thread This thread is used for both
* cleanup of expired sessions in the repository and for the Repository health
* checking. The thread always runs with smallest value of cleanUpPeriod and
* healthCheckPeriod.
*/
public void run() {
try {
if (debug.messageEnabled()) {
}
/*
* HealthChecking is done based on the runPeriod but only when
* the Database is down.
*/
logDBStatus();
}
} catch (Exception e) {
e);
}
}
}