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/11/07 09:39:48 UTC
[sling-org-apache-sling-hc-support] 01/31: SLING-2987 - split into
several bundles
This is an automated email from the ASF dual-hosted git repository.
rombert pushed a commit to annotated tag org.apache.sling.hc.support-1.0.4
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-hc-support.git
commit 730094505f2d9e4791a9bf76fe2627a0155424fb
Author: Bertrand Delacretaz <bd...@apache.org>
AuthorDate: Mon Aug 12 16:01:50 2013 +0000
SLING-2987 - split into several bundles
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/healthcheck/healthchecks@1513179 13f79535-47bb-0310-9956-ffa450edef68
---
pom.xml | 154 ++++++++++
.../impl/DefaultLoginsHealthCheck.java | 129 +++++++++
.../hc/healthchecks/impl/HealthCheckInfo.java | 42 +++
.../hc/healthchecks/impl/InternalRequest.java | 319 +++++++++++++++++++++
.../hc/healthchecks/impl/InternalResponse.java | 185 ++++++++++++
.../healthchecks/impl/JmxAttributeHealthCheck.java | 115 ++++++++
.../hc/healthchecks/impl/JmxScriptBinding.java | 62 ++++
.../hc/healthchecks/impl/OsgiScriptBinding.java | 73 +++++
.../healthchecks/impl/ScriptableHealthCheck.java | 131 +++++++++
.../impl/SlingRequestStatusHealthCheck.java | 153 ++++++++++
src/test/java/org/apache/sling/hc/healthcheck | 44 +++
.../healthchecks/DefaultLoginsHealthCheckTest.java | 77 +++++
.../healthchecks/JmxAttributeHealthCheckTest.java | 57 ++++
.../hc/healthchecks/JmxScriptBindingTest.java | 41 +++
.../hc/healthchecks/OsgiScriptBindingTest.java | 67 +++++
.../hc/healthchecks/ScriptableHealthCheckTest.java | 94 ++++++
16 files changed, 1743 insertions(+)
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..b146639
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>sling</artifactId>
+ <version>16</version>
+ <relativePath>16</relativePath>
+ </parent>
+
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.hc.healthchecks</artifactId>
+ <packaging>bundle</packaging>
+ <version>0.0.2-SNAPSHOT</version>
+
+ <name>Sling Health Check Module - Health Check Services</name>
+ <inceptionYear>2013</inceptionYear>
+
+ <description>
+ Default Sling Health Check Services
+ </description>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-scr-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Private-Package>
+ org.apache.sling.hc.healthchecks.*
+ </Private-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>animal-sniffer-maven-plugin</artifactId>
+ <configuration>
+ <signature>
+ <groupId>org.codehaus.mojo.signature</groupId>
+ <artifactId>java16</artifactId>
+ <version>1.0</version>
+ </signature>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.scr.annotations</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.hc.api</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </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>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.api</artifactId>
+ <version>2.1.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.jcr.api</artifactId>
+ <version>2.0.4</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.engine</artifactId>
+ <version>2.2.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.6.2</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.jcr</groupId>
+ <artifactId>jcr</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>1.6.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.11</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>1.9.5</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>rhino</groupId>
+ <artifactId>js</artifactId>
+ <version>1.6R6</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/src/main/java/org/apache/sling/hc/healthchecks/impl/DefaultLoginsHealthCheck.java b/src/main/java/org/apache/sling/hc/healthchecks/impl/DefaultLoginsHealthCheck.java
new file mode 100644
index 0000000..357c5c1
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/healthchecks/impl/DefaultLoginsHealthCheck.java
@@ -0,0 +1,129 @@
+/*
+ * 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.healthchecks.impl;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.Credentials;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.apache.sling.hc.api.Constants;
+import org.apache.sling.hc.api.HealthCheck;
+import org.apache.sling.hc.api.Result;
+import org.apache.sling.hc.api.ResultLogEntry;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** {@link HealthCheck} that checks that Sling default logins fail.
+ * Used to verify that those logins are disabled on production systems */
+@Component(
+ name="org.apache.sling.hc.DefaultLoginsHealthCheck",
+ configurationFactory=true,
+ policy=ConfigurationPolicy.REQUIRE,
+ metatype=true)
+@Service
+public class DefaultLoginsHealthCheck implements HealthCheck {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+ private Map<String, String> info;
+
+ @Property(cardinality=500)
+ public static final String PROP_LOGINS = "logins";
+ private List<String> logins;
+
+ @Property(cardinality=50)
+ public static final String PROP_TAGS = Constants.HC_TAGS;
+
+ @Property
+ public static final String PROP_NAME = Constants.HC_NAME;
+
+ @Property
+ public static final String PROP_MBEAN_NAME = Constants.HC_MBEAN_NAME;
+
+ @Reference
+ private SlingRepository repository;
+
+ @Activate
+ public void activate(ComponentContext ctx) {
+ info = new HealthCheckInfo(ctx.getProperties());
+ logins = Arrays.asList(PropertiesUtil.toStringArray(ctx.getProperties().get(PROP_LOGINS), new String[] {}));
+ log.info("Activated, logins={}", logins);
+ }
+
+ @Override
+ public Result execute() {
+ final Result result = new Result(log);
+ int checked=0;
+ int failures=0;
+
+ for(String login : logins) {
+ final String [] parts = login.split(":");
+ if(parts.length != 2) {
+ result.log(ResultLogEntry.LT_WARN, "Expected login in the form username:password, got " + login);
+ continue;
+ }
+ checked++;
+ final String username = parts[0].trim();
+ final String password = parts[1].trim();
+ final Credentials creds = new SimpleCredentials(username, password.toCharArray());
+ Session s = null;
+ try {
+ s = repository.login(creds);
+ if(s != null) {
+ failures++;
+ result.log(ResultLogEntry.LT_WARN_SECURITY, "Login as [" + username + "] succeeded, was expecting it to fail");
+ } else {
+ result.log(ResultLogEntry.LT_DEBUG, "Login as [" + username + "] didn't throw an Exception but returned null Session");
+ }
+ } catch(RepositoryException re) {
+ result.log(ResultLogEntry.LT_DEBUG, "Login as [" + username + "] failed, as expected");
+ } finally {
+ if(s != null) {
+ s.logout();
+ }
+ }
+ }
+
+ if(checked==0) {
+ result.log(ResultLogEntry.LT_WARN, "Did not check any logins, configured logins=" + logins);
+ } else if(failures != 0){
+ result.log(ResultLogEntry.LT_WARN_SECURITY, "Checked " + checked + " logins, " + failures + " tests failed");
+ } else {
+ result.log(ResultLogEntry.LT_DEBUG, "Checked " + checked + " logins, all tests successful");
+ }
+ return result;
+ }
+
+ @Override
+ public Map<String, String> getInfo() {
+ return info;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/hc/healthchecks/impl/HealthCheckInfo.java b/src/main/java/org/apache/sling/hc/healthchecks/impl/HealthCheckInfo.java
new file mode 100644
index 0000000..ac3dc61
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/healthchecks/impl/HealthCheckInfo.java
@@ -0,0 +1,42 @@
+/*
+ * 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.healthchecks.impl;
+
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.HashMap;
+
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.apache.sling.hc.api.Constants;
+
+// TODO move to services bundle
+
+/** Utility that copies useful HealthCheck service
+ * properties to a Map that can be used as the Result's
+ * info(). Copies all service properties that have names
+ * that start with the {#Constants.HC_PROP_PREFIX} */
+public class HealthCheckInfo extends HashMap<String, String> {
+ private static final long serialVersionUID = 8661195387931574705L;
+
+ public HealthCheckInfo(Dictionary<?, ?> serviceProperties) {
+ put(Constants.HC_NAME, PropertiesUtil.toString(serviceProperties.get(Constants.HC_NAME), ""));
+ put(Constants.HC_MBEAN_NAME, PropertiesUtil.toString(serviceProperties.get(Constants.HC_MBEAN_NAME), ""));
+ put(Constants.HC_TAGS,
+ Arrays.asList(PropertiesUtil.toStringArray(serviceProperties.get(Constants.HC_TAGS), new String[] {})).toString());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/hc/healthchecks/impl/InternalRequest.java b/src/main/java/org/apache/sling/hc/healthchecks/impl/InternalRequest.java
new file mode 100644
index 0000000..570e57c
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/healthchecks/impl/InternalRequest.java
@@ -0,0 +1,319 @@
+/*
+ * 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.healthchecks.impl;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.security.Principal;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Vector;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+public class InternalRequest implements HttpServletRequest {
+
+ private final String path;
+ private final Map<String, Object> attributes = new HashMap<String, Object>();
+
+ public InternalRequest(String path) {
+ this.path = path;
+ }
+
+ @Override
+ public Object getAttribute(String key) {
+ return attributes.get(key);
+ }
+
+ @Override
+ public Enumeration<?> getAttributeNames() {
+ return new Vector<String>(attributes.keySet()).elements();
+ }
+
+ @Override
+ public String getCharacterEncoding() {
+ return "UTF-8";
+ }
+
+ @Override
+ public int getContentLength() {
+ return 0;
+ }
+
+ @Override
+ public String getContentType() {
+ return "text/plain";
+ }
+
+ @Override
+ public ServletInputStream getInputStream() throws IOException {
+ return new ServletInputStream() {
+ @Override
+ public int read() throws IOException {
+ return 0;
+ }
+ };
+ }
+
+ @Override
+ public String getLocalAddr() {
+ return "127.0.0.1";
+ }
+
+ @Override
+ public String getLocalName() {
+ return "localhost";
+ }
+
+ @Override
+ public int getLocalPort() {
+ return 0;
+ }
+
+ @Override
+ public Locale getLocale() {
+ return Locale.getDefault();
+ }
+
+ @Override
+ public Enumeration<?> getLocales() {
+ return new Vector<Locale>().elements();
+ }
+
+ @Override
+ public String getParameter(String arg0) {
+ return null;
+ }
+
+ @Override
+ public Map<?,?> getParameterMap() {
+ return new HashMap<String, Object>();
+ }
+
+ @Override
+ public Enumeration<?> getParameterNames() {
+ return new Vector<String>().elements();
+ }
+
+ @Override
+ public String[] getParameterValues(String arg0) {
+ return null;
+ }
+
+ @Override
+ public String getProtocol() {
+ return "http";
+ }
+
+ @Override
+ public BufferedReader getReader() throws IOException {
+ return new BufferedReader(new StringReader(""));
+ }
+
+ @Override
+ public String getRealPath(String arg0) {
+ return path;
+ }
+
+ @Override
+ public String getRemoteAddr() {
+ return "127.0.0.1";
+ }
+
+ @Override
+ public String getRemoteHost() {
+ return "localhost";
+ }
+
+ @Override
+ public int getRemotePort() {
+ return 1234;
+ }
+
+ @Override
+ public RequestDispatcher getRequestDispatcher(String arg0) {
+ return null;
+ }
+
+ @Override
+ public String getScheme() {
+ return "http";
+ }
+
+ @Override
+ public String getServerName() {
+ return "localhost";
+ }
+
+ @Override
+ public int getServerPort() {
+ return 80;
+ }
+
+ @Override
+ public boolean isSecure() {
+ return false;
+ }
+
+ @Override
+ public void removeAttribute(String arg0) {
+ }
+
+ @Override
+ public void setAttribute(String key, Object value) {
+ attributes.put(key, value);
+ }
+
+ @Override
+ public void setCharacterEncoding(String arg0)
+ throws UnsupportedEncodingException {
+ }
+
+ @Override
+ public String getAuthType() {
+ return null;
+ }
+
+ @Override
+ public String getContextPath() {
+ return "";
+ }
+
+ @Override
+ public Cookie[] getCookies() {
+ return null;
+ }
+
+ @Override
+ public long getDateHeader(String arg0) {
+ return 0;
+ }
+
+ @Override
+ public String getHeader(String arg0) {
+ return null;
+ }
+
+ @Override
+ public Enumeration<?> getHeaderNames() {
+ return new Vector<String>().elements();
+ }
+
+ @Override
+ public Enumeration<?> getHeaders(String arg0) {
+ return new Vector<String>().elements();
+ }
+
+ @Override
+ public int getIntHeader(String arg0) {
+ return 0;
+ }
+
+ @Override
+ public String getMethod() {
+ return "GET";
+ }
+
+ @Override
+ public String getPathInfo() {
+ return path;
+ }
+
+ @Override
+ public String getPathTranslated() {
+ return path;
+ }
+
+ @Override
+ public String getQueryString() {
+ return "";
+ }
+
+ @Override
+ public String getRemoteUser() {
+ return "remoteuser";
+ }
+
+ @Override
+ public String getRequestURI() {
+ return "http://localhost" + path;
+ }
+
+ @Override
+ public StringBuffer getRequestURL() {
+ return new StringBuffer(getRequestURI());
+ }
+
+ @Override
+ public String getRequestedSessionId() {
+ return "";
+ }
+
+ @Override
+ public String getServletPath() {
+ return "";
+ }
+
+ @Override
+ public HttpSession getSession() {
+ return null;
+ }
+
+ @Override
+ public HttpSession getSession(boolean arg0) {
+ return null;
+ }
+
+ @Override
+ public Principal getUserPrincipal() {
+ return null;
+ }
+
+ @Override
+ public boolean isRequestedSessionIdFromCookie() {
+ return false;
+ }
+
+ @Override
+ public boolean isRequestedSessionIdFromURL() {
+ return false;
+ }
+
+ @Override
+ public boolean isRequestedSessionIdFromUrl() {
+ return false;
+ }
+
+ @Override
+ public boolean isRequestedSessionIdValid() {
+ return false;
+ }
+
+ @Override
+ public boolean isUserInRole(String arg0) {
+ return false;
+ }
+}
diff --git a/src/main/java/org/apache/sling/hc/healthchecks/impl/InternalResponse.java b/src/main/java/org/apache/sling/hc/healthchecks/impl/InternalResponse.java
new file mode 100644
index 0000000..ead7da5
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/healthchecks/impl/InternalResponse.java
@@ -0,0 +1,185 @@
+/*
+ * 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.healthchecks.impl;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Locale;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+
+public class InternalResponse implements HttpServletResponse {
+
+ private int status = 200;
+
+ private static class DevNullOutputStream extends ServletOutputStream {
+ @Override
+ public void write(int b) {
+ }
+ }
+
+ @Override
+ public void flushBuffer() throws IOException {
+ }
+
+ @Override
+ public int getBufferSize() {
+ return 0;
+ }
+
+ @Override
+ public String getCharacterEncoding() {
+ return "UTF-8";
+ }
+
+ @Override
+ public String getContentType() {
+ return "text/plain";
+ }
+
+ @Override
+ public Locale getLocale() {
+ return Locale.getDefault();
+ }
+
+ @Override
+ public ServletOutputStream getOutputStream() throws IOException {
+ return new DevNullOutputStream();
+ }
+
+ @Override
+ public PrintWriter getWriter() throws IOException {
+ return new PrintWriter(new DevNullOutputStream());
+ }
+
+ @Override
+ public boolean isCommitted() {
+ return false;
+ }
+
+ @Override
+ public void reset() {
+ }
+
+ @Override
+ public void resetBuffer() {
+ }
+
+ @Override
+ public void setBufferSize(int arg0) {
+ }
+
+ @Override
+ public void setCharacterEncoding(String arg0) {
+ }
+
+ @Override
+ public void setContentLength(int arg0) {
+ }
+
+ @Override
+ public void setContentType(String arg0) {
+ }
+
+ @Override
+ public void setLocale(Locale arg0) {
+ }
+
+ @Override
+ public void addCookie(Cookie arg0) {
+ }
+
+ @Override
+ public void addDateHeader(String arg0, long arg1) {
+ }
+
+ @Override
+ public void addHeader(String arg0, String arg1) {
+ }
+
+ @Override
+ public void addIntHeader(String arg0, int arg1) {
+ }
+
+ @Override
+ public boolean containsHeader(String arg0) {
+ return false;
+ }
+
+ @Override
+ public String encodeRedirectURL(String url) {
+ return url;
+ }
+
+ @Override
+ public String encodeRedirectUrl(String url) {
+ return url;
+ }
+
+ @Override
+ public String encodeURL(String url) {
+ return url;
+ }
+
+ @Override
+ public String encodeUrl(String url) {
+ return url;
+ }
+
+ @Override
+ public void sendError(int s, String arg1) throws IOException {
+ status = s;
+ }
+
+ @Override
+ public void sendError(int s) throws IOException {
+ status = s;
+ }
+
+ @Override
+ public void sendRedirect(String arg0) throws IOException {
+ }
+
+ @Override
+ public void setDateHeader(String arg0, long arg1) {
+ }
+
+ @Override
+ public void setHeader(String arg0, String arg1) {
+ }
+
+ @Override
+ public void setIntHeader(String arg0, int arg1) {
+ }
+
+ @Override
+ public void setStatus(int s, String arg1) {
+ status = s;
+ }
+
+ @Override
+ public void setStatus(int s) {
+ status = s;
+ }
+
+ public int getStatus() {
+ return status;
+ }
+}
diff --git a/src/main/java/org/apache/sling/hc/healthchecks/impl/JmxAttributeHealthCheck.java b/src/main/java/org/apache/sling/hc/healthchecks/impl/JmxAttributeHealthCheck.java
new file mode 100644
index 0000000..a536fbd
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/healthchecks/impl/JmxAttributeHealthCheck.java
@@ -0,0 +1,115 @@
+/*
+ * 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.healthchecks.impl;
+
+import java.lang.management.ManagementFactory;
+import java.util.Map;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.apache.sling.hc.api.Constants;
+import org.apache.sling.hc.api.HealthCheck;
+import org.apache.sling.hc.api.Result;
+import org.apache.sling.hc.api.ResultLogEntry;
+import org.apache.sling.hc.util.SimpleConstraintChecker;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.helpers.MessageFormatter;
+
+/** {@link HealthCheck} that checks a single JMX attribute */
+@Component(
+ name="org.apache.sling.hc.JmxAttributeHealthCheck",
+ configurationFactory=true,
+ policy=ConfigurationPolicy.REQUIRE,
+ metatype=true)
+@Service
+public class JmxAttributeHealthCheck implements HealthCheck {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+ private Map<String, String> info;
+ private String mbeanName;
+ private String attributeName;
+ private String constraint;
+
+ @Property
+ public static final String PROP_OBJECT_NAME = "mbean.name";
+
+ @Property
+ public static final String PROP_ATTRIBUTE_NAME = "attribute.name";
+
+ @Property
+ public static final String PROP_CONSTRAINT = "attribute.value.constraint";
+
+ @Property(cardinality=50)
+ public static final String PROP_TAGS = Constants.HC_TAGS;
+
+ @Property
+ public static final String PROP_NAME = Constants.HC_NAME;
+
+ @Property
+ public static final String PROP_MBEAN_NAME = Constants.HC_MBEAN_NAME;
+
+ @Activate
+ public void activate(ComponentContext ctx) {
+ info = new HealthCheckInfo(ctx.getProperties());
+ mbeanName = PropertiesUtil.toString(ctx.getProperties().get(PROP_OBJECT_NAME), "");
+ attributeName = PropertiesUtil.toString(ctx.getProperties().get(PROP_ATTRIBUTE_NAME), "");
+ constraint = PropertiesUtil.toString(ctx.getProperties().get(PROP_CONSTRAINT), "");
+
+ info.put(PROP_OBJECT_NAME, mbeanName);
+ info.put(PROP_ATTRIBUTE_NAME, attributeName);
+ info.put(PROP_CONSTRAINT, constraint);
+
+ log.info("Activated with HealthCheck name={}, objectName={}, attribute={}, constraint={}",
+ new Object[] { info.get(Constants.HC_NAME), mbeanName, attributeName, constraint });
+ }
+
+ @Override
+ public Result execute() {
+ final Result result = new Result(log);
+ result.log(ResultLogEntry.LT_DEBUG,
+ MessageFormatter.format("Checking {} / {} with constraint {}",
+ new Object[] { mbeanName, attributeName, constraint }).getMessage());
+ try {
+ final MBeanServer jmxServer = ManagementFactory.getPlatformMBeanServer();
+ final ObjectName objectName = new ObjectName(mbeanName);
+ if(jmxServer.queryNames(objectName, null).size() == 0) {
+ log.error("MBean not found: {}", objectName);
+ }
+ final Object value = jmxServer.getAttribute(objectName, attributeName);
+ log.debug("{} {} returns {}", new Object[] { mbeanName, attributeName, value });
+ new SimpleConstraintChecker().check(value, constraint, result);
+ } catch(Exception e) {
+ log.warn(e.toString(), e);
+ }
+ return result;
+ }
+
+ @Override
+ public Map<String, String> getInfo() {
+ return info;
+ }
+}
diff --git a/src/main/java/org/apache/sling/hc/healthchecks/impl/JmxScriptBinding.java b/src/main/java/org/apache/sling/hc/healthchecks/impl/JmxScriptBinding.java
new file mode 100644
index 0000000..bbfc95e
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/healthchecks/impl/JmxScriptBinding.java
@@ -0,0 +1,62 @@
+/*
+ * 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.healthchecks.impl;
+
+import java.lang.management.ManagementFactory;
+
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+
+import org.apache.sling.hc.api.Result;
+import org.apache.sling.hc.api.ResultLogEntry;
+import org.slf4j.helpers.MessageFormatter;
+
+/** The JmxBinding is meant to be bound as "jmx" global variables
+ * in scripted rules, to allow for writing scripted expressions
+ * like jmx.attribute("java.lang:type=ClassLoading", "LoadedClassCount") > 100
+ */
+public class JmxScriptBinding {
+ private MBeanServer jmxServer = ManagementFactory.getPlatformMBeanServer();
+ private final Result result;
+
+ public JmxScriptBinding(Result result) {
+ this.result = result;
+ }
+
+ public Object attribute(String objectNameString, String attributeName)
+ throws MalformedObjectNameException, AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException {
+ final ObjectName name = new ObjectName(objectNameString);
+ if(jmxServer.queryNames(name, null).size() == 0) {
+ final String msg = "JMX object name not found: [" + objectNameString + "]";
+ result.log(ResultLogEntry.LT_WARN, msg);
+ throw new IllegalStateException(msg);
+ }
+ result.log(ResultLogEntry.LT_DEBUG, MessageFormatter.format("Got JMX Object [{}]", name).getMessage());
+ final Object value = jmxServer.getAttribute(name, attributeName);
+ result.log(ResultLogEntry.LT_DEBUG,
+ MessageFormatter.format(
+ "JMX Object [{}] Attribute [{}] = [{}]",
+ new Object[] { name, attributeName, value }).getMessage());
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/hc/healthchecks/impl/OsgiScriptBinding.java b/src/main/java/org/apache/sling/hc/healthchecks/impl/OsgiScriptBinding.java
new file mode 100644
index 0000000..27e9f28
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/healthchecks/impl/OsgiScriptBinding.java
@@ -0,0 +1,73 @@
+/*
+ * 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.healthchecks.impl;
+
+import org.apache.sling.hc.api.Result;
+import org.apache.sling.hc.api.ResultLogEntry;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.slf4j.helpers.MessageFormatter;
+
+/** The OsgiBinding is meant to be bound as an "osgi" global variable
+ * in scripted rules, to allow for checking some OSGi states in
+ * a simple way
+ */
+public class OsgiScriptBinding {
+ private final Result result;
+ private final BundleContext bundleContext;
+
+ public OsgiScriptBinding(BundleContext ctx, Result result) {
+ this.result = result;
+ this.bundleContext = ctx;
+ }
+
+ public int inactiveBundlesCount() {
+ int count = 0;
+ for(Bundle b : bundleContext.getBundles()) {
+ if(!isActive(b)) {
+ count++;
+ }
+ }
+ result.log(ResultLogEntry.LT_DEBUG, MessageFormatter.format("inactiveBundlesCount={}", count).getMessage());
+ return count;
+ }
+
+ private boolean isActive(Bundle b) {
+ boolean active = true;
+ if(!isFragment(b) && Bundle.ACTIVE != b.getState()) {
+ active = false;
+ result.log(ResultLogEntry.LT_INFO,
+ MessageFormatter.format(
+ "Bundle {} is not active, state={} ({})",
+ new Object[] { b.getSymbolicName(), b.getState(), b.getState()}).getMessage());
+ }
+ return active;
+ }
+
+ private boolean isFragment(Bundle b) {
+ final String header = (String) b.getHeaders().get( Constants.FRAGMENT_HOST );
+ if(header!= null && header.trim().length() > 0) {
+ result.log(ResultLogEntry.LT_DEBUG,
+ MessageFormatter.format("{} is a fragment bundle, state won't be checked", b).getMessage());
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/hc/healthchecks/impl/ScriptableHealthCheck.java b/src/main/java/org/apache/sling/hc/healthchecks/impl/ScriptableHealthCheck.java
new file mode 100644
index 0000000..6e5d82f
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/healthchecks/impl/ScriptableHealthCheck.java
@@ -0,0 +1,131 @@
+/*
+ * 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.healthchecks.impl;
+import java.util.Map;
+
+import javax.script.Bindings;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.apache.sling.hc.api.Constants;
+import org.apache.sling.hc.api.HealthCheck;
+import org.apache.sling.hc.api.Result;
+import org.apache.sling.hc.api.ResultLogEntry;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.helpers.MessageFormatter;
+
+/** {@link HealthCheck} that checks a scriptable expression */
+@Component(
+ name="org.apache.sling.hc.ScriptableHealthCheck",
+ configurationFactory=true,
+ policy=ConfigurationPolicy.REQUIRE,
+ metatype=true)
+@Service
+public class ScriptableHealthCheck implements HealthCheck {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+ private Map<String, String> info;
+ private String expression;
+ private String languageExtension;
+ private BundleContext bundleContext;
+
+ public static final String DEFAULT_LANGUAGE_EXTENSION = "ecma";
+
+ @Property
+ public static final String PROP_EXPRESSION = "expression";
+
+ @Property
+ public static final String PROP_LANGUAGE_EXTENSION = "language.extension";
+
+ @Property(cardinality=50)
+ public static final String PROP_TAGS = Constants.HC_TAGS;
+
+ @Property
+ public static final String PROP_NAME = Constants.HC_NAME;
+
+ @Property
+ public static final String PROP_MBEAN_NAME = Constants.HC_MBEAN_NAME;
+
+ @Reference
+ private ScriptEngineManager scriptEngineManager;
+
+ @Activate
+ public void activate(ComponentContext ctx) {
+ info = new HealthCheckInfo(ctx.getProperties());
+ bundleContext = ctx.getBundleContext();
+ expression = PropertiesUtil.toString(ctx.getProperties().get(PROP_EXPRESSION), "");
+ languageExtension = PropertiesUtil.toString(ctx.getProperties().get(PROP_LANGUAGE_EXTENSION), DEFAULT_LANGUAGE_EXTENSION);
+
+ info.put(PROP_EXPRESSION, expression);
+ info.put(PROP_LANGUAGE_EXTENSION, languageExtension);
+
+ log.info("Activated, name={}, languageExtension={}, expression={}", languageExtension, expression);
+ }
+
+ @Override
+ public Result execute() {
+ final Result result = new Result(log);
+ result.log(ResultLogEntry.LT_DEBUG,
+ MessageFormatter.format(
+ "Checking expression [{}], language extension=[{}]",
+ expression, languageExtension).getMessage());
+ try {
+ final ScriptEngine engine = scriptEngineManager.getEngineByExtension(languageExtension);
+ if(engine == null) {
+ result.log(ResultLogEntry.LT_WARN,
+ MessageFormatter.format(
+ "No ScriptEngine available for extension {}",
+ languageExtension).getMessage());
+ } else {
+ // TODO pluggable Bindings? Reuse the Sling bindings providers?
+ final Bindings b = engine.createBindings();
+ b.put("jmx", new JmxScriptBinding(result));
+ b.put("osgi", new OsgiScriptBinding(bundleContext, result));
+ final Object value = engine.eval(expression, b);
+ if(value!=null && "true".equals(value.toString())) {
+ result.log(ResultLogEntry.LT_DEBUG,
+ MessageFormatter.format(
+ "Expression [{}] evaluates to true as expected", expression).getMessage());
+ } else {
+ result.log(ResultLogEntry.LT_WARN,
+ MessageFormatter.format(
+ "Expression [{}] does not evaluate to true, value={}",
+ expression, value).getMessage());
+ }
+ }
+ } catch(Exception e) {
+ result.log(ResultLogEntry.LT_WARN, e.toString());
+ }
+ return result;
+ }
+
+ @Override
+ public Map<String, String> getInfo() {
+ return info;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/hc/healthchecks/impl/SlingRequestStatusHealthCheck.java b/src/main/java/org/apache/sling/hc/healthchecks/impl/SlingRequestStatusHealthCheck.java
new file mode 100644
index 0000000..744561d
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/healthchecks/impl/SlingRequestStatusHealthCheck.java
@@ -0,0 +1,153 @@
+/*
+ * 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.healthchecks.impl;
+
+import java.util.Arrays;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.apache.sling.engine.SlingRequestProcessor;
+import org.apache.sling.hc.api.Constants;
+import org.apache.sling.hc.api.HealthCheck;
+import org.apache.sling.hc.api.Result;
+import org.apache.sling.hc.api.ResultLogEntry;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.helpers.MessageFormatter;
+
+/** {@link HealthCheck} that checks the HTTP status of Sling requests */
+@Component(
+ name="org.apache.sling.hc.SlingRequestStatusHealthCheck",
+ configurationFactory=true,
+ policy=ConfigurationPolicy.REQUIRE,
+ metatype=true)
+@Service
+public class SlingRequestStatusHealthCheck implements HealthCheck {
+
+ private static final Logger log = LoggerFactory.getLogger(SlingRequestStatusHealthCheck.class);
+ private Map<String, String> info;
+ private String [] paths;
+
+ static class PathSpec {
+ int status;
+ String path;
+
+ PathSpec(String configuredPath) {
+ path = configuredPath;
+ status = 200;
+
+ final String [] parts = configuredPath.split(":");
+ if(parts.length == 2) {
+ try {
+ status = Integer.valueOf(parts[1].trim());
+ path = parts[0].trim();
+ } catch(NumberFormatException nfe) {
+ log.warn("NumberFormatException while parsing [{}], invalid status value?", configuredPath);
+ }
+ }
+ }
+ }
+
+ @Property(cardinality=Integer.MAX_VALUE)
+ public static final String PROP_PATH = "path";
+
+ @Property(cardinality=50)
+ public static final String PROP_TAGS = Constants.HC_TAGS;
+
+ @Property
+ public static final String PROP_NAME = Constants.HC_NAME;
+
+ @Property
+ public static final String PROP_MBEAN_NAME = Constants.HC_MBEAN_NAME;
+
+ @Reference
+ private SlingRequestProcessor requestProcessor;
+
+ @Reference
+ private ResourceResolverFactory resolverFactory;
+
+ @Activate
+ public void activate(ComponentContext ctx) {
+ info = new HealthCheckInfo(ctx.getProperties());
+ paths = PropertiesUtil.toStringArray(ctx.getProperties().get(PROP_PATH), new String [] {});
+ log.info("Activated, paths={}", Arrays.asList(paths));
+ }
+
+ @Override
+ public Result execute() {
+ final Result result = new Result(log);
+
+ ResourceResolver resolver = null;
+ int checked = 0;
+ int failed = 0;
+
+ try {
+ resolver = resolverFactory.getAdministrativeResourceResolver(null);
+ for(String p : paths) {
+ final PathSpec ps = new PathSpec(p);
+ final HttpServletRequest request = new InternalRequest(ps.path);
+ final InternalResponse response = new InternalResponse();
+ requestProcessor.processRequest(request, response, resolver);
+ final int status = response.getStatus();
+ if(status != ps.status) {
+ failed++;
+ result.log(ResultLogEntry.LT_WARN,
+ MessageFormatter.format(
+ "[{}] returns status {}, expected {}", new Object[] { ps.path, status, ps.status }).getMessage());
+ } else {
+ result.log(ResultLogEntry.LT_DEBUG,
+ MessageFormatter.format(
+ "[{}] returns status {} as expected", ps.path, status).getMessage());
+ }
+ checked++;
+ }
+ } catch(Exception e) {
+ result.log(ResultLogEntry.LT_WARN, "Exception while executing request: " + e.toString());
+ } finally {
+ if(resolver != null) {
+ resolver.close();
+ }
+ }
+
+ if(checked == 0) {
+ result.log(ResultLogEntry.LT_WARN, "No paths checked, empty paths list?");
+ } else {
+ result.log(ResultLogEntry.LT_DEBUG,
+ MessageFormatter.format(
+ "{} paths checked, {} failures", checked, failed).getMessage());
+ }
+
+ return result;
+ }
+
+ @Override
+ public Map<String, String> getInfo() {
+ return info;
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/hc/healthcheck b/src/test/java/org/apache/sling/hc/healthcheck
new file mode 100644
index 0000000..954f535
--- /dev/null
+++ b/src/test/java/org/apache/sling/hc/healthcheck
@@ -0,0 +1,44 @@
+package org.apache.sling.hc.impl.healthchecks;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class PathSpecTest {
+ private final String pathSpec;
+ private final String expectedPath;
+ private final int expectedStatus;
+
+ @Parameters(name="{1}")
+ public static List<Object[]> data() {
+ final List<Object[]> result = new ArrayList<Object[]>();
+
+ result.add(new Object[] { "/one.html", "/one.html", 200 } );
+ result.add(new Object[] { "/two.html:404", "/two.html", 404 } );
+ result.add(new Object[] { "three.html : 404 ", "three.html", 404 } );
+ result.add(new Object[] { "four.html:not an integer", "four.html:not an integer", 200 } );
+ result.add(new Object[] { "", "", 200 } );
+
+ return result;
+ }
+
+ public PathSpecTest(String pathSpec, String expectedPath, int expectedStatus) {
+ this.pathSpec = pathSpec;
+ this.expectedPath = expectedPath;
+ this.expectedStatus = expectedStatus;
+ }
+
+ @Test
+ public void testParsing() {
+ final SlingRequestStatusHealthCheck.PathSpec ps = new SlingRequestStatusHealthCheck.PathSpec(pathSpec);
+ assertEquals(expectedPath, ps.path);
+ assertEquals(expectedStatus, ps.status);
+ }
+}
diff --git a/src/test/java/org/apache/sling/hc/healthchecks/DefaultLoginsHealthCheckTest.java b/src/test/java/org/apache/sling/hc/healthchecks/DefaultLoginsHealthCheckTest.java
new file mode 100644
index 0000000..1c48f00
--- /dev/null
+++ b/src/test/java/org/apache/sling/hc/healthchecks/DefaultLoginsHealthCheckTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.healthchecks;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+
+import javax.jcr.Credentials;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+
+import org.apache.sling.hc.api.Result;
+import org.apache.sling.hc.healthchecks.impl.DefaultLoginsHealthCheck;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+public class DefaultLoginsHealthCheckTest {
+
+ private Result getTestResult(String login) throws Exception {
+ final DefaultLoginsHealthCheck c = new DefaultLoginsHealthCheck();
+ setField(c, "logins", Arrays.asList(new String[] { login }));
+
+ final SlingRepository repo = Mockito.mock(SlingRepository.class);
+ setField(c, "repository", repo);
+ final Session s = Mockito.mock(Session.class);
+ Mockito.when(repo.login(Matchers.any(Credentials.class))).thenAnswer(new Answer<Session>() {
+ @Override
+ public Session answer(InvocationOnMock invocation) {
+ final SimpleCredentials c = (SimpleCredentials)invocation.getArguments()[0];
+ if("admin".equals(c.getUserID())) {
+ return s;
+ }
+ return null;
+ }
+ });
+
+ return c.execute();
+ }
+
+ private void setField(Object o, String name, Object value) throws Exception {
+ final Field f = o.getClass().getDeclaredField(name);
+ f.setAccessible(true);
+ f.set(o, value);
+ }
+
+ @Test
+ public void testHealthCheckFails() throws Exception {
+ assertFalse("Expecting failed check", getTestResult("admin:admin").isOk());
+ }
+
+ @Test
+ public void testHealthCheckSucceeds() throws Exception {
+ assertTrue("Expecting successful check", getTestResult("FOO:bar").isOk());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/hc/healthchecks/JmxAttributeHealthCheckTest.java b/src/test/java/org/apache/sling/hc/healthchecks/JmxAttributeHealthCheckTest.java
new file mode 100644
index 0000000..81f68fc
--- /dev/null
+++ b/src/test/java/org/apache/sling/hc/healthchecks/JmxAttributeHealthCheckTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.healthchecks;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.sling.hc.api.Result;
+import org.apache.sling.hc.healthchecks.impl.JmxAttributeHealthCheck;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.osgi.service.component.ComponentContext;
+
+public class JmxAttributeHealthCheckTest {
+
+ static void assertJmxValue(String objectName, String attributeName, String constraint, boolean expected) {
+ final JmxAttributeHealthCheck hc = new JmxAttributeHealthCheck();
+
+ final ComponentContext ctx = Mockito.mock(ComponentContext.class);
+ final Dictionary<String, String> props = new Hashtable<String, String>();
+ props.put(JmxAttributeHealthCheck.PROP_OBJECT_NAME, objectName);
+ props.put(JmxAttributeHealthCheck.PROP_ATTRIBUTE_NAME, attributeName);
+ props.put(JmxAttributeHealthCheck.PROP_CONSTRAINT, constraint);
+ Mockito.when(ctx.getProperties()).thenReturn(props);
+ hc.activate(ctx);
+
+ final Result r = hc.execute();
+ assertEquals("Expected result " + expected, expected, r.isOk());
+ }
+
+ @Test
+ public void testJmxAttributeMatch() {
+ assertJmxValue("java.lang:type=ClassLoading", "LoadedClassCount", "> 10", true);
+ }
+
+ @Test
+ public void testJmxAttributeNoMatch() {
+ assertJmxValue("java.lang:type=ClassLoading", "LoadedClassCount", "< 10", false);
+ }
+}
diff --git a/src/test/java/org/apache/sling/hc/healthchecks/JmxScriptBindingTest.java b/src/test/java/org/apache/sling/hc/healthchecks/JmxScriptBindingTest.java
new file mode 100644
index 0000000..7cad43b
--- /dev/null
+++ b/src/test/java/org/apache/sling/hc/healthchecks/JmxScriptBindingTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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.healthchecks;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.sling.hc.api.Result;
+import org.apache.sling.hc.healthchecks.impl.JmxScriptBinding;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class JmxScriptBindingTest {
+
+ private final Logger logger = LoggerFactory.getLogger(getClass());
+
+ @Test
+ public void testJmxAttribute() throws Exception {
+ final Result r = new Result(logger);
+ final JmxScriptBinding b = new JmxScriptBinding(r);
+ final Object value= b.attribute("java.lang:type=ClassLoading", "LoadedClassCount");
+ assertNotNull("Expecting non-null attribute value", value);
+ assertTrue("Expecting non-empty value", value.toString().length() > 0);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/hc/healthchecks/OsgiScriptBindingTest.java b/src/test/java/org/apache/sling/hc/healthchecks/OsgiScriptBindingTest.java
new file mode 100644
index 0000000..b9dcf83
--- /dev/null
+++ b/src/test/java/org/apache/sling/hc/healthchecks/OsgiScriptBindingTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.healthchecks;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.sling.hc.api.Result;
+import org.apache.sling.hc.healthchecks.impl.OsgiScriptBinding;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OsgiScriptBindingTest {
+
+ private final Logger logger = LoggerFactory.getLogger(getClass());
+
+ private Bundle mockBundle(boolean isFragment, boolean isActive) {
+ final Bundle b = Mockito.mock(Bundle.class);
+ Mockito.when(b.getState()).thenReturn(isActive ? Bundle.ACTIVE : Bundle.RESOLVED);
+
+ final Dictionary<String, String> headers = new Hashtable<String, String>();
+ if(isFragment) {
+ headers.put(Constants.FRAGMENT_HOST, "FOO");
+ }
+ Mockito.when(b.getHeaders()).thenReturn(headers);
+
+ return b;
+ }
+
+ @Test
+ public void testInactiveBundles() throws Exception {
+ final BundleContext ctx = Mockito.mock(BundleContext.class);
+ final Bundle [] bundles = {
+ mockBundle(false, true),
+ mockBundle(false, false),
+ mockBundle(false, true),
+ mockBundle(true, false)
+ };
+ Mockito.when(ctx.getBundles()).thenReturn(bundles);
+
+ final Result r = new Result(logger);
+ final OsgiScriptBinding b = new OsgiScriptBinding(ctx, r);
+ assertEquals(1, b.inactiveBundlesCount());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/hc/healthchecks/ScriptableHealthCheckTest.java b/src/test/java/org/apache/sling/hc/healthchecks/ScriptableHealthCheckTest.java
new file mode 100644
index 0000000..351b88f
--- /dev/null
+++ b/src/test/java/org/apache/sling/hc/healthchecks/ScriptableHealthCheckTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.healthchecks;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.lang.reflect.Field;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+
+import org.apache.sling.hc.api.Result;
+import org.apache.sling.hc.healthchecks.impl.ScriptableHealthCheck;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.mockito.Mockito;
+import org.osgi.service.component.ComponentContext;
+
+public class ScriptableHealthCheckTest {
+
+ private ScriptableHealthCheck hc;
+ private Dictionary<String, String> props;
+ private ComponentContext ctx;
+
+ private void assertExpression(String expression, String languageExtension, boolean expected) throws Exception {
+ hc = new ScriptableHealthCheck();
+ ctx = Mockito.mock(ComponentContext.class);
+ props = new Hashtable<String, String>();
+
+ final ScriptEngine rhino = new ScriptEngineManager().getEngineByExtension("js");
+ assertNotNull("With the rhino jar in our classpath, we should get a js script engine", rhino);
+ final ScriptEngineManager manager = Mockito.mock(ScriptEngineManager.class);
+ Mockito.when(manager.getEngineByExtension(Matchers.same("ecma"))).thenReturn(rhino);
+ final Field f = hc.getClass().getDeclaredField("scriptEngineManager");
+ f.setAccessible(true);
+ f.set(hc, manager);
+
+ props.put(ScriptableHealthCheck.PROP_EXPRESSION, expression);
+ if(languageExtension != null) {
+ props.put(ScriptableHealthCheck.PROP_LANGUAGE_EXTENSION, languageExtension);
+ }
+ Mockito.when(ctx.getProperties()).thenReturn(props);
+ hc.activate(ctx);
+ final Result r = hc.execute();
+ assertEquals("Expecting result " + expected, expected, r.isOk());
+ }
+
+ @Test
+ public void testSimpleExpression() throws Exception {
+ assertExpression("2 + 3 == 5", null, true);
+ }
+
+ @Test
+ public void testJmxExpression() throws Exception {
+ assertExpression(
+ "jmx.attribute('java.lang:type=ClassLoading', 'LoadedClassCount') > 10"
+ + " && jmx.attribute('java.lang:type=Runtime', 'ManagementSpecVersion') > 1",
+ "ecma", true);
+ }
+
+ @Test
+ public void testFalseExpression() throws Exception {
+ assertExpression("2 + 3 == 15", null, false);
+ }
+
+ @Test
+ public void testSyntaxError() throws Exception {
+ assertExpression("{not [valid ok?", null, false);
+ }
+
+ @Test
+ public void testNoEngine() throws Exception {
+ assertExpression("2 + 3 == 5", null, true);
+ assertExpression("2 + 3 == 5", "groovy", false);
+ }
+}
--
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.