Author: cziegeler
Date: Wed Sep 30 01:52:52 2015
New Revision: 1705954
URL: http://svn.apache.org/viewvc?rev=1705954&view=rev
Log:
SLING-4941 : JMX-configurable OK/NOK-Check for testing purposes. Apply patch
from Georg Henzler
Added:
sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/JmxAdjustableStatusForTesting.java
(with props)
Added:
sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/JmxAdjustableStatusForTesting.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/JmxAdjustableStatusForTesting.java?rev=1705954&view=auto
==============================================================================
---
sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/JmxAdjustableStatusForTesting.java
(added)
+++
sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/JmxAdjustableStatusForTesting.java
Wed Sep 30 01:52:52 2015
@@ -0,0 +1,247 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The SF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.apache.sling.hc.core.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.DynamicMBean;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+import javax.management.ReflectionException;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.sling.hc.api.HealthCheck;
+import org.apache.sling.hc.api.Result;
+import org.apache.sling.hc.api.Result.Status;
+import org.apache.sling.hc.api.ResultLog.Entry;
+import org.apache.sling.hc.util.FormattingResultLog;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Allows to dynamically add a health check that returns WARN or CRITICAL for
certain tags for testing purposes. Uses an MBean to add/remove the
DynamicTestingHealthCheck dynamically. */
+@Component(
+ metatype = false,
+ immediate = true)
+public class JmxAdjustableStatusForTesting {
+ private static final Logger LOG =
LoggerFactory.getLogger(JmxAdjustableStatusForTesting.class);
+
+ private static final String OBJECT_NAME =
"org.apache.sling.healthcheck:type=AdjustableHealthCheckForTesting";
+
+ private BundleContext bundleContext;
+
+ private ServiceRegistration mbeanRegistration = null;
+ private ServiceRegistration healthCheckRegistration = null;
+
+ @Activate
+ protected final void activate(final ComponentContext context) {
+ this.bundleContext = context.getBundleContext();
+ registerMbean();
+ }
+
+ @Deactivate
+ protected final void deactivate(final ComponentContext context) {
+ unregisterMbean();
+ unregisterDynamicTestingHealthCheck();
+ }
+
+ private void registerMbean() {
+ final Dictionary<String, String> mbeanProps = new Hashtable<String,
String>();
+ mbeanProps.put("jmx.objectname", OBJECT_NAME);
+ AdjustableHealthCheckStatusMBean adjustableHealthCheckStatusMBean =
new AdjustableHealthCheckStatusMBean();
+ this.mbeanRegistration =
bundleContext.registerService(DynamicMBean.class.getName(),
adjustableHealthCheckStatusMBean, mbeanProps);
+ LOG.debug("Registered mbean {} as {}",
adjustableHealthCheckStatusMBean, OBJECT_NAME);
+ }
+
+ private void unregisterMbean() {
+ if (this.mbeanRegistration != null) {
+ this.mbeanRegistration.unregister();
+ this.mbeanRegistration = null;
+ LOG.debug("Unregistered mbean AdjustableHealthCheckStatusMBean");
+ }
+ }
+
+ /* synchronized as potentially multiple users can run JMX operations */
+ private synchronized void registerDynamicTestingHealthCheck(Result.Status
status, String[] tags) {
+ unregisterDynamicTestingHealthCheck();
+ HealthCheck healthCheck = new DynamicTestingHealthCheck(status);
+ Dictionary<String, Object> props = new Hashtable<String, Object>();
+ props.put(HealthCheck.NAME, "JMX-adjustable Testing Check");
+ props.put(HealthCheck.TAGS, tags);
+
+ healthCheckRegistration =
bundleContext.registerService(HealthCheck.class.getName(), healthCheck, props);
+
+ }
+
+ /* synchronized as potentially multiple users can run JMX operations */
+ private synchronized void unregisterDynamicTestingHealthCheck() {
+ if (this.healthCheckRegistration != null) {
+ this.healthCheckRegistration.unregister();
+ this.healthCheckRegistration = null;
+ LOG.debug("Unregistered DynamicTestingHealthCheck");
+ }
+ }
+
+ class DynamicTestingHealthCheck implements HealthCheck {
+
+ private final Result.Status status;
+
+ DynamicTestingHealthCheck(Result.Status status) {
+ this.status = status;
+ }
+
+ @Override
+ public Result execute() {
+ FormattingResultLog resultLog = new FormattingResultLog();
+ resultLog.add(new Entry(status, "Set by JMX bean " + OBJECT_NAME +
" (someone from IT operations is configuring this instance)"));
+ return new Result(resultLog);
+ }
+
+ }
+
+ private class AdjustableHealthCheckStatusMBean implements DynamicMBean {
+
+ private static final String OP_RESET = "reset";
+ private static final String OP_ADD_WARN_RESULT_FOR_TAGS =
"addWarnResultForTags";
+ private static final String OP_ADD_CRITICAL_RESULT_FOR_TAGS =
"addCriticalResultForTags";
+
+ private static final String ATT_TAGS = "tags";
+ private static final String ATT_STATUS = "status";
+
+ private static final String STATUS_INACTIVE = "INACTIVE";
+
+ /** The mbean info. */
+ private final MBeanInfo mbeanInfo;
+
+ private List<String> tags = new ArrayList<String>();
+ private String status = STATUS_INACTIVE;
+
+ public AdjustableHealthCheckStatusMBean() {
+ this.mbeanInfo = this.createMBeanInfo();
+ }
+
+ @Override
+ public Object getAttribute(final String attribute) throws
AttributeNotFoundException, MBeanException, ReflectionException {
+
+ if (ATT_TAGS.equals(attribute)) {
+ return StringUtils.join(tags, ",");
+ } else if (ATT_STATUS.equals(attribute)) {
+ return status.toString();
+ } else {
+ throw new AttributeNotFoundException("Attribute " + attribute
+ " not found.");
+ }
+ }
+
+ @Override
+ public AttributeList getAttributes(final String[] attributes) {
+ final AttributeList result = new AttributeList();
+ for (String att : attributes) {
+ try {
+ result.add(new Attribute(att, getAttribute(att)));
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e.getMessage(), e);
+ }
+ }
+ return result;
+ }
+
+ private MBeanInfo createMBeanInfo() {
+ final List<MBeanAttributeInfo> attrs = new
ArrayList<MBeanAttributeInfo>();
+
+ attrs.add(new MBeanAttributeInfo(ATT_TAGS, String.class.getName(),
"Tags", true, false, false));
+ attrs.add(new MBeanAttributeInfo(ATT_STATUS,
String.class.getName(), "Status", true, false, false));
+
+ MBeanParameterInfo[] params = new MBeanParameterInfo[] { new
MBeanParameterInfo(ATT_TAGS, "java.lang.String", "Comma separated list of
tags") };
+
+ final List<MBeanOperationInfo> ops = new
ArrayList<MBeanOperationInfo>();
+ ops.add(new MBeanOperationInfo(OP_RESET, "Resets this testing
mechanism and removes the failing HC",
+ new MBeanParameterInfo[0], "java.lang.String",
MBeanOperationInfo.ACTION));
+ ops.add(new MBeanOperationInfo(OP_ADD_CRITICAL_RESULT_FOR_TAGS,
"Adds a critical result for the given tags",
+ params, "java.lang.String", MBeanOperationInfo.ACTION));
+ ops.add(new MBeanOperationInfo(OP_ADD_WARN_RESULT_FOR_TAGS, "Adds
a warn result for the given tags",
+ params, "java.lang.String", MBeanOperationInfo.ACTION));
+
+ return new MBeanInfo(this.getClass().getName(),
+ "Adjustable Health Check", attrs.toArray(new
MBeanAttributeInfo[attrs.size()]), null, ops.toArray(new
MBeanOperationInfo[ops.size()]), null);
+ }
+
+ @Override
+ public MBeanInfo getMBeanInfo() {
+ return this.mbeanInfo;
+ }
+
+ @Override
+ public Object invoke(final String actionName, final Object[] params,
final String[] signature) throws MBeanException, ReflectionException {
+ if (OP_RESET.equals(actionName)) {
+ tags = Arrays.asList("");
+ status = STATUS_INACTIVE;
+ unregisterDynamicTestingHealthCheck();
+ LOG.info("JMX-adjustable Health Check for testing was reset");
+ return "Reset successful";
+ } else if (OP_ADD_CRITICAL_RESULT_FOR_TAGS.equals(actionName)) {
+ String[] newTags = params[0].toString().split("[,; ]+");
+ tags = Arrays.asList(newTags);
+ Status critical = Result.Status.CRITICAL;
+ status = critical.toString();
+ registerDynamicTestingHealthCheck(critical, newTags);
+ LOG.info("Activated JMX-adjustable Health Check with status
CRITICAL and tags " + StringUtils.join(tags, ","));
+ return "Added check with result CRITICAL";
+ } else if (OP_ADD_WARN_RESULT_FOR_TAGS.equals(actionName)) {
+ String[] newTags = params[0].toString().split("[,; ]+");
+ tags = Arrays.asList(newTags);
+ Status warn = Result.Status.WARN;
+ status = warn.toString();
+ registerDynamicTestingHealthCheck(warn, newTags);
+ LOG.info("Activated JMX-adjustable Health Check with status
WARN and tags " + StringUtils.join(tags, ","));
+ return "Added check with result WARN";
+ } else {
+ throw new MBeanException(new
UnsupportedOperationException(getClass().getSimpleName() + " does not support
operation " + actionName));
+ }
+ }
+
+ @Override
+ public void setAttribute(final Attribute attribute) throws
AttributeNotFoundException, InvalidAttributeValueException, MBeanException,
+ ReflectionException {
+ throw new MBeanException(new
UnsupportedOperationException(getClass().getSimpleName() + " does not support
setting attributes."));
+ }
+
+ @Override
+ public AttributeList setAttributes(final AttributeList attributes) {
+ return new AttributeList();
+ }
+ }
+
+
+
+}
Propchange:
sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/JmxAdjustableStatusForTesting.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/trunk/bundles/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/JmxAdjustableStatusForTesting.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url