This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-hc-samples.git
commit 0f9910faefb5883c377c1e552d5f26d7b7bc7fe6 Author: Bertrand Delacretaz <[email protected]> AuthorDate: Thu Sep 26 13:17:13 2013 +0000 SLING-3127 - prepare Health Check tools release git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1526476 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 112 ++++++++++++++++++++ .../hc/samples/impl/AsyncHealthCheckSample.java | 89 ++++++++++++++++ .../samples/impl/OsgiScriptBindingsProvider.java | 113 +++++++++++++++++++++ .../sling/hc/samples/junit/SampleJUnitTest.java | 54 ++++++++++ ....sling.hc.core.impl.CompositeHealthCheck-1.json | 7 ++ ...ing.hc.core.impl.JmxAttributeHealthCheck-1.json | 9 ++ ...sling.hc.core.impl.ScriptableHealthCheck-1.json | 8 ++ ...sling.hc.core.impl.ScriptableHealthCheck-2.json | 9 ++ ...g.hc.samples.impl.AsyncHealthCheckSample-1.json | 6 ++ ...ling.hc.support.DefaultLoginsHealthCheck-1.json | 7 ++ ...hc.support.SlingRequestStatusHealthCheck-1.json | 12 +++ ....junit.healthcheck.impl.JUnitHealthCheck-1.json | 7 ++ .../impl/OsgiScriptBindingsProviderTest.java | 62 +++++++++++ 13 files changed, 495 insertions(+) diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..42add80 --- /dev/null +++ b/pom.xml @@ -0,0 +1,112 @@ +<?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>17</version> + <relativePath/> + </parent> + + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.hc.samples</artifactId> + <packaging>bundle</packaging> + <version>0.0.2-SNAPSHOT</version> + + <name>Sling Health Check Samples</name> + <inceptionYear>2013</inceptionYear> + + <description> + Sling Health Check sample content and configurations + </description> + + <properties> + <sling.java.version>6</sling.java.version> + </properties> + + <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> + <Import-Package> + org.junit.*;resolution:=optional, + org.apache.sling.junit.*;resolution:=optional, + * + </Import-Package> + <Sling-Initial-Content>SLING-CONTENT/apps/hc/demo;path:=/apps/hc/demo;overwrite:=true</Sling-Initial-Content> + <Sling-Test-Regexp>.*Test</Sling-Test-Regexp> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + </dependency> + <dependency> + <groupId>org.apache.felix</groupId> + <artifactId>org.apache.felix.scr.annotations</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>1.6.2</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + <version>1.6.2</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.hc.core</artifactId> + <version>0.0.2-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.junit.core</artifactId> + <version>1.0.8</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> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <version>1.9.5</version> + <scope>test</scope> + </dependency> + </dependencies> +</project> diff --git a/src/main/java/org/apache/sling/hc/samples/impl/AsyncHealthCheckSample.java b/src/main/java/org/apache/sling/hc/samples/impl/AsyncHealthCheckSample.java new file mode 100644 index 0000000..67af69b --- /dev/null +++ b/src/main/java/org/apache/sling/hc/samples/impl/AsyncHealthCheckSample.java @@ -0,0 +1,89 @@ +/* + * 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.samples.impl; + +import java.util.concurrent.atomic.AtomicInteger; + +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.Service; +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; + +/** Sample that demonstrates how to implement asynchronous health checks + * that run in the background at regular intervals. + * The execute() method stays fast as it just reads a pre-computed value. + */ +@Component( + configurationFactory=true, + policy=ConfigurationPolicy.REQUIRE, + metatype=true) +@Properties({ + @Property(name=HealthCheck.NAME), + @Property(name=HealthCheck.TAGS, unbounded=PropertyUnbounded.ARRAY), + @Property(name=HealthCheck.MBEAN_NAME), + + // Period *must* be a Long + @Property(name="scheduler.period", longValue=AsyncHealthCheckSample.PERIOD_SECONDS, propertyPrivate=true), + // Concurrent=false avoids reentrant calls to run() + @Property(name="scheduler.concurrent", boolValue=false) +}) +@Service(value={HealthCheck.class,Runnable.class}) +public class AsyncHealthCheckSample implements HealthCheck, Runnable { + + private final Logger log = LoggerFactory.getLogger(getClass()); + private final AtomicInteger counter = new AtomicInteger(); + + public static final int PERIOD_SECONDS = 5; + + @Override + public Result execute() { + final FormattingResultLog resultLog = new FormattingResultLog(); + final int value = counter.get(); + resultLog.debug("{} - counter value is {}", this, value); + if(value % 2 != 0) { + resultLog.warn("Counter value ({}) is not even", value); + } + return new Result(resultLog); + } + + /** Called by the Sling scheduler, every {@link #SCHEDULER_PERIOD} seconds, without + * reentrant calls, as configured by our scheduler.* service properties. + * + * Simulates an expensive operation by waiting a random time up to twice that period + * before incrementing our counter. + */ + @Override + public void run() { + final long toWait = (long)(Math.random() * 2 * PERIOD_SECONDS); + log.info("{} - Waiting {} seconds to simulate an expensive operation...", this, toWait); + try { + Thread.sleep(toWait * 1000L); + } catch(InterruptedException iex) { + log.warn("Sleep interrupted", iex); + } + counter.incrementAndGet(); + log.info("{} - counter set to {}", this, counter.get()); + } +} \ No newline at end of file diff --git a/src/main/java/org/apache/sling/hc/samples/impl/OsgiScriptBindingsProvider.java b/src/main/java/org/apache/sling/hc/samples/impl/OsgiScriptBindingsProvider.java new file mode 100644 index 0000000..0955111 --- /dev/null +++ b/src/main/java/org/apache/sling/hc/samples/impl/OsgiScriptBindingsProvider.java @@ -0,0 +1,113 @@ +/* + * 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.samples.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. + */ +@Component +@Service +@Property(name="context", value="healthcheck") +public class OsgiScriptBindingsProvider implements BindingsValuesProvider { + private BundleContext bundleContext; + private final Logger log = LoggerFactory.getLogger(getClass()); + public static final String OSGI_BINDING_NAME = "osgi"; + + 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; + } + } + } + + @Activate + protected void activate(ComponentContext ctx) { + bundleContext = ctx.getBundleContext(); + } + + @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); + return; + } + 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 diff --git a/src/main/java/org/apache/sling/hc/samples/junit/SampleJUnitTest.java b/src/main/java/org/apache/sling/hc/samples/junit/SampleJUnitTest.java new file mode 100644 index 0000000..d0f712a --- /dev/null +++ b/src/main/java/org/apache/sling/hc/samples/junit/SampleJUnitTest.java @@ -0,0 +1,54 @@ +package org.apache.sling.hc.samples.junit; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.apache.sling.junit.annotations.SlingAnnotationsTestRunner; +import org.apache.sling.junit.annotations.TestReference; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; + +/* + * 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. + */ + +/** Trivial test used to demonstrate the junit Health Check service. + * Verify that the BundleContext is injected and that a specific + * bundle is active. + */ +@RunWith(SlingAnnotationsTestRunner.class) +public class SampleJUnitTest { + + @TestReference + private BundleContext bundleContext; + + @Test + public void checkBundleContext() { + assertNotNull(bundleContext); + } + + @Test + public void checkGroovyBundleActive() { + final String symbolicName = "org.apache.sling.extensions.groovy"; + for(Bundle b : bundleContext.getBundles()) { + if(symbolicName.equals(b.getSymbolicName())) { + assertEquals("Expecting " + symbolicName + " to be active", Bundle.ACTIVE, b.getState()); + } + } + } +} diff --git a/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.core.impl.CompositeHealthCheck-1.json b/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.core.impl.CompositeHealthCheck-1.json new file mode 100644 index 0000000..c60b492 --- /dev/null +++ b/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.core.impl.CompositeHealthCheck-1.json @@ -0,0 +1,7 @@ +{ + "jcr:primaryType" : "sling:OsgiConfig", + "hc.name" : "CompositeHealthCheck: execute all HealthCheck tagged with 'script'", + "hc.tags" : [composite], + "filter.tags" : [script], + "hc.mbean.name" : "CompositeHealthCheck/script" +} diff --git a/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.core.impl.JmxAttributeHealthCheck-1.json b/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.core.impl.JmxAttributeHealthCheck-1.json new file mode 100644 index 0000000..87f949f --- /dev/null +++ b/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.core.impl.JmxAttributeHealthCheck-1.json @@ -0,0 +1,9 @@ +{ + "jcr:primaryType" : "sling:OsgiConfig", + "mbean.name" : "java.lang:type=ClassLoading", + "attribute.name" : "LoadedClassCount", + "attribute.value.constraint" : "between 5000 and 50000", + "hc.name" : "LoadedClassCount is in range", + "hc.mbean.name" : "JMX LoadedClassCount", + "hc.tags" : [jvm, classloading, jmx] +} diff --git a/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.core.impl.ScriptableHealthCheck-1.json b/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.core.impl.ScriptableHealthCheck-1.json new file mode 100644 index 0000000..ca2dee0 --- /dev/null +++ b/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.core.impl.ScriptableHealthCheck-1.json @@ -0,0 +1,8 @@ +{ + "jcr:primaryType" : "sling:OsgiConfig", + "expression" : "jmx.attribute('java.lang:type=ClassLoading', 'LoadedClassCount') > 10 && jmx.attribute('java.lang:type=Runtime', 'ManagementSpecVersion') > 1", + "hc.name" : "LoadedClassCount and ManagementSpecVersion are in range", + "language.extension" : "ecma", + "hc.tags" : [jvm, script], + "hc.mbean.name" : "LoadedClassCount and ManagementSpecVersion" +} diff --git a/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.core.impl.ScriptableHealthCheck-2.json b/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.core.impl.ScriptableHealthCheck-2.json new file mode 100644 index 0000000..5e6c2f2 --- /dev/null +++ b/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.core.impl.ScriptableHealthCheck-2.json @@ -0,0 +1,9 @@ +{ + "jcr:primaryType" : "sling:OsgiConfig", + "expression" : "osgi.inactiveBundlesCount() == 0 ", + "hc.name" : "No inactive bundles", + "hc.mbean.name" : "InactiveBundlesCheck", + "language.extension" : "ecma", + "hc.tags" : [bundles, script], + "hc.mbean.name" : "NoInactiveBundles" +} diff --git a/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.samples.impl.AsyncHealthCheckSample-1.json b/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.samples.impl.AsyncHealthCheckSample-1.json new file mode 100644 index 0000000..9984ce5 --- /dev/null +++ b/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.samples.impl.AsyncHealthCheckSample-1.json @@ -0,0 +1,6 @@ +{ + "jcr:primaryType" : "sling:OsgiConfig", + "hc.name" : "Asynchronous Health Check sample", + "hc.tags" : [async], + "hc.mbean.name" : "AsyncHealthCheckSample" +} diff --git a/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.support.DefaultLoginsHealthCheck-1.json b/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.support.DefaultLoginsHealthCheck-1.json new file mode 100644 index 0000000..3ab3bdb --- /dev/null +++ b/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.support.DefaultLoginsHealthCheck-1.json @@ -0,0 +1,7 @@ +{ + "jcr:primaryType" : "sling:OsgiConfig", + "logins" : ["admin:admin","foo:bar"], + "hc.name" : "Default logins should fail", + "hc.tags" : [security], + "hc.mbean.name" : "DefaultLoginsFail" +} diff --git a/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.support.SlingRequestStatusHealthCheck-1.json b/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.support.SlingRequestStatusHealthCheck-1.json new file mode 100644 index 0000000..7887f92 --- /dev/null +++ b/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.hc.support.SlingRequestStatusHealthCheck-1.json @@ -0,0 +1,12 @@ +{ + "jcr:primaryType" : "sling:OsgiConfig", + "path" : [ + "index.html", + "index.html.json", + "apps/hc.tidy.json", + "some/non/existent/path:404" + ], + "hc.name" : "Initial content is present", + "hc.tags" : [request, sling], + "hc.mbean.name" : "InitialContentPresent" +} diff --git a/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.junit.healthcheck.impl.JUnitHealthCheck-1.json b/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.junit.healthcheck.impl.JUnitHealthCheck-1.json new file mode 100644 index 0000000..ee2d4b4 --- /dev/null +++ b/src/main/resources/SLING-CONTENT/apps/hc/demo/install/org.apache.sling.junit.healthcheck.impl.JUnitHealthCheck-1.json @@ -0,0 +1,7 @@ +{ + "jcr:primaryType" : "sling:OsgiConfig", + "hc.name" : "JUnit Health Check Sample", + "hc.tags" : [junit], + "test.package.or.class" : "org.apache.sling.hc", + "hc.mbean.name" : "JUnitHealthCheck" +} diff --git a/src/test/java/org/apache/sling/hc/samples/impl/OsgiScriptBindingsProviderTest.java b/src/test/java/org/apache/sling/hc/samples/impl/OsgiScriptBindingsProviderTest.java new file mode 100644 index 0000000..5c1e1a5 --- /dev/null +++ b/src/test/java/org/apache/sling/hc/samples/impl/OsgiScriptBindingsProviderTest.java @@ -0,0 +1,62 @@ +/* + * 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.samples.impl; + +import static org.junit.Assert.assertEquals; + +import java.util.Dictionary; +import java.util.Hashtable; + +import org.apache.sling.hc.util.FormattingResultLog; +import org.junit.Test; +import org.mockito.Mockito; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; + +public class OsgiScriptBindingsProviderTest { + + private Bundle mockBundle(boolean isFragment, boolean isActive) { + final Bundle b = Mockito.mock(Bundle.class); + Mockito.when(b.getState()).thenReturn(isActive ? Bundle.ACTIVE : Bundle.RESOLVED); + + final Dictionary<String, String> headers = new Hashtable<String, String>(); + if(isFragment) { + headers.put(Constants.FRAGMENT_HOST, "FOO"); + } + Mockito.when(b.getHeaders()).thenReturn(headers); + + return b; + } + + @Test + public void testInactiveBundles() throws Exception { + final BundleContext ctx = Mockito.mock(BundleContext.class); + final Bundle [] bundles = { + mockBundle(false, true), + mockBundle(false, false), + mockBundle(false, true), + mockBundle(true, false) + }; + Mockito.when(ctx.getBundles()).thenReturn(bundles); + + final FormattingResultLog resultLog = new FormattingResultLog(); + final OsgiScriptBindingsProvider.OsgiBinding b = new OsgiScriptBindingsProvider.OsgiBinding(ctx, resultLog); + assertEquals(1, b.inactiveBundlesCount()); + } +} \ No newline at end of file -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
