You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/10/18 23:20:02 UTC

[sling-org-apache-sling-hc-api] branch master created (now 1ab6911)

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-hc-api.git.


      at 1ab6911  SLING-7167 Adjust READMEs

This branch includes the following new commits:

     new 2766dc5  SLING-6773 - separate HC API from Core
     new d88078c  Use parent pom 30, OSGi annotations, clean up
     new 26fb773  [maven-release-plugin] prepare release org.apache.sling.hc.api-1.0.0
     new 13ecfbe  [maven-release-plugin] prepare for next development iteration
     new bd44d27  SLING-6804 - allow selecting health checks by name
     new 515631f  SLING-6855 Introducing property hc.warningsStickForMinutes that makes warn HC results sticky for the given minutes
     new c13813e  SLING-6855 - accept String as well for WARNINGS_STICK_FOR_MINUTES (could do the same for other values but lets minimize changes)
     new 1ab6911  SLING-7167 Adjust READMEs

The 8 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


-- 
To stop receiving notification emails like this one, please contact
['"commits@sling.apache.org" <co...@sling.apache.org>'].

[sling-org-apache-sling-hc-api] 04/08: [maven-release-plugin] prepare for next development iteration

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-hc-api.git

commit 13ecfbee5a75e48113650dda9a7772b3c939d17f
Author: Karl Pauls <pa...@apache.org>
AuthorDate: Mon May 8 10:54:53 2017 +0000

    [maven-release-plugin] prepare for next development iteration
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1794324 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/pom.xml b/pom.xml
index a83e864..86ded93 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,7 @@
     <groupId>org.apache.sling</groupId>
     <artifactId>org.apache.sling.hc.api</artifactId>
     <packaging>bundle</packaging>
-    <version>1.0.0</version>
+    <version>1.0.1-SNAPSHOT</version>
 
     <name>Apache Sling Health Check API</name>
     <inceptionYear>2013</inceptionYear>
@@ -39,9 +39,9 @@
     </description>
 
     <scm>
-        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/tags/org.apache.sling.hc.api-1.0.0</connection>
-        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/tags/org.apache.sling.hc.api-1.0.0</developerConnection>
-        <url>http://svn.apache.org/viewvc/sling/tags/org.apache.sling.hc.api-1.0.0</url>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/healthcheck/api</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/healthcheck/api</developerConnection>
+        <url>http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/healthcheck/api</url>
     </scm>
 
     <build>

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-hc-api] 08/08: SLING-7167 Adjust READMEs

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-hc-api.git

commit 1ab6911bccc6c11daec7edf3179981b7520844a9
Author: Oliver Lietz <ol...@apache.org>
AuthorDate: Tue Oct 3 09:22:13 2017 +0000

    SLING-7167 Adjust READMEs
    
    add missing README
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1810693 13f79535-47bb-0310-9956-ffa450edef68
---
 README.md | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..49a71f3
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+# Apache Sling Health Check API
+
+This module is part of the [Apache Sling](https://sling.apache.org) project.

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-hc-api] 02/08: Use parent pom 30, OSGi annotations, clean up

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-hc-api.git

commit d88078c431aaea09f76493587fb48238a1fe9806
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Thu Apr 27 08:26:45 2017 +0000

    Use parent pom 30, OSGi annotations, clean up
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1792850 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            | 20 ++++------------
 .../java/org/apache/sling/hc/api/HealthCheck.java  |  7 +++---
 .../api/execution/HealthCheckExecutionResult.java  |  2 +-
 .../hc/api/execution/HealthCheckExecutor.java      |  4 ++--
 .../sling/hc/api/execution/package-info.java       |  3 +--
 .../java/org/apache/sling/hc/api/package-info.java |  3 +--
 .../apache/sling/hc/util/HealthCheckMetadata.java  | 27 ++++++++++++++--------
 .../org/apache/sling/hc/util/package-info.java     |  3 +--
 8 files changed, 30 insertions(+), 39 deletions(-)

diff --git a/pom.xml b/pom.xml
index 35ad1bb..9d88e9c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,9 +21,10 @@
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>org.apache.sling.hc.reactor</artifactId>
         <groupId>org.apache.sling</groupId>
-        <version>1.0.3-SNAPSHOT</version>
+        <artifactId>sling</artifactId>
+        <version>30</version>
+        <relativePath />
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -58,24 +59,11 @@
     <dependencies>
         <dependency>
             <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.commons.osgi</artifactId>
-            <version>2.2.0</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>commons-lang</groupId>
-            <artifactId>commons-lang</artifactId>
-            <version>2.5</version>
-            <scope>provided</scope>
+            <artifactId>osgi.core</artifactId>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
-            <version>1.6.2</version>
         </dependency>
         <dependency>
             <groupId>junit</groupId>
diff --git a/src/main/java/org/apache/sling/hc/api/HealthCheck.java b/src/main/java/org/apache/sling/hc/api/HealthCheck.java
index 2fd269a..6ef4c77 100644
--- a/src/main/java/org/apache/sling/hc/api/HealthCheck.java
+++ b/src/main/java/org/apache/sling/hc/api/HealthCheck.java
@@ -17,8 +17,7 @@
  */
 package org.apache.sling.hc.api;
 
-import aQute.bnd.annotation.ConsumerType;
-
+import org.osgi.annotation.versioning.ConsumerType;
 
 /**
  * Health Check services can be executed and
@@ -60,7 +59,7 @@ public interface HealthCheck {
      * The value of this property must be of type String or String array.
      */
     String TAGS = "hc.tags";
-    
+
     /**
      * Optional service property: If this property is set the health check
      * will be executed asynchronously using the cron expression provided.
@@ -69,7 +68,7 @@ public interface HealthCheck {
 
     /**
      * Optional service property: TTL for health check {@link Result}.
-     * The value of this property must be of type {@link Long} and is 
+     * The value of this property must be of type {@link Long} and is
      * specified in ms.
      */
     String RESULT_CACHE_TTL_IN_MS = "hc.resultCacheTtlInMs";
diff --git a/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutionResult.java b/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutionResult.java
index 8a09920..0f8ecd7 100644
--- a/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutionResult.java
+++ b/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutionResult.java
@@ -21,8 +21,8 @@ import java.util.Date;
 
 import org.apache.sling.hc.api.Result;
 import org.apache.sling.hc.util.HealthCheckMetadata;
+import org.osgi.annotation.versioning.ProviderType;
 
-import aQute.bnd.annotation.ProviderType;
 
 /**
  * Interface for health check executions via the {@link HealthCheckExecutor}.
diff --git a/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutor.java b/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutor.java
index e26843f..e41858c 100644
--- a/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutor.java
+++ b/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutor.java
@@ -20,8 +20,8 @@ package org.apache.sling.hc.api.execution;
 import java.util.List;
 
 import org.apache.sling.hc.api.HealthCheck;
+import org.osgi.annotation.versioning.ProviderType;
 
-import aQute.bnd.annotation.ProviderType;
 
 /**
  * Executes health checks registered as OSGi services and
@@ -42,7 +42,7 @@ public interface HealthCheckExecutor {
     /**
      * Executes all health checks with the supplied list of tags.
      * If no tags are supplied, all health checks are executed.
-     * 
+     *
      * @param options options for controlling execution behavior
      * @param tags tags to be executed
      *
diff --git a/src/main/java/org/apache/sling/hc/api/execution/package-info.java b/src/main/java/org/apache/sling/hc/api/execution/package-info.java
index 26383c4..dc8b8aa 100644
--- a/src/main/java/org/apache/sling/hc/api/execution/package-info.java
+++ b/src/main/java/org/apache/sling/hc/api/execution/package-info.java
@@ -20,5 +20,4 @@
 @Version("1.1.0")
 package org.apache.sling.hc.api.execution;
 
-import aQute.bnd.annotation.Version;
-
+import org.osgi.annotation.versioning.Version;
diff --git a/src/main/java/org/apache/sling/hc/api/package-info.java b/src/main/java/org/apache/sling/hc/api/package-info.java
index 659caa4..c79b3b4 100644
--- a/src/main/java/org/apache/sling/hc/api/package-info.java
+++ b/src/main/java/org/apache/sling/hc/api/package-info.java
@@ -20,5 +20,4 @@
 @Version("1.1.0")
 package org.apache.sling.hc.api;
 
-import aQute.bnd.annotation.Version;
-
+import org.osgi.annotation.versioning.Version;
diff --git a/src/main/java/org/apache/sling/hc/util/HealthCheckMetadata.java b/src/main/java/org/apache/sling/hc/util/HealthCheckMetadata.java
index f5fdcb5..efc378a 100644
--- a/src/main/java/org/apache/sling/hc/util/HealthCheckMetadata.java
+++ b/src/main/java/org/apache/sling/hc/util/HealthCheckMetadata.java
@@ -21,8 +21,6 @@ import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.List;
 
-import org.apache.commons.lang.StringUtils;
-import org.apache.sling.commons.osgi.PropertiesUtil;
 import org.apache.sling.hc.api.HealthCheck;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
@@ -120,8 +118,8 @@ public class HealthCheckMetadata {
     }
 
     /**
-     * TTL for the result cache in ms. 
-     * 
+     * TTL for the result cache in ms.
+     *
      * @return TTL for the result cache or <code>null</code> if not configured.
      */
     public Long getResultCacheTtlInMs() {
@@ -152,13 +150,22 @@ public class HealthCheckMetadata {
 
     private String getHealthCheckTitle(final ServiceReference ref) {
         String name = (String) ref.getProperty(HealthCheck.NAME);
-        if (StringUtils.isBlank(name)) {
-            name = PropertiesUtil.toString(ref.getProperty(Constants.SERVICE_DESCRIPTION), null);
+        if (name == null || name.isEmpty()) {
+            final Object val = ref.getProperty(Constants.SERVICE_DESCRIPTION);
+            if ( val != null ) {
+                name = val.toString();
+            }
         }
-        if (StringUtils.isBlank(name)) {
+        if (name == null || name.isEmpty()) {
             name = "HealthCheck:" + ref.getProperty(Constants.SERVICE_ID);
-            final String pid = PropertiesUtil.toString(ref.getProperty(Constants.SERVICE_PID), null);
-            if ( !StringUtils.isBlank(pid) ) {
+            final Object val = ref.getProperty(Constants.SERVICE_PID);
+            String pid = null;
+            if ( val instanceof String ) {
+                pid = (String)val;
+            } else if ( val instanceof String[]) {
+                pid = Arrays.toString((String[])val);
+            }
+            if ( pid != null && !pid.isEmpty() ) {
                 name = name + " (" + pid + ")";
             }
         }
@@ -166,7 +173,7 @@ public class HealthCheckMetadata {
     }
 
     private List<String> arrayPropertyToListOfStr(final Object arrayProp) {
-        List<String> res = new LinkedList<String>();
+        List<String> res = new LinkedList<>();
         if (arrayProp instanceof String) {
             res.add((String) arrayProp);
         } else if (arrayProp instanceof String[]) {
diff --git a/src/main/java/org/apache/sling/hc/util/package-info.java b/src/main/java/org/apache/sling/hc/util/package-info.java
index 17a9969..131d715 100644
--- a/src/main/java/org/apache/sling/hc/util/package-info.java
+++ b/src/main/java/org/apache/sling/hc/util/package-info.java
@@ -20,5 +20,4 @@
 @Version("1.3.0")
 package org.apache.sling.hc.util;
 
-import aQute.bnd.annotation.Version;
-
+import org.osgi.annotation.versioning.Version;

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-hc-api] 01/08: SLING-6773 - separate HC API from Core

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-hc-api.git

commit 2766dc52f4db3875c45d7d9251444b702ee49f1c
Author: Justin Edelson <ju...@apache.org>
AuthorDate: Mon Apr 10 17:13:25 2017 +0000

    SLING-6773 - separate HC API from Core
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1790879 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            |  86 ++++++++++
 .../java/org/apache/sling/hc/api/HealthCheck.java  |  83 ++++++++++
 src/main/java/org/apache/sling/hc/api/Result.java  |  81 ++++++++++
 .../java/org/apache/sling/hc/api/ResultLog.java    | 124 +++++++++++++++
 .../api/execution/HealthCheckExecutionOptions.java | 110 +++++++++++++
 .../api/execution/HealthCheckExecutionResult.java  |  65 ++++++++
 .../hc/api/execution/HealthCheckExecutor.java      |  53 ++++++
 .../sling/hc/api/execution/package-info.java       |  24 +++
 .../java/org/apache/sling/hc/api/package-info.java |  24 +++
 .../apache/sling/hc/util/FormattingResultLog.java  |  80 ++++++++++
 .../apache/sling/hc/util/HealthCheckFilter.java    | 160 +++++++++++++++++++
 .../apache/sling/hc/util/HealthCheckMetadata.java  | 177 +++++++++++++++++++++
 .../sling/hc/util/SimpleConstraintChecker.java     |  80 ++++++++++
 .../org/apache/sling/hc/util/package-info.java     |  24 +++
 .../org/apache/sling/hc/api/ResultLogTest.java     | 107 +++++++++++++
 .../java/org/apache/sling/hc/api/ResultTest.java   |  65 ++++++++
 .../sling/hc/util/SimpleConstraintCheckerTest.java | 167 +++++++++++++++++++
 17 files changed, 1510 insertions(+)

diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..35ad1bb
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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 ASF 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>org.apache.sling.hc.reactor</artifactId>
+        <groupId>org.apache.sling</groupId>
+        <version>1.0.3-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.apache.sling</groupId>
+    <artifactId>org.apache.sling.hc.api</artifactId>
+    <packaging>bundle</packaging>
+    <version>0.0.99-SNAPSHOT</version>
+
+    <name>Apache Sling Health Check API</name>
+    <inceptionYear>2013</inceptionYear>
+
+    <description>
+        The Sling Health Check API
+    </description>
+
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/healthcheck/api</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/healthcheck/api</developerConnection>
+        <url>http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/healthcheck/api</url>
+    </scm>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.osgi</artifactId>
+            <version>2.2.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+            <version>2.5</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.6.2</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/hc/api/HealthCheck.java b/src/main/java/org/apache/sling/hc/api/HealthCheck.java
new file mode 100644
index 0000000..2fd269a
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/api/HealthCheck.java
@@ -0,0 +1,83 @@
+/*
+ * 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.api;
+
+import aQute.bnd.annotation.ConsumerType;
+
+
+/**
+ * Health Check services can be executed and
+ * return an execution {@link Result}.
+ *
+ * Clients should not look up health checks directly but
+ * rather use the {@link org.apache.sling.hc.api.execution.HealthCheckExecutor}
+ * service and executed checks based on tags.
+ *
+ * If the {@link #MBEAN_NAME} service registration property is set,
+ * the health check is registered as an mbean and can be invoked
+ * by getting the MBean from the JMX registry.
+ */
+@ConsumerType
+public interface HealthCheck {
+
+    /**
+     * Optional service property: the name of a health check.
+     * This name should be unique, however there might be more than one
+     * health check service with the same value for this property.
+     * The value of this property must be of type String.
+     */
+    String NAME = "hc.name";
+
+    /**
+     * Optional service property: the name of the MBean for registering
+     * the health check as an MBean. If this property is missing the
+     * health check is not registered as a JMX MBean.
+     * If there is more than one service with the same value for this
+     * property, the one with the highest service ranking is registered
+     * only.
+     * The value of this property must be of type String.
+     */
+    String MBEAN_NAME = "hc.mbean.name";
+
+    /**
+     * Optional service property: tags for categorizing the health check
+     * services.
+     * The value of this property must be of type String or String array.
+     */
+    String TAGS = "hc.tags";
+    
+    /**
+     * Optional service property: If this property is set the health check
+     * will be executed asynchronously using the cron expression provided.
+     */
+    String ASYNC_CRON_EXPRESSION = "hc.async.cronExpression";
+
+    /**
+     * Optional service property: TTL for health check {@link Result}.
+     * The value of this property must be of type {@link Long} and is 
+     * specified in ms.
+     */
+    String RESULT_CACHE_TTL_IN_MS = "hc.resultCacheTtlInMs";
+
+    /**
+     * Execute this health check and return a {@link Result}
+     * This is meant to execute quickly, access to external
+     * systems, for example, should be managed asynchronously.
+     */
+    Result execute();
+}
diff --git a/src/main/java/org/apache/sling/hc/api/Result.java b/src/main/java/org/apache/sling/hc/api/Result.java
new file mode 100644
index 0000000..85e4153
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/api/Result.java
@@ -0,0 +1,81 @@
+/*
+ * 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.api;
+
+import java.util.Iterator;
+
+/** The result of executing a {@link HealthCheck} */
+public class Result implements Iterable <ResultLog.Entry> {
+
+    protected final ResultLog resultLog;
+
+    public enum Status {
+        DEBUG,              // used by ResultLog for debug messages, not an actual output status
+        INFO,               // used by ResultLog for info messages, not an actual output status
+        OK,                 // no problem
+        WARN,               // health check detected something wrong but not critical
+        CRITICAL,           // health check detected a critical problem
+        HEALTH_CHECK_ERROR  // health check did not execute properly
+    }
+
+    /** Build a single-value Result
+     *  @param s if lower than OK, our status is set to OK */
+    public Result(final Status s, final String explanation) {
+        resultLog = new ResultLog().add(new ResultLog.Entry(s, explanation));
+    }
+
+    /**
+     * Build a single-value Result with exception
+     * 
+     * @param s if lower than OK, our status is set to OK
+     */
+    public Result(final Status s, final String explanation, final Exception e) {
+        resultLog = new ResultLog().add(new ResultLog.Entry(s, explanation, e));
+    }
+
+    /** Build a a Result based on a ResultLog, which can provide
+     *  more details than a single-value Result.
+     */
+    public Result(final ResultLog log) {
+        resultLog = new ResultLog(log);
+    }
+
+    /** True if our status is OK - provides a convenient way of
+     *  checking that.
+     */
+    public boolean isOk() {
+        return getStatus().equals(Status.OK);
+    }
+
+    /** Return our Status */
+    public Status getStatus() {
+        return resultLog.getAggregateStatus();
+    }
+
+    /** Return an Iterator on the entries of our ResultLog */
+    @Override
+    public Iterator<ResultLog.Entry> iterator() {
+        return resultLog.iterator();
+    }
+
+    @Override
+    public String toString() {
+        return "Result [status=" + getStatus() + ", resultLog=" + resultLog + "]";
+    }
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/hc/api/ResultLog.java b/src/main/java/org/apache/sling/hc/api/ResultLog.java
new file mode 100644
index 0000000..a5f1d0e
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/api/ResultLog.java
@@ -0,0 +1,124 @@
+/*
+ * 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.api;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.sling.hc.api.Result.Status;
+
+/** The log of a Result, allows for providing multiple lines
+ *  of information which are aggregated as a single Result. */
+public class ResultLog implements Iterable<ResultLog.Entry> {
+
+    private List<Entry> entries = new LinkedList<Entry>();
+    private Status aggregateStatus;
+
+    /** An entry in this log */
+    public static class Entry {
+        private final Status status;
+        private final String message;
+        private final Exception exception;
+
+        public Entry(Status s, String message) {
+            this(s, message, null);
+        }
+
+        public Entry(Status s, String message, Exception exception) {
+            this.status = s;
+            this.message = message;
+            this.exception = exception;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder(status.toString()).append(" ").append(message);
+            if (exception != null) {
+                builder.append(" Exception: " + exception.getMessage());
+            }
+            return builder.toString();
+        }
+
+        public Status getStatus() {
+            return status;
+        }
+
+        public String getMessage() {
+            return message;
+        }
+
+        public Exception getException() {
+            return exception;
+        }
+
+    }
+
+    /** Build a log. Initial aggregate status is
+     *  set to WARN, as an empty log is not considered ok.
+     *  That's reset to OK before adding the first log entry,
+     *  and then the status aggregation rules take over.
+     */
+    public ResultLog() {
+        aggregateStatus = Result.Status.WARN;
+    }
+
+    /**
+     * Create a copy of the result log
+     */
+    public ResultLog(final ResultLog log) {
+        this.aggregateStatus = log.aggregateStatus;
+        this.entries = new ArrayList<ResultLog.Entry>(log.entries);
+    }
+
+    /** Add an entry to this log. The aggregate status of
+     *  this is set to the highest of the current aggregate status
+     *  and the new Entry's status */
+    public ResultLog add(Entry e) {
+        if(entries.isEmpty()) {
+            aggregateStatus = Result.Status.OK;
+        }
+        entries.add(e);
+        if(e.getStatus().ordinal() > aggregateStatus.ordinal()) {
+            aggregateStatus = e.getStatus();
+        }
+        return this;
+    }
+
+    /** Return an Iterator on our entries */
+    @Override
+    public Iterator<ResultLog.Entry> iterator() {
+        return entries.iterator();
+    }
+
+    /** Return our aggregate status, i.e. the highest status
+     *  of the entries added to this log. Starts at OK for an
+     *  empty ResultLog, so cannot be lower than that.
+     */
+    public Status getAggregateStatus() {
+        return aggregateStatus;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder("ResultLog: ");
+        sb.append(this.entries.toString());
+        return sb.toString();
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutionOptions.java b/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutionOptions.java
new file mode 100644
index 0000000..460323d
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutionOptions.java
@@ -0,0 +1,110 @@
+/*
+ * 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.api.execution;
+
+
+/** Options for behavior of health check execution. */
+public class HealthCheckExecutionOptions {
+
+    private boolean forceInstantExecution = false;
+    private boolean combineTagsWithOr = false;
+    private int overrideGlobalTimeout = 0;
+
+    @Override
+    public String toString() {
+        return "[HealthCheckExecutionOptions forceInstantExecution=" + forceInstantExecution + ", combineTagsWithOr=" + combineTagsWithOr
+                + ", overrideGlobalTimeout=" + overrideGlobalTimeout + "]";
+    }
+
+    /**
+     * If activated, this will ensure that asynchronous checks will be executed immediately.
+     * 
+     * @param forceInstantExecution boolean flag
+     */
+    public void setForceInstantExecution(boolean forceInstantExecution) {
+        this.forceInstantExecution = forceInstantExecution;
+    }
+
+    /**
+     * If activated, the given tags will be combined with a logical "or" instead of "and".
+     * 
+     * @param combineTagsWithOr boolean flag
+     */
+    public void setCombineTagsWithOr(boolean combineTagsWithOr) {
+        this.combineTagsWithOr = combineTagsWithOr;
+    }
+
+    /**
+     * Allows to override the global timeout for this particular execution of the health check. 
+     * 
+     * @param overrideGlobalTimeout timeout in ms to be used for this execution of the execution
+     */
+    public void setOverrideGlobalTimeout(int overrideGlobalTimeout) {
+        this.overrideGlobalTimeout = overrideGlobalTimeout;
+    }
+
+    /**
+     * @return true if instant execution is turned on
+     */
+    public boolean isForceInstantExecution() {
+        return forceInstantExecution;
+    }
+
+    /**
+     * @return true if combining tags with or is turned on
+     */
+    public boolean isCombineTagsWithOr() {
+        return combineTagsWithOr;
+    }
+
+    /**
+     * @return the timeout to be used for this execution (overriding the global timeout)
+     */
+    public int getOverrideGlobalTimeout() {
+        return overrideGlobalTimeout;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (combineTagsWithOr ? 1231 : 1237);
+        result = prime * result + (forceInstantExecution ? 1231 : 1237);
+        result = prime * result + overrideGlobalTimeout;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        HealthCheckExecutionOptions other = (HealthCheckExecutionOptions) obj;
+        if (combineTagsWithOr != other.combineTagsWithOr)
+            return false;
+        if (forceInstantExecution != other.forceInstantExecution)
+            return false;
+        if (overrideGlobalTimeout != other.overrideGlobalTimeout)
+            return false;
+        return true;
+    }
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutionResult.java b/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutionResult.java
new file mode 100644
index 0000000..8a09920
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutionResult.java
@@ -0,0 +1,65 @@
+/*
+ * 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.api.execution;
+
+import java.util.Date;
+
+import org.apache.sling.hc.api.Result;
+import org.apache.sling.hc.util.HealthCheckMetadata;
+
+import aQute.bnd.annotation.ProviderType;
+
+/**
+ * Interface for health check executions via the {@link HealthCheckExecutor}.
+ *
+ * If the execution of the health check timed out, the method
+ *
+ */
+@ProviderType
+public interface HealthCheckExecutionResult {
+
+    /**
+     * Get the result of the health check run.
+     */
+    Result getHealthCheckResult();
+
+    /**
+     * Get the elapsed time in ms
+     */
+    long getElapsedTimeInMs();
+
+    /**
+     * Get the date, the health check finished or if the
+     * execution timed out, the execution was aborted.
+     * @return The finished date of the execution.
+     */
+    Date getFinishedAt();
+
+    /**
+     * Returns true if the execution has timed out. In this
+     * case the result does not reflect the real result of the
+     * underlying check, but a result indicating the timeout.
+     * @return <code>true</code> if execution timed out.
+     */
+    boolean hasTimedOut();
+
+    /**
+     * Get the meta data about the health check service
+     */
+    HealthCheckMetadata getHealthCheckMetadata();
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutor.java b/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutor.java
new file mode 100644
index 0000000..e26843f
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutor.java
@@ -0,0 +1,53 @@
+/*
+ * 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.api.execution;
+
+import java.util.List;
+
+import org.apache.sling.hc.api.HealthCheck;
+
+import aQute.bnd.annotation.ProviderType;
+
+/**
+ * Executes health checks registered as OSGi services and
+ * implementing the interface {@link HealthCheck}.
+ *
+ */
+@ProviderType
+public interface HealthCheckExecutor {
+
+    /**
+     * Executes all health checks with the supplied list of tags.
+     * If no tags are supplied, all health checks are executed.
+     *
+     * @return List of results. The list might be empty.
+     */
+    List<HealthCheckExecutionResult> execute(String... tags);
+
+    /**
+     * Executes all health checks with the supplied list of tags.
+     * If no tags are supplied, all health checks are executed.
+     * 
+     * @param options options for controlling execution behavior
+     * @param tags tags to be executed
+     *
+     * @return List of results. The list might be empty.
+     */
+    List<HealthCheckExecutionResult> execute(HealthCheckExecutionOptions options, String... tags);
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/hc/api/execution/package-info.java b/src/main/java/org/apache/sling/hc/api/execution/package-info.java
new file mode 100644
index 0000000..26383c4
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/api/execution/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * 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 ASF 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.
+ */
+
+@Version("1.1.0")
+package org.apache.sling.hc.api.execution;
+
+import aQute.bnd.annotation.Version;
+
diff --git a/src/main/java/org/apache/sling/hc/api/package-info.java b/src/main/java/org/apache/sling/hc/api/package-info.java
new file mode 100644
index 0000000..659caa4
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/api/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * 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 ASF 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.
+ */
+
+@Version("1.1.0")
+package org.apache.sling.hc.api;
+
+import aQute.bnd.annotation.Version;
+
diff --git a/src/main/java/org/apache/sling/hc/util/FormattingResultLog.java b/src/main/java/org/apache/sling/hc/util/FormattingResultLog.java
new file mode 100644
index 0000000..e37dd72
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/util/FormattingResultLog.java
@@ -0,0 +1,80 @@
+/*
+ * 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.util;
+
+import java.text.NumberFormat;
+import java.util.Locale;
+
+import org.apache.sling.hc.api.Result;
+import org.apache.sling.hc.api.ResultLog;
+import org.slf4j.helpers.MessageFormatter;
+
+/** Utility that provides a logging-like facade on a ResultLog */
+public class FormattingResultLog extends ResultLog {
+    
+    private ResultLog.Entry createEntry(Result.Status status, String format, Object ... args) {
+        return new ResultLog.Entry(status, MessageFormatter.arrayFormat(format, args).getMessage());
+    }
+    
+    public void debug(String format, Object ... args) {
+        add(createEntry(Result.Status.DEBUG, format, args));
+    }
+    
+    public void info(String format, Object ... args) {
+        add(createEntry(Result.Status.INFO, format, args));
+    }
+    
+    public void warn(String format, Object ... args) {
+        add(createEntry(Result.Status.WARN, format, args));
+    }
+    
+    public void critical(String format, Object ... args) {
+        add(createEntry(Result.Status.CRITICAL, format, args));
+    }
+
+    public void healthCheckError(String format, Object ... args) {
+        add(createEntry(Result.Status.HEALTH_CHECK_ERROR, format, args));
+    }
+
+    /** Utility method to return any magnitude of milliseconds in a human readable format using the appropriate time unit (ms, sec, min) depending on the
+     * magnitude of the input.
+     * 
+     * @param millis milliseconds
+     * @return a string with a number and a unit */
+    public static String msHumanReadable(final long millis) {
+
+        double number = millis;
+        final String[] units = new String[] { "ms", "sec", "min", "h", "days" };
+        final double[] divisors = new double[] { 1000, 60, 60, 24 };
+
+        int magnitude = 0;
+        do {
+            double currentDivisor = divisors[Math.min(magnitude, divisors.length - 1)];
+            if (number < currentDivisor) {
+                break;
+            }
+            number /= currentDivisor;
+            magnitude++;
+        } while (magnitude < units.length - 1);
+        NumberFormat format = NumberFormat.getNumberInstance(Locale.UK);
+        format.setMinimumFractionDigits(0);
+        format.setMaximumFractionDigits(1);
+        String result = format.format(number) + units[magnitude];
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/hc/util/HealthCheckFilter.java b/src/main/java/org/apache/sling/hc/util/HealthCheckFilter.java
new file mode 100644
index 0000000..5466492
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/util/HealthCheckFilter.java
@@ -0,0 +1,160 @@
+/*
+ * 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.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.sling.hc.api.HealthCheck;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Select from available {@link HealthCheck} services.
+ * Once this filter object and the returned health check services are no longer
+ * be used {@link #dispose()} should be called, to free the service
+ * references.
+ *
+ * This class is not thread safe and instances shouldn't be used concurrently
+ * from different threads.
+ */
+public class HealthCheckFilter {
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+    private final BundleContext bundleContext;
+
+
+    public static final String OMIT_PREFIX = "-";
+
+    private final Set<ServiceReference> usedReferences = new HashSet<ServiceReference>();
+
+    /**
+     * Create a new filter object
+     */
+    public HealthCheckFilter(final BundleContext bc) {
+        bundleContext = bc;
+    }
+
+    /**
+     * Get all health check services with one of the supplied tags.
+     * @return A list of services - might be the empty list if none matches
+     */
+    @SuppressWarnings("unchecked")
+    public List<HealthCheck> getTaggedHealthChecks(final String... tags) {
+        final ServiceReference [] refs = this.getTaggedHealthCheckServiceReferences(tags);
+        final List<HealthCheck> result = new ArrayList<HealthCheck>();
+
+        if ( refs != null ) {
+            final List<ServiceReference> sortedRefs = Arrays.asList(refs);
+            Collections.sort(sortedRefs);
+
+            for(final ServiceReference ref : sortedRefs) {
+                final HealthCheck hc = (HealthCheck)bundleContext.getService(ref);
+                log.debug("Selected HealthCheck service {}", hc);
+                if ( hc != null ) {
+                    this.usedReferences.add(ref);
+                    result.add(hc);
+                }
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Get all service references for health check services with one of the supplied tags. Uses logical "and" to combine tags.
+     * @return An array of service references - might be an empty error if none matches
+     */
+    public ServiceReference[] getTaggedHealthCheckServiceReferences(final String... tags) {
+        return getTaggedHealthCheckServiceReferences(false, tags);
+    }
+
+    /**
+     * Get all service references for health check services with one of the supplied tags.
+     * 
+     * @param combineWithOr If true will return all health checks that have at least one of the tags set. 
+     *        If false will return only health checks that have all given tags assigned.
+     * @param tags the tags to look for
+     * @return An array of service references - might be an empty error if none matches
+     */
+    public ServiceReference[] getTaggedHealthCheckServiceReferences(boolean combineWithOr, final String... tags) {
+        // Build service filter
+        final StringBuilder filterBuilder = new StringBuilder();
+        filterBuilder.append("(&(objectClass=").append(HealthCheck.class.getName()).append(")");
+        final int prefixLen = OMIT_PREFIX.length();
+        final StringBuilder filterBuilderForOrOperator = new StringBuilder(); // or filters
+        for(String tag : tags) {
+            tag = tag.trim();
+            if(tag.length() == 0) {
+                continue;
+            }
+            if(tag.startsWith(OMIT_PREFIX)) {
+                // ommit tags always have to be added as and-clause
+                filterBuilder.append("(!(").append(HealthCheck.TAGS).append("=").append(tag.substring(prefixLen)).append("))");
+            } else {
+                // add regular tags in the list either to outer and-clause or inner or-clause 
+                if (combineWithOr) {
+                    filterBuilderForOrOperator.append("(").append(HealthCheck.TAGS).append("=").append(tag).append(")");
+                } else {
+                    filterBuilder.append("(").append(HealthCheck.TAGS).append("=").append(tag).append(")");
+                }
+            }
+        }
+        // add "or" clause if we have accumulated any 
+        if (filterBuilderForOrOperator.length() > 0) {
+            filterBuilder.append("(|").append(filterBuilderForOrOperator).append(")");
+        }
+        filterBuilder.append(")");
+
+        log.debug("OSGi service filter in getTaggedHealthCheckServiceReferences(): {}", filterBuilder);
+
+        try {
+            final String filterString = filterBuilder.length() == 0 ? null : filterBuilder.toString();
+            bundleContext.createFilter(filterString); // check syntax early
+            final ServiceReference[] refs = bundleContext.getServiceReferences(HealthCheck.class.getName(), filterString);
+            if (refs == null) {
+                log.debug("Found no HealthCheck services with filter [{}]", filterString);
+                return new ServiceReference[0];
+            } else {
+                log.debug("Found {} HealthCheck services with filter [{}]", refs.length, filterString);
+            }
+            return refs;
+        } catch (final InvalidSyntaxException ise) {
+            // this should not happen, but we fail gracefully
+            log.error("Invalid OSGi filter syntax in '" + filterBuilder + "'", ise);
+            return new ServiceReference[0];
+        }
+    }
+
+    /**
+     * Dispose all used service references
+     */
+    public void dispose() {
+        for(final ServiceReference ref : this.usedReferences) {
+            this.bundleContext.ungetService(ref);
+        }
+        this.usedReferences.clear();
+    }
+}
diff --git a/src/main/java/org/apache/sling/hc/util/HealthCheckMetadata.java b/src/main/java/org/apache/sling/hc/util/HealthCheckMetadata.java
new file mode 100644
index 0000000..f5fdcb5
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/util/HealthCheckMetadata.java
@@ -0,0 +1,177 @@
+/*
+ * 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.util;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.apache.sling.hc.api.HealthCheck;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * This class helps retrieving meta data information about a health check service.
+ * @since 1.1
+ */
+public class HealthCheckMetadata {
+
+    private final String name;
+
+    private final String mbeanName;
+
+    private final String title;
+
+    private final long serviceId;
+
+    private final List<String> tags;
+
+    private final String asyncCronExpression;
+
+    private final transient ServiceReference serviceReference;
+
+    private final Long resultCacheTtlInMs;
+
+    public HealthCheckMetadata(final ServiceReference ref) {
+        this.serviceId = (Long) ref.getProperty(Constants.SERVICE_ID);
+        this.name = (String) ref.getProperty(HealthCheck.NAME);
+        this.mbeanName = (String) ref.getProperty(HealthCheck.MBEAN_NAME);
+        this.title = getHealthCheckTitle(ref);
+        this.tags = arrayPropertyToListOfStr(ref.getProperty(HealthCheck.TAGS));
+        this.asyncCronExpression = (String) ref.getProperty(HealthCheck.ASYNC_CRON_EXPRESSION);
+        this.resultCacheTtlInMs = (Long)ref.getProperty(HealthCheck.RESULT_CACHE_TTL_IN_MS);
+        this.serviceReference = ref;
+    }
+
+    /**
+     * The name of the health check as defined through the {@link HealthCheck#NAME}
+     * property.
+     * @return The name or <code>null</code>
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * The mbean name of the health check as defined through the {@link HealthCheck#MBEAN_NAME}
+     * property.
+     * @return The mbean name or <code>null</code>
+     */
+    public String getMBeanName() {
+        return mbeanName;
+    }
+
+    /**
+     * The title of the health check.
+     * If the health check has a name, this is used as the title.
+     * Otherwise the description, PID and service ID are checked
+     * for values.
+     */
+    public String getTitle() {
+        return title;
+    }
+
+    /**
+     * Return the list of defined tags for this check as set
+     * through {@link HealthCheckMetadata#tags}
+     * @return
+     */
+    public List<String> getTags() {
+        return tags;
+    }
+
+
+    /**
+     * Return the cron expression used for asynchronous execution.
+     */
+    public String getAsyncCronExpression() {
+        return asyncCronExpression;
+    }
+
+    /**
+     * Return the service id.
+     */
+    public long getServiceId() {
+        return this.serviceId;
+    }
+
+    /**
+     * Get the service reference.
+     */
+    public ServiceReference getServiceReference() {
+        return this.serviceReference;
+    }
+
+    /**
+     * TTL for the result cache in ms. 
+     * 
+     * @return TTL for the result cache or <code>null</code> if not configured.
+     */
+    public Long getResultCacheTtlInMs() {
+        return resultCacheTtlInMs;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (int) (serviceId ^ (serviceId >>> 32));
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if ( !(obj instanceof HealthCheckMetadata)) {
+            return false;
+        }
+        final HealthCheckMetadata other = (HealthCheckMetadata) obj;
+        return serviceId == other.serviceId;
+    }
+
+    @Override
+    public String toString() {
+        return "HealthCheck '" + name + "'";
+    }
+
+    private String getHealthCheckTitle(final ServiceReference ref) {
+        String name = (String) ref.getProperty(HealthCheck.NAME);
+        if (StringUtils.isBlank(name)) {
+            name = PropertiesUtil.toString(ref.getProperty(Constants.SERVICE_DESCRIPTION), null);
+        }
+        if (StringUtils.isBlank(name)) {
+            name = "HealthCheck:" + ref.getProperty(Constants.SERVICE_ID);
+            final String pid = PropertiesUtil.toString(ref.getProperty(Constants.SERVICE_PID), null);
+            if ( !StringUtils.isBlank(pid) ) {
+                name = name + " (" + pid + ")";
+            }
+        }
+        return name;
+    }
+
+    private List<String> arrayPropertyToListOfStr(final Object arrayProp) {
+        List<String> res = new LinkedList<String>();
+        if (arrayProp instanceof String) {
+            res.add((String) arrayProp);
+        } else if (arrayProp instanceof String[]) {
+            res.addAll(Arrays.asList((String[]) arrayProp));
+        }
+        return res;
+    }
+}
diff --git a/src/main/java/org/apache/sling/hc/util/SimpleConstraintChecker.java b/src/main/java/org/apache/sling/hc/util/SimpleConstraintChecker.java
new file mode 100644
index 0000000..b506840
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/util/SimpleConstraintChecker.java
@@ -0,0 +1,80 @@
+/*
+ * 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.util;
+
+import org.apache.sling.hc.api.Result;
+import org.apache.sling.hc.api.ResultLog;
+
+/** Simple check of numeric values against expressions
+ *  like &lt; N, &gt; N, between two values etc.
+ *  See the SimpleConstraintCheckerTest for examples.
+ */
+public class SimpleConstraintChecker {
+
+    public static final String CONTAINS = "contains";
+
+    /** Check value against expression and report to result */
+    public void check(Object inputValue, String constraint, ResultLog resultLog) {
+
+        final String stringValue = inputValue == null ? "" : inputValue.toString();
+
+        if(constraint == null || constraint.trim().length() == 0) {
+            throw new IllegalArgumentException("Empty constraint, cannot evaluate");
+        }
+
+        final String [] parts = constraint.split(" ");
+        boolean matches = false;
+        try {
+            if(constraint.startsWith(">") && parts.length == 2) {
+                final int value = Integer.valueOf(stringValue).intValue();
+                matches = value > Integer.valueOf(parts[1]);
+
+            } else if(constraint.startsWith("<") && parts.length == 2) {
+                final int value = Integer.valueOf(stringValue).intValue();
+                matches = value < Integer.valueOf(parts[1]);
+
+            } else if(parts.length == 4 && "between".equalsIgnoreCase(parts[0]) && "and".equalsIgnoreCase(parts[2]) ) {
+                final int value = Integer.valueOf(stringValue).intValue();
+                final int lowerBound = Integer.valueOf(parts[1]);
+                final int upperBound = Integer.valueOf(parts[3]);
+                matches = value > lowerBound && value < upperBound;
+
+            } else if(parts.length >1 && CONTAINS.equalsIgnoreCase(parts[0])) {
+                final String pattern = constraint.substring(CONTAINS.length()).trim();
+                matches = stringValue.contains(pattern);
+
+            } else {
+                matches = constraint.equals(stringValue);
+            }
+        } catch(NumberFormatException nfe) {
+            resultLog.add(new ResultLog.Entry(
+                    Result.Status.WARN,
+                    "Invalid numeric value [" + inputValue + "] while evaluating " + constraint));
+        }
+
+        if(matches) {
+            resultLog.add(new ResultLog.Entry(
+                    Result.Status.DEBUG,
+                    "Value [" + inputValue + "] matches constraint [" + constraint + "]"));
+        } else {
+            resultLog.add(new ResultLog.Entry(
+                    Result.Status.WARN,
+                    "Value [" + inputValue + "] does not match constraint [" + constraint + "]"));
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/hc/util/package-info.java b/src/main/java/org/apache/sling/hc/util/package-info.java
new file mode 100644
index 0000000..17a9969
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/util/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * 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 ASF 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.
+ */
+
+@Version("1.3.0")
+package org.apache.sling.hc.util;
+
+import aQute.bnd.annotation.Version;
+
diff --git a/src/test/java/org/apache/sling/hc/api/ResultLogTest.java b/src/test/java/org/apache/sling/hc/api/ResultLogTest.java
new file mode 100644
index 0000000..06a2349
--- /dev/null
+++ b/src/test/java/org/apache/sling/hc/api/ResultLogTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.api;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.util.Iterator;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class ResultLogTest {
+
+    private ResultLog log;
+    
+    @Before
+    public void setup() {
+        log = new ResultLog();
+    }
+    
+    @Test
+    public void testEmptyLogIsNotOk() {
+        assertEquals(Result.Status.WARN, log.getAggregateStatus());
+        assertFalse(log.iterator().hasNext());
+    }
+    
+    @Test
+    public void testSetStatusGoingUp() {
+        log.add(new ResultLog.Entry(Result.Status.DEBUG, "argh"));
+        assertEquals(Result.Status.OK, log.getAggregateStatus());
+        log.add(new ResultLog.Entry(Result.Status.INFO, "argh"));
+        assertEquals(Result.Status.OK, log.getAggregateStatus());
+        log.add(new ResultLog.Entry(Result.Status.OK, "argh"));
+        assertEquals(Result.Status.OK, log.getAggregateStatus());
+        log.add(new ResultLog.Entry(Result.Status.WARN, "argh"));
+        assertEquals(Result.Status.WARN, log.getAggregateStatus());
+        log.add(new ResultLog.Entry(Result.Status.CRITICAL, "argh"));
+        assertEquals(Result.Status.CRITICAL, log.getAggregateStatus());
+        log.add(new ResultLog.Entry(Result.Status.HEALTH_CHECK_ERROR, "argh"));
+        assertEquals(Result.Status.HEALTH_CHECK_ERROR, log.getAggregateStatus());
+    }
+    
+    @Test
+    public void testSetStatusGoingDownHCE() {
+        log.add(new ResultLog.Entry(Result.Status.HEALTH_CHECK_ERROR, "argh"));
+        assertEquals(Result.Status.HEALTH_CHECK_ERROR, log.getAggregateStatus());
+        log.add(new ResultLog.Entry(Result.Status.CRITICAL, "argh"));
+        assertEquals(Result.Status.HEALTH_CHECK_ERROR, log.getAggregateStatus());
+    }
+    
+    @Test
+    public void testSetStatusGoingDownCRIT() {
+        log.add(new ResultLog.Entry(Result.Status.CRITICAL, "argh"));
+        assertEquals(Result.Status.CRITICAL, log.getAggregateStatus());
+        log.add(new ResultLog.Entry(Result.Status.WARN, "argh"));
+        assertEquals(Result.Status.CRITICAL, log.getAggregateStatus());
+    }
+    
+    @Test
+    public void testSetStatusGoingDownWARN() {
+        log.add(new ResultLog.Entry(Result.Status.WARN, "argh"));
+        assertEquals(Result.Status.WARN, log.getAggregateStatus());
+        log.add(new ResultLog.Entry(Result.Status.OK, "argh"));
+        assertEquals(Result.Status.WARN, log.getAggregateStatus());
+    }
+    
+    @Test
+    public void testSetStatusGoingDownOK() {
+        log.add(new ResultLog.Entry(Result.Status.OK, "argh"));
+        assertEquals(Result.Status.OK, log.getAggregateStatus());
+        log.add(new ResultLog.Entry(Result.Status.INFO, "argh"));
+        assertEquals(Result.Status.OK, log.getAggregateStatus());
+        log.add(new ResultLog.Entry(Result.Status.DEBUG, "argh"));
+        assertEquals(Result.Status.OK, log.getAggregateStatus());
+    }
+    
+    @Test
+    public void testLogEntries() {
+        log.add(new ResultLog.Entry(Result.Status.OK, "ok 1"));
+        log.add(new ResultLog.Entry(Result.Status.DEBUG, "debug 2"));
+        log.add(new ResultLog.Entry(Result.Status.WARN, "warn 3"));
+        log.add(new ResultLog.Entry(Result.Status.CRITICAL, "critical 4"));
+        
+        final Iterator<ResultLog.Entry> it = log.iterator();
+        assertEquals("OK ok 1", it.next().toString());
+        assertEquals("DEBUG debug 2", it.next().toString());
+        assertEquals("WARN warn 3", it.next().toString());
+        assertEquals("CRITICAL critical 4", it.next().toString());
+        assertFalse(it.hasNext());
+    }
+    }
diff --git a/src/test/java/org/apache/sling/hc/api/ResultTest.java b/src/test/java/org/apache/sling/hc/api/ResultTest.java
new file mode 100644
index 0000000..dff455d
--- /dev/null
+++ b/src/test/java/org/apache/sling/hc/api/ResultTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.api;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.Test;
+
+public class ResultTest {
+    
+    private final AtomicInteger counter = new AtomicInteger();
+    
+    private void assertSingleResult(Result.Status toSet, Result.Status expected, boolean expectOk) {
+        final String msg = "test " + counter.incrementAndGet();
+        final Result r = new Result(toSet, msg);
+        assertEquals(expected, r.getStatus());
+        assertEquals(expectOk, r.isOk());
+        assertTrue(r.iterator().hasNext());
+        assertEquals(toSet.toString() + " " + msg, r.iterator().next().toString());
+    }
+    
+    @Test
+    public void testSingleResult() {
+        assertSingleResult(Result.Status.DEBUG, Result.Status.OK, true);
+        assertSingleResult(Result.Status.INFO, Result.Status.OK, true);
+        assertSingleResult(Result.Status.OK, Result.Status.OK, true);
+        assertSingleResult(Result.Status.WARN, Result.Status.WARN, false);
+        assertSingleResult(Result.Status.CRITICAL, Result.Status.CRITICAL, false);
+        assertSingleResult(Result.Status.HEALTH_CHECK_ERROR, Result.Status.HEALTH_CHECK_ERROR, false);
+    }
+    
+    @Test
+    public void testLog() {
+        final ResultLog log = new ResultLog();
+        log.add(new ResultLog.Entry(Result.Status.INFO, "argh"));
+        log.add(new ResultLog.Entry(Result.Status.WARN, "bad stuff"));
+        
+        final Result result = new Result(log);
+        assertEquals(Result.Status.WARN, result.getStatus());
+        
+        final StringBuilder sb = new StringBuilder();
+        for(ResultLog.Entry e : result) {
+            sb.append(e.toString()).append("#");
+        }
+        assertEquals("INFO argh#WARN bad stuff#", sb.toString());
+    }
+}
diff --git a/src/test/java/org/apache/sling/hc/util/SimpleConstraintCheckerTest.java b/src/test/java/org/apache/sling/hc/util/SimpleConstraintCheckerTest.java
new file mode 100644
index 0000000..3a58eb0
--- /dev/null
+++ b/src/test/java/org/apache/sling/hc/util/SimpleConstraintCheckerTest.java
@@ -0,0 +1,167 @@
+/*
+ * 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.util;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.sling.hc.api.Result;
+import org.apache.sling.hc.api.ResultLog;
+import org.apache.sling.hc.util.SimpleConstraintChecker;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SimpleConstraintCheckerTest {
+    private ResultLog resultLog; 
+
+    private final SimpleConstraintChecker checker = new SimpleConstraintChecker();
+
+    @Before
+    public void setup() {
+        resultLog = new ResultLog();
+    }
+    
+    @Test
+    public void testStringEquals() {
+        final String s = "test_" + System.currentTimeMillis();
+        checker.check(s, s, resultLog);
+        assertTrue(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+    
+    @Test
+    public void testStringNotEquals() {
+        final String s = "test_" + System.currentTimeMillis();
+        checker.check(s, "something else", resultLog);
+        assertFalse(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+    
+    @Test
+    public void testFiveEquals() {
+        final String s = "5";
+        checker.check(s, s, resultLog);
+        assertTrue(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+    
+    @Test
+    public void testIntTwelveEquals() {
+        checker.check(12, "12", resultLog);
+        assertTrue(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+    
+    @Test
+    public void testIntTwelveGreaterThan() {
+        checker.check(12, "> 11", resultLog);
+        assertTrue(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+    
+    @Test
+    public void testFiveNotEquals() {
+        checker.check("5", "foo", resultLog);
+        assertFalse(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+    
+    @Test
+    public void testNullNotEquals() {
+        checker.check(null, "foo", resultLog);
+        assertFalse(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+    
+    @Test
+    public void testNullNotGreater() {
+        checker.check(null, "> 2", resultLog);
+        assertFalse(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+    
+    @Test
+    public void testGreaterThanTrue() {
+        checker.check("5", "> 2", resultLog);
+        assertTrue(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+    
+    @Test
+    public void testGreaterThanFalse() {
+        checker.check("5", "> 12", resultLog);
+        assertFalse(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+    
+    @Test
+    public void testLessThanTrue() {
+        checker.check("5", "< 12", resultLog);
+        assertTrue(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+    
+    @Test
+    public void testLessThanFalse() {
+        checker.check("5", "< 2", resultLog);
+        assertFalse(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+    
+    @Test
+    public void testBetweenA() {
+        checker.check("5", "between 2 and 6", resultLog);
+        assertTrue(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+    
+    @Test
+    public void testBetweenB() {
+        checker.check("5", "between 12 and 16", resultLog);
+        assertFalse(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+    
+    @Test
+    public void testBetweenC() {
+        checker.check(5L, "between 12 and 16", resultLog);
+        assertFalse(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+    
+    @Test
+    public void testBetweenD() {
+        checker.check(5L, "between 4 and 16", resultLog);
+        assertTrue(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+    
+    @Test
+    public void testBetweenE() {
+        checker.check(5L, "betWEEN 4 aND 16", resultLog);
+        assertTrue(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+    
+    @Test
+    public void testNotAnInteger() {
+        checker.check("foo", "between 12 and 16", resultLog);
+        assertFalse(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+    
+    @Test
+    public void testContainsA() {
+        checker.check("This is a NICE STRING ok?", "contains NICE STRING", resultLog);
+        assertTrue(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+    
+    @Test
+    public void testContainsB() {
+        checker.check("This is a NICE TOUCH ok?", "contains NICE STRING", resultLog);
+        assertFalse(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+    
+    @Test
+    public void testContainsC() {
+        checker.check("This is a NICE TOUCH ok?", "contains NICE", resultLog);
+        assertTrue(resultLog.getAggregateStatus().equals(Result.Status.OK));
+    }
+}

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-hc-api] 07/08: SLING-6855 - accept String as well for WARNINGS_STICK_FOR_MINUTES (could do the same for other values but lets minimize changes)

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-hc-api.git

commit c13813ead0cfe20ab1f704a43dc465d92bc0902d
Author: Bertrand Delacretaz <bd...@apache.org>
AuthorDate: Fri Jun 9 13:52:59 2017 +0000

    SLING-6855 - accept String as well for WARNINGS_STICK_FOR_MINUTES (could do the same for other values but lets minimize changes)
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1798218 13f79535-47bb-0310-9956-ffa450edef68
---
 .../java/org/apache/sling/hc/util/HealthCheckMetadata.java   | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/src/main/java/org/apache/sling/hc/util/HealthCheckMetadata.java b/src/main/java/org/apache/sling/hc/util/HealthCheckMetadata.java
index b59eb0a..f996652 100644
--- a/src/main/java/org/apache/sling/hc/util/HealthCheckMetadata.java
+++ b/src/main/java/org/apache/sling/hc/util/HealthCheckMetadata.java
@@ -59,10 +59,20 @@ public class HealthCheckMetadata {
         this.tags = arrayPropertyToListOfStr(ref.getProperty(HealthCheck.TAGS));
         this.asyncCronExpression = (String) ref.getProperty(HealthCheck.ASYNC_CRON_EXPRESSION);
         this.resultCacheTtlInMs = (Long)ref.getProperty(HealthCheck.RESULT_CACHE_TTL_IN_MS);
-        this.warningsStickForMinutes = (Long) ref.getProperty(HealthCheck.WARNINGS_STICK_FOR_MINUTES);
+        this.warningsStickForMinutes = toLong(ref.getProperty(HealthCheck.WARNINGS_STICK_FOR_MINUTES));
         this.serviceReference = ref;
     }
 
+    private Long toLong(Object configValue) {
+        if(configValue == null) {
+            return null;
+        }
+        if(configValue instanceof Long) {
+            return (Long)configValue;
+        }
+        return Long.valueOf(configValue.toString());
+    }
+    
     /**
      * The name of the health check as defined through the {@link HealthCheck#NAME}
      * property.

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-hc-api] 03/08: [maven-release-plugin] prepare release org.apache.sling.hc.api-1.0.0

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-hc-api.git

commit 26fb773280923f7630c9fc09ca36d805f6320959
Author: Karl Pauls <pa...@apache.org>
AuthorDate: Mon May 8 10:54:35 2017 +0000

    [maven-release-plugin] prepare release org.apache.sling.hc.api-1.0.0
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1794322 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/pom.xml b/pom.xml
index 9d88e9c..a83e864 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,9 +17,7 @@
     specific language governing permissions and limitations
     under the License.
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
         <groupId>org.apache.sling</groupId>
         <artifactId>sling</artifactId>
@@ -31,7 +29,7 @@
     <groupId>org.apache.sling</groupId>
     <artifactId>org.apache.sling.hc.api</artifactId>
     <packaging>bundle</packaging>
-    <version>0.0.99-SNAPSHOT</version>
+    <version>1.0.0</version>
 
     <name>Apache Sling Health Check API</name>
     <inceptionYear>2013</inceptionYear>
@@ -41,9 +39,9 @@
     </description>
 
     <scm>
-        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/healthcheck/api</connection>
-        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/healthcheck/api</developerConnection>
-        <url>http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/healthcheck/api</url>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/tags/org.apache.sling.hc.api-1.0.0</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/tags/org.apache.sling.hc.api-1.0.0</developerConnection>
+        <url>http://svn.apache.org/viewvc/sling/tags/org.apache.sling.hc.api-1.0.0</url>
     </scm>
 
     <build>

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-hc-api] 05/08: SLING-6804 - allow selecting health checks by name

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-hc-api.git

commit bd44d276971ef72906ccddcc5f0982b2d7e2afff
Author: Justin Edelson <ju...@apache.org>
AuthorDate: Thu May 11 20:05:21 2017 +0000

    SLING-6804 - allow selecting health checks by name
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1794887 13f79535-47bb-0310-9956-ffa450edef68
---
 .../hc/api/execution/HealthCheckExecutor.java      |  24 +++
 .../hc/api/execution/HealthCheckSelector.java      | 105 ++++++++++++++
 .../sling/hc/api/execution/package-info.java       |   2 +-
 .../apache/sling/hc/util/FormattingResultLog.java  |   2 +
 .../apache/sling/hc/util/HealthCheckFilter.java    | 161 ++++++++++++++-------
 .../apache/sling/hc/util/HealthCheckMetadata.java  |   2 +
 .../org/apache/sling/hc/util/package-info.java     |   2 +-
 .../sling/hc/util/HealthCheckFilterTest.java       |  97 +++++++++++++
 8 files changed, 343 insertions(+), 52 deletions(-)

diff --git a/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutor.java b/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutor.java
index e41858c..4cab49c 100644
--- a/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutor.java
+++ b/src/main/java/org/apache/sling/hc/api/execution/HealthCheckExecutor.java
@@ -32,11 +32,33 @@ import org.osgi.annotation.versioning.ProviderType;
 public interface HealthCheckExecutor {
 
     /**
+     * Executes all health checks matching the supplied filter options.
+     * If no options are supplied, all health checks are executed.
+     *
+     * @param selector filter selector
+     * @return List of results. The list might be empty.
+     */
+    List<HealthCheckExecutionResult> execute(HealthCheckSelector selector);
+
+    /**
+     * Executes all health checks with the supplied filter options.
+     * If no options are supplied, all health checks are executed.
+     *
+     * @param selector filter selector
+     * @param options options for controlling execution behavior
+     *
+     * @return List of results. The list might be empty.
+     */
+    List<HealthCheckExecutionResult> execute(HealthCheckSelector selector, HealthCheckExecutionOptions options);
+
+    /**
      * Executes all health checks with the supplied list of tags.
      * If no tags are supplied, all health checks are executed.
      *
      * @return List of results. The list might be empty.
+     * @deprecated use execute(HealthCheckFilter.Options)
      */
+    @Deprecated
     List<HealthCheckExecutionResult> execute(String... tags);
 
     /**
@@ -47,7 +69,9 @@ public interface HealthCheckExecutor {
      * @param tags tags to be executed
      *
      * @return List of results. The list might be empty.
+     * @deprecated use execute(HealthCheckFilter.Options, HealthCheckExecutionOptions)
      */
+    @Deprecated
     List<HealthCheckExecutionResult> execute(HealthCheckExecutionOptions options, String... tags);
 
 }
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/hc/api/execution/HealthCheckSelector.java b/src/main/java/org/apache/sling/hc/api/execution/HealthCheckSelector.java
new file mode 100644
index 0000000..362d817
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/api/execution/HealthCheckSelector.java
@@ -0,0 +1,105 @@
+/*
+ * 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 ASF 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.api.execution;
+
+import org.apache.sling.hc.api.HealthCheck;
+import org.apache.sling.hc.util.HealthCheckFilter;
+import org.osgi.annotation.versioning.ProviderType;
+
+import java.util.Arrays;
+
+/**
+ * Parameter class to pass a set of tags and names to the filter.
+ */
+@ProviderType
+public final class HealthCheckSelector {
+
+    private String[] tags;
+    private String[] names;
+
+    public String[] tags() {
+        return tags;
+    }
+
+    public String[] names() {
+        return names;
+    }
+
+    private HealthCheckSelector() {}
+
+    /**
+     * Copy the specified names into the current tags array.
+     * @param tags the new tags. Specify null to clear the current tag array
+     * @return this
+     */
+    public HealthCheckSelector withTags(String... tags) {
+        if (this.tags == null) {
+            this.tags = tags;
+        } else if (tags != null) {
+            String[] copy = Arrays.copyOf(this.tags, this.tags.length + tags.length);
+            System.arraycopy(tags, 0, copy, this.tags.length, tags.length);
+            this.tags = copy;
+        } else {
+            this.tags = null;
+        }
+        return this;
+    }
+
+
+    /**
+     * Copy the specified names into the current names array.
+     * @param names the new names. Specify null to clear the current name array
+     * @return this
+     */
+    public HealthCheckSelector withNames(String... names) {
+        if (this.names == null) {
+            this.names = names;
+        } else if (names != null) {
+            String[] copy = Arrays.copyOf(this.names, this.names.length + names.length);
+            System.arraycopy(names, 0, copy, this.names.length, names.length);
+            this.names = copy;
+        } else {
+            this.names = null;
+        }
+        return this;
+    }
+
+
+    public static HealthCheckSelector empty() {
+        return  new HealthCheckSelector();
+    }
+
+    public static HealthCheckSelector tags(String... tags) {
+        HealthCheckSelector selector = new HealthCheckSelector();
+        selector.tags = tags;
+        return selector;
+    }
+
+    public static HealthCheckSelector names(String... names) {
+        HealthCheckSelector selector = new HealthCheckSelector();
+        selector.names = names;
+        return selector;
+    }
+
+    @Override
+    public String toString() {
+        return "HealthCheckSelector{" +
+                "tags=" + tags == null ? "*" : Arrays.toString(tags) +
+                ", names=" + names == null ? "*" : Arrays.toString(names) +
+                '}';
+    }
+}
diff --git a/src/main/java/org/apache/sling/hc/api/execution/package-info.java b/src/main/java/org/apache/sling/hc/api/execution/package-info.java
index dc8b8aa..d34f80e 100644
--- a/src/main/java/org/apache/sling/hc/api/execution/package-info.java
+++ b/src/main/java/org/apache/sling/hc/api/execution/package-info.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-@Version("1.1.0")
+@Version("1.2.0")
 package org.apache.sling.hc.api.execution;
 
 import org.osgi.annotation.versioning.Version;
diff --git a/src/main/java/org/apache/sling/hc/util/FormattingResultLog.java b/src/main/java/org/apache/sling/hc/util/FormattingResultLog.java
index e37dd72..2493722 100644
--- a/src/main/java/org/apache/sling/hc/util/FormattingResultLog.java
+++ b/src/main/java/org/apache/sling/hc/util/FormattingResultLog.java
@@ -22,9 +22,11 @@ import java.util.Locale;
 
 import org.apache.sling.hc.api.Result;
 import org.apache.sling.hc.api.ResultLog;
+import org.osgi.annotation.versioning.ProviderType;
 import org.slf4j.helpers.MessageFormatter;
 
 /** Utility that provides a logging-like facade on a ResultLog */
+@ProviderType
 public class FormattingResultLog extends ResultLog {
     
     private ResultLog.Entry createEntry(Result.Status status, String format, Object ... args) {
diff --git a/src/main/java/org/apache/sling/hc/util/HealthCheckFilter.java b/src/main/java/org/apache/sling/hc/util/HealthCheckFilter.java
index 5466492..c851a66 100644
--- a/src/main/java/org/apache/sling/hc/util/HealthCheckFilter.java
+++ b/src/main/java/org/apache/sling/hc/util/HealthCheckFilter.java
@@ -25,12 +25,17 @@ import java.util.List;
 import java.util.Set;
 
 import org.apache.sling.hc.api.HealthCheck;
+import org.apache.sling.hc.api.execution.HealthCheckSelector;
+import org.osgi.annotation.versioning.ProviderType;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.sling.hc.api.execution.HealthCheckSelector.tags;
+import static org.apache.sling.hc.api.execution.HealthCheckSelector.empty;
+
 /**
  * Select from available {@link HealthCheck} services.
  * Once this filter object and the returned health check services are no longer
@@ -40,6 +45,7 @@ import org.slf4j.LoggerFactory;
  * This class is not thread safe and instances shouldn't be used concurrently
  * from different threads.
  */
+@ProviderType
 public class HealthCheckFilter {
 
     private final Logger log = LoggerFactory.getLogger(getClass());
@@ -57,13 +63,8 @@ public class HealthCheckFilter {
         bundleContext = bc;
     }
 
-    /**
-     * Get all health check services with one of the supplied tags.
-     * @return A list of services - might be the empty list if none matches
-     */
-    @SuppressWarnings("unchecked")
-    public List<HealthCheck> getTaggedHealthChecks(final String... tags) {
-        final ServiceReference [] refs = this.getTaggedHealthCheckServiceReferences(tags);
+    public List<HealthCheck> getHealthChecks(final HealthCheckSelector selector) {
+        final ServiceReference [] refs = this.getHealthCheckServiceReferences(selector);
         final List<HealthCheck> result = new ArrayList<HealthCheck>();
 
         if ( refs != null ) {
@@ -83,52 +84,14 @@ public class HealthCheckFilter {
         return result;
     }
 
-    /**
-     * Get all service references for health check services with one of the supplied tags. Uses logical "and" to combine tags.
-     * @return An array of service references - might be an empty error if none matches
-     */
-    public ServiceReference[] getTaggedHealthCheckServiceReferences(final String... tags) {
-        return getTaggedHealthCheckServiceReferences(false, tags);
+    public ServiceReference[] getHealthCheckServiceReferences(final HealthCheckSelector selector) {
+        return getHealthCheckServiceReferences(selector, false);
     }
 
-    /**
-     * Get all service references for health check services with one of the supplied tags.
-     * 
-     * @param combineWithOr If true will return all health checks that have at least one of the tags set. 
-     *        If false will return only health checks that have all given tags assigned.
-     * @param tags the tags to look for
-     * @return An array of service references - might be an empty error if none matches
-     */
-    public ServiceReference[] getTaggedHealthCheckServiceReferences(boolean combineWithOr, final String... tags) {
-        // Build service filter
-        final StringBuilder filterBuilder = new StringBuilder();
-        filterBuilder.append("(&(objectClass=").append(HealthCheck.class.getName()).append(")");
-        final int prefixLen = OMIT_PREFIX.length();
-        final StringBuilder filterBuilderForOrOperator = new StringBuilder(); // or filters
-        for(String tag : tags) {
-            tag = tag.trim();
-            if(tag.length() == 0) {
-                continue;
-            }
-            if(tag.startsWith(OMIT_PREFIX)) {
-                // ommit tags always have to be added as and-clause
-                filterBuilder.append("(!(").append(HealthCheck.TAGS).append("=").append(tag.substring(prefixLen)).append("))");
-            } else {
-                // add regular tags in the list either to outer and-clause or inner or-clause 
-                if (combineWithOr) {
-                    filterBuilderForOrOperator.append("(").append(HealthCheck.TAGS).append("=").append(tag).append(")");
-                } else {
-                    filterBuilder.append("(").append(HealthCheck.TAGS).append("=").append(tag).append(")");
-                }
-            }
-        }
-        // add "or" clause if we have accumulated any 
-        if (filterBuilderForOrOperator.length() > 0) {
-            filterBuilder.append("(|").append(filterBuilderForOrOperator).append(")");
-        }
-        filterBuilder.append(")");
+    public ServiceReference[] getHealthCheckServiceReferences(final HealthCheckSelector selector, boolean combineTagsWithOr) {
+        final CharSequence filterBuilder = selector != null ? getServiceFilter(selector, combineTagsWithOr) : getServiceFilter(empty(), combineTagsWithOr);
 
-        log.debug("OSGi service filter in getTaggedHealthCheckServiceReferences(): {}", filterBuilder);
+        log.debug("OSGi service filter in getHealthCheckServiceReferences(): {}", filterBuilder);
 
         try {
             final String filterString = filterBuilder.length() == 0 ? null : filterBuilder.toString();
@@ -149,6 +112,42 @@ public class HealthCheckFilter {
     }
 
     /**
+     * Get all health check services with one of the supplied tags.
+     * @return A list of services - might be the empty list if none matches
+     * @deprecated use getHealthChecks() instead
+     */
+    @Deprecated
+    public List<HealthCheck> getTaggedHealthChecks(final String... tags) {
+        final HealthCheckSelector selector = tags(tags);
+        return getHealthChecks(selector);
+    }
+
+    /**
+     * Get all service references for health check services with one of the supplied tags. Uses logical "and" to combine tags.
+     * @return An array of service references - might be an empty error if none matches
+     * @deprecated use getHealthCheckServiceReferences() instead
+     */
+    @Deprecated
+    public ServiceReference[] getTaggedHealthCheckServiceReferences(final String... tags) {
+        return getHealthCheckServiceReferences(tags(tags), false);
+    }
+
+    /**
+     * Get all service references for health check services with one of the supplied tags.
+     * 
+     * @param combineWithOr If true will return all health checks that have at least one of the tags set. 
+     *        If false will return only health checks that have all given tags assigned.
+     * @param tags the tags to look for
+     * @return An array of service references - might be an empty error if none matches
+     * @deprecated use getHealthCheckServiceReferences() instead
+     */
+    @Deprecated
+    public ServiceReference[] getTaggedHealthCheckServiceReferences(boolean combineWithOr, final String... tags) {
+        final HealthCheckSelector selector = tags(tags);
+        return getHealthCheckServiceReferences(selector, combineWithOr);
+    }
+
+    /**
      * Dispose all used service references
      */
     public void dispose() {
@@ -157,4 +156,66 @@ public class HealthCheckFilter {
         }
         this.usedReferences.clear();
     }
+
+    CharSequence getServiceFilter(HealthCheckSelector selector, boolean combineTagsWithOr) {
+        // Build service filter
+        final StringBuilder filterBuilder = new StringBuilder();
+        filterBuilder.append("(&(objectClass=").append(HealthCheck.class.getName()).append(")");
+        final int prefixLen = HealthCheckFilter.OMIT_PREFIX.length();
+        final StringBuilder filterBuilderForOrOperator = new StringBuilder(); // or filters
+        final StringBuilder tagsBuilder = new StringBuilder();
+        int tagsAndClauses = 0;
+        if (selector.tags() != null) {
+            for (String tag : selector.tags()) {
+                tag = tag.trim();
+                if (tag.length() == 0) {
+                    continue;
+                }
+                if (tag.startsWith(HealthCheckFilter.OMIT_PREFIX)) {
+                    // ommit tags always have to be added as and-clause
+                    filterBuilder.append("(!(").append(HealthCheck.TAGS).append("=").append(tag.substring(prefixLen)).append("))");
+                } else {
+                    // add regular tags in the list either to outer and-clause or inner or-clause
+                    if (combineTagsWithOr) {
+                        filterBuilderForOrOperator.append("(").append(HealthCheck.TAGS).append("=").append(tag).append(")");
+                    } else {
+                        tagsBuilder.append("(").append(HealthCheck.TAGS).append("=").append(tag).append(")");
+                        tagsAndClauses++;
+                    }
+                }
+            }
+        }
+        boolean addedNameToOrBuilder = false;
+        if (selector.names() != null) {
+            for (String name : selector.names()) {
+                name = name.trim();
+                if (name.length() == 0) {
+                    continue;
+                }
+                if (name.startsWith(HealthCheckFilter.OMIT_PREFIX)) {
+                    // ommit tags always have to be added as and-clause
+                    filterBuilder.append("(!(").append(HealthCheck.NAME).append("=").append(name.substring(prefixLen)).append("))");
+                } else {
+                    // names are always ORd
+                    filterBuilderForOrOperator.append("(").append(HealthCheck.NAME).append("=").append(name).append(")");
+                    addedNameToOrBuilder = true;
+                }
+            }
+        }
+        if (addedNameToOrBuilder) {
+            if (tagsAndClauses > 1) {
+                filterBuilderForOrOperator.append("(&").append(tagsBuilder).append(")");
+            } else {
+                filterBuilderForOrOperator.append(tagsBuilder);
+            }
+        } else {
+            filterBuilder.append(tagsBuilder);
+        }
+        // add "or" clause if we have accumulated any
+        if (filterBuilderForOrOperator.length() > 0) {
+            filterBuilder.append("(|").append(filterBuilderForOrOperator).append(")");
+        }
+        filterBuilder.append(")");
+        return filterBuilder;
+    }
 }
diff --git a/src/main/java/org/apache/sling/hc/util/HealthCheckMetadata.java b/src/main/java/org/apache/sling/hc/util/HealthCheckMetadata.java
index efc378a..d4a9ed1 100644
--- a/src/main/java/org/apache/sling/hc/util/HealthCheckMetadata.java
+++ b/src/main/java/org/apache/sling/hc/util/HealthCheckMetadata.java
@@ -22,6 +22,7 @@ import java.util.LinkedList;
 import java.util.List;
 
 import org.apache.sling.hc.api.HealthCheck;
+import org.osgi.annotation.versioning.ProviderType;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
 
@@ -29,6 +30,7 @@ import org.osgi.framework.ServiceReference;
  * This class helps retrieving meta data information about a health check service.
  * @since 1.1
  */
+@ProviderType
 public class HealthCheckMetadata {
 
     private final String name;
diff --git a/src/main/java/org/apache/sling/hc/util/package-info.java b/src/main/java/org/apache/sling/hc/util/package-info.java
index 131d715..374c719 100644
--- a/src/main/java/org/apache/sling/hc/util/package-info.java
+++ b/src/main/java/org/apache/sling/hc/util/package-info.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-@Version("1.3.0")
+@Version("1.4.0")
 package org.apache.sling.hc.util;
 
 import org.osgi.annotation.versioning.Version;
diff --git a/src/test/java/org/apache/sling/hc/util/HealthCheckFilterTest.java b/src/test/java/org/apache/sling/hc/util/HealthCheckFilterTest.java
new file mode 100644
index 0000000..44be3ae
--- /dev/null
+++ b/src/test/java/org/apache/sling/hc/util/HealthCheckFilterTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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 ASF 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.util;
+
+import org.apache.sling.hc.api.execution.HealthCheckSelector;
+import org.junit.Test;
+import static org.junit.Assert.*;
+import static org.apache.sling.hc.api.execution.HealthCheckSelector.*;
+
+public class HealthCheckFilterTest {
+    
+    private HealthCheckFilter filter = new HealthCheckFilter(null);
+
+    private static void assertStrEquals(String expected, CharSequence actual) {
+        assertEquals(expected, actual.toString());
+    }
+
+    @Test
+    public void testEmptyOptions() {
+        assertStrEquals("(&(objectClass=org.apache.sling.hc.api.HealthCheck))", filter.getServiceFilter(empty(), false));
+    }
+
+    @Test
+    public void testWithOneTag() {
+        HealthCheckSelector selector = tags("foo");
+        assertStrEquals("(&(objectClass=org.apache.sling.hc.api.HealthCheck)(hc.tags=foo))", filter.getServiceFilter(selector, false));
+    }
+
+    @Test
+    public void testWithTwoTags() {
+        HealthCheckSelector selector = tags("foo", "bar");
+        assertStrEquals("(&(objectClass=org.apache.sling.hc.api.HealthCheck)(hc.tags=foo)(hc.tags=bar))", filter.getServiceFilter(selector, false));
+    }
+
+    @Test
+    public void testWithTwoTagsOr() {
+        HealthCheckSelector selector = tags("foo", "bar");
+        assertStrEquals("(&(objectClass=org.apache.sling.hc.api.HealthCheck)(|(hc.tags=foo)(hc.tags=bar)))", filter.getServiceFilter(selector, true));
+    }
+
+    @Test
+    public void testWithTwoTagsExcludeOne() {
+        HealthCheckSelector selector = tags("foo", "bar").withTags("-baz");
+        assertStrEquals("(&(objectClass=org.apache.sling.hc.api.HealthCheck)(!(hc.tags=baz))(hc.tags=foo)(hc.tags=bar))", filter.getServiceFilter(selector, false));
+    }
+
+    @Test
+    public void testWithOneName() {
+        HealthCheckSelector selector = names("foo");
+        assertStrEquals("(&(objectClass=org.apache.sling.hc.api.HealthCheck)(|(hc.name=foo)))", filter.getServiceFilter(selector, false));
+    }
+
+    @Test
+    public void testWithTwoNames() {
+        HealthCheckSelector selector = names("foo").withNames("bar");
+        assertStrEquals("(&(objectClass=org.apache.sling.hc.api.HealthCheck)(|(hc.name=foo)(hc.name=bar)))", filter.getServiceFilter(selector, false));
+    }
+
+    @Test
+    public void testWithTwoNamesExcludingOne() {
+        HealthCheckSelector selector = names("foo", "bar", "-baz");
+        assertStrEquals("(&(objectClass=org.apache.sling.hc.api.HealthCheck)(!(hc.name=baz))(|(hc.name=foo)(hc.name=bar)))", filter.getServiceFilter(selector, false));
+    }
+
+    @Test
+    public void testWithTagAndName() {
+        HealthCheckSelector selector = empty().withTags("t1").withNames("foo");
+        assertStrEquals("(&(objectClass=org.apache.sling.hc.api.HealthCheck)(|(hc.name=foo)(hc.tags=t1)))", filter.getServiceFilter(selector, false));
+    }
+
+    @Test
+    public void testWithTwoOrTagsAndTwoNames() {
+        HealthCheckSelector selector = empty().withNames("foo", "bar").withTags("t1", "t2");
+        assertStrEquals("(&(objectClass=org.apache.sling.hc.api.HealthCheck)(|(hc.tags=t1)(hc.tags=t2)(hc.name=foo)(hc.name=bar)))", filter.getServiceFilter(selector, true));
+    }
+
+    @Test
+    public void testWithTwoAndTagsAndTwoNames() {
+        HealthCheckSelector selector = empty().withNames("foo", "bar").withTags("t1", "t2");
+        assertStrEquals("(&(objectClass=org.apache.sling.hc.api.HealthCheck)(|(hc.name=foo)(hc.name=bar)(&(hc.tags=t1)(hc.tags=t2))))", filter.getServiceFilter(selector, false));
+    }
+
+}

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-hc-api] 06/08: SLING-6855 Introducing property hc.warningsStickForMinutes that makes warn HC results sticky for the given minutes

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-hc-api.git

commit 515631ffde35c202d506d986bdfe755eddff36d7
Author: Georg Henzler <gh...@apache.org>
AuthorDate: Thu Jun 8 20:42:33 2017 +0000

    SLING-6855 Introducing property hc.warningsStickForMinutes that makes warn HC results sticky for the given minutes
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1798123 13f79535-47bb-0310-9956-ffa450edef68
---
 src/main/java/org/apache/sling/hc/api/HealthCheck.java       | 11 +++++++++++
 src/main/java/org/apache/sling/hc/api/package-info.java      |  2 +-
 .../java/org/apache/sling/hc/util/HealthCheckMetadata.java   | 12 ++++++++++++
 src/main/java/org/apache/sling/hc/util/package-info.java     |  2 +-
 4 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/src/main/java/org/apache/sling/hc/api/HealthCheck.java b/src/main/java/org/apache/sling/hc/api/HealthCheck.java
index 6ef4c77..f32b483 100644
--- a/src/main/java/org/apache/sling/hc/api/HealthCheck.java
+++ b/src/main/java/org/apache/sling/hc/api/HealthCheck.java
@@ -74,6 +74,17 @@ public interface HealthCheck {
     String RESULT_CACHE_TTL_IN_MS = "hc.resultCacheTtlInMs";
 
     /**
+     * Optional service property: If given, warning results (that is WARN, 
+     * CRITICAL or HEALTH_CHECK_ERROR) from the past executions will be 
+     * taken into account as well for the given minutes (use 
+     * Integer.MAX_VALUE for indefinitely). Useful for unhealthy system 
+     * states that disappear but might leave the system at an inconsistent
+     * state (e.g. an event queue overflow).  
+     * 
+     */
+    String WARNINGS_STICK_FOR_MINUTES = "hc.warningsStickForMinutes";
+
+    /**
      * Execute this health check and return a {@link Result}
      * This is meant to execute quickly, access to external
      * systems, for example, should be managed asynchronously.
diff --git a/src/main/java/org/apache/sling/hc/api/package-info.java b/src/main/java/org/apache/sling/hc/api/package-info.java
index c79b3b4..c2b2dc6 100644
--- a/src/main/java/org/apache/sling/hc/api/package-info.java
+++ b/src/main/java/org/apache/sling/hc/api/package-info.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-@Version("1.1.0")
+@Version("1.2.0")
 package org.apache.sling.hc.api;
 
 import org.osgi.annotation.versioning.Version;
diff --git a/src/main/java/org/apache/sling/hc/util/HealthCheckMetadata.java b/src/main/java/org/apache/sling/hc/util/HealthCheckMetadata.java
index d4a9ed1..b59eb0a 100644
--- a/src/main/java/org/apache/sling/hc/util/HealthCheckMetadata.java
+++ b/src/main/java/org/apache/sling/hc/util/HealthCheckMetadata.java
@@ -49,6 +49,8 @@ public class HealthCheckMetadata {
 
     private final Long resultCacheTtlInMs;
 
+    private final Long warningsStickForMinutes;
+
     public HealthCheckMetadata(final ServiceReference ref) {
         this.serviceId = (Long) ref.getProperty(Constants.SERVICE_ID);
         this.name = (String) ref.getProperty(HealthCheck.NAME);
@@ -57,6 +59,7 @@ public class HealthCheckMetadata {
         this.tags = arrayPropertyToListOfStr(ref.getProperty(HealthCheck.TAGS));
         this.asyncCronExpression = (String) ref.getProperty(HealthCheck.ASYNC_CRON_EXPRESSION);
         this.resultCacheTtlInMs = (Long)ref.getProperty(HealthCheck.RESULT_CACHE_TTL_IN_MS);
+        this.warningsStickForMinutes = (Long) ref.getProperty(HealthCheck.WARNINGS_STICK_FOR_MINUTES);
         this.serviceReference = ref;
     }
 
@@ -128,6 +131,15 @@ public class HealthCheckMetadata {
         return resultCacheTtlInMs;
     }
 
+    /**
+     * Make warnings stick for the given amount of time.
+     *
+     * @return Time to make warn results sticky in minutes.
+     */
+    public Long getWarningsStickForMinutes() {
+        return warningsStickForMinutes;
+    }
+
     @Override
     public int hashCode() {
         final int prime = 31;
diff --git a/src/main/java/org/apache/sling/hc/util/package-info.java b/src/main/java/org/apache/sling/hc/util/package-info.java
index 374c719..12e8182 100644
--- a/src/main/java/org/apache/sling/hc/util/package-info.java
+++ b/src/main/java/org/apache/sling/hc/util/package-info.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-@Version("1.4.0")
+@Version("1.5.0")
 package org.apache.sling.hc.util;
 
 import org.osgi.annotation.versioning.Version;

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.