/*
* 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]".
*
* Copyright 2012-2015 ForgeRock AS.
*/
/**
* A health service determining system state.
*/
@Properties({
public class HealthService
/**
* Setup logging for the {@link HealthService}.
*/
/**
* Application states
*/
enum AppState {
}
/**
* The Cluster Management Service
*/
/**
* An {@link ScheduledExecutorService} used to schedule a task to check the state of OpenIDM
*/
/**
* A boolean indicating if we consider the underlying framework as started
*/
private static volatile boolean frameworkStarted = false;
/**
* Flag to help in processing state during start-up. For clients to querying application state,
* use the state detail instead
*/
private volatile boolean appStarting = true;
/**
* A boolean indicating if the cluster management thread is up in the "running" state
*/
private volatile boolean clusterUp = false;
/**
* A boolean indicating if the cluster management service is enabled
*/
private volatile boolean clusterEnabled = true;
/**
* A framework status instance used to store the latest framework event status.
*/
/**
* The current state of OpenIDM
*/
/**
* Bundles and bundle fragments required to be started or resolved respectively for the system to
* consider itself READY. Required bundles may be expressed as a regex, for example:
*
* "org.forgerock.openidm.repo-(orientdb|jdbc)"
*/
/**
* An array default bundles and bundle fragments required to be started or resolved respectively
* for the system to consider itself READY.
*/
//ICF Bundles
"org.forgerock.openicf.framework.connector-framework",
"org.forgerock.openicf.framework.connector-framework-internal",
"org.forgerock.openicf.framework.connector-framework-protobuf",
"org.forgerock.openicf.framework.connector-framework-rpc",
"org.forgerock.openicf.framework.connector-framework-server",
"org.forgerock.openicf.framework.icfl-over-slf4j",
// ForgeRock Commons Bundles
"org.forgerock.commons.forgerock-audit-core",
"org.forgerock.commons.forgerock-util",
"org.forgerock.commons.forgerock-jaspi-runtime",
"org.forgerock.commons.forgerock-jaspi-.*-module",
"org.forgerock.commons.guava.forgerock-guava-.*",
"org.forgerock.commons.i18n-core",
"org.forgerock.commons.i18n-slf4j",
"org.forgerock.commons.json-crypto-core",
"org.forgerock.commons.json-resource",
"org.forgerock.commons.json-resource-http",
"org.forgerock.commons.json-schema-core",
"org.forgerock.commons.json-web-token",
"org.forgerock.commons.script-common",
"org.forgerock.commons.script-javascript",
"org.forgerock.commons.script-groovy",
"org.forgerock.http.chf-http-core",
"org.forgerock.http.chf-http-servlet",
// OpenIDM Bundles
"org.forgerock.openidm.api-servlet",
"org.forgerock.openidm.audit",
"org.forgerock.openidm.authnfilter",
"org.forgerock.openidm.cluster",
"org.forgerock.openidm.core",
"org.forgerock.openidm.crypto",
"org.forgerock.openidm.customendpoint",
"org.forgerock.openidm.enhanced-config",
"org.forgerock.openidm.external-email",
"org.forgerock.openidm.external-rest",
"org.forgerock.openidm.httpcontext",
"org.forgerock.openidm.infoservice",
"org.forgerock.openidm.jetty-fragment",
"org.forgerock.openidm.maintenance",
"org.forgerock.openidm.policy",
"org.forgerock.openidm.provisioner",
"org.forgerock.openidm.provisioner-openicf",
"org.forgerock.openidm.quartz-fragment",
"org.forgerock.openidm.repo",
"org.forgerock.openidm.repo-(orientdb|jdbc)",
"org.forgerock.openidm.router",
"org.forgerock.openidm.scheduler",
"org.forgerock.openidm.security",
"org.forgerock.openidm.security-jetty",
"org.forgerock.openidm.servlet",
"org.forgerock.openidm.servlet-registrator",
"org.forgerock.openidm.smartevent",
"org.forgerock.openidm.script",
"org.forgerock.openidm.system",
"org.forgerock.openidm.util",
// 3rd Party Bundles
"org.ops4j.pax.web.pax-web-jetty-bundle"
};
/**
* Maximum time after framework start for required services to register to consider the system
* startup as successful
*/
/**
* Services required to be registered for the system to consider itself READY. Required services
* may be expressed as a regex, for example:
*
* "org.forgerock.openidm.bootrepo.(orientdb|jdbc)"
*/
/**
* An array default services required to be registered for the system to consider itself READY.
* Required services may be expressed as a regex, for example:
*
* "org.forgerock.openidm.bootrepo.(orientdb|jdbc)"
*/
"org.forgerock.openidm.api-servlet",
"org.forgerock.openidm.audit",
"org.forgerock.openidm.authentication",
"org.forgerock.openidm.bootrepo.(orientdb|jdbc)",
"org.forgerock.openidm.cluster",
"org.forgerock.openidm.config.enhanced",
"org.forgerock.openidm.config.manage",
"org.forgerock.openidm.crypto",
"org.forgerock.openidm.external.rest",
"org.forgerock.openidm.internal",
"org.forgerock.openidm.maintenance",
"org.forgerock.openidm.managed",
"org.forgerock.openidm.policy",
"org.forgerock.openidm.provisioner",
"org.forgerock.openidm.provisioner.openicf.connectorinfoprovider",
"org.forgerock.openidm.repo.(orientdb|jdbc)",
"org.forgerock.openidm.router",
"org.forgerock.openidm.scheduler",
"org.forgerock.openidm.script",
"org.forgerock.openidm.security",
"org.forgerock.openidm.servletfilter.registrator"
};
/**
* A router used to service requests for system health endpoints such as: os, memory, recon, jdbc.
*/
// Get the framework status service instance
// Set up tracker
// Handle framework changes
frameworkListener = new FrameworkListener() {
// Store the framework event type as the framework status
frameworkStarted = true;
}
// Start checking status once framework reported started
if (frameworkStarted) {
switch (eventType) {
case FrameworkEvent.INFO:
// For now do not re-check state for these
break;
default:
checkState();
}
}
// IF it's not yet ready, give it up to max service startup
// time before reporting failure
}
}
}
};
// Handle service changes
svcListener = new ServiceListener() {
if (frameworkStarted) {
case ServiceEvent.MODIFIED:
checkState();
break;
}
}
}
};
// Handle bundle changes
bundleListener = new BundleListener() {
if (frameworkStarted) {
case BundleEvent.UNRESOLVED:
checkState();
break;
case BundleEvent.RESOLVED:
checkState();
}
break;
}
}
}
};
// Check if the framework has already started. If so, schedule the start up
// thread that checks the state of OpenIDM.
if (frameworkStatus.isReady()) {
scheduleCheckStartup(2000);
}
}
/**
* Apply configuration overrides from properties if present
*/
private void applyPropertyConfig() {
// Override default requirements
if (reqBundlesProp != null) {
}
if (reqServicesProp != null) {
}
// Optionally add to requirements
"openidm.healthservice.additionalreqbundles");
if (additionalReqBundlesProp != null) {
}
"openidm.healthservice.additionalreqservices");
if (additionalReqServicesProp != null) {
}
if (serviceStartMaxProp != null) {
}
}
/**
* After the timeout period passes past framework start event, check that
* the required services are present. If not, report startup error
*
* @param delay a delay in milliseconds before checking the state.
*/
public void run() {
appStarting = false; // From now on, report not ready rather
// than starting if something fails
checkState();
} else {
}
}
};
if (scheduledExecutor.isShutdown()) {
}
}
/*
* (non-Javadoc)
*
* @see org.forgerock.openidm.info.HealthInfo#getHealthInfo()
*/
return stateDetail.toJsonValue();
}
/**
* Initialize the service tracker and open it.
*
* @param context
* the BundleContext
* @return the ServiceTracker
*/
return tracker;
}
if (clusterService != null) {
}
}
}
clusterUp = false;
}
}
}
if (clusterService != null) {
}
}
/**
* Check and update the application state
*/
private void checkState() {
// Check if the required bundles are started or bundle fragments
// resolved
if (isFragment(bundle)) {
}
} else {
}
}
}
}
}
// Get currently registered services
try {
} catch (Exception e) {
// Bundles and context may be in flux during shutdown
}
// Scan the registered services for matches to our list of
// required services. Required services can be expressed as a regex,
// for example: "org.forgerock.openidm.bootrepo.(orientdb|jdbc)"
break;
}
}
}
}
// Ensure state is up to date
updatedShortDesc = "Not all modules started " + missingBundles + " " + bundleFailures + " " + fragmentFailures;
} else if (clusterEnabled && !clusterUp) {
updatedShortDesc = "This node can not yet join the cluster";
} else {
updatedShortDesc = "OpenIDM ready";
}
}
/**
* Process detected state, if it's different than the current state process
* the state change and report appropriately
*
* @param state
* new app state
* @param shortDesc
* new short description of state
*/
synchronized (this) {
// Whilst we're still not past start-up timeout or successful
// start, keep it at starting rather than error
if (appStarting) {
appStarting = false; // From now on, report not ready
// rather than starting if
// something fails
} else {
return;
}
}
// If we're changing from ready to another state, report
// Whilst we do not have a mechanism to detect regular
// system shut down and distinguish, we log as info
} else {
}
}
// IF we're changing to a ready state, report ready
// Show ready on the system console
}
}
}
}
/**
* @param bundle
* the bundle / bundle fragment to check
* @return true if a bundle is a bundle fragment, false if it's a full
* bundle
*/
}
/**
* Parse the comma delimited property into a list
*
* @param prop
* comma delimited values
* @return properties split by comma
*/
}
}
if (scheduledExecutor != null) {
}
if (frameworkListener != null) {
}
if (svcListener != null) {
}
if (bundleListener != null) {
}
}
// For now we have to rely on this bundle stopping as an indicator
// that the system may be shutting down
// Ideally replace with enhanced detection on regular shutdown initiated
frameworkStarted = false;
}
/**
* Detailed State
*
*/
private static class StateDetail {
}
return state;
}
return shortDesc;
}
return state == compareState;
}
return state == compareState
}
return jsonState;
}
}
case INSTANCE_FAILED:
clusterUp = false;
checkState();
break;
case INSTANCE_RUNNING:
clusterUp = true;
checkState();
break;
default:
break;
}
return true;
}
/**
* {@inheritDoc}
*/
public Promise<ActionResponse, ResourceException> handleAction(Context context, ActionRequest request) {
}
/**
* {@inheritDoc}
*/
public Promise<ResourceResponse, ResourceException> handleCreate(Context context, CreateRequest request) {
}
/**
* {@inheritDoc}
*/
public Promise<ResourceResponse, ResourceException> handleDelete(Context context, DeleteRequest request) {
}
/**
* {@inheritDoc}
*/
public Promise<ResourceResponse, ResourceException> handlePatch(Context context, PatchRequest request) {
}
/**
* {@inheritDoc}
*/
}
/**
* {@inheritDoc}
*/
public Promise<ResourceResponse, ResourceException> handleRead(Context context, ReadRequest request) {
}
/**
* {@inheritDoc}
*/
public Promise<ResourceResponse, ResourceException> handleUpdate(Context context, UpdateRequest request) {
}
}