From 66b8cbfbfae54d41b9881573904042c9813a8339 Mon Sep 17 00:00:00 2001 From: BJ Hargrave Date: Tue, 29 Mar 2022 14:06:04 -0400 Subject: [PATCH 1/2] installedbundle: Ignore case when url prefix matching Signed-off-by: BJ Hargrave --- .../junit5/context/InstalledBundleExtension.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/org.osgi.test.junit5/src/main/java/org/osgi/test/junit5/context/InstalledBundleExtension.java b/org.osgi.test.junit5/src/main/java/org/osgi/test/junit5/context/InstalledBundleExtension.java index ab848d34..ec7f4a00 100644 --- a/org.osgi.test.junit5/src/main/java/org/osgi/test/junit5/context/InstalledBundleExtension.java +++ b/org.osgi.test.junit5/src/main/java/org/osgi/test/junit5/context/InstalledBundleExtension.java @@ -25,7 +25,6 @@ import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; import org.osgi.test.common.annotation.InjectInstalledBundle; import org.osgi.test.common.inject.TargetType; import org.osgi.test.common.install.BundleInstaller; @@ -50,14 +49,14 @@ public InstalledBundleExtension() { public static Bundle installedBundleOf(InjectInstalledBundle injectBundle, ExtensionContext extensionContext) { try { - BundleContext bc = BundleContextExtension.getBundleContext(extensionContext); BundleInstaller ib = BundleInstallerExtension.getBundleInstaller(extensionContext); String spec = injectBundle.value(); - if (spec.startsWith("http:") || spec.startsWith("https:") || spec.startsWith("file:")) { + if (prefixMatch(spec, "http:", "https:", "file:")) { return ib.installBundle(new URL(spec), injectBundle.start()); } else { - return ib.installBundle(BundleInstaller.EmbeddedLocation.of(bc, spec), injectBundle.start()); + return ib.installBundle(BundleInstaller.EmbeddedLocation.of(ib.getBundleContext(), spec), + injectBundle.start()); } } catch (MalformedURLException e) { throw new ExtensionConfigurationException( @@ -65,6 +64,15 @@ public static Bundle installedBundleOf(InjectInstalledBundle injectBundle, Exten } } + private static boolean prefixMatch(String target, String... prefixes) { + for (String prefix : prefixes) { + if (target.regionMatches(true, 0, prefix, 0, prefix.length())) { + return true; + } + } + return false; + } + @Override protected Object resolveValue(TargetType targetType, InjectInstalledBundle injectBundle, ExtensionContext extensionContext) throws ParameterResolutionException { From 3051148cc8f443ee13ace46c856050fa66415962 Mon Sep 17 00:00:00 2001 From: BJ Hargrave Date: Tue, 29 Mar 2022 14:30:00 -0400 Subject: [PATCH 2/2] context: Improve error when no bundle context is available We add a new common method to obtain the BundleContext for a test class. If the class is not in a bundle or the bundle is not started, the method will now throw an exception with the appropriate message. A test class must be in a bundle loaded by an OSGi framework and that bundle must be started (lazy activation is OK since the test runner must have loaded the test class which would complete activation). Signed-off-by: BJ Hargrave --- .../context/CloseableBundleContext.java | 3 +- .../test/common/context/ContextHelper.java | 43 +++++++++++++++++++ .../test/common/context/package-info.java | 2 +- .../test/common/install/BundleInstaller.java | 3 +- .../common/service/ServiceConfiguration.java | 1 + .../junit4/context/BundleContextRule.java | 6 +-- .../osgi/test/junit4/service/ServiceRule.java | 6 +-- .../context/BundleContextExtension.java | 14 +++--- 8 files changed, 60 insertions(+), 18 deletions(-) create mode 100644 org.osgi.test.common/src/main/java/org/osgi/test/common/context/ContextHelper.java diff --git a/org.osgi.test.common/src/main/java/org/osgi/test/common/context/CloseableBundleContext.java b/org.osgi.test.common/src/main/java/org/osgi/test/common/context/CloseableBundleContext.java index 0b6a38a1..6c1702f8 100644 --- a/org.osgi.test.common/src/main/java/org/osgi/test/common/context/CloseableBundleContext.java +++ b/org.osgi.test.common/src/main/java/org/osgi/test/common/context/CloseableBundleContext.java @@ -18,6 +18,7 @@ package org.osgi.test.common.context; +import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.toMap; import static org.osgi.test.common.exceptions.ConsumerWithException.asConsumer; import static org.osgi.test.common.exceptions.ConsumerWithException.asConsumerIgnoreException; @@ -138,7 +139,7 @@ public static BundleContext proxy(BundleContext bundleContext) { } public CloseableBundleContext(BundleContext bundleContext) { - this.bundleContext = bundleContext; + this.bundleContext = requireNonNull(bundleContext); } @Override diff --git a/org.osgi.test.common/src/main/java/org/osgi/test/common/context/ContextHelper.java b/org.osgi.test.common/src/main/java/org/osgi/test/common/context/ContextHelper.java new file mode 100644 index 00000000..e59be1ad --- /dev/null +++ b/org.osgi.test.common/src/main/java/org/osgi/test/common/context/ContextHelper.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) Contributors to the Eclipse Foundation + * + * Licensed 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. + * + * SPDX-License-Identifier: Apache-2.0 + *******************************************************************************/ + +package org.osgi.test.common.context; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.test.common.bitmaps.BundleState; + +public final class ContextHelper { + private ContextHelper() {} + + public static BundleContext getBundleContext(Class testClass) { + Bundle bundle = FrameworkUtil.getBundle(testClass); + if (bundle == null) { + throw new IllegalStateException( + String.format("No BundleContext available - The class (%s) must be loaded from a bundle", testClass)); + } + BundleContext context = bundle.getBundleContext(); + if (context == null) { + throw new IllegalStateException(String.format( + "No BundleContext available - The bundle of the class (%s) must be started to have a BundleContext; bundle current state: %s", + testClass, BundleState.toString(bundle.getState()))); + } + return context; + } +} diff --git a/org.osgi.test.common/src/main/java/org/osgi/test/common/context/package-info.java b/org.osgi.test.common/src/main/java/org/osgi/test/common/context/package-info.java index 3f8d5a16..459ea7f6 100644 --- a/org.osgi.test.common/src/main/java/org/osgi/test/common/context/package-info.java +++ b/org.osgi.test.common/src/main/java/org/osgi/test/common/context/package-info.java @@ -17,5 +17,5 @@ *******************************************************************************/ @org.osgi.annotation.bundle.Export -@org.osgi.annotation.versioning.Version("1.0.0") +@org.osgi.annotation.versioning.Version("1.1.0") package org.osgi.test.common.context; diff --git a/org.osgi.test.common/src/main/java/org/osgi/test/common/install/BundleInstaller.java b/org.osgi.test.common/src/main/java/org/osgi/test/common/install/BundleInstaller.java index 91ea8107..c3789fe7 100644 --- a/org.osgi.test.common/src/main/java/org/osgi/test/common/install/BundleInstaller.java +++ b/org.osgi.test.common/src/main/java/org/osgi/test/common/install/BundleInstaller.java @@ -18,6 +18,7 @@ package org.osgi.test.common.install; +import static java.util.Objects.requireNonNull; import static org.osgi.test.common.exceptions.Exceptions.duck; import java.io.FileNotFoundException; @@ -243,7 +244,7 @@ public String toString() { private final BundleContext bundleContext; public BundleInstaller(BundleContext bundleContext) { - this.bundleContext = bundleContext; + this.bundleContext = requireNonNull(bundleContext); } /** diff --git a/org.osgi.test.common/src/main/java/org/osgi/test/common/service/ServiceConfiguration.java b/org.osgi.test.common/src/main/java/org/osgi/test/common/service/ServiceConfiguration.java index 7c9098be..8caaa617 100644 --- a/org.osgi.test.common/src/main/java/org/osgi/test/common/service/ServiceConfiguration.java +++ b/org.osgi.test.common/src/main/java/org/osgi/test/common/service/ServiceConfiguration.java @@ -79,6 +79,7 @@ public ServiceConfiguration(Class serviceType, String format, String[] args, } public ServiceConfiguration init(BundleContext bundleContext) { + requireNonNull(bundleContext); CountDownLatch countDownLatch = new CountDownLatch(getCardinality()); ServiceTracker tracker = new ServiceTracker<>(bundleContext, getFilter(), diff --git a/org.osgi.test.junit4/src/main/java/org/osgi/test/junit4/context/BundleContextRule.java b/org.osgi.test.junit4/src/main/java/org/osgi/test/junit4/context/BundleContextRule.java index f7416942..ebaec86c 100644 --- a/org.osgi.test.junit4/src/main/java/org/osgi/test/junit4/context/BundleContextRule.java +++ b/org.osgi.test.junit4/src/main/java/org/osgi/test/junit4/context/BundleContextRule.java @@ -29,10 +29,10 @@ import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.Statement; import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; import org.osgi.test.common.annotation.InjectBundleContext; import org.osgi.test.common.annotation.InjectBundleInstaller; import org.osgi.test.common.context.CloseableBundleContext; +import org.osgi.test.common.context.ContextHelper; import org.osgi.test.common.install.BundleInstaller; /** @@ -71,8 +71,8 @@ public BundleContextRule init(Object testInstance) { return this; } - BundleContext bundleContext = CloseableBundleContext.proxy(FrameworkUtil.getBundle(testInstance.getClass()) - .getBundleContext()); + BundleContext bundleContext = CloseableBundleContext + .proxy(ContextHelper.getBundleContext(testInstance.getClass())); bundleInstaller = new BundleInstaller(bundleContext); diff --git a/org.osgi.test.junit4/src/main/java/org/osgi/test/junit4/service/ServiceRule.java b/org.osgi.test.junit4/src/main/java/org/osgi/test/junit4/service/ServiceRule.java index bdb16669..5dd898d3 100644 --- a/org.osgi.test.junit4/src/main/java/org/osgi/test/junit4/service/ServiceRule.java +++ b/org.osgi.test.junit4/src/main/java/org/osgi/test/junit4/service/ServiceRule.java @@ -36,8 +36,8 @@ import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.Statement; import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; import org.osgi.test.common.annotation.InjectService; +import org.osgi.test.common.context.ContextHelper; import org.osgi.test.common.list.ListSupplierDelegate; import org.osgi.test.common.service.ServiceAware; import org.osgi.test.common.service.ServiceConfiguration; @@ -66,9 +66,7 @@ public class ServiceRule implements AutoCloseable, MethodRule { private final Map, ServiceConfiguration> configurations = new ConcurrentHashMap<>(); public ServiceRule init(Object testInstance) { - BundleContext bundleContext = FrameworkUtil.getBundle(testInstance - .getClass()) - .getBundleContext(); + BundleContext bundleContext = ContextHelper.getBundleContext(testInstance.getClass()); List fields = findAnnotatedNonStaticFields(testInstance.getClass(), InjectService.class); fields.forEach(field -> { diff --git a/org.osgi.test.junit5/src/main/java/org/osgi/test/junit5/context/BundleContextExtension.java b/org.osgi.test.junit5/src/main/java/org/osgi/test/junit5/context/BundleContextExtension.java index cda039b7..9d424dac 100644 --- a/org.osgi.test.junit5/src/main/java/org/osgi/test/junit5/context/BundleContextExtension.java +++ b/org.osgi.test.junit5/src/main/java/org/osgi/test/junit5/context/BundleContextExtension.java @@ -25,9 +25,9 @@ import org.junit.jupiter.api.extension.ExtensionContext.Store.CloseableResource; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; import org.osgi.test.common.annotation.InjectBundleContext; import org.osgi.test.common.context.CloseableBundleContext; +import org.osgi.test.common.context.ContextHelper; import org.osgi.test.common.inject.TargetType; import org.osgi.test.common.install.BundleInstaller; import org.osgi.test.junit5.inject.InjectingExtension; @@ -94,8 +94,7 @@ private static BundleContext getParentBundleContext(ExtensionContext extensionCo .filter(context -> context.getTestClass() .isPresent()) .map(BundleContextExtension::getBundleContext) - .orElseGet(() -> FrameworkUtil.getBundle(extensionContext.getRequiredTestClass()) - .getBundleContext()); + .orElseGet(() -> ContextHelper.getBundleContext(extensionContext.getRequiredTestClass())); return parentContext; } @@ -130,11 +129,10 @@ static Store getStore(ExtensionContext extensionContext) { @Override protected Object resolveValue(TargetType targetType, InjectBundleContext injection, ExtensionContext extensionContext) throws ParameterResolutionException { - BundleContext retval = getBundleContext(extensionContext); - if (retval == null) { - throw new ParameterResolutionException( - "Bundle context was null. Check that you are running your test in an OSGi framework."); + try { + return getBundleContext(extensionContext); + } catch (IllegalStateException e) { + throw new ParameterResolutionException("No BundleContext available", e); } - return retval; } }