Author: bdelacretaz
Date: Fri Sep 6 14:27:21 2013
New Revision: 1520576
URL: http://svn.apache.org/r1520576
Log:
SLING-3034 - use BindingsValuesProvider for script bindings
Modified:
sling/trunk/contrib/extensions/healthcheck/core/pom.xml
sling/trunk/contrib/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/JmxScriptBinding.java
sling/trunk/contrib/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/OsgiScriptBinding.java
sling/trunk/contrib/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/ScriptableHealthCheck.java
sling/trunk/contrib/extensions/healthcheck/core/src/test/java/org/apache/sling/hc/core/impl/JmxScriptBindingTest.java
sling/trunk/contrib/extensions/healthcheck/core/src/test/java/org/apache/sling/hc/core/impl/OsgiScriptBindingTest.java
sling/trunk/contrib/extensions/healthcheck/core/src/test/java/org/apache/sling/hc/core/impl/ScriptableHealthCheckTest.java
sling/trunk/contrib/extensions/healthcheck/it/src/test/java/org/apache/sling/hc/it/core/U.java
Modified: sling/trunk/contrib/extensions/healthcheck/core/pom.xml
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/healthcheck/core/pom.xml?rev=1520576&r1=1520575&r2=1520576&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/healthcheck/core/pom.xml (original)
+++ sling/trunk/contrib/extensions/healthcheck/core/pom.xml Fri Sep 6 14:27:21
2013
@@ -90,5 +90,11 @@
<version>2.2.0</version>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.scripting.api</artifactId>
+ <version>2.1.0</version>
+ <scope>provided</scope>
+ </dependency>
</dependencies>
</project>
Modified:
sling/trunk/contrib/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/JmxScriptBinding.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/JmxScriptBinding.java?rev=1520576&r1=1520575&r2=1520576&view=diff
==============================================================================
---
sling/trunk/contrib/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/JmxScriptBinding.java
(original)
+++
sling/trunk/contrib/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/JmxScriptBinding.java
Fri Sep 6 14:27:21 2013
@@ -26,37 +26,63 @@ import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
+import javax.script.Bindings;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
import org.apache.sling.hc.util.FormattingResultLog;
+import org.apache.sling.scripting.api.BindingsValuesProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/** The JmxBinding is meant to be bound as "jmx" global variables
* in scripted rules, to allow for writing scripted expressions
* like jmx.attribute("java.lang:type=ClassLoading", "LoadedClassCount") > 100
- *
- * TODO this should really be a {@link BindingsValuesProvider} service,
- * but for this we need to modify the default Sling script handling
- * so that BindingsValuesProvider which have a specific scope service
- * property are ignored.
*/
-public class JmxScriptBinding {
+@Component
+@Service
+@Property(name="context", value="healthcheck")
+public class JmxScriptBinding implements BindingsValuesProvider {
private MBeanServer jmxServer = ManagementFactory.getPlatformMBeanServer();
- private final FormattingResultLog resultLog;
+ private final Logger log = LoggerFactory.getLogger(getClass());
+ public static final String JMX_BINDING_NAME = "jmx";
- public JmxScriptBinding(FormattingResultLog resultLog) {
- this.resultLog = resultLog;
+ public static class AttributeBinding {
+ private final MBeanServer jmxServer;
+ private final FormattingResultLog resultLog;
+
+ AttributeBinding(MBeanServer s, FormattingResultLog r) {
+ jmxServer = s;
+ resultLog = r;
+ }
+
+ public Object attribute(String objectNameString, String attributeName)
+ throws MalformedObjectNameException,
AttributeNotFoundException, InstanceNotFoundException, MBeanException,
ReflectionException {
+ final ObjectName name = new ObjectName(objectNameString);
+ if(jmxServer.queryNames(name, null).size() == 0) {
+ final String msg = "JMX object name not found: [" +
objectNameString + "]";
+ resultLog.warn(msg);
+ throw new IllegalStateException(msg);
+ }
+ resultLog.debug("Got JMX Object [{}]", name);
+ final Object value = jmxServer.getAttribute(name, attributeName);
+ resultLog.debug("JMX Object [{}] Attribute [{}] = [{}]", name,
attributeName, value);
+ return value;
+ }
}
-
- public Object attribute(String objectNameString, String attributeName)
- throws MalformedObjectNameException, AttributeNotFoundException,
InstanceNotFoundException, MBeanException, ReflectionException {
- final ObjectName name = new ObjectName(objectNameString);
- if(jmxServer.queryNames(name, null).size() == 0) {
- final String msg = "JMX object name not found: [" +
objectNameString + "]";
- resultLog.warn(msg);
- throw new IllegalStateException(msg);
+
+ @Override
+ public void addBindings(Bindings b) {
+ final String logBindingName = FormattingResultLog.class.getName();
+ final Object resultLog = b.get(logBindingName);
+ if(resultLog == null) {
+ log.info("No {} found in Bindings, cannot activate {} binding",
logBindingName, JMX_BINDING_NAME);
+ }
+ try {
+ b.put("jmx", new AttributeBinding(jmxServer,
(FormattingResultLog)resultLog));
+ } catch(Exception e) {
+ log.error("Exception while activating " + JMX_BINDING_NAME, e);
}
- resultLog.debug("Got JMX Object [{}]", name);
- final Object value = jmxServer.getAttribute(name, attributeName);
- resultLog.debug("JMX Object [{}] Attribute [{}] = [{}]", name,
attributeName, value);
- return value;
}
}
\ No newline at end of file
Modified:
sling/trunk/contrib/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/OsgiScriptBinding.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/OsgiScriptBinding.java?rev=1520576&r1=1520575&r2=1520576&view=diff
==============================================================================
---
sling/trunk/contrib/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/OsgiScriptBinding.java
(original)
+++
sling/trunk/contrib/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/OsgiScriptBinding.java
Fri Sep 6 14:27:21 2013
@@ -17,56 +17,96 @@
*/
package org.apache.sling.hc.core.impl;
+import javax.script.Bindings;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
import org.apache.sling.hc.util.FormattingResultLog;
+import org.apache.sling.scripting.api.BindingsValuesProvider;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import aQute.bnd.annotation.component.Deactivate;
/** The OsgiBinding is meant to be bound as an "osgi" global variable
* in scripted rules, to allow for checking some OSGi states in
* a simple way.
- *
- * TODO this should really be a {@link BindingsValuesProvider} service,
- * but for this we need to modify the default Sling script handling
- * so that BindingsValuesProvider which have a specific scope service
- * property are ignored.
*/
-public class OsgiScriptBinding {
- private final FormattingResultLog resultLog;
- private final BundleContext bundleContext;
-
- public OsgiScriptBinding(BundleContext ctx, FormattingResultLog resultLog)
{
- this.resultLog = resultLog;
- this.bundleContext = ctx;
- }
+@Component
+@Service
+@Property(name="context", value="healthcheck")
+public class OsgiScriptBinding implements BindingsValuesProvider {
+ private BundleContext bundleContext;
+ private final Logger log = LoggerFactory.getLogger(getClass());
+ public static final String OSGI_BINDING_NAME = "osgi";
- public int inactiveBundlesCount() {
- int count = 0;
- for(Bundle b : bundleContext.getBundles()) {
- if(!isActive(b)) {
- count++;
+ public static class OsgiBinding {
+ private final BundleContext bundleContext;
+ private final FormattingResultLog resultLog;
+
+ public OsgiBinding(BundleContext bc, FormattingResultLog r) {
+ bundleContext = bc;
+ resultLog = r;
+ }
+
+ public int inactiveBundlesCount() {
+ int count = 0;
+ for(Bundle b : bundleContext.getBundles()) {
+ if(!isActive(b)) {
+ count++;
+ }
+ }
+ resultLog.debug("inactiveBundlesCount={}", count);
+ return count;
+ }
+
+ private boolean isActive(Bundle b) {
+ boolean active = true;
+ if(!isFragment(b) && Bundle.ACTIVE != b.getState()) {
+ active = false;
+ resultLog.info("Bundle {} is not active, state={} ({})",
b.getSymbolicName(), b.getState(), b.getState());
+ }
+ return active;
+ }
+
+ private boolean isFragment(Bundle b) {
+ final String header = (String) b.getHeaders().get(
Constants.FRAGMENT_HOST );
+ if(header!= null && header.trim().length() > 0) {
+ resultLog.debug("{} is a fragment bundle, state won't be
checked", b);
+ return true;
+ } else {
+ return false;
}
}
- resultLog.debug("inactiveBundlesCount={}", count);
- return count;
}
- private boolean isActive(Bundle b) {
- boolean active = true;
- if(!isFragment(b) && Bundle.ACTIVE != b.getState()) {
- active = false;
- resultLog.info("Bundle {} is not active, state={} ({})",
b.getSymbolicName(), b.getState(), b.getState());
- }
- return active;
+ @Activate
+ protected void activate(ComponentContext ctx) {
+ bundleContext = ctx.getBundleContext();
}
- private boolean isFragment(Bundle b) {
- final String header = (String) b.getHeaders().get(
Constants.FRAGMENT_HOST );
- if(header!= null && header.trim().length() > 0) {
- resultLog.debug("{} is a fragment bundle, state won't be checked",
b);
- return true;
- } else {
- return false;
+ @Deactivate
+ protected void deactivate(ComponentContext ctx) {
+ bundleContext = null;
+ }
+
+ @Override
+ public void addBindings(Bindings b) {
+ final String logBindingName = FormattingResultLog.class.getName();
+ final Object resultLog = b.get(logBindingName);
+ if(resultLog == null) {
+ log.info("No {} found in Bindings, cannot activate {} binding",
logBindingName, OSGI_BINDING_NAME);
+ }
+ try {
+ b.put("osgi", new OsgiBinding(bundleContext,
(FormattingResultLog)resultLog));
+ } catch(Exception e) {
+ log.error("Exception while activating " + OSGI_BINDING_NAME, e);
}
}
}
\ No newline at end of file
Modified:
sling/trunk/contrib/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/ScriptableHealthCheck.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/ScriptableHealthCheck.java?rev=1520576&r1=1520575&r2=1520576&view=diff
==============================================================================
---
sling/trunk/contrib/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/ScriptableHealthCheck.java
(original)
+++
sling/trunk/contrib/extensions/healthcheck/core/src/main/java/org/apache/sling/hc/core/impl/ScriptableHealthCheck.java
Fri Sep 6 14:27:21 2013
@@ -16,6 +16,9 @@
* specific language governing permissions and limitations under the License.
*/
package org.apache.sling.hc.core.impl;
+import java.util.HashSet;
+import java.util.Set;
+
import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
@@ -27,12 +30,14 @@ import org.apache.felix.scr.annotations.
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.ReferenceCardinality;
+import org.apache.felix.scr.annotations.ReferencePolicy;
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.osgi.framework.BundleContext;
+import org.apache.sling.scripting.api.BindingsValuesProvider;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -53,7 +58,6 @@ public class ScriptableHealthCheck imple
private final Logger log = LoggerFactory.getLogger(getClass());
private String expression;
private String languageExtension;
- private BundleContext bundleContext;
private static final String DEFAULT_LANGUAGE_EXTENSION = "ecma";
@@ -65,10 +69,16 @@ public class ScriptableHealthCheck imple
@Reference
private ScriptEngineManager scriptEngineManager;
+
+ @Reference(
+ cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE,
+ policy=ReferencePolicy.DYNAMIC,
+ referenceInterface=BindingsValuesProvider.class,
+ target="(context=healthcheck)")
+ private final Set<BindingsValuesProvider> bindingsValuesProviders = new
HashSet<BindingsValuesProvider>();
@Activate
public void activate(ComponentContext ctx) {
- bundleContext = ctx.getBundleContext();
expression =
PropertiesUtil.toString(ctx.getProperties().get(PROP_EXPRESSION), "");
languageExtension =
PropertiesUtil.toString(ctx.getProperties().get(PROP_LANGUAGE_EXTENSION),
DEFAULT_LANGUAGE_EXTENSION);
@@ -86,10 +96,17 @@ public class ScriptableHealthCheck imple
if (engine == null) {
resultLog.healthCheckError("No ScriptEngine available for
extension {}", languageExtension);
} else {
- // TODO pluggable Bindings? Reuse the Sling bindings providers?
+ // Set Bindings, with our ResultLog as a binding first, so
that other bindings can use it
final Bindings b = engine.createBindings();
- b.put("jmx", new JmxScriptBinding(resultLog));
- b.put("osgi", new OsgiScriptBinding(bundleContext, resultLog));
+ b.put(FormattingResultLog.class.getName(), resultLog);
+ synchronized (bindingsValuesProviders) {
+ for(BindingsValuesProvider bvp : bindingsValuesProviders) {
+ log.debug("Adding Bindings provided by {}", bvp);
+ bvp.addBindings(b);
+ }
+ }
+ log.debug("All Bindings added: {}", b.keySet());
+
final Object value = engine.eval(expression, b);
if(value!=null &&
"true".equals(value.toString().toLowerCase())) {
resultLog.debug("Expression [{}] evaluates to true as
expected", expression);
@@ -104,4 +121,18 @@ public class ScriptableHealthCheck imple
}
return new Result(resultLog);
}
+
+ public void bindBindingsValuesProvider(BindingsValuesProvider bvp) {
+ synchronized (bindingsValuesProviders) {
+ bindingsValuesProviders.add(bvp);
+ }
+ log.debug("{} registered: {}", bvp, bindingsValuesProviders);
+ }
+
+ public void unbindBindingsValuesProvider(BindingsValuesProvider bvp) {
+ synchronized (bindingsValuesProviders) {
+ bindingsValuesProviders.remove(bvp);
+ }
+ log.debug("{} unregistered: {}", bvp, bindingsValuesProviders);
+ }
}
\ No newline at end of file
Modified:
sling/trunk/contrib/extensions/healthcheck/core/src/test/java/org/apache/sling/hc/core/impl/JmxScriptBindingTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/healthcheck/core/src/test/java/org/apache/sling/hc/core/impl/JmxScriptBindingTest.java?rev=1520576&r1=1520575&r2=1520576&view=diff
==============================================================================
---
sling/trunk/contrib/extensions/healthcheck/core/src/test/java/org/apache/sling/hc/core/impl/JmxScriptBindingTest.java
(original)
+++
sling/trunk/contrib/extensions/healthcheck/core/src/test/java/org/apache/sling/hc/core/impl/JmxScriptBindingTest.java
Fri Sep 6 14:27:21 2013
@@ -20,6 +20,8 @@ package org.apache.sling.hc.core.impl;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import java.lang.management.ManagementFactory;
+
import org.apache.sling.hc.core.impl.JmxScriptBinding;
import org.apache.sling.hc.util.FormattingResultLog;
import org.junit.Test;
@@ -29,7 +31,7 @@ public class JmxScriptBindingTest {
@Test
public void testJmxAttribute() throws Exception {
final FormattingResultLog resultLog = new FormattingResultLog();
- final JmxScriptBinding b = new JmxScriptBinding(resultLog);
+ final JmxScriptBinding.AttributeBinding b = new
JmxScriptBinding.AttributeBinding(ManagementFactory.getPlatformMBeanServer(),
resultLog);
final Object value= b.attribute("java.lang:type=ClassLoading",
"LoadedClassCount");
assertNotNull("Expecting non-null attribute value", value);
assertTrue("Expecting non-empty value", value.toString().length() > 0);
Modified:
sling/trunk/contrib/extensions/healthcheck/core/src/test/java/org/apache/sling/hc/core/impl/OsgiScriptBindingTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/healthcheck/core/src/test/java/org/apache/sling/hc/core/impl/OsgiScriptBindingTest.java?rev=1520576&r1=1520575&r2=1520576&view=diff
==============================================================================
---
sling/trunk/contrib/extensions/healthcheck/core/src/test/java/org/apache/sling/hc/core/impl/OsgiScriptBindingTest.java
(original)
+++
sling/trunk/contrib/extensions/healthcheck/core/src/test/java/org/apache/sling/hc/core/impl/OsgiScriptBindingTest.java
Fri Sep 6 14:27:21 2013
@@ -57,7 +57,7 @@ public class OsgiScriptBindingTest {
Mockito.when(ctx.getBundles()).thenReturn(bundles);
final FormattingResultLog resultLog = new FormattingResultLog();
- final OsgiScriptBinding b = new OsgiScriptBinding(ctx, resultLog);
+ final OsgiScriptBinding.OsgiBinding b = new
OsgiScriptBinding.OsgiBinding(ctx, resultLog);
assertEquals(1, b.inactiveBundlesCount());
}
}
\ No newline at end of file
Modified:
sling/trunk/contrib/extensions/healthcheck/core/src/test/java/org/apache/sling/hc/core/impl/ScriptableHealthCheckTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/healthcheck/core/src/test/java/org/apache/sling/hc/core/impl/ScriptableHealthCheckTest.java?rev=1520576&r1=1520575&r2=1520576&view=diff
==============================================================================
---
sling/trunk/contrib/extensions/healthcheck/core/src/test/java/org/apache/sling/hc/core/impl/ScriptableHealthCheckTest.java
(original)
+++
sling/trunk/contrib/extensions/healthcheck/core/src/test/java/org/apache/sling/hc/core/impl/ScriptableHealthCheckTest.java
Fri Sep 6 14:27:21 2013
@@ -28,7 +28,7 @@ import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import org.apache.sling.hc.api.Result;
-import org.apache.sling.hc.core.impl.ScriptableHealthCheck;
+import org.junit.Before;
import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.Mockito;
@@ -39,12 +39,9 @@ public class ScriptableHealthCheckTest {
private ScriptableHealthCheck hc;
private Dictionary<String, String> props;
private ComponentContext ctx;
+ private final JmxScriptBinding jmxScriptBinding = new JmxScriptBinding();
private void assertExpression(String expression, String languageExtension,
boolean expected) throws Exception {
- hc = new ScriptableHealthCheck();
- ctx = Mockito.mock(ComponentContext.class);
- props = new Hashtable<String, String>();
-
final ScriptEngine rhino = new
ScriptEngineManager().getEngineByExtension("js");
assertNotNull("With the rhino jar in our classpath, we should get a js
script engine", rhino);
final ScriptEngineManager manager =
Mockito.mock(ScriptEngineManager.class);
@@ -63,12 +60,28 @@ public class ScriptableHealthCheckTest {
assertEquals("Expecting result " + expected, expected, r.isOk());
}
+ @Before
+ public void setup() {
+ hc = new ScriptableHealthCheck();
+ ctx = Mockito.mock(ComponentContext.class);
+ props = new Hashtable<String, String>();
+ hc.bindBindingsValuesProvider(jmxScriptBinding);
+ }
+
@Test
public void testSimpleExpression() throws Exception {
assertExpression("2 + 3 == 5", null, true);
}
@Test
+ public void testRemoveBinding() throws Exception {
+ final String expr = "jmx.attribute('java.lang:type=ClassLoading',
'LoadedClassCount') > 10";
+ assertExpression(expr, "ecma", true);
+ hc.unbindBindingsValuesProvider(jmxScriptBinding);
+ assertExpression(expr, "ecma", false);
+ }
+
+ @Test
public void testJmxExpression() throws Exception {
assertExpression(
"jmx.attribute('java.lang:type=ClassLoading',
'LoadedClassCount') > 10"
Modified:
sling/trunk/contrib/extensions/healthcheck/it/src/test/java/org/apache/sling/hc/it/core/U.java
URL:
http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/healthcheck/it/src/test/java/org/apache/sling/hc/it/core/U.java?rev=1520576&r1=1520575&r2=1520576&view=diff
==============================================================================
---
sling/trunk/contrib/extensions/healthcheck/it/src/test/java/org/apache/sling/hc/it/core/U.java
(original)
+++
sling/trunk/contrib/extensions/healthcheck/it/src/test/java/org/apache/sling/hc/it/core/U.java
Fri Sep 6 14:27:21 2013
@@ -58,6 +58,7 @@ public class U {
mavenBundle("org.apache.sling",
"org.apache.sling.commons.mime", "2.1.4"),
mavenBundle("org.apache.sling",
"org.apache.sling.settings", "1.2.2"),
mavenBundle("org.apache.sling",
"org.apache.sling.launchpad.api", "1.1.0"),
+ mavenBundle("org.apache.sling",
"org.apache.sling.scripting.api", "2.1.0"),
mavenBundle("commons-collections", "commons-collections",
"3.2.1"),
mavenBundle("commons-io", "commons-io", "1.4"),
mavenBundle("commons-fileupload", "commons-fileupload",
"1.2.2"),