Skip to content

Commit

Permalink
Merge pull request #796 from stbischof/confann
Browse files Browse the repository at this point in the history
[cm] use Config Annotations on custom Annotations
  • Loading branch information
timothyjward authored Feb 12, 2024
2 parents c088997 + e803bf9 commit 2bf2b1a
Show file tree
Hide file tree
Showing 5 changed files with 463 additions and 69 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*******************************************************************************
* 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.junit5.cm;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Predicate;

import org.osgi.test.common.annotation.config.WithConfiguration;
import org.osgi.test.common.annotation.config.WithConfigurations;
import org.osgi.test.common.annotation.config.WithFactoryConfiguration;
import org.osgi.test.common.annotation.config.WithFactoryConfigurations;

class AnnotationUtil {

private AnnotationUtil() {}

private static Predicate<Annotation> ANY_WITH_CONF_ANNNOTATIONS = t -> t.annotationType()
.equals(WithFactoryConfiguration.class)
|| t.annotationType()
.equals(WithFactoryConfigurations.class)
|| t.annotationType()
.equals(WithConfiguration.class)
|| t.annotationType()
.equals(WithConfigurations.class);

public static List<Annotation> findAllConfigAnnotations(AnnotatedElement annotatedElement) {
return findAllAnnotationsMatching(annotatedElement, ANY_WITH_CONF_ANNNOTATIONS);
}

private static List<Annotation> findAllAnnotationsMatching(AnnotatedElement annotatedElement,
Predicate<Annotation> test) {
final ArrayList<Annotation> found = new ArrayList<>();
findAllAnnotationsMatching(annotatedElement, test, found, new HashSet<>());
return found;
}

private static void findAllAnnotationsMatching(AnnotatedElement annotatedElement, Predicate<Annotation> test,
ArrayList<? super Annotation> found, Set<Entry<AnnotatedElement, Annotation>> visited) {
Annotation[] declaredAnnotations = annotatedElement.getDeclaredAnnotations();

for (Annotation ann : declaredAnnotations) {
if (isJavaLangAnnotation(ann) || isJunitAnnotation(ann)) {
continue;
}

if (visited.add(new AbstractMap.SimpleEntry<>(annotatedElement, ann))) {
findAllAnnotationsMatching(ann.annotationType(), test, found, visited);
}

if (test.test(ann)) {
found.add(ann);
}
}
}

private static boolean isJavaLangAnnotation(Annotation annotation) {

return annotation.annotationType()
.getName()
.startsWith("java.lang.annotation");
}

private static boolean isJunitAnnotation(Annotation annotation) {

return annotation.annotationType()
.getName()
.startsWith("org.junit");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public boolean update(Configuration configuration, Dictionary<String, Object> di
CountDownLatch latch = createCountdownLatchUpdate(configuration.getPid());
boolean updatedBecauseDifferent = configuration.updateIfDifferent(dictionary);
if (!updatedBecauseDifferent) {
updateMap.remove(configuration.getPid());
return true;
}
boolean isOk = latch.await(timeout, TimeUnit.MILLISECONDS);
Expand Down Expand Up @@ -72,16 +73,14 @@ public void configurationEvent(ConfigurationEvent event) {
String pid = event.getPid();
if (event.getType() == ConfigurationEvent.CM_UPDATED) {

CountDownLatch countDownLatch = updateMap.get(pid);
CountDownLatch countDownLatch = updateMap.remove(pid);
if (countDownLatch != null) {
updateMap.remove(pid);
countDownLatch.countDown();
}
} else if (event.getType() == ConfigurationEvent.CM_DELETED) {

CountDownLatch countDownLatch = deleteMap.get(pid);
CountDownLatch countDownLatch = deleteMap.remove(pid);
if (countDownLatch != null) {
deleteMap.remove(pid);
countDownLatch.countDown();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public void add(ConfigurationHolder holder) {
})
.findAny();

// if we habe a state, we can ignore later ons
// if we have a state, we can ignore later ons
if (!preStoresConfig.isPresent()) {
holders.add(holder);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@
import static java.util.Collections.singletonList;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.AfterEachCallback;
Expand Down Expand Up @@ -66,12 +68,12 @@ public ConfigurationExtension() {
super(InjectConfiguration.class);
}

private static final String STORE_CONFIG_HANDLER = "store.config.handler";
private static final String STORE_CONFIG_HANDLER_REG = "store.config.handler.reg";
private static final String STORE_CONFIG_HANDLER = "store.config.handler";
private static final String STORE_CONFIG_HANDLER_REG = "store.config.handler.reg";
private static final String STORE_CONFIGURATION_CLASS_KEY = "store.configurationAdmin.class";
private static final String STORE_CONFIGURATION_BA_KEY = "store.configurationAdmin.beforeAll";
private static final String STORE_CONFIGURATION_BE_KEY = "store.configurationAdmin.beforeEach";
private static final String STORE_CONFIGURATION_TEST_KEY = "store.configurationAdmin.test";
private static final String STORE_CONFIGURATION_TEST_KEY = "store.configurationAdmin.test";

private static ExtensionContext DO_NOT_USE_CONTEXT;

Expand All @@ -86,8 +88,7 @@ private static BlockingConfigurationHandler getBlockingConfigurationHandler(Exte
BlockingConfigurationHandlerImpl impl = store.getOrComputeIfAbsent(STORE_CONFIG_HANDLER,
y -> new BlockingConfigurationHandlerImpl(), BlockingConfigurationHandlerImpl.class);
ServiceRegistration<?> svc = store.getOrComputeIfAbsent(STORE_CONFIG_HANDLER_REG,
y -> BundleContextExtension.getBundleContext(extensionContext)
.registerService(ConfigurationListener.class, impl, null), ServiceRegistration.class);
y -> BundleContextExtension.getBundleContext(extensionContext).registerService(ConfigurationListener.class, impl, null), ServiceRegistration.class);
return impl;
}

Expand Down Expand Up @@ -143,8 +144,7 @@ public void afterTestExecution(ExtensionContext extensionContext) throws Excepti
}

private void clearConfigurations(ExtensionContext extensionContext, String key) {
ConfigCloseableResource resource = getStore(extensionContext).remove(key,
ConfigCloseableResource.class);
ConfigCloseableResource resource = getStore(extensionContext).remove(key, ConfigCloseableResource.class);
if (resource != null) {
try {
resource.close();
Expand Down Expand Up @@ -174,8 +174,7 @@ private ConfigurationHolder handleWithConfiguration(ExtensionContext context, Wi
configAnnotation.location());
}

updateConfigurationRespectNew(context, configuration,
PropertiesConverter.of(configAnnotation.properties()),
updateConfigurationRespectNew(context, configuration, PropertiesConverter.of(configAnnotation.properties()),
configBefore == null);

return new ConfigurationHolder(ConfigurationCopy.of(configuration), copyOfBefore);
Expand All @@ -190,7 +189,7 @@ private ConfigurationHolder handleWithFactoryConfiguration(ExtensionContext cont

try {
Configuration configBefore = ConfigUtil.getConfigsByServicePid(configurationAdmin,
configAnnotation.factoryPid() + "~" + configAnnotation.name());
configAnnotation.factoryPid() + "~" + configAnnotation.name(), 0l);

Optional<ConfigurationCopy> copyOfBefore = createConfigurationCopy(configBefore);

Expand Down Expand Up @@ -316,8 +315,7 @@ protected Object resolveValue(TargetType targetType, InjectConfiguration injectC
break;
case 4 :
configurationHolder = handleWithFactoryConfiguration(extensionContext,
injectConfiguration.withFactoryConfig(),
configurationAdmin(extensionContext));
injectConfiguration.withFactoryConfig(), configurationAdmin(extensionContext));
try {
configuration = ConfigUtil.getConfigsByServicePid(configurationAdmin(extensionContext),
configurationHolder.getConfiguration()
Expand Down Expand Up @@ -376,62 +374,43 @@ private String getFinestScopeKey(ExtensionContext extensionContext) {
}

private List<ConfigurationHolder> handleAnnotationsOnActiveElement(ExtensionContext extensionContext) {
List<ConfigurationHolder> list = new ArrayList<ConfigurationHolder>();
list.addAll(handleWithConfigurations(extensionContext));
list.addAll(handleWithConfiguration(extensionContext));
list.addAll(handleWithFactoryConfigurations(extensionContext));
list.addAll(handleWithFactoryConfiguration(extensionContext));
return list;
}

private List<ConfigurationHolder> handleWithFactoryConfiguration(ExtensionContext extensionContext) {
ConfigurationAdmin ca = configurationAdmin(extensionContext);
List<ConfigurationHolder> list = new ArrayList<ConfigurationHolder>();
extensionContext.getElement()
.map(element -> element.getAnnotation(WithFactoryConfiguration.class))
.ifPresent(
factoryConfigAnnotation -> list
.add(handleWithFactoryConfiguration(extensionContext, factoryConfigAnnotation, ca)));
return list;
return extensionContext.getElement()
.map(AnnotationUtil::findAllConfigAnnotations)
.orElse(emptyList())
.stream()
.flatMap(annotation -> handleConfiguration(extensionContext, annotation, ca).stream())
.collect(Collectors.toList());
}

private List<ConfigurationHolder> handleWithFactoryConfigurations(ExtensionContext extensionContext) {
ConfigurationAdmin ca = configurationAdmin(extensionContext);
List<ConfigurationHolder> list = new ArrayList<ConfigurationHolder>();
extensionContext.getElement()
.map(element -> element.getAnnotation(WithFactoryConfigurations.class))
.map(WithFactoryConfigurations::value)
.ifPresent(factoryConfigAnnotations -> {
for (WithFactoryConfiguration factoryConfigAnnotation : factoryConfigAnnotations) {
list.add(handleWithFactoryConfiguration(extensionContext, factoryConfigAnnotation, ca));
}
});
return list;
private List<ConfigurationHolder> handleConfiguration(ExtensionContext extensionContext, Annotation an,
ConfigurationAdmin ca) {

}
ArrayList<ConfigurationHolder> configHolders = new ArrayList<>();
if (an instanceof WithConfigurations) {

private List<ConfigurationHolder> handleWithConfiguration(ExtensionContext extensionContext) {
ConfigurationAdmin ca = configurationAdmin(extensionContext);
List<ConfigurationHolder> list = new ArrayList<ConfigurationHolder>();
WithConfigurations withConfigurations = (WithConfigurations) an;
for (WithConfiguration factoryConfigAnnotation : withConfigurations.value()) {
configHolders.add(handleWithConfiguration(extensionContext, factoryConfigAnnotation, ca));

extensionContext.getElement()
.map(element -> element.getAnnotation(WithConfiguration.class))
.ifPresent(configAnnotation -> list.add(handleWithConfiguration(extensionContext, configAnnotation, ca)));
return list;
}
}

private List<ConfigurationHolder> handleWithConfigurations(ExtensionContext extensionContext) {
ConfigurationAdmin ca = configurationAdmin(extensionContext);
List<ConfigurationHolder> list = new ArrayList<ConfigurationHolder>();
extensionContext.getElement()
.map(element -> element.getAnnotation(WithConfigurations.class))
.map(WithConfigurations::value)
.ifPresent((configAnnotations -> {
for (WithConfiguration configAnnotation : configAnnotations) {
list.add(handleWithConfiguration(extensionContext, configAnnotation, ca));
}
}));
return list;
} else if (an instanceof WithConfiguration) {

configHolders.add(handleWithConfiguration(extensionContext, (WithConfiguration) an, ca));

} else if (an instanceof WithFactoryConfigurations) {

WithFactoryConfigurations withFactoryConfigurations = (WithFactoryConfigurations) an;
for (WithFactoryConfiguration factoryConfigAnnotation : withFactoryConfigurations.value()) {
configHolders.add(handleWithFactoryConfiguration(extensionContext, factoryConfigAnnotation, ca));
}

} else if (an instanceof WithFactoryConfiguration) {

configHolders.add(handleWithFactoryConfiguration(extensionContext, (WithFactoryConfiguration) an, ca));
}
return configHolders;
}

static Store getStore(ExtensionContext extensionContext) {
Expand Down Expand Up @@ -471,9 +450,8 @@ public void updateConfigurationRespectNew(Configuration configurationToBeUpdated
}

private void updateConfigurationRespectNew(ExtensionContext extensionContext,
Configuration configurationToBeUpdated,
Dictionary<String, Object> newConfigurationProperties, boolean isNewConfiguration)
throws InterruptedException, IOException {
Configuration configurationToBeUpdated, Dictionary<String, Object> newConfigurationProperties,
boolean isNewConfiguration) throws InterruptedException, IOException {
if (configurationToBeUpdated != null) {
BlockingConfigurationHandler blockingConfigHandler = getBlockingConfigurationHandler(extensionContext);
if (newConfigurationProperties != null
Expand Down
Loading

0 comments on commit 2bf2b1a

Please sign in to comment.