You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by gh...@apache.org on 2019/01/25 21:22:55 UTC
svn commit: r1852182 - in /felix/trunk/healthcheck/generalchecks: ./
src/main/java/org/apache/felix/hc/generalchecks/
src/main/java/org/apache/felix/hc/generalchecks/util/
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