You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by gh...@apache.org on 2019/04/03 22:34:21 UTC
[sling-org-apache-sling-hc-support] branch master updated:
SLING-8342 Migration to Felix HC runtime
This is an automated email from the ASF dual-hosted git repository.
ghenzler pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-hc-support.git
The following commit(s) were added to refs/heads/master by this push:
new b465fbd SLING-8342 Migration to Felix HC runtime
b465fbd is described below
commit b465fbd9137214365681f6ee9b3e57a55403e81f
Author: georg.henzler <ge...@netcentric.biz>
AuthorDate: Thu Apr 4 00:30:51 2019 +0200
SLING-8342 Migration to Felix HC runtime
---
pom.xml | 88 +++---
.../hc/support/impl/DefaultLoginsHealthCheck.java | 105 ++++---
.../sling/hc/support/impl/InternalRequest.java | 319 ---------------------
.../sling/hc/support/impl/InternalResponse.java | 185 ------------
.../sling/hc/support/impl/ScriptedHealthCheck.java | 214 ++++++++++++++
.../impl/SlingRequestStatusHealthCheck.java | 149 ----------
.../hc/support/impl/ThreadUsageHealthCheck.java | 190 ------------
src/test/java/org/apache/sling/hc/healthcheck | 61 ----
.../SlingRequestStatusHealthCheckTest.java | 113 --------
.../impl}/DefaultLoginsHealthCheckTest.java | 5 +-
.../{healthchecks => support/impl}/SetField.java | 2 +-
.../support/impl/ThreadUsageHealthCheckTest.java | 112 --------
12 files changed, 320 insertions(+), 1223 deletions(-)
diff --git a/pom.xml b/pom.xml
index 9de1a67..d14156f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,11 +24,10 @@
<parent>
<groupId>org.apache.sling</groupId>
<artifactId>sling</artifactId>
- <version>26</version>
+ <version>34</version>
<relativePath/>
</parent>
- <groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.hc.support</artifactId>
<packaging>bundle</packaging>
<version>1.0.5-SNAPSHOT</version>
@@ -50,10 +49,6 @@
<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>
</plugin>
@@ -61,73 +56,88 @@
</build>
<dependencies>
+
<dependency>
<groupId>org.osgi</groupId>
- <artifactId>org.osgi.compendium</artifactId>
+ <artifactId>osgi.core</artifactId>
+ <scope>provided</scope>
</dependency>
<dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>osgi.cmpn</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>osgi.annotation</artifactId>
+ <version>6.0.1</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
<groupId>org.apache.felix</groupId>
- <artifactId>org.apache.felix.scr.annotations</artifactId>
+ <artifactId>org.apache.felix.healthcheck.api</artifactId>
+ <version>2.0.0</version>
<scope>provided</scope>
</dependency>
+
<dependency>
- <groupId>org.apache.sling</groupId>
- <artifactId>org.apache.sling.hc.core</artifactId>
- <version>1.0.4</version>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.healthcheck.annotation</artifactId>
+ <version>2.0.0</version>
<scope>provided</scope>
</dependency>
+
<dependency>
- <groupId>org.apache.sling</groupId>
- <artifactId>org.apache.sling.hc.annotations</artifactId>
- <version>1.0.4</version>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.healthcheck.generalchecks</artifactId>
+ <version>2.0.2</version>
+ <scope>provided</scope>
</dependency>
-
+
<dependency>
- <groupId>org.apache.sling</groupId>
- <artifactId>org.apache.sling.commons.osgi</artifactId>
- <version>2.2.0</version>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>3.4</version>
<scope>provided</scope>
</dependency>
+
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.api</artifactId>
- <version>2.1.0</version>
+ <version>2.16.2</version>
<scope>provided</scope>
</dependency>
+
<dependency>
<groupId>org.apache.sling</groupId>
- <artifactId>org.apache.sling.jcr.api</artifactId>
- <version>2.0.4</version>
+ <artifactId>org.apache.sling.scripting.core</artifactId>
+ <version>2.0.44</version>
<scope>provided</scope>
- </dependency>
+ </dependency>
+
<dependency>
<groupId>org.apache.sling</groupId>
- <artifactId>org.apache.sling.engine</artifactId>
- <version>2.2.0</version>
+ <artifactId>org.apache.sling.jcr.api</artifactId>
+ <version>2.0.4</version>
<scope>provided</scope>
</dependency>
+
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
- <version>1.6.2</version>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>servlet-api</artifactId>
</dependency>
+
<dependency>
<groupId>javax.jcr</groupId>
<artifactId>jcr</artifactId>
</dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-simple</artifactId>
- <version>1.6.2</version>
- <scope>test</scope>
- </dependency>
+
+ <!-- TEST DEPENDENCIES -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
+ <scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
@@ -135,5 +145,13 @@
<version>1.9.5</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>1.6.2</version>
+ <scope>test</scope>
+ </dependency>
+ <!-- END TEST DEPENDENCIES -->
+
</dependencies>
</project>
diff --git a/src/main/java/org/apache/sling/hc/support/impl/DefaultLoginsHealthCheck.java b/src/main/java/org/apache/sling/hc/support/impl/DefaultLoginsHealthCheck.java
index 0f1e854..2960f2f 100644
--- a/src/main/java/org/apache/sling/hc/support/impl/DefaultLoginsHealthCheck.java
+++ b/src/main/java/org/apache/sling/hc/support/impl/DefaultLoginsHealthCheck.java
@@ -25,53 +25,46 @@ 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.Properties;
-import org.apache.felix.scr.annotations.Property;
-import org.apache.felix.scr.annotations.PropertyUnbounded;
-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.HealthCheck;
-import org.apache.sling.hc.api.Result;
-import org.apache.sling.hc.util.FormattingResultLog;
+import org.apache.felix.hc.api.FormattingResultLog;
+import org.apache.felix.hc.api.HealthCheck;
+import org.apache.felix.hc.api.Result;
import org.apache.sling.jcr.api.SlingRepository;
-import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.ConfigurationPolicy;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
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.support.DefaultLoginsHealthCheck",
- configurationFactory=true,
- policy=ConfigurationPolicy.REQUIRE,
- metatype=true,
- label="Apache Sling Default Logins Health Check",
- description="Expects default logins to fail, used to verify " +
- "that they are disabled on production systems")
-@Properties({
- @Property(name=HealthCheck.NAME,
- label="Health Check Name", description="Name of this Health Check service."),
- @Property(name=HealthCheck.TAGS, unbounded=PropertyUnbounded.ARRAY,
- label="Health Check tags", description="List of tags for this Health Check service, used to select " +
- "subsets of Health Check services for execution"),
- @Property(name=HealthCheck.MBEAN_NAME,
- label="MBean Name", description="Name of the MBean to create for this Health Check.")
-})
-@Service(value=HealthCheck.class)
+/** {@link HealthCheck} that runs an arbitrary script. */
+@Component(service = HealthCheck.class, name = "org.apache.sling.hc.support.DefaultLoginsHealthCheck", configurationPolicy = ConfigurationPolicy.REQUIRE)
+@Designate(ocd = DefaultLoginsHealthCheck.Config.class, factory = true)
public class DefaultLoginsHealthCheck implements HealthCheck {
- private final Logger log = LoggerFactory.getLogger(getClass());
+ private static final Logger LOG = LoggerFactory.getLogger(DefaultLoginsHealthCheck.class);
- @Property(unbounded=PropertyUnbounded.ARRAY,
- label="Login credentials",
- description="Which credentials to check. Each one is in the format \"user:password\" " +
- "like \"admin:admin\" for example. Do *not* put any confidential passwords here, the goal " +
- "is just to check that the default/demo logins, which passwords are known anyway, are disabled.")
- private static final String PROP_LOGINS = "logins";
+ public static final String HC_LABEL = "Health Check: Default Logins";
+
+ @ObjectClassDefinition(name = HC_LABEL, description = "Expects default logins to fail, used to verify that they are disabled on production systems")
+ @interface Config {
+
+ @AttributeDefinition(name = "Name", description = "Name of this health check.")
+ String hc_name() default "Default Logins Check";
+
+ @AttributeDefinition(name = "Tags", description = "List of tags for this health check, used to select subsets of health checks for execution e.g. by a composite health check.")
+ String[] hc_tags() default {};
+
+ @AttributeDefinition(name = "Default Logins", description = "Which credentials to check. Each one is in the format"
+ + " \"user:password\" like \"admin:admin\" for example. Do *not* put any confidential passwords here, the goal "
+ + "is just to check that the default/demo logins, which passwords are known anyway, are disabled.")
+ String[] logins() default "logins";
+
+ @AttributeDefinition
+ String webconsole_configurationFactory_nameHint() default "Default Logins Check: {logins}";
+ }
private List<String> logins;
@@ -79,20 +72,20 @@ public class DefaultLoginsHealthCheck implements HealthCheck {
private SlingRepository repository;
@Activate
- public void activate(ComponentContext ctx) {
- logins = Arrays.asList(PropertiesUtil.toStringArray(ctx.getProperties().get(PROP_LOGINS), new String[] {}));
- log.info("Activated, logins={}", logins);
+ protected void activate(Config config) {
+ this.logins = Arrays.asList(config.logins());
+ LOG.info("Activated, logins={}", logins);
}
@Override
public Result execute() {
- final FormattingResultLog resultLog = new FormattingResultLog();
- int checked=0;
- int failures=0;
+ FormattingResultLog resultLog = new FormattingResultLog();
+ int checked = 0;
+ int failures = 0;
- for(String login : logins) {
- final String [] parts = login.split(":");
- if(parts.length != 2) {
+ for (String login : logins) {
+ final String[] parts = login.split(":");
+ if (parts.length != 2) {
resultLog.warn("Expected login in the form username:password, got [{}]", login);
continue;
}
@@ -103,28 +96,30 @@ public class DefaultLoginsHealthCheck implements HealthCheck {
Session s = null;
try {
s = repository.login(creds);
- if(s != null) {
+ if (s != null) {
failures++;
resultLog.warn("Login as [{}] succeeded, was expecting it to fail", username);
} else {
resultLog.debug("Login as [{}] didn't throw an Exception but returned null Session", username);
}
- } catch(RepositoryException re) {
+ } catch (RepositoryException re) {
resultLog.debug("Login as [{}] failed, as expected", username);
} finally {
- if(s != null) {
+ if (s != null) {
s.logout();
}
}
}
- if(checked==0) {
+ if (checked == 0) {
resultLog.warn("Did not check any logins, configured logins={}", logins);
- } else if(failures != 0){
+ } else if (failures != 0) {
resultLog.warn("Checked {} logins, {} failures", checked, failures);
} else {
resultLog.debug("Checked {} logins, all successful", checked, failures);
}
+
return new Result(resultLog);
}
-}
\ No newline at end of file
+
+}
diff --git a/src/main/java/org/apache/sling/hc/support/impl/InternalRequest.java b/src/main/java/org/apache/sling/hc/support/impl/InternalRequest.java
deleted file mode 100644
index b79fdfe..0000000
--- a/src/main/java/org/apache/sling/hc/support/impl/InternalRequest.java
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * 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.support.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/support/impl/InternalResponse.java b/src/main/java/org/apache/sling/hc/support/impl/InternalResponse.java
deleted file mode 100644
index 8752628..0000000
--- a/src/main/java/org/apache/sling/hc/support/impl/InternalResponse.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * 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.support.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/support/impl/ScriptedHealthCheck.java b/src/main/java/org/apache/sling/hc/support/impl/ScriptedHealthCheck.java
new file mode 100644
index 0000000..bc6cbe8
--- /dev/null
+++ b/src/main/java/org/apache/sling/hc/support/impl/ScriptedHealthCheck.java
@@ -0,0 +1,214 @@
+/*
+ * 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.support.impl;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.Session;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptEngineManager;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.felix.hc.api.FormattingResultLog;
+import org.apache.felix.hc.api.HealthCheck;
+import org.apache.felix.hc.api.Result;
+import org.apache.felix.hc.generalchecks.util.ScriptEnginesTracker;
+import org.apache.felix.hc.generalchecks.util.ScriptHelper;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.ConfigurationPolicy;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** {@link HealthCheck} that runs an arbitrary script. */
+@Component(service = HealthCheck.class, name = "org.apache.sling.hc.support.ScriptedHealthCheck", configurationPolicy = ConfigurationPolicy.REQUIRE)
+@Designate(ocd = ScriptedHealthCheck.Config.class, factory = true)
+public class ScriptedHealthCheck implements HealthCheck {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ScriptedHealthCheck.class);
+
+ public static final String HC_LABEL = "Health Check: Sling Script";
+
+ public static final String JCR_FILE_URL_PREFIX = "jcr:";
+ private static final String JCR_CONTENT = "/jcr:content";
+
+ @ObjectClassDefinition(name = HC_LABEL, description = "NOTE: This Sling pendant of org.apache.felix.hc.generalchecks.ScriptedHealthCheck allows to use scriptUrls with prefix 'jcr:' and has the additional bindings 'resourceResolver' and 'session'. "
+ + "Runs an arbitrary script in given scriping language (via javax.script). "
+ + "The script has the following default bindings available: 'log', 'scriptHelper', 'bundleContext', 'resourceResolver' and 'session'. "
+ + "'log' is an instance of org.apache.felix.hc.api.FormattingResultLog and is used to define the result of the HC. "
+ + "'scriptHelper.getService(classObj)' can be used as shortcut to retrieve a service."
+ + "'scriptHelper.getServices(classObj, filter)' used to retrieve multiple services for a class using given filter. "
+ + "For all services retrieved via scriptHelper, unget() is called automatically at the end of the script execution."
+ + "'bundleContext' is available for advanced use cases. The script does not need to return any value, but if it does and it is "
+ + "a org.apache.felix.hc.api.Result, that result and entries in 'log' are combined then).")
+ @interface Config {
+
+ @AttributeDefinition(name = "Name", description = "Name of this health check.")
+ String hc_name() default "Scripted Health Check";
+
+ @AttributeDefinition(name = "Tags", description = "List of tags for this health check, used to select subsets of health checks for execution e.g. by a composite health check.")
+ String[] hc_tags() default {};
+
+ @AttributeDefinition(name = "Language", description = "The language the script is written in. To use e.g. 'groovy', ensure osgi bundle 'groovy-all' is available.")
+ String language() default "groovy";
+
+ @AttributeDefinition(name = "Script", description = "The script itself (either use 'script' or 'scriptUrl').")
+ String script() default "log.info('ok'); log.warn('not so good'); log.critical('bad') // minimal example";
+
+ @AttributeDefinition(name = "Script Url", description = "Url to the script to be used as alternative source (either use 'script' or 'scriptUrl').")
+ String scriptUrl() default "";
+
+ @AttributeDefinition
+ String webconsole_configurationFactory_nameHint() default "Scripted HC: {hc.name} (tags: {hc.tags}) {scriptUrl} language: {language}";
+ }
+
+ private String language;
+ private String script;
+ private String scriptUrl;
+
+ private BundleContext bundleContext;
+
+ @Reference
+ private ScriptEngineManager scriptEngineManager;
+
+ @Reference
+ private ScriptEnginesTracker scriptEnginesTracker;
+
+ private ScriptHelper scriptHelper = new ScriptHelper();
+
+ @Reference
+ private ResourceResolverFactory resourceResolverFactory;
+
+ @Activate
+ protected void activate(BundleContext context, Config config) {
+ this.bundleContext = context;
+ this.language = config.language().toLowerCase();
+ this.script = config.script();
+ this.scriptUrl = config.scriptUrl();
+
+ if (StringUtils.isNotBlank(script) && StringUtils.isNotBlank(scriptUrl)) {
+ LOG.info("Both 'script' and 'scriptUrl' (=()) are configured, ignoring 'scriptUrl'", scriptUrl);
+ scriptUrl = null;
+ }
+
+ LOG.info("Activated Scripted HC " + config.hc_name() + " with "
+ + (StringUtils.isNotBlank(script) ? "script " + script : "script url " + scriptUrl));
+
+ }
+
+ @Override
+ public Result execute() {
+ FormattingResultLog log = new FormattingResultLog();
+
+ ResourceResolver resourceResolver = null;
+ try {
+ resourceResolver = resourceResolverFactory.getServiceResourceResolver(null);
+
+ boolean urlIsUsed = StringUtils.isBlank(script);
+ String scriptToExecute;
+ if (urlIsUsed) {
+ if (scriptUrl.startsWith(JCR_FILE_URL_PREFIX)) {
+ String jcrPath = StringUtils.substringAfter(scriptUrl, JCR_FILE_URL_PREFIX);
+ scriptToExecute = getScriptFromRepository(resourceResolver, jcrPath);
+ } else {
+ scriptToExecute = scriptHelper.getFileContents(scriptUrl);
+ }
+ } else {
+ scriptToExecute = script;
+ }
+
+ log.info("Executing script {} ({} lines)...", (urlIsUsed ? scriptUrl : " as configured"), scriptToExecute.split("\n").length);
+
+ try {
+ ScriptEngine scriptEngine = getScriptEngine(language);
+
+ Map<String, Object> additionalBindings = new HashMap<String, Object>();
+ additionalBindings.put("resourceResolver", resourceResolver);
+ additionalBindings.put("session", resourceResolver.adaptTo(Session.class));
+ scriptHelper.evalScript(bundleContext, scriptEngine, scriptToExecute, log, additionalBindings, true);
+ } catch (Exception e) {
+ log.healthCheckError("Exception while executing script: " + e, e);
+ }
+
+ return new Result(log);
+ } catch (LoginException e) {
+ throw new IllegalStateException("Could not get resource resolver: " + e, e);
+ } finally {
+ if (resourceResolver != null) {
+ resourceResolver.close();
+ }
+ }
+ }
+
+ private String factoriesToString(List<ScriptEngineFactory> engineFactories) {
+ List<String> factoryArr = new ArrayList<String>();
+ for (ScriptEngineFactory ef : engineFactories) {
+ factoryArr.add(ef.getEngineName() + " (" + StringUtils.join(ef.getExtensions(), ",") + ")");
+ }
+ return StringUtils.join(factoryArr, ", ");
+ }
+
+ private ScriptEngine getScriptEngine(String language) {
+ ScriptEngine scriptEngine = scriptEngineManager.getEngineByExtension(language);
+ if (scriptEngine == null) {
+ try {
+ scriptEngine = scriptHelper.getScriptEngine(scriptEnginesTracker, language);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalStateException("Could not get script engine for " + language + " from available factories: "
+ + factoriesToString(scriptEngineManager.getEngineFactories()) + ") nor from regular bundles: " + e.getMessage());
+ }
+ }
+ return scriptEngine;
+ }
+
+ private String getScriptFromRepository(ResourceResolver resourceResolver, String jcrPath) {
+ String fileContent;
+ try {
+ Resource dataResource = resourceResolver.getResource(jcrPath + JCR_CONTENT);
+ InputStream is = dataResource.adaptTo(InputStream.class);
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int length;
+ while ((length = is.read(buffer)) != -1) {
+ result.write(buffer, 0, length);
+ }
+ fileContent = result.toString(StandardCharsets.UTF_8.name());
+ } catch (IOException e) {
+ throw new IllegalStateException("Could not load script from path " + jcrPath + ": " + e, e);
+ }
+ return fileContent;
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/hc/support/impl/SlingRequestStatusHealthCheck.java b/src/main/java/org/apache/sling/hc/support/impl/SlingRequestStatusHealthCheck.java
deleted file mode 100644
index 6e33ad3..0000000
--- a/src/main/java/org/apache/sling/hc/support/impl/SlingRequestStatusHealthCheck.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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.support.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.Properties;
-import org.apache.felix.scr.annotations.Property;
-import org.apache.felix.scr.annotations.PropertyUnbounded;
-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.HealthCheck;
-import org.apache.sling.hc.api.Result;
-import org.apache.sling.hc.util.FormattingResultLog;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/** {@link HealthCheck} that checks the HTTP status of Sling requests.
- * Typically used to check that a freshly installed Sling-based system
- * is in good shape, contains all required content etc. */
-@Component(
- name="org.apache.sling.hc.support.SlingRequestStatusHealthCheck",
- configurationFactory=true,
- policy=ConfigurationPolicy.REQUIRE,
- metatype=true,
- label="Apache Sling Request Status Health Check",
- description="Checks the HTTP status of Sling requests.")
-@Properties({
- @Property(name=HealthCheck.NAME,
- label="Health Check Name", description="Name of this Health Check service."),
- @Property(name=HealthCheck.TAGS, unbounded=PropertyUnbounded.ARRAY,
- label="Health Check tags", description="List of tags for this Health Check service, used to select " +
- "subsets of Health Check services for execution"),
- @Property(name=HealthCheck.MBEAN_NAME,
- label="MBean Name", description="Name of the MBean to create for this Health Check.")
-})
-@Service(value=HealthCheck.class)
-public class SlingRequestStatusHealthCheck implements HealthCheck {
-
- private static final Logger log = LoggerFactory.getLogger(SlingRequestStatusHealthCheck.class);
- private String [] paths;
-
- static class PathSpec {
- int status;
- String path;
-
- PathSpec(String configuredPath, FormattingResultLog resultLog) {
- 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) {
- resultLog.healthCheckError("NumberFormatException while parsing [{}], invalid status value?", configuredPath);
- }
- }
- }
- }
-
- @Property(unbounded=PropertyUnbounded.ARRAY,
- label="Paths to Check",
- description="The list of paths to check, optionally with expected HTTP status responses. " +
- "An entry like \"/tmp/test.txt:301\", for example, checks that /tmp/test.txt returns a " +
- "301 response.")
- private static final String PROP_PATH = "path";
-
- @Reference
- private SlingRequestProcessor requestProcessor;
-
- @Reference
- private ResourceResolverFactory resolverFactory;
-
- @Activate
- public void activate(final Map<String, Object> properties) {
- paths = PropertiesUtil.toStringArray(properties.get(PROP_PATH), new String [] {});
- log.info("Activated, paths={}", Arrays.asList(paths));
- }
-
- @Override
- public Result execute() {
- final FormattingResultLog resultLog = new FormattingResultLog();
-
- ResourceResolver resolver = null;
- int checked = 0;
- int failed = 0;
- String lastPath = null;
-
- try {
- resolver = resolverFactory.getAdministrativeResourceResolver(null);
- for(String p : paths) {
- lastPath = p;
- final PathSpec ps = new PathSpec(p, resultLog);
- 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++;
- resultLog.warn("[{}] returns status {}, expected {}", new Object[] { ps.path, status, ps.status });
- } else {
- resultLog.debug("[{}] returns status {} as expected", ps.path, status);
- }
- checked++;
- }
- } catch(Exception e) {
- resultLog.warn("Exception while executing request [{}]: {}", lastPath, e);
- } finally {
- if(resolver != null) {
- resolver.close();
- }
- }
-
- if(checked == 0) {
- resultLog.warn("No paths checked, empty paths list?");
- } else {
- resultLog.info("{} paths checked, {} failures", checked, failed);
- }
-
- return new Result(resultLog);
- }
-}
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/hc/support/impl/ThreadUsageHealthCheck.java b/src/main/java/org/apache/sling/hc/support/impl/ThreadUsageHealthCheck.java
deleted file mode 100644
index e08bb92..0000000
--- a/src/main/java/org/apache/sling/hc/support/impl/ThreadUsageHealthCheck.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * 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.support.impl;
-
-import java.lang.management.ManagementFactory;
-import java.lang.management.ThreadInfo;
-import java.lang.management.ThreadMXBean;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.ConfigurationPolicy;
-import org.apache.felix.scr.annotations.Property;
-import org.apache.sling.commons.osgi.PropertiesUtil;
-import org.apache.sling.hc.annotations.SlingHealthCheck;
-import org.apache.sling.hc.api.HealthCheck;
-import org.apache.sling.hc.api.Result;
-import org.apache.sling.hc.util.FormattingResultLog;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Uses ThreadMXBean to show (and potentially WARN about) information about thread usage. Use deadlock detection provided by ThreadMXBean to send CRITICAL.
- */
-@SlingHealthCheck(name = ThreadUsageHealthCheck.HC_NAME, label = "Apache Sling "
- + ThreadUsageHealthCheck.HC_NAME, description = "Checks time threads are using ThreadMXBean", tags = { "resources",
- "threads" }, configurationPolicy = ConfigurationPolicy.REQUIRE)
-public class ThreadUsageHealthCheck implements HealthCheck {
- private static final Logger LOG = LoggerFactory.getLogger(ThreadUsageHealthCheck.class);
-
- public static final String HC_NAME = "Thread Usage Health Check";
-
- private static final long DEFAULT_SAMPLE_PERIOD_IN_MS = 200;
-
- static final String PROP_SAMPLE_PERIOD_IN_MS = "samplePeriodInMs";
- @Property(name = PROP_SAMPLE_PERIOD_IN_MS, label = "Sample Period", description = "Period this HC uses to measure", longValue = DEFAULT_SAMPLE_PERIOD_IN_MS)
- private long samplePeriodInMs;
-
- static final String PROP_CPU_TIME_THRESHOLD_WARN = "cpuTimeThresholdWarn";
- @Property(name = PROP_CPU_TIME_THRESHOLD_WARN, label = "CPU Time Threshold for WARN in %", description = "Will WARN once this threshold is reached. Has to be configured according to cores of the system (e.g. use 400% for 4 cores)")
- private long cpuTimeThresholdWarn;
-
- private int availableProcessors;
- private boolean cpuTimeThresholdWarnIsConfigured;
-
- @Activate
- protected final void activate(final Map<String, Object> properties) {
- this.samplePeriodInMs = PropertiesUtil.toLong(properties.get(PROP_SAMPLE_PERIOD_IN_MS), DEFAULT_SAMPLE_PERIOD_IN_MS);
-
- this.availableProcessors = Runtime.getRuntime().availableProcessors();
- long defaultThresholdWarn = availableProcessors * 90; // 100% is rarely reached, 90% means a very busy system
- this.cpuTimeThresholdWarn = PropertiesUtil.toLong(properties.get(PROP_CPU_TIME_THRESHOLD_WARN), defaultThresholdWarn);
- this.cpuTimeThresholdWarnIsConfigured = properties.get(PROP_CPU_TIME_THRESHOLD_WARN) !=null;
-
- }
-
- @Override
- public Result execute() {
- FormattingResultLog log = new FormattingResultLog();
-
- log.debug("Checking threads for exceeding {}% CPU time within time period of {}ms", cpuTimeThresholdWarn, samplePeriodInMs);
-
- try {
- ThreadMXBean threadMxBean = ManagementFactory.getThreadMXBean();
-
- List<ThreadTimeInfo> threadTimeInfos = collectThreadTimeInfos(log, threadMxBean);
-
- Collections.sort(threadTimeInfos);
-
- float totalCpuTimePercentage = 0;
- for (int i = 0; i < threadTimeInfos.size(); i++) {
-
- ThreadTimeInfo threadInfo = threadTimeInfos.get(i);
- float cpuTimePercentage = ((float) threadInfo.getCpuTime() / ((float) samplePeriodInMs * 1000000)) * 100f;
- totalCpuTimePercentage +=cpuTimePercentage;
-
- String msg = String.format("%4.1f", cpuTimePercentage) + "% used by thread \"" + threadInfo.name + "\"";
- if (i<3 || (i<10 && cpuTimePercentage > 15)) {
- log.info(msg);
- } else {
- log.debug(msg);
- }
- }
- log.info(threadTimeInfos.size() + " threads using "+String.format("%4.1f", totalCpuTimePercentage)+"% CPU Time");
- boolean isHighCpuTime = totalCpuTimePercentage > cpuTimeThresholdWarn;
- if(isHighCpuTime) {
- log.warn("Threads are consuming significant CPU time "+ ( cpuTimeThresholdWarnIsConfigured ?
- "(more than configured " + cpuTimeThresholdWarn + "% within " + samplePeriodInMs + "ms)"
- : "(more than "+availableProcessors+" cores * 90% = "+cpuTimeThresholdWarn + "%)"));
- }
-
- checkForDeadlock(log, threadMxBean);
-
- } catch (Exception e) {
- LOG.error("Could not analyse thread usage "+e, e);
- log.healthCheckError("Could not analyse thread usage", e);
- }
-
- return new Result(log);
-
- }
-
- List<ThreadTimeInfo> collectThreadTimeInfos(FormattingResultLog log, ThreadMXBean threadMxBean) {
-
-
- Map<Long, ThreadTimeInfo> threadTimeInfos = new HashMap<Long, ThreadTimeInfo>();
-
- long[] allThreadIds = threadMxBean.getAllThreadIds();
- for (long threadId : allThreadIds) {
- ThreadTimeInfo threadTimeInfo = new ThreadTimeInfo();
- long threadCpuTimeStart = threadMxBean.getThreadCpuTime(threadId);
- threadTimeInfo.start = threadCpuTimeStart;
- ThreadInfo threadInfo = threadMxBean.getThreadInfo(threadId);
- threadTimeInfo.name = threadInfo!=null?threadInfo.getThreadName():"Thread id "+threadId+" (name not resolvable)";
- threadTimeInfos.put(threadId, threadTimeInfo);
- }
-
- try {
- Thread.sleep(samplePeriodInMs);
- } catch (InterruptedException e) {
- log.warn("Could not sleep configured samplePeriodInMs={} to gather thread load", samplePeriodInMs);
- }
-
- for (long threadId : allThreadIds) {
- ThreadTimeInfo threadTimeInfo = threadTimeInfos.get(threadId);
- if (threadTimeInfo == null) {
- continue;
- }
- long threadCpuTimeStop = threadMxBean.getThreadCpuTime(threadId);
- threadTimeInfo.stop = threadCpuTimeStop;
- }
-
- List<ThreadTimeInfo> threads = new ArrayList<ThreadTimeInfo>(threadTimeInfos.values());
-
- return threads;
- }
-
-
- void checkForDeadlock(FormattingResultLog log, ThreadMXBean threadMxBean) {
- long[] findDeadlockedThreads = threadMxBean.findDeadlockedThreads();
- if (findDeadlockedThreads != null) {
- for (long threadId : findDeadlockedThreads) {
- log.critical("Thread " + threadMxBean.getThreadInfo(threadId).getThreadName() + " is DEADLOCKED");
- }
- }
- }
-
- static class ThreadTimeInfo implements Comparable<ThreadTimeInfo> {
- long start;
- long stop;
- String name;
-
- long getCpuTime() {
- long cpuTime = stop - start;
- if(cpuTime < 0) {
- cpuTime = 0;
- }
- return cpuTime;
- }
-
- @Override
- public int compareTo(ThreadTimeInfo otherThreadTimeInfo) {
- if (otherThreadTimeInfo == null) {
- return -1;
- }
- return (int) (otherThreadTimeInfo.getCpuTime() - this.getCpuTime());
- }
-
- }
-
-}
\ 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
deleted file mode 100644
index 95de634..0000000
--- a/src/test/java/org/apache/sling/hc/healthcheck
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.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/SlingRequestStatusHealthCheckTest.java b/src/test/java/org/apache/sling/hc/healthchecks/SlingRequestStatusHealthCheckTest.java
deleted file mode 100644
index 00bba41..0000000
--- a/src/test/java/org/apache/sling/hc/healthchecks/SlingRequestStatusHealthCheckTest.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.api.resource.ResourceResolverFactory;
-import org.apache.sling.engine.SlingRequestProcessor;
-import org.apache.sling.hc.api.Result;
-import org.apache.sling.hc.support.impl.SlingRequestStatusHealthCheck;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-import org.mockito.Matchers;
-import org.mockito.Mockito;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-@RunWith(Parameterized.class)
-public class SlingRequestStatusHealthCheckTest {
- private SlingRequestStatusHealthCheck hc;
- private final Result.Status expectedStatus;
- private final String [] paths;
-
- @Parameters(name="{0}")
- public static List<Object[]> data() {
- final List<Object[]> result = new ArrayList<Object[]>();
- result.add(new Object[] { "200.html:200,502.html:1234,436.json:436", Result.Status.WARN });
-
- result.add(new Object[] { "", Result.Status.OK });
- result.add(new Object[] { "200.x", Result.Status.OK });
- result.add(new Object[] { "404.html:404", Result.Status.OK });
- result.add(new Object[] { "200.html:200,502.html:502,436.json:436" , Result.Status.OK });
- result.add(new Object[] { "200.html:1234,502.html:502,436.json:436" , Result.Status.WARN });
- result.add(new Object[] { "200.html:200,502.html:1234,436.json:436" , Result.Status.WARN });
- result.add(new Object[] { "200.html:200,502.html:502,436.json:1234" , Result.Status.WARN });
- result.add(new Object[] { "200.html:1234,502.html:1234,436.json:1234" , Result.Status.WARN });
- return result;
- }
-
- @Before
- public void setup() throws Exception {
- hc = new SlingRequestStatusHealthCheck();
-
- final ResourceResolverFactory rrf = Mockito.mock(ResourceResolverFactory.class);
- SetField.set(hc, "resolverFactory", rrf);
-
- final Answer<Void> a = new Answer<Void> () {
- @Override
- public Void answer(InvocationOnMock invocation) {
- final HttpServletRequest request = (HttpServletRequest)invocation.getArguments()[0];
- final HttpServletResponse response = (HttpServletResponse)invocation.getArguments()[1];
- final String path = request.getPathInfo();
- if(path.length() > 0) {
- final String status = path.substring(0, path.indexOf('.'));
- response.setStatus(Integer.valueOf(status));
- }
- return null;
- }
-
- };
-
- final SlingRequestProcessor srp = Mockito.mock(SlingRequestProcessor.class);
- SetField.set(hc, "requestProcessor", srp);
- Mockito.doAnswer(a).when(srp).processRequest(
- Matchers.any(HttpServletRequest.class),
- Matchers.any(HttpServletResponse.class),
- Matchers.any(ResourceResolver.class));
-
-
- final Map<String, Object> properties = new HashMap<String, Object>();
- properties.put("path", paths);
- hc.activate(properties);
- }
-
- public SlingRequestStatusHealthCheckTest(String paths, Result.Status expectedStatus) {
- this.paths = paths.split(",");
- this.expectedStatus = expectedStatus;
-
- }
-
- @Test
- public void testResult() {
- assertEquals("Expecting result " + expectedStatus + " for paths=" + paths,
- expectedStatus, hc.execute().getStatus());
- }
-}
diff --git a/src/test/java/org/apache/sling/hc/healthchecks/DefaultLoginsHealthCheckTest.java b/src/test/java/org/apache/sling/hc/support/impl/DefaultLoginsHealthCheckTest.java
similarity index 94%
rename from src/test/java/org/apache/sling/hc/healthchecks/DefaultLoginsHealthCheckTest.java
rename to src/test/java/org/apache/sling/hc/support/impl/DefaultLoginsHealthCheckTest.java
index 862b6f8..5b4c382 100644
--- a/src/test/java/org/apache/sling/hc/healthchecks/DefaultLoginsHealthCheckTest.java
+++ b/src/test/java/org/apache/sling/hc/support/impl/DefaultLoginsHealthCheckTest.java
@@ -15,7 +15,7 @@
* 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;
+package org.apache.sling.hc.support.impl;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -26,8 +26,7 @@ import javax.jcr.Credentials;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
-import org.apache.sling.hc.api.Result;
-import org.apache.sling.hc.support.impl.DefaultLoginsHealthCheck;
+import org.apache.felix.hc.api.Result;
import org.apache.sling.jcr.api.SlingRepository;
import org.junit.Test;
import org.mockito.Matchers;
diff --git a/src/test/java/org/apache/sling/hc/healthchecks/SetField.java b/src/test/java/org/apache/sling/hc/support/impl/SetField.java
similarity index 96%
rename from src/test/java/org/apache/sling/hc/healthchecks/SetField.java
rename to src/test/java/org/apache/sling/hc/support/impl/SetField.java
index c4577a3..db436c9 100644
--- a/src/test/java/org/apache/sling/hc/healthchecks/SetField.java
+++ b/src/test/java/org/apache/sling/hc/support/impl/SetField.java
@@ -15,7 +15,7 @@
* 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;
+package org.apache.sling.hc.support.impl;
import java.lang.reflect.Field;
diff --git a/src/test/java/org/apache/sling/hc/support/impl/ThreadUsageHealthCheckTest.java b/src/test/java/org/apache/sling/hc/support/impl/ThreadUsageHealthCheckTest.java
deleted file mode 100644
index 257f72b..0000000
--- a/src/test/java/org/apache/sling/hc/support/impl/ThreadUsageHealthCheckTest.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.support.impl;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.MockitoAnnotations.initMocks;
-
-import java.lang.management.ThreadMXBean;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.sling.hc.api.Result;
-import org.apache.sling.hc.support.impl.ThreadUsageHealthCheck.ThreadTimeInfo;
-import org.apache.sling.hc.util.FormattingResultLog;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.Spy;
-
-public class ThreadUsageHealthCheckTest {
-
- @Spy
- ThreadUsageHealthCheck threadsHealthCheck;
-
-
- @Mock
- Map<String, Object> componentConfig;
-
- @Before
- public void setup() {
- initMocks(this);
- doNothing().when(threadsHealthCheck).checkForDeadlock(any(FormattingResultLog.class), any(ThreadMXBean.class));
- }
-
- @Test
- public void testThreadActivityWithinThreshold() {
-
- long samplePeriod = 200L;
- int processorsAvailable = 4;
- int busyThreads = 3;
-
- List<ThreadTimeInfo> resultListOverloaded = getFullLoadThreadInfos(samplePeriod, busyThreads);
-
- setupExpectations(samplePeriod, processorsAvailable, resultListOverloaded);
-
- Result result = threadsHealthCheck.execute();
-
- assertEquals(Result.Status.OK, result.getStatus());
-
- }
-
- @Test
- public void testThreadActivityOverloaded() {
-
- long samplePeriod = 200L;
- int processorsAvailable = 4;
- int busyThreads = 5;
-
- List<ThreadTimeInfo> resultListOverloaded = getFullLoadThreadInfos(samplePeriod, busyThreads);
-
- setupExpectations(samplePeriod, processorsAvailable, resultListOverloaded);
-
- Result result = threadsHealthCheck.execute();
-
- assertEquals(Result.Status.WARN, result.getStatus());
-
- }
-
- private List<ThreadTimeInfo> getFullLoadThreadInfos(long samplePeriod, int count) {
- List<ThreadTimeInfo> resultList = new ArrayList<ThreadTimeInfo>();
- for (int i = 0; i < count; i++) {
- resultList.add(getThreadTimeInfo((long) (samplePeriod * .95)));
- }
- return resultList;
- }
-
- private void setupExpectations(long samplePeriod, int processorsAvailable, List<ThreadTimeInfo> resultListOk) {
- doReturn(processorsAvailable * 90).when(componentConfig).get(ThreadUsageHealthCheck.PROP_CPU_TIME_THRESHOLD_WARN);
- doReturn(samplePeriod).when(componentConfig).get(ThreadUsageHealthCheck.PROP_SAMPLE_PERIOD_IN_MS);
- threadsHealthCheck.activate(componentConfig);
- doReturn(resultListOk).when(threadsHealthCheck).collectThreadTimeInfos(any(FormattingResultLog.class), any(ThreadMXBean.class));
- }
-
- private ThreadUsageHealthCheck.ThreadTimeInfo getThreadTimeInfo(long diffInMs) {
- ThreadUsageHealthCheck.ThreadTimeInfo threadTimeInfo = new ThreadUsageHealthCheck.ThreadTimeInfo();
- threadTimeInfo.start = new Date().getTime();
- threadTimeInfo.stop = threadTimeInfo.start + (diffInMs * 1000000);
- threadTimeInfo.name = "Unit Test Thread";
- return threadTimeInfo;
- }
-
-}