HealthService.java revision e492c2715769a2d88e4c4c3279a627421f9f94b6
/**
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2012-2013 ForgeRock AS. All Rights Reserved
*
* 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
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*/
/**
* A health service determining system state
*
* @author aegloff
*/
/*
* @References({ @Reference(referenceInterface = ClusterManagementService.class,
* cardinality = ReferenceCardinality.OPTIONAL_UNARY, policy =
* ReferencePolicy.DYNAMIC, bind = "bindClusterManagementService", unbind =
* "unbindClusterManagementService"
*//*
* , updated = "updatedClusterManagementService"
*//* ) }) */
@Properties({
/**
* Setup logging for the {@link HealthService}.
*/
/**
* Application states
*/
enum AppState {
}
static ServiceTracker tracker;
private ComponentContext context;
private FrameworkListener frameworkListener;
private ServiceListener svcListener;
private BundleListener bundleListener;
// Whether we consider the underlying framework as started
private volatile boolean frameworkStarted = false;
// Flag to help in processing state during start-up.
// For clients to query application state, use the state detail instead
private volatile boolean appStarting = true;
// Whether the cluster management thread is up in the "running" state
private volatile boolean clusterUp = false;
// Whether the cluster management service is enabled
private volatile boolean clusterEnabled = true;
"OpenIDM starting");
/**
* Bundles and bundle fragments required to be started or resolved
* respectively for the system to consider itself READY
*/
/* @formatter:off */
"org.forgerock.openicf.framework.connector-framework",
"org.forgerock.openicf.framework.connector-framework-internal",
"org.forgerock.openicf.framework.connector-framework-osgi",
"org.forgerock.openidm.audit",
"org.forgerock.openidm.core",
"org.forgerock.openidm.enhanced-config",
"org.forgerock.openidm.external-email",
"org.forgerock.openidm.external-rest",
"org.forgerock.openidm.authnfilter",
"org.forgerock.openidm.filter",
"org.forgerock.openidm.httpcontext",
"org.forgerock.openidm.infoservice",
"org.forgerock.openidm.policy",
"org.forgerock.openidm.provisioner",
"org.forgerock.openidm.provisioner-openicf",
"org.forgerock.openidm.repo",
"org.forgerock.openidm.restlet",
"org.forgerock.openidm.smartevent",
"org.forgerock.openidm.system",
"org.forgerock.openidm.ui",
"org.forgerock.openidm.util",
"org.forgerock.commons.org.forgerock.json.resource",
"org.forgerock.commons.org.forgerock.json.resource.restlet",
"org.forgerock.commons.org.forgerock.restlet",
"org.forgerock.commons.org.forgerock.util",
"org.forgerock.openidm.security-jetty",
"org.forgerock.openidm.jetty-fragment",
"org.forgerock.openidm.quartz-fragment",
"org.ops4j.pax.web.pax-web-extender-whiteboard",
"org.forgerock.openidm.scheduler",
"org.ops4j.pax.web.pax-web-jetty-bundle",
"org.forgerock.openidm.repo-jdbc",
"org.forgerock.openidm.repo-orientdb",
"org.forgerock.openidm.crypto",
"org.forgerock.openidm.cluster"
// For now, default to not check for the workflow engine
//"org.activiti.engine",
//"org.activiti.osgi",
//"org.forgerock.openidm.workflow-activiti",
//"UserApplicationAcceptance.bar"
};
/* @formatter:on */
/**
* Maximum time after framework start for required services to register to
* consider the system startup as successful
*/
private long serviceStartMax = 10000;
/**
* Services required to be registered for the system to consider itself
* READY
*/
/* @formatter:off */
//"org.forgerock.openidm.config",
"org.forgerock.openidm.provisioner",
"org.forgerock.openidm.provisioner.openicf.connectorinfoprovider",
"org.forgerock.openidm.external.rest",
"org.forgerock.openidm.audit",
"org.forgerock.openidm.policy",
"org.forgerock.openidm.managed",
"org.forgerock.openidm.script",
"org.forgerock.openidm.crypto",
//"org.forgerock.openidm.recon",
//TODO: add once committed "org.forgerock.openidm.info",
"org.forgerock.openidm.router",
"org.forgerock.openidm.scheduler",
//"org.forgerock.openidm.taskscanner",
"org.forgerock.openidm.cluster"
//"org.forgerock.openidm.bootrepo.orientdb",
//"org.forgerock.openidm.bootrepo.jdbc",
//"org.forgerock.openidm.workflow.activiti.engine",
//"org.forgerock.openidm.workflow"
};
/* @formatter:on */
// Set up tracker
// Handle framework changes
frameworkListener = new FrameworkListener() {
frameworkStarted = true;
}
// Start checking status once framework reported started
if (frameworkStarted) {
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;
}
}
}
};
}
/**
* 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
*/
private void scheduleCheckStartup() {
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()
*/
public JsonValue getHealthInfo() {
return stateDetail.toJsonValue();
}
/**
* Initialize the service tracker and open it.
*
* @param context
* the BundleContext
* @return the ServiceTracker
*/
this);
return tracker;
}
if (clusterService != null) {
}
}
}
}
}
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 {
}
}
}
}
// Check if the required services are present
try {
} catch (InvalidSyntaxException e) {
// Since we are not passing a filter this should not happen
}
}
}
}
}
// Ensure state is up to date
} 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
*/
}
/**
* Translate Bundle state int
*
* @param bundleState
* bundle state int
* @return String version of the state
*/
switch (bundleState) {
return "ACTIVE";
return "INSTALLED";
return "RESOLVED";
return "STARTING";
return "STOPPING";
case Bundle.UNINSTALLED:
return "UNINSTALLED ";
}
return "UNKNDWN";
}
/**
* 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
*
* @author aegloff
*/
private static class StateDetail {
}
return state;
}
protected String getShortDesc() {
return shortDesc;
}
return state == compareState;
}
return state == compareState
}
protected JsonValue toJsonValue() {
return jsonState;
}
}
case INSTANCE_FAILED:
clusterUp = false;
checkState();
break;
case INSTANCE_RUNNING:
clusterUp = true;
checkState();
break;
}
return true;
}
}