This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.hc.webconsole-1.0.4 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-hc-webconsole.git
commit 88168b8fa1f670ebcf21d453c841043634b0f270 Author: Bertrand Delacretaz <[email protected]> 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/webconsole@1513179 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 101 ++++++++++ .../impl/HealthCheckWebconsolePlugin.java | 220 +++++++++++++++++++++ .../sling/hc/webconsole/impl/WebConsoleHelper.java | 68 +++++++ src/main/resources/res/ui/healthcheck.css | 46 +++++ 4 files changed, 435 insertions(+) diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..175ec7b --- /dev/null +++ b/pom.xml @@ -0,0 +1,101 @@ +<?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.webconsole</artifactId> + <packaging>bundle</packaging> + <version>0.0.2-SNAPSHOT</version> + + <name>Sling Health Check Module - Webconsole</name> + <inceptionYear>2013</inceptionYear> + + <description> + Webconsole plugin for 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.webconsole.* + </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.api</artifactId> + <version>2.1.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>servlet-api</artifactId> + <scope>provided</scope> + </dependency> + </dependencies> +</project> diff --git a/src/main/java/org/apache/sling/hc/webconsole/impl/HealthCheckWebconsolePlugin.java b/src/main/java/org/apache/sling/hc/webconsole/impl/HealthCheckWebconsolePlugin.java new file mode 100644 index 0000000..6e18f50 --- /dev/null +++ b/src/main/java/org/apache/sling/hc/webconsole/impl/HealthCheckWebconsolePlugin.java @@ -0,0 +1,220 @@ +/* + * 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.webconsole.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.util.List; + +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Properties; +import org.apache.felix.scr.annotations.Property; +import org.apache.felix.scr.annotations.Service; +import org.apache.sling.api.request.ResponseUtil; +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.HealthCheckSelector; +import org.osgi.framework.BundleContext; +import org.osgi.service.component.ComponentContext; + +/** Webconsole plugin to execute health check services */ +@Component(immediate=true) +@Service(Servlet.class) +@SuppressWarnings("serial") +@Properties({ + @Property(name=org.osgi.framework.Constants.SERVICE_DESCRIPTION, value="Sling Health Check Web Console Plugin"), + @Property(name=org.osgi.framework.Constants.SERVICE_VENDOR, value="The Apache Software Foundation"), + @Property(name="felix.webconsole.label", value=HealthCheckWebconsolePlugin.LABEL), + @Property(name="felix.webconsole.title", value=HealthCheckWebconsolePlugin.TITLE), + @Property(name="felix.webconsole.category", value=HealthCheckWebconsolePlugin.CATEGORY), + @Property(name="felix.webconsole.css", value="/healthcheck/res/ui/healthcheck.css") +}) +public class HealthCheckWebconsolePlugin extends HttpServlet { + + public static final String TITLE = "Sling Health Check"; + public static final String LABEL = "healthcheck"; + public static final String CATEGORY = "Sling"; + public static final String PARAM_TAGS = "tags"; + public static final String PARAM_DEBUG = "debug"; + public static final String PARAM_QUIET = "quiet"; + + private BundleContext bundleContext; + + @Activate + protected void activate(ComponentContext ctx) { + bundleContext = ctx.getBundleContext(); + } + + /** Serve static resource if applicable, and return true in that case */ + private boolean getStaticResource(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + final String pathInfo = req.getPathInfo(); + if(pathInfo!= null && pathInfo.contains("res/ui")) { + final String prefix = "/" + LABEL; + final InputStream is = getClass().getResourceAsStream(pathInfo.substring(prefix.length())); + if(is == null) { + resp.sendError(HttpServletResponse.SC_NOT_FOUND, pathInfo); + } + final byte [] buffer = new byte[16384]; + int n=0; + while( (n = is.read(buffer, 0, buffer.length)) > 0) { + resp.getOutputStream().write(buffer, 0, n); + } + resp.getOutputStream().flush(); + return true; + } + return false; + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + if(getStaticResource(req, resp)) { + return; + } + + final String tags = getParam(req, PARAM_TAGS, ""); + final boolean debug = Boolean.valueOf(getParam(req, PARAM_DEBUG, "false")); + final boolean quiet = Boolean.valueOf(getParam(req, PARAM_QUIET, "false")); + + doForm(req, resp, tags, debug, quiet); + + // Execute health checks only if tags are specified (even if empty) + if(req.getParameter(PARAM_TAGS) != null) { + final List<HealthCheck> checks = new HealthCheckSelector(bundleContext).getTaggedHealthCheck(tags.split(",")); + final PrintWriter pw = resp.getWriter(); + pw.println("<table class='content healthcheck' cellpadding='0' cellspacing='0' width='100%'>"); + int total = 0; + int failed = 0; + for(HealthCheck hc : checks) { + final Result r = hc.execute(); + total++; + if(!r.isOk()) { + failed++; + } + if(!quiet || !r.isOk()) { + renderResult(resp, hc, r, debug); + } + } + final WebConsoleHelper c = new WebConsoleHelper(resp.getWriter()); + c.titleHtml("Summary", total + " HealthCheck executed, " + failed + " failures"); + pw.println("</table>"); + } + } + + private void renderResult(HttpServletResponse resp, HealthCheck hc, Result result, boolean debug) throws IOException { + final WebConsoleHelper c = new WebConsoleHelper(resp.getWriter()); + + final StringBuilder status = new StringBuilder(); + status.append("Tags: ").append(hc.getInfo().get(Constants.HC_TAGS)); + c.titleHtml(getDescription(hc), null); + + c.tr(); + c.tdContent(); + c.writer().print(ResponseUtil.escapeXml(status.toString())); + c.writer().print("<br/>Result: <span class='resultOk"); + c.writer().print(result.isOk()); + c.writer().print("'>"); + c.writer().print(result.getStatus().toString()); + c.writer().print("</span>"); + c.closeTd(); + c.closeTr(); + + c.tr(); + c.tdContent(); + for(ResultLogEntry e : result) { + if(!debug && e.getEntryType().equals(ResultLogEntry.LT_DEBUG)) { + continue; + } + final StringBuilder sb = new StringBuilder(); + sb.append("<div class='log").append(e.getEntryType()).append("'>"); + sb.append(e.getEntryType()) + .append(" ") + .append(ResponseUtil.escapeXml(e.getMessage())) + .append("</div>"); + c.writer().println(sb.toString()); + } + c.closeTd(); + } + + private String getDescription(HealthCheck hc) { + String result = hc.getInfo().get(Constants.HC_NAME); + if(result == null) { + result = hc.toString(); + } + return result; + } + + private void doForm(HttpServletRequest req, HttpServletResponse resp, String tags, boolean debug, boolean quiet) + throws IOException { + final PrintWriter pw = resp.getWriter(); + final WebConsoleHelper c = new WebConsoleHelper(pw); + pw.print("<form method='get'>"); + pw.println("<table class='content' cellpadding='0' cellspacing='0' width='100%'>"); + c.titleHtml(TITLE, "To execute health check services, enter " + + " an optional list of tags, to select specific health checks, or no tags for all checks." + + " Prefix a tag with a minus sign (-) to omit checks having that tag."); + + c.tr(); + c.tdLabel("Health Check tags (comma-separated)"); + c.tdContent(); + pw.println("<input type='text' name='" + PARAM_TAGS + "' value='" + tags + "' class='input' size='80'>"); + c.closeTd(); + c.closeTr(); + + c.tr(); + c.tdLabel("Show DEBUG logs"); + c.tdContent(); + pw.println("<input type='checkbox' name='" + PARAM_DEBUG + "' class='input' value='true'" + + (debug ? " checked=true " : "") + ">"); + c.closeTd(); + c.closeTr(); + + c.tr(); + c.tdLabel("Show failed checks only"); + c.tdContent(); + pw.println("<input type='checkbox' name='" + PARAM_QUIET + "' class='input' value='true'" + + (quiet ? " checked=true " : "") + ">"); + c.closeTd(); + c.closeTr(); + + c.tr(); + c.tdContent(); + pw.println("<input type='submit' value='Execute selected health checks'/>"); + c.closeTd(); + c.closeTr(); + + pw.println("</table></form>"); + } + + private String getParam(HttpServletRequest req, String name, String defaultValue) { + String result = req.getParameter(name); + if(result == null) { + result = defaultValue; + } + return result; + } +} diff --git a/src/main/java/org/apache/sling/hc/webconsole/impl/WebConsoleHelper.java b/src/main/java/org/apache/sling/hc/webconsole/impl/WebConsoleHelper.java new file mode 100644 index 0000000..beb1b34 --- /dev/null +++ b/src/main/java/org/apache/sling/hc/webconsole/impl/WebConsoleHelper.java @@ -0,0 +1,68 @@ +/* + * 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.webconsole.impl; + +import java.io.PrintWriter; + +import org.apache.sling.api.request.ResponseUtil; + +/** Webconsole plugin to execute health check rules */ +class WebConsoleHelper { + + final PrintWriter pw; + + WebConsoleHelper(PrintWriter w) { + pw = w; + } + + PrintWriter writer() { + return pw; + } + + void tdContent() { + pw.print("<td class='content' colspan='2'>"); + } + + void closeTd() { + pw.print("</td>"); + } + + void closeTr() { + pw.println("</tr>"); + } + + void tdLabel(final String label) { + pw.println("<td class='content'>" + ResponseUtil.escapeXml(label) + "</td>"); + } + + void tr() { + pw.println("<tr class='content'>"); + } + + void titleHtml(String title, String description) { + tr(); + pw.println("<th colspan='3' class='content container'>" + ResponseUtil.escapeXml(title) + "</th>"); + closeTr(); + + if (description != null) { + tr(); + pw.println("<td colspan='3' class='content'>" +ResponseUtil.escapeXml(description) + "</th>"); + closeTr(); + } + } +} diff --git a/src/main/resources/res/ui/healthcheck.css b/src/main/resources/res/ui/healthcheck.css new file mode 100644 index 0000000..5eb7183 --- /dev/null +++ b/src/main/resources/res/ui/healthcheck.css @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.healthcheck .logDEBUG { + color:grey; +} + +.healthcheck .logINFO { + color:blue; +} + +.healthcheck .logWARN, +.healthcheck .logSECURITY, +.healthcheck .logCONFIG +{ + color:red; +} + +.healthcheck .logERROR { + color:red; + font-weight:bold; +} + +.healthcheck .resultOktrue { + color:green; + font-weight:bold; +} + +.healthcheck .resultOkfalse { + color:red; + font-weight:bold; +} -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
