Author: ghenzler
Date: Fri Jan 25 21:22:55 2019
New Revision: 1852182
URL: http://svn.apache.org/viewvc?rev=1852182&view=rev
Log:
FELIX-6025 ScriptedHealthCheck - refactoring to allow reuse in sling
Added:
felix/trunk/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/util/ScriptHelper.java
(with props)
felix/trunk/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/util/package-info.java
(with props)
Modified:
felix/trunk/healthcheck/generalchecks/bnd.bnd
felix/trunk/healthcheck/generalchecks/pom.xml
felix/trunk/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/ScriptedHealthCheck.java
Modified: felix/trunk/healthcheck/generalchecks/bnd.bnd
URL:
http://svn.apache.org/viewvc/felix/trunk/healthcheck/generalchecks/bnd.bnd?rev=1852182&r1=1852181&r2=1852182&view=diff
==============================================================================
--- felix/trunk/healthcheck/generalchecks/bnd.bnd (original)
+++ felix/trunk/healthcheck/generalchecks/bnd.bnd Fri Jan 25 21:22:55 2019
@@ -9,3 +9,5 @@ Bundle-License: Apache License, Version
Bundle-Vendor: The Apache Software Foundation
Conditional-Package: org.apache.commons.cli.*,org.apache.felix.utils.*
+
+Export-Package: org.apache.felix.hc.generalchecks.util
Modified: felix/trunk/healthcheck/generalchecks/pom.xml
URL:
http://svn.apache.org/viewvc/felix/trunk/healthcheck/generalchecks/pom.xml?rev=1852182&r1=1852181&r2=1852182&view=diff
==============================================================================
--- felix/trunk/healthcheck/generalchecks/pom.xml (original)
+++ felix/trunk/healthcheck/generalchecks/pom.xml Fri Jan 25 21:22:55 2019
@@ -95,6 +95,12 @@
<version>6.0.0</version>
<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>
Modified:
felix/trunk/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/ScriptedHealthCheck.java
URL:
http://svn.apache.org/viewvc/felix/trunk/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/ScriptedHealthCheck.java?rev=1852182&r1=1852181&r2=1852182&view=diff
==============================================================================
---
felix/trunk/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/ScriptedHealthCheck.java
(original)
+++
felix/trunk/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/ScriptedHealthCheck.java
Fri Jan 25 21:22:55 2019
@@ -17,36 +17,15 @@
*/
package org.apache.felix.hc.generalchecks;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.StringWriter;
-import java.lang.reflect.Array;
-import java.net.URL;
-import java.net.URLConnection;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-import javax.script.Bindings;
-import javax.script.ScriptContext;
import javax.script.ScriptEngine;
-import javax.script.SimpleBindings;
-import javax.script.SimpleScriptContext;
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.api.ResultLog;
import org.apache.felix.hc.generalchecks.util.ScriptEnginesTracker;
+import org.apache.felix.hc.generalchecks.util.ScriptHelper;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
@@ -67,11 +46,11 @@ public class ScriptedHealthCheck impleme
public static final String HC_LABEL = "Health Check: Script";
@ObjectClassDefinition(name = HC_LABEL, description = "Runs an arbitrary
script in given scriping language (via javax.script). "
- + "The script has the following default bindings available: 'log',
'osgi' and 'bundleContext'. "
+ + "The script has the following default bindings available: 'log',
'scriptHelper' and 'bundleContext'. "
+ "'log' is an instance of
org.apache.felix.hc.api.FormattingResultLog and is used to define the result of
the HC. "
- + "'osgi.getService(classObj)' can be used as shortcut to retrieve
a service."
- + "'osgi.getServices(classObj, filter)' used to retrieve multiple
services for a class using given filter. "
- + "For all services retrieved via osgi binding, unget() is called
automatically at the end of the script execution."
+ + "'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 {
@@ -104,6 +83,8 @@ public class ScriptedHealthCheck impleme
@Reference
private ScriptEnginesTracker scriptEnginesTracker;
+ private ScriptHelper scriptHelper = new ScriptHelper();
+
@Activate
protected void activate(BundleContext context, Config config) {
this.bundleContext = context;
@@ -124,153 +105,20 @@ public class ScriptedHealthCheck impleme
public Result execute() {
FormattingResultLog log = new FormattingResultLog();
- ScriptEngine scriptEngine =
scriptEnginesTracker.getEngineByLanguage(language);
- if(scriptEngine == null) {
- log.healthCheckError("No ScriptEngineFactory found for language "+
language + " (available languages:
"+scriptEnginesTracker.getLanguagesByBundle()+")");
- return new Result(log);
- }
- final Bindings bindings = new SimpleBindings();
- final ScriptHelper osgi = new ScriptHelper(bundleContext);
-
- StringWriter stdout = new StringWriter();
- StringWriter stderr = new StringWriter();
-
- bindings.put("osgi", osgi);
- bindings.put("log", log);
- bindings.put("bundleContext", bundleContext);
-
- SimpleScriptContext scriptContext = new SimpleScriptContext();
- scriptContext.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
- scriptContext.setWriter(stdout);
- scriptContext.setErrorWriter(stderr);
+ boolean urlIsUsed = StringUtils.isBlank(script);
+ String scriptToExecute = urlIsUsed ?
scriptHelper.getFileContents(scriptUrl): script;
+ log.info("Executing script {} ({} lines)...", (urlIsUsed?scriptUrl:"
as configured"), scriptToExecute.split("\n").length);
try {
- boolean urlIsUsed = StringUtils.isBlank(script);
- String scriptToExecute = urlIsUsed ? getFileContents(scriptUrl):
script;
- log.info("Executing script {} ({} lines)...",
(urlIsUsed?scriptUrl:" as configured"), scriptToExecute.split("\n").length);
- log.debug(scriptToExecute);
- Object scriptResult = scriptEngine.eval(scriptToExecute,
scriptContext);
- appendStreamsToResult(log, stdout, stderr, scriptContext);
-
- if(scriptResult instanceof Result) {
- Result result = (Result) scriptResult;
- for(ResultLog.Entry entry: result) {
- log.add(entry);
- }
- } else if(scriptResult != null){
- log.info("Script result: {}", scriptResult);
- }
-
-
+ ScriptEngine scriptEngine =
scriptHelper.getScriptEngine(scriptEnginesTracker, language);
+ scriptHelper.evalScript(bundleContext, scriptEngine,
scriptToExecute, log, null, true);
} catch (Exception e) {
- log.healthCheckError("Exception during script execution: "+e, e);
- } finally {
- osgi.ungetServices();
+ log.healthCheckError("Exception while executing script: "+e, e);
}
return new Result(log);
}
- private void appendStreamsToResult(FormattingResultLog log, StringWriter
stdout, StringWriter stderr, SimpleScriptContext scriptContext)
- throws IOException {
- scriptContext.getWriter().flush();
- String stdoutStr = stdout.toString();
- if(StringUtils.isNotBlank(stdoutStr)) {
- log.info("stdout of script: {}", stdoutStr);
- }
-
- scriptContext.getErrorWriter().flush();
- String stderrStr = stderr.toString();
- if(StringUtils.isNotBlank(stderrStr)) {
- log.critical("stderr of script: {}", stderrStr);
- }
- }
-
- public String getFileContents(String url) {
- String content;
- try {
- URLConnection conn = new URL(url).openConnection();
- try (BufferedReader reader = new BufferedReader(new
InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
- content = reader.lines().collect(Collectors.joining("\n"));
- }
- return content;
- }catch(IOException e) {
- throw new IllegalArgumentException("Could not read URL "+url+":
"+e, e);
- }
- }
-
- // Script Helper for OSGi available as binding 'osgi'
- class ScriptHelper {
-
- private final BundleContext bundleContext;
- private List<ServiceReference<?>> references;
- private Map<String, Object> services;
-
- public ScriptHelper(BundleContext bundleContext) {
- this.bundleContext = bundleContext;
- }
-
- @SuppressWarnings("unchecked")
- public <ServiceType> ServiceType getService(Class<ServiceType> type) {
- ServiceType service = (this.services == null ? null :
(ServiceType) this.services.get(type.getName()));
- if (service == null) {
- final ServiceReference<?> ref =
this.bundleContext.getServiceReference(type.getName());
- if (ref != null) {
- service = (ServiceType) this.bundleContext.getService(ref);
- if (service != null) {
- if (this.services == null) {
- this.services = new HashMap<String, Object>();
- }
- if (this.references == null) {
- this.references = new
ArrayList<ServiceReference<?>>();
- }
- this.references.add(ref);
- this.services.put(type.getName(), service);
- }
- }
- }
- return service;
- }
-
- public <T> T[] getServices(Class<T> serviceType, String filter)
throws InvalidSyntaxException {
- final ServiceReference<?>[] refs =
this.bundleContext.getServiceReferences(serviceType.getName(), filter);
- T[] result = null;
- if (refs != null) {
- final List<T> objects = new ArrayList<T>();
- for (int i = 0; i < refs.length; i++) {
- @SuppressWarnings("unchecked")
- final T service = (T)
this.bundleContext.getService(refs[i]);
- if (service != null) {
- if (this.references == null) {
- this.references = new
ArrayList<ServiceReference<?>>();
- }
- this.references.add(refs[i]);
- objects.add(service);
- }
- }
- if (objects.size() > 0) {
- @SuppressWarnings("unchecked")
- T[] srv = (T[]) Array.newInstance(serviceType,
objects.size());
- result = objects.toArray(srv);
- }
- }
- return result;
- }
- public void ungetServices() {
- if (this.references != null) {
- final Iterator<ServiceReference<?>> i =
this.references.iterator();
- while (i.hasNext()) {
- final ServiceReference<?> ref = i.next();
- this.bundleContext.ungetService(ref);
- }
- this.references.clear();
- }
- if (this.services != null) {
- this.services.clear();
- }
- }
- }
-
}
Added:
felix/trunk/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/util/ScriptHelper.java
URL:
http://svn.apache.org/viewvc/felix/trunk/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/util/ScriptHelper.java?rev=1852182&view=auto
==============================================================================
---
felix/trunk/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/util/ScriptHelper.java
(added)
+++
felix/trunk/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/util/ScriptHelper.java
Fri Jan 25 21:22:55 2019
@@ -0,0 +1,207 @@
+/*
+ * 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.felix.hc.generalchecks.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.StringWriter;
+import java.lang.reflect.Array;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+import javax.script.SimpleBindings;
+import javax.script.SimpleScriptContext;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.felix.hc.api.FormattingResultLog;
+import org.apache.felix.hc.api.Result;
+import org.apache.felix.hc.api.ResultLog;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+/** Script Helper to interact with . */
+public class ScriptHelper {
+
+ public String getFileContents(String url) {
+ String content;
+ try {
+ URLConnection conn = new URL(url).openConnection();
+ try (BufferedReader reader = new BufferedReader(new
InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
+ content = reader.lines().collect(Collectors.joining("\n"));
+ }
+ return content;
+ }catch(IOException e) {
+ throw new IllegalArgumentException("Could not read URL "+url+":
"+e, e);
+ }
+ }
+
+ public ScriptEngine getScriptEngine(ScriptEnginesTracker
scriptEnginesTracker, String language) {
+ ScriptEngine scriptEngine =
scriptEnginesTracker.getEngineByLanguage(language);
+ if(scriptEngine == null) {
+ throw new IllegalArgumentException("No ScriptEngineFactory found
for language "+ language + " (available languages:
"+scriptEnginesTracker.getLanguagesByBundle()+")");
+ }
+ return scriptEngine;
+ }
+
+ public Object evalScript(BundleContext bundleContext, ScriptEngine
scriptEngine, String scriptToExecute, FormattingResultLog log,
Map<String,Object> additionalBindings, boolean logScriptResult) throws
ScriptException, IOException {
+
+ final Bindings bindings = new SimpleBindings();
+ final ScriptHelperBinding scriptHelper = new
ScriptHelperBinding(bundleContext);
+
+ StringWriter stdout = new StringWriter();
+ StringWriter stderr = new StringWriter();
+
+ bindings.put("scriptHelper", scriptHelper);
+ bindings.put("osgi", scriptHelper); // also register script helper
like in web console script console
+ bindings.put("log", log);
+ bindings.put("bundleContext", bundleContext);
+ if (additionalBindings != null) {
+ for (Map.Entry<String, Object> additionalBinding :
additionalBindings.entrySet()) {
+ bindings.put(additionalBinding.getKey(),
additionalBinding.getValue());
+ }
+ }
+
+ SimpleScriptContext scriptContext = new SimpleScriptContext();
+ scriptContext.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
+ scriptContext.setWriter(stdout);
+ scriptContext.setErrorWriter(stderr);
+
+ try {
+ log.debug(scriptToExecute);
+ Object scriptResult = scriptEngine.eval(scriptToExecute,
scriptContext);
+ appendStreamsToResult(log, stdout, stderr, scriptContext);
+
+ if(scriptResult instanceof Result) {
+ Result result = (Result) scriptResult;
+ for(ResultLog.Entry entry: result) {
+ log.add(entry);
+ }
+ } else if(scriptResult != null && logScriptResult){
+ log.info("Script result: {}", scriptResult);
+ }
+
+ return scriptResult;
+ } finally {
+ scriptHelper.ungetServices();
+ }
+ }
+
+
+
+ private void appendStreamsToResult(FormattingResultLog log, StringWriter
stdout, StringWriter stderr, SimpleScriptContext scriptContext)
+ throws IOException {
+ scriptContext.getWriter().flush();
+ String stdoutStr = stdout.toString();
+ if(StringUtils.isNotBlank(stdoutStr)) {
+ log.info("stdout of script: {}", stdoutStr);
+ }
+
+ scriptContext.getErrorWriter().flush();
+ String stderrStr = stderr.toString();
+ if(StringUtils.isNotBlank(stderrStr)) {
+ log.critical("stderr of script: {}", stderrStr);
+ }
+ }
+
+ // Script Helper for OSGi available as binding 'scriptHelper'
+ class ScriptHelperBinding {
+
+ private final BundleContext bundleContext;
+ private List<ServiceReference<?>> references;
+ private Map<String, Object> services;
+
+ public ScriptHelperBinding(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <ServiceType> ServiceType getService(Class<ServiceType> type) {
+ ServiceType service = (this.services == null ? null :
(ServiceType) this.services.get(type.getName()));
+ if (service == null) {
+ final ServiceReference<?> ref =
this.bundleContext.getServiceReference(type.getName());
+ if (ref != null) {
+ service = (ServiceType) this.bundleContext.getService(ref);
+ if (service != null) {
+ if (this.services == null) {
+ this.services = new HashMap<String, Object>();
+ }
+ if (this.references == null) {
+ this.references = new
ArrayList<ServiceReference<?>>();
+ }
+ this.references.add(ref);
+ this.services.put(type.getName(), service);
+ }
+ }
+ }
+ return service;
+ }
+
+ public <T> T[] getServices(Class<T> serviceType, String filter)
throws InvalidSyntaxException {
+ final ServiceReference<?>[] refs =
this.bundleContext.getServiceReferences(serviceType.getName(), filter);
+ T[] result = null;
+ if (refs != null) {
+ final List<T> objects = new ArrayList<T>();
+ for (int i = 0; i < refs.length; i++) {
+ @SuppressWarnings("unchecked")
+ final T service = (T)
this.bundleContext.getService(refs[i]);
+ if (service != null) {
+ if (this.references == null) {
+ this.references = new
ArrayList<ServiceReference<?>>();
+ }
+ this.references.add(refs[i]);
+ objects.add(service);
+ }
+ }
+ if (objects.size() > 0) {
+ @SuppressWarnings("unchecked")
+ T[] srv = (T[]) Array.newInstance(serviceType,
objects.size());
+ result = objects.toArray(srv);
+ }
+ }
+ return result;
+ }
+
+ public void ungetServices() {
+ if (this.references != null) {
+ final Iterator<ServiceReference<?>> i =
this.references.iterator();
+ while (i.hasNext()) {
+ final ServiceReference<?> ref = i.next();
+ this.bundleContext.ungetService(ref);
+ }
+ this.references.clear();
+ }
+ if (this.services != null) {
+ this.services.clear();
+ }
+ }
+ }
+
+}
Propchange:
felix/trunk/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/util/ScriptHelper.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added:
felix/trunk/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/util/package-info.java
URL:
http://svn.apache.org/viewvc/felix/trunk/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/util/package-info.java?rev=1852182&view=auto
==============================================================================
---
felix/trunk/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/util/package-info.java
(added)
+++
felix/trunk/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/util/package-info.java
Fri Jan 25 21:22:55 2019
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+@Version("2.0.0")
+package org.apache.felix.hc.generalchecks.util;
+
+import org.osgi.annotation.versioning.Version;
Propchange:
felix/trunk/healthcheck/generalchecks/src/main/java/org/apache/felix/hc/generalchecks/util/package-info.java
------------------------------------------------------------------------------
svn:mime-type = text/plain