You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ss...@apache.org on 2021/12/22 22:34:26 UTC
[sling-org-apache-sling-models-caconfig] branch master updated: SLING-7256 Sling Models injector for CAConfig (#1)
This is an automated email from the ASF dual-hosted git repository.
sseifert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-models-caconfig.git
The following commit(s) were added to refs/heads/master by this push:
new fcff806 SLING-7256 Sling Models injector for CAConfig (#1)
fcff806 is described below
commit fcff806e6aab1f791a5a52cd55997a851bb435ce
Author: Stefan Seifert <st...@users.noreply.github.com>
AuthorDate: Wed Dec 22 23:34:23 2021 +0100
SLING-7256 Sling Models injector for CAConfig (#1)
---
pom.xml | 63 ++++--
.../annotations/ContextAwareConfiguration.java | 57 +++++
.../caconfig/{ => annotations}/package-info.java | 2 +-
.../ContextAwareConfigurationInjector.java | 196 +++++++++++++++++
.../ContextAwareConfigurationProcessor.java} | 21 +-
.../caconfig/example/caconfig/ListConfig.java} | 15 +-
.../caconfig/example/caconfig/SingleConfig.java} | 15 +-
.../caconfig/model/ConfigurationValuesModel.java | 58 +++++
.../example/model/InvalidAnnotationListModel.java} | 22 +-
.../example/model/InvalidAnnotationModel.java} | 20 +-
.../example/model/InvalidInjectModel.java} | 24 +-
.../caconfig/example/model/InvalidSetModel.java} | 23 +-
.../example/model/ListConfigAdaptModel.java | 57 +++++
.../caconfig/example/model/ListConfigGetter.java} | 15 +-
.../caconfig/example/model/ListConfigModel.java | 57 +++++
.../example/model/ListConfigValueMapModel.java | 57 +++++
.../example/model/SingleConfigAdaptModel.java} | 21 +-
.../example/model/SingleConfigGetter.java} | 8 +-
.../caconfig/example/model/SingleConfigModel.java} | 22 +-
.../example/model/SingleConfigValueMapModel.java} | 21 +-
.../ContextAwareConfigurationInjectorTest.java | 243 +++++++++++++++++++++
21 files changed, 959 insertions(+), 58 deletions(-)
diff --git a/pom.xml b/pom.xml
index a5d6f19..8bbc630 100644
--- a/pom.xml
+++ b/pom.xml
@@ -46,30 +46,55 @@
<dependencies>
<dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.annotation.versioning</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.service.component.annotations</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.service.metatype.annotations</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.api</artifactId>
+ <version>2.16.4</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.models.api</artifactId>
- <version>1.3.0</version>
+ <version>1.3.8</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.caconfig.api</artifactId>
- <version>1.0.0</version>
+ <version>1.1.2</version>
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.annotation.versioning</artifactId>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.caconfig.spi</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.service.component.annotations</artifactId>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.caconfig.impl</artifactId>
+ <version>1.6.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.service.metatype.annotations</artifactId>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>3.4</version>
<scope>provided</scope>
</dependency>
@@ -79,12 +104,6 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.apache.sling</groupId>
- <artifactId>org.apache.sling.api</artifactId>
- <version>2.4.0</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
@@ -103,7 +122,7 @@
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
- <artifactId>org.apache.sling.testing.osgi-mock.junit5</artifactId>
+ <artifactId>org.apache.sling.testing.sling-mock.junit5</artifactId>
<version>3.2.2</version>
<scope>test</scope>
</dependency>
@@ -114,14 +133,16 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-core</artifactId>
- <version>4.2.0</version>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.testing.caconfig-mock-plugin</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ <scope>test</scope>
</dependency>
<dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-junit-jupiter</artifactId>
- <version>4.2.0</version>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <version>1.3.2</version>
+ <scope>test</scope>
</dependency>
</dependencies>
diff --git a/src/main/java/org/apache/sling/models/caconfig/annotations/ContextAwareConfiguration.java b/src/main/java/org/apache/sling/models/caconfig/annotations/ContextAwareConfiguration.java
new file mode 100644
index 0000000..0c527b5
--- /dev/null
+++ b/src/main/java/org/apache/sling/models/caconfig/annotations/ContextAwareConfiguration.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package org.apache.sling.models.caconfig.annotations;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import org.apache.sling.models.annotations.Source;
+import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy;
+import org.apache.sling.models.spi.injectorspecific.InjectAnnotation;
+
+/**
+ * Annotation to be used on either methods, fields or constructor parameters to let Sling Models inject a context-aware configuration.
+ * The annotation supports the same features and semantics as {@link org.apache.sling.caconfig.ConfigurationBuilder}.
+ * For configuration collections, you can use arrays, {@link java.util.List} or {@link java.util.Collection} variables.
+ */
+@Target({ METHOD, FIELD, PARAMETER })
+@Retention(RUNTIME)
+@InjectAnnotation
+@Source("caconfig")
+public @interface ContextAwareConfiguration {
+
+ /**
+ * Define configuration name.
+ * Optional if used together with a context-aware configuration annotation class, which implictely defines a configuration name.
+ * @return Configuration name
+ */
+ public String name() default "";
+
+ /**
+ * if set to REQUIRED injection is mandatory, if set to OPTIONAL injection is optional, in case of DEFAULT
+ * the standard annotations ({@link org.apache.sling.models.annotations.Optional}, {@link org.apache.sling.models.annotations.Required}) are used.
+ * If even those are not available the default injection strategy defined on the {@link org.apache.sling.models.annotations.Model} applies.
+ * Default value = DEFAULT.
+ */
+ public InjectionStrategy injectionStrategy() default InjectionStrategy.DEFAULT;
+
+}
diff --git a/src/main/java/org/apache/sling/models/caconfig/package-info.java b/src/main/java/org/apache/sling/models/caconfig/annotations/package-info.java
similarity index 89%
copy from src/main/java/org/apache/sling/models/caconfig/package-info.java
copy to src/main/java/org/apache/sling/models/caconfig/annotations/package-info.java
index b5cef1e..35cfc58 100644
--- a/src/main/java/org/apache/sling/models/caconfig/package-info.java
+++ b/src/main/java/org/apache/sling/models/caconfig/annotations/package-info.java
@@ -18,6 +18,6 @@
*/
@Version("1.0.0")
-package org.apache.sling.models.caconfig;
+package org.apache.sling.models.caconfig.annotations;
import org.osgi.annotation.versioning.Version;
\ No newline at end of file
diff --git a/src/main/java/org/apache/sling/models/caconfig/impl/injectors/ContextAwareConfigurationInjector.java b/src/main/java/org/apache/sling/models/caconfig/impl/injectors/ContextAwareConfigurationInjector.java
new file mode 100644
index 0000000..ff28cbf
--- /dev/null
+++ b/src/main/java/org/apache/sling/models/caconfig/impl/injectors/ContextAwareConfigurationInjector.java
@@ -0,0 +1,196 @@
+/*
+ * 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.
+ */
+package org.apache.sling.models.caconfig.impl.injectors;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Array;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.caconfig.ConfigurationBuilder;
+import org.apache.sling.caconfig.ConfigurationResolveException;
+import org.apache.sling.caconfig.ConfigurationResolver;
+import org.apache.sling.caconfig.annotation.Configuration;
+import org.apache.sling.caconfig.management.multiplexer.ConfigurationInjectResourceDetectionStrategyMultiplexer;
+import org.apache.sling.models.caconfig.annotations.ContextAwareConfiguration;
+import org.apache.sling.models.spi.AcceptsNullName;
+import org.apache.sling.models.spi.DisposalCallbackRegistry;
+import org.apache.sling.models.spi.Injector;
+import org.apache.sling.models.spi.injectorspecific.InjectAnnotationProcessor2;
+import org.apache.sling.models.spi.injectorspecific.StaticInjectAnnotationProcessorFactory;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.propertytypes.ServiceRanking;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(service = { Injector.class, StaticInjectAnnotationProcessorFactory.class, AcceptsNullName.class })
+@ServiceRanking(6000)
+public class ContextAwareConfigurationInjector implements Injector, StaticInjectAnnotationProcessorFactory, AcceptsNullName {
+
+ private static final Logger log = LoggerFactory.getLogger(ContextAwareConfigurationInjector.class);
+
+ @Reference
+ private ConfigurationResolver configurationResolver;
+ @Reference
+ private ConfigurationInjectResourceDetectionStrategyMultiplexer configurationInjectResourceDetectionStrategyMultiplexer;
+
+ @Override
+ public @NotNull String getName() {
+ return "caconfig";
+ }
+
+ @Override
+ public InjectAnnotationProcessor2 createAnnotationProcessor(AnnotatedElement element) {
+ // check if the element has the expected annotation
+ ContextAwareConfiguration annotation = getAnnotation(element);
+ if (annotation != null) {
+ return new ContextAwareConfigurationProcessor(annotation);
+ }
+ return null;
+ }
+
+ @Override
+ public Object getValue(@NotNull Object adaptable, String name,
+ @NotNull Type declaredType, @NotNull AnnotatedElement element,
+ @NotNull DisposalCallbackRegistry callbackRegistry) {
+
+ ContextAwareConfiguration annotation = getAnnotation(element);
+ if (annotation == null) {
+ // support injections only with explicit @ContextAwareConfiguration annotation
+ log.warn("Injection only supported using @ContextAwareConfiguration annotation.");
+ return null;
+ }
+
+ // get resource
+ Resource resource = getResource(adaptable);
+ if (resource == null) {
+ log.warn("Unable to get resource from {}", adaptable);
+ return null;
+ }
+
+ // initialize configuration builder
+ ConfigurationBuilder configurationBuilder = configurationResolver.get(resource);
+ if (StringUtils.isNotBlank(annotation.name())) {
+ configurationBuilder = configurationBuilder.name(annotation.name());
+ }
+
+ // detect from declared type if a single configuration or configuration collection is requested and return the configuration
+ if (declaredType instanceof Class) {
+ Class<?> clazz = (Class<?>)declaredType;
+ if (clazz.isArray()) {
+ Collection<?> result = getConfigurationCollection(configurationBuilder, clazz.getComponentType());
+ Object array = Array.newInstance(clazz.getComponentType(), result.size());
+ Iterator<?> resultIterator = result.iterator();
+ int i = 0;
+ while (resultIterator.hasNext()) {
+ Array.set(array, i++, resultIterator.next());
+ }
+ return array;
+ }
+ else {
+ return getConfiguration(configurationBuilder, clazz);
+ }
+ }
+ else if (declaredType instanceof ParameterizedType) {
+ ParameterizedType parameterizedType = (ParameterizedType)declaredType;
+ if (parameterizedType.getActualTypeArguments().length != 1) {
+ return null;
+ }
+ Class<?> collectionType = (Class<?>) parameterizedType.getRawType();
+ if (!(collectionType.equals(Collection.class) || collectionType.equals(List.class))) {
+ return null;
+ }
+ Class<?> clazz = (Class<?>) parameterizedType.getActualTypeArguments()[0];
+ Collection<?> result = getConfigurationCollection(configurationBuilder, clazz);
+ if (collectionType.equals(List.class)) {
+ return new ArrayList<>(result);
+ }
+ else {
+ return result;
+ }
+ }
+ else {
+ log.warn("Cannot handle type {}", declaredType);
+ return null;
+ }
+ }
+
+ private @Nullable ContextAwareConfiguration getAnnotation(AnnotatedElement element) {
+ return element.getAnnotation(ContextAwareConfiguration.class);
+ }
+
+ private @Nullable Resource getResource(@NotNull Object adaptable) {
+ if (adaptable instanceof Resource) {
+ return (Resource)adaptable;
+ }
+ if (adaptable instanceof SlingHttpServletRequest) {
+ SlingHttpServletRequest request = (SlingHttpServletRequest)adaptable;
+ Resource resource = configurationInjectResourceDetectionStrategyMultiplexer.detectResource(request);
+ if (resource == null) {
+ resource = request.getResource();
+ }
+ return resource;
+ }
+ return null;
+ }
+
+ private @Nullable Object getConfiguration(@NotNull ConfigurationBuilder configurationBuilder, @NotNull Class<?> clazz) {
+ try {
+ if (clazz.equals(ValueMap.class)) {
+ return configurationBuilder.asValueMap();
+ }
+ if (isContextAwareConfigAnnotationClass(clazz)) {
+ return configurationBuilder.as(clazz);
+ }
+ return configurationBuilder.asAdaptable(clazz);
+ }
+ catch (ConfigurationResolveException ex) {
+ throw new ConfigurationResolveException("Class " + clazz.getName() + ": " + ex.getMessage(), ex);
+ }
+ }
+
+ private @NotNull Collection<?> getConfigurationCollection(@NotNull ConfigurationBuilder configurationBuilder, @NotNull Class<?> clazz) {
+ try {
+ if (clazz.equals(ValueMap.class)) {
+ return configurationBuilder.asValueMapCollection();
+ }
+ if (isContextAwareConfigAnnotationClass(clazz)) {
+ return configurationBuilder.asCollection(clazz);
+ }
+ return configurationBuilder.asAdaptableCollection(clazz);
+ }
+ catch (ConfigurationResolveException ex) {
+ throw new ConfigurationResolveException("Class " + clazz.getName() + ": " + ex.getMessage(), ex);
+ }
+ }
+
+ private boolean isContextAwareConfigAnnotationClass(Class<?> clazz) {
+ return clazz.isAnnotation() && clazz.isAnnotationPresent(Configuration.class);
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/models/caconfig/package-info.java b/src/main/java/org/apache/sling/models/caconfig/impl/injectors/ContextAwareConfigurationProcessor.java
similarity index 53%
copy from src/main/java/org/apache/sling/models/caconfig/package-info.java
copy to src/main/java/org/apache/sling/models/caconfig/impl/injectors/ContextAwareConfigurationProcessor.java
index b5cef1e..30bcec4 100644
--- a/src/main/java/org/apache/sling/models/caconfig/package-info.java
+++ b/src/main/java/org/apache/sling/models/caconfig/impl/injectors/ContextAwareConfigurationProcessor.java
@@ -16,8 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.sling.models.caconfig.impl.injectors;
-@Version("1.0.0")
-package org.apache.sling.models.caconfig;
+import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy;
+import org.apache.sling.models.caconfig.annotations.ContextAwareConfiguration;
+import org.apache.sling.models.spi.injectorspecific.AbstractInjectAnnotationProcessor2;
-import org.osgi.annotation.versioning.Version;
\ No newline at end of file
+class ContextAwareConfigurationProcessor extends AbstractInjectAnnotationProcessor2 {
+
+ private final ContextAwareConfiguration annotation;
+
+ public ContextAwareConfigurationProcessor(ContextAwareConfiguration annotation) {
+ this.annotation = annotation;
+ }
+
+ @Override
+ public InjectionStrategy getInjectionStrategy() {
+ return annotation.injectionStrategy();
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/models/caconfig/package-info.java b/src/test/java/org/apache/sling/models/caconfig/example/caconfig/ListConfig.java
similarity index 75%
copy from src/main/java/org/apache/sling/models/caconfig/package-info.java
copy to src/test/java/org/apache/sling/models/caconfig/example/caconfig/ListConfig.java
index b5cef1e..104419d 100644
--- a/src/main/java/org/apache/sling/models/caconfig/package-info.java
+++ b/src/test/java/org/apache/sling/models/caconfig/example/caconfig/ListConfig.java
@@ -16,8 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.sling.models.caconfig.example.caconfig;
-@Version("1.0.0")
-package org.apache.sling.models.caconfig;
+import org.apache.sling.caconfig.annotation.Configuration;
-import org.osgi.annotation.versioning.Version;
\ No newline at end of file
+@Configuration(collection = true)
+public @interface ListConfig {
+
+ String stringParam();
+
+ int intParam() default 5;
+
+ boolean boolParam();
+
+}
diff --git a/src/main/java/org/apache/sling/models/caconfig/package-info.java b/src/test/java/org/apache/sling/models/caconfig/example/caconfig/SingleConfig.java
similarity index 74%
copy from src/main/java/org/apache/sling/models/caconfig/package-info.java
copy to src/test/java/org/apache/sling/models/caconfig/example/caconfig/SingleConfig.java
index b5cef1e..61ee707 100644
--- a/src/main/java/org/apache/sling/models/caconfig/package-info.java
+++ b/src/test/java/org/apache/sling/models/caconfig/example/caconfig/SingleConfig.java
@@ -16,8 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.sling.models.caconfig.example.caconfig;
-@Version("1.0.0")
-package org.apache.sling.models.caconfig;
+import org.apache.sling.caconfig.annotation.Configuration;
-import org.osgi.annotation.versioning.Version;
\ No newline at end of file
+@Configuration(name = "testSingleConfig")
+public @interface SingleConfig {
+
+ String stringParam();
+
+ int intParam() default 5;
+
+ boolean boolParam();
+
+}
diff --git a/src/test/java/org/apache/sling/models/caconfig/example/caconfig/model/ConfigurationValuesModel.java b/src/test/java/org/apache/sling/models/caconfig/example/caconfig/model/ConfigurationValuesModel.java
new file mode 100644
index 0000000..664463d
--- /dev/null
+++ b/src/test/java/org/apache/sling/models/caconfig/example/caconfig/model/ConfigurationValuesModel.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+package org.apache.sling.models.caconfig.example.caconfig.model;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.DefaultInjectionStrategy;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
+
+/**
+ * This model can be used to adapt configuration resource to a model.
+ */
+@Model(adaptables = Resource.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
+public class ConfigurationValuesModel {
+
+ @ValueMapValue
+ private String stringParam;
+ @ValueMapValue
+ private int intParam;
+ @ValueMapValue
+ private boolean boolParam;
+
+ public String getStringParam() {
+ return stringParam;
+ }
+ public void setStringParam(String stringParam) {
+ this.stringParam = stringParam;
+ }
+ public int getIntParam() {
+ return intParam;
+ }
+ public void setIntParam(int intParam) {
+ this.intParam = intParam;
+ }
+ public boolean isBoolParam() {
+ return boolParam;
+ }
+ public void setBoolParam(boolean boolParam) {
+ this.boolParam = boolParam;
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/models/caconfig/package-info.java b/src/test/java/org/apache/sling/models/caconfig/example/model/InvalidAnnotationListModel.java
similarity index 56%
copy from src/main/java/org/apache/sling/models/caconfig/package-info.java
copy to src/test/java/org/apache/sling/models/caconfig/example/model/InvalidAnnotationListModel.java
index b5cef1e..71f2571 100644
--- a/src/main/java/org/apache/sling/models/caconfig/package-info.java
+++ b/src/test/java/org/apache/sling/models/caconfig/example/model/InvalidAnnotationListModel.java
@@ -16,8 +16,24 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.sling.models.caconfig.example.model;
-@Version("1.0.0")
-package org.apache.sling.models.caconfig;
+import java.util.List;
-import org.osgi.annotation.versioning.Version;
\ No newline at end of file
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.caconfig.annotations.ContextAwareConfiguration;
+
+@Model(adaptables = { SlingHttpServletRequest.class, Resource.class })
+public class InvalidAnnotationListModel {
+
+ // "Model" is not a valid caconfig annotation
+ @ContextAwareConfiguration
+ private List<Model> configList;
+
+ public List<Model> getConfigList() {
+ return configList;
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/models/caconfig/package-info.java b/src/test/java/org/apache/sling/models/caconfig/example/model/InvalidAnnotationModel.java
similarity index 58%
copy from src/main/java/org/apache/sling/models/caconfig/package-info.java
copy to src/test/java/org/apache/sling/models/caconfig/example/model/InvalidAnnotationModel.java
index b5cef1e..f17ed25 100644
--- a/src/main/java/org/apache/sling/models/caconfig/package-info.java
+++ b/src/test/java/org/apache/sling/models/caconfig/example/model/InvalidAnnotationModel.java
@@ -16,8 +16,22 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.sling.models.caconfig.example.model;
-@Version("1.0.0")
-package org.apache.sling.models.caconfig;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.caconfig.annotations.ContextAwareConfiguration;
-import org.osgi.annotation.versioning.Version;
\ No newline at end of file
+@Model(adaptables = { SlingHttpServletRequest.class, Resource.class })
+public class InvalidAnnotationModel {
+
+ // "Model" is not a valid caconfig annotation
+ @ContextAwareConfiguration
+ private Model config;
+
+ public Model getConfig() {
+ return config;
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/models/caconfig/package-info.java b/src/test/java/org/apache/sling/models/caconfig/example/model/InvalidInjectModel.java
similarity index 54%
copy from src/main/java/org/apache/sling/models/caconfig/package-info.java
copy to src/test/java/org/apache/sling/models/caconfig/example/model/InvalidInjectModel.java
index b5cef1e..3d98300 100644
--- a/src/main/java/org/apache/sling/models/caconfig/package-info.java
+++ b/src/test/java/org/apache/sling/models/caconfig/example/model/InvalidInjectModel.java
@@ -16,8 +16,26 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.sling.models.caconfig.example.model;
-@Version("1.0.0")
-package org.apache.sling.models.caconfig;
+import javax.inject.Inject;
-import org.osgi.annotation.versioning.Version;
\ No newline at end of file
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.Source;
+import org.apache.sling.models.caconfig.example.caconfig.SingleConfig;
+
+@Model(adaptables = { SlingHttpServletRequest.class, Resource.class })
+public class InvalidInjectModel {
+
+ // only injection with explicit annotation @ContextAwareConfiguration is supported
+ @Inject
+ @Source("caconfig")
+ private SingleConfig config;
+
+ public SingleConfig getConfig() {
+ return config;
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/models/caconfig/package-info.java b/src/test/java/org/apache/sling/models/caconfig/example/model/InvalidSetModel.java
similarity index 54%
copy from src/main/java/org/apache/sling/models/caconfig/package-info.java
copy to src/test/java/org/apache/sling/models/caconfig/example/model/InvalidSetModel.java
index b5cef1e..615cdc3 100644
--- a/src/main/java/org/apache/sling/models/caconfig/package-info.java
+++ b/src/test/java/org/apache/sling/models/caconfig/example/model/InvalidSetModel.java
@@ -16,8 +16,25 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.sling.models.caconfig.example.model;
-@Version("1.0.0")
-package org.apache.sling.models.caconfig;
+import java.util.Set;
-import org.osgi.annotation.versioning.Version;
\ No newline at end of file
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.caconfig.annotations.ContextAwareConfiguration;
+import org.apache.sling.models.caconfig.example.caconfig.ListConfig;
+
+@Model(adaptables = { SlingHttpServletRequest.class, Resource.class })
+public class InvalidSetModel {
+
+ // Set is not supported as collection type
+ @ContextAwareConfiguration
+ private Set<ListConfig> configList;
+
+ public Set<ListConfig> getConfigList() {
+ return configList;
+ }
+
+}
diff --git a/src/test/java/org/apache/sling/models/caconfig/example/model/ListConfigAdaptModel.java b/src/test/java/org/apache/sling/models/caconfig/example/model/ListConfigAdaptModel.java
new file mode 100644
index 0000000..59838b2
--- /dev/null
+++ b/src/test/java/org/apache/sling/models/caconfig/example/model/ListConfigAdaptModel.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package org.apache.sling.models.caconfig.example.model;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.caconfig.annotations.ContextAwareConfiguration;
+import org.apache.sling.models.caconfig.example.caconfig.model.ConfigurationValuesModel;
+
+@Model(adaptables = { SlingHttpServletRequest.class, Resource.class })
+public class ListConfigAdaptModel implements ListConfigGetter<ConfigurationValuesModel> {
+
+ @ContextAwareConfiguration(name = "org.apache.sling.models.caconfig.example.caconfig.ListConfig")
+ private List<ConfigurationValuesModel> configList;
+
+ @ContextAwareConfiguration(name = "org.apache.sling.models.caconfig.example.caconfig.ListConfig")
+ private Collection<ConfigurationValuesModel> configCollection;
+
+ @ContextAwareConfiguration(name = "org.apache.sling.models.caconfig.example.caconfig.ListConfig")
+ private ConfigurationValuesModel[] configArray;
+
+ @Override
+ public List<ConfigurationValuesModel> getConfigList() {
+ return configList;
+ }
+
+ @Override
+ public Collection<ConfigurationValuesModel> getConfigCollection() {
+ return configCollection;
+ }
+
+ @Override
+ public ConfigurationValuesModel[] getConfigArray() {
+ return configArray;
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/models/caconfig/package-info.java b/src/test/java/org/apache/sling/models/caconfig/example/model/ListConfigGetter.java
similarity index 76%
copy from src/main/java/org/apache/sling/models/caconfig/package-info.java
copy to src/test/java/org/apache/sling/models/caconfig/example/model/ListConfigGetter.java
index b5cef1e..a552c7a 100644
--- a/src/main/java/org/apache/sling/models/caconfig/package-info.java
+++ b/src/test/java/org/apache/sling/models/caconfig/example/model/ListConfigGetter.java
@@ -16,8 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.sling.models.caconfig.example.model;
-@Version("1.0.0")
-package org.apache.sling.models.caconfig;
+import java.util.Collection;
+import java.util.List;
-import org.osgi.annotation.versioning.Version;
\ No newline at end of file
+public interface ListConfigGetter<T> {
+
+ List<T> getConfigList();
+
+ Collection<T> getConfigCollection();
+
+ T[] getConfigArray();
+
+}
diff --git a/src/test/java/org/apache/sling/models/caconfig/example/model/ListConfigModel.java b/src/test/java/org/apache/sling/models/caconfig/example/model/ListConfigModel.java
new file mode 100644
index 0000000..ecc65df
--- /dev/null
+++ b/src/test/java/org/apache/sling/models/caconfig/example/model/ListConfigModel.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package org.apache.sling.models.caconfig.example.model;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.caconfig.annotations.ContextAwareConfiguration;
+import org.apache.sling.models.caconfig.example.caconfig.ListConfig;
+
+@Model(adaptables = { SlingHttpServletRequest.class, Resource.class })
+public class ListConfigModel implements ListConfigGetter<ListConfig> {
+
+ @ContextAwareConfiguration
+ private List<ListConfig> configList;
+
+ @ContextAwareConfiguration
+ private Collection<ListConfig> configCollection;
+
+ @ContextAwareConfiguration
+ private ListConfig[] configArray;
+
+ @Override
+ public List<ListConfig> getConfigList() {
+ return configList;
+ }
+
+ @Override
+ public Collection<ListConfig> getConfigCollection() {
+ return configCollection;
+ }
+
+ @Override
+ public ListConfig[] getConfigArray() {
+ return configArray;
+ }
+
+}
diff --git a/src/test/java/org/apache/sling/models/caconfig/example/model/ListConfigValueMapModel.java b/src/test/java/org/apache/sling/models/caconfig/example/model/ListConfigValueMapModel.java
new file mode 100644
index 0000000..a83b6c4
--- /dev/null
+++ b/src/test/java/org/apache/sling/models/caconfig/example/model/ListConfigValueMapModel.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+package org.apache.sling.models.caconfig.example.model;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.caconfig.annotations.ContextAwareConfiguration;
+
+@Model(adaptables = { SlingHttpServletRequest.class, Resource.class })
+public class ListConfigValueMapModel implements ListConfigGetter<ValueMap> {
+
+ @ContextAwareConfiguration(name = "org.apache.sling.models.caconfig.example.caconfig.ListConfig")
+ private List<ValueMap> configList;
+
+ @ContextAwareConfiguration(name = "org.apache.sling.models.caconfig.example.caconfig.ListConfig")
+ private Collection<ValueMap> configCollection;
+
+ @ContextAwareConfiguration(name = "org.apache.sling.models.caconfig.example.caconfig.ListConfig")
+ private ValueMap[] configArray;
+
+ @Override
+ public List<ValueMap> getConfigList() {
+ return configList;
+ }
+
+ @Override
+ public Collection<ValueMap> getConfigCollection() {
+ return configCollection;
+ }
+
+ @Override
+ public ValueMap[] getConfigArray() {
+ return configArray;
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/models/caconfig/package-info.java b/src/test/java/org/apache/sling/models/caconfig/example/model/SingleConfigAdaptModel.java
similarity index 52%
copy from src/main/java/org/apache/sling/models/caconfig/package-info.java
copy to src/test/java/org/apache/sling/models/caconfig/example/model/SingleConfigAdaptModel.java
index b5cef1e..ccfaf50 100644
--- a/src/main/java/org/apache/sling/models/caconfig/package-info.java
+++ b/src/test/java/org/apache/sling/models/caconfig/example/model/SingleConfigAdaptModel.java
@@ -16,8 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.sling.models.caconfig.example.model;
-@Version("1.0.0")
-package org.apache.sling.models.caconfig;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.caconfig.annotations.ContextAwareConfiguration;
+import org.apache.sling.models.caconfig.example.caconfig.model.ConfigurationValuesModel;
-import org.osgi.annotation.versioning.Version;
\ No newline at end of file
+@Model(adaptables = { SlingHttpServletRequest.class, Resource.class })
+public class SingleConfigAdaptModel implements SingleConfigGetter<ConfigurationValuesModel> {
+
+ @ContextAwareConfiguration(name = "testSingleConfig")
+ private ConfigurationValuesModel config;
+
+ @Override
+ public ConfigurationValuesModel getConfig() {
+ return config;
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/models/caconfig/package-info.java b/src/test/java/org/apache/sling/models/caconfig/example/model/SingleConfigGetter.java
similarity index 87%
copy from src/main/java/org/apache/sling/models/caconfig/package-info.java
copy to src/test/java/org/apache/sling/models/caconfig/example/model/SingleConfigGetter.java
index b5cef1e..a69e327 100644
--- a/src/main/java/org/apache/sling/models/caconfig/package-info.java
+++ b/src/test/java/org/apache/sling/models/caconfig/example/model/SingleConfigGetter.java
@@ -16,8 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.sling.models.caconfig.example.model;
-@Version("1.0.0")
-package org.apache.sling.models.caconfig;
+public interface SingleConfigGetter<T> {
-import org.osgi.annotation.versioning.Version;
\ No newline at end of file
+ T getConfig();
+
+}
diff --git a/src/main/java/org/apache/sling/models/caconfig/package-info.java b/src/test/java/org/apache/sling/models/caconfig/example/model/SingleConfigModel.java
similarity index 52%
copy from src/main/java/org/apache/sling/models/caconfig/package-info.java
copy to src/test/java/org/apache/sling/models/caconfig/example/model/SingleConfigModel.java
index b5cef1e..1243232 100644
--- a/src/main/java/org/apache/sling/models/caconfig/package-info.java
+++ b/src/test/java/org/apache/sling/models/caconfig/example/model/SingleConfigModel.java
@@ -16,8 +16,24 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.sling.models.caconfig.example.model;
-@Version("1.0.0")
-package org.apache.sling.models.caconfig;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.caconfig.annotations.ContextAwareConfiguration;
+import org.apache.sling.models.caconfig.example.caconfig.SingleConfig;
-import org.osgi.annotation.versioning.Version;
\ No newline at end of file
+@Model(adaptables = { SlingHttpServletRequest.class, Resource.class, ResourceResolver.class })
+public class SingleConfigModel implements SingleConfigGetter<SingleConfig> {
+
+ @ContextAwareConfiguration
+ private SingleConfig config;
+
+ @Override
+ public SingleConfig getConfig() {
+ return config;
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/models/caconfig/package-info.java b/src/test/java/org/apache/sling/models/caconfig/example/model/SingleConfigValueMapModel.java
similarity index 55%
rename from src/main/java/org/apache/sling/models/caconfig/package-info.java
rename to src/test/java/org/apache/sling/models/caconfig/example/model/SingleConfigValueMapModel.java
index b5cef1e..10a8939 100644
--- a/src/main/java/org/apache/sling/models/caconfig/package-info.java
+++ b/src/test/java/org/apache/sling/models/caconfig/example/model/SingleConfigValueMapModel.java
@@ -16,8 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
+package org.apache.sling.models.caconfig.example.model;
-@Version("1.0.0")
-package org.apache.sling.models.caconfig;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.caconfig.annotations.ContextAwareConfiguration;
-import org.osgi.annotation.versioning.Version;
\ No newline at end of file
+@Model(adaptables = { SlingHttpServletRequest.class, Resource.class })
+public class SingleConfigValueMapModel implements SingleConfigGetter<ValueMap> {
+
+ @ContextAwareConfiguration(name = "testSingleConfig")
+ private ValueMap config;
+
+ @Override
+ public ValueMap getConfig() {
+ return config;
+ }
+
+}
diff --git a/src/test/java/org/apache/sling/models/caconfig/impl/injectors/ContextAwareConfigurationInjectorTest.java b/src/test/java/org/apache/sling/models/caconfig/impl/injectors/ContextAwareConfigurationInjectorTest.java
new file mode 100644
index 0000000..26f1e4b
--- /dev/null
+++ b/src/test/java/org/apache/sling/models/caconfig/impl/injectors/ContextAwareConfigurationInjectorTest.java
@@ -0,0 +1,243 @@
+/*
+ * 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.
+ */
+package org.apache.sling.models.caconfig.impl.injectors;
+
+import static org.apache.sling.testing.mock.caconfig.ContextPlugins.CACONFIG;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import java.util.List;
+import java.util.function.Function;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.adapter.Adaptable;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.caconfig.management.multiplexer.ConfigurationInjectResourceDetectionStrategyMultiplexer;
+import org.apache.sling.caconfig.spi.ConfigurationInjectResourceDetectionStrategy;
+import org.apache.sling.models.caconfig.example.caconfig.ListConfig;
+import org.apache.sling.models.caconfig.example.caconfig.SingleConfig;
+import org.apache.sling.models.caconfig.example.caconfig.model.ConfigurationValuesModel;
+import org.apache.sling.models.caconfig.example.model.InvalidAnnotationListModel;
+import org.apache.sling.models.caconfig.example.model.InvalidAnnotationModel;
+import org.apache.sling.models.caconfig.example.model.InvalidInjectModel;
+import org.apache.sling.models.caconfig.example.model.InvalidSetModel;
+import org.apache.sling.models.caconfig.example.model.ListConfigAdaptModel;
+import org.apache.sling.models.caconfig.example.model.ListConfigGetter;
+import org.apache.sling.models.caconfig.example.model.ListConfigModel;
+import org.apache.sling.models.caconfig.example.model.ListConfigValueMapModel;
+import org.apache.sling.models.caconfig.example.model.SingleConfigAdaptModel;
+import org.apache.sling.models.caconfig.example.model.SingleConfigGetter;
+import org.apache.sling.models.caconfig.example.model.SingleConfigModel;
+import org.apache.sling.models.caconfig.example.model.SingleConfigValueMapModel;
+import org.apache.sling.testing.mock.caconfig.MockContextAwareConfig;
+import org.apache.sling.testing.mock.sling.junit5.SlingContext;
+import org.apache.sling.testing.mock.sling.junit5.SlingContextBuilder;
+import org.apache.sling.testing.mock.sling.junit5.SlingContextExtension;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.osgi.framework.Constants;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+@ExtendWith(SlingContextExtension.class)
+class ContextAwareConfigurationInjectorTest {
+
+ private final SlingContext context = new SlingContextBuilder()
+ .plugin(CACONFIG)
+ .build();
+
+ @BeforeEach
+ void setUp() {
+ MockContextAwareConfig.registerAnnotationPackages(context, "org.apache.sling.models.caconfig.example.caconfig");
+ context.addModelsForPackage("org.apache.sling.models.caconfig.example.model");
+
+ context.create().resource("/content/region/site",
+ "sling:configRef", "/conf/region/site");
+
+ context.currentResource(context.create().resource("/content/region/site/en"));
+
+ MockContextAwareConfig.writeConfiguration(context, "/content/region/site", SingleConfig.class,
+ "stringParam", "value1");
+
+ MockContextAwareConfig.writeConfigurationCollection(context, "/content/region/site", ListConfig.class, ImmutableList.of(
+ ImmutableMap.<String,Object>of("stringParam", "item1"),
+ ImmutableMap.<String,Object>of("stringParam", "item2")));
+ }
+
+ @Test
+ void testSingleConfigModel_Request() {
+ assertSingleConfig(SingleConfigModel.class, context.request(), SingleConfig::stringParam);
+ }
+
+ @Test
+ void testSingleConfigModel_Request_WithConfigurationInjectResourceDetectionStrategy() {
+ // set another resource as current resource which has not caconfig applied
+ Resource otherCurrentResource = context.currentResource(context.create().resource("/content/region2/site2/en2"));
+ // register a custom ConfigurationInjectResourceDetectionStrategy which redirects to a resource with caconfig available
+ context.registerService(ConfigurationInjectResourceDetectionStrategy.class, new ConfigurationInjectResourceDetectionStrategy() {
+ @Override
+ @SuppressWarnings("null")
+ public @Nullable Resource detectResource(@NotNull SlingHttpServletRequest request) {
+ if (StringUtils.equals(request.getResource().getPath(), otherCurrentResource.getPath())) {
+ return context.resourceResolver().getResource("/content/region/site/en");
+ }
+ return null;
+ }
+ }, Constants.SERVICE_RANKING, 100);
+ assertSingleConfig(SingleConfigModel.class, context.request(), SingleConfig::stringParam);
+ }
+
+ @Test
+ void testSingleConfigModel_Request_WithConfigurationInjectResourceDetectionStrategy_NoStrategies() {
+ // simulate no registered strategies
+ context.registerService(ConfigurationInjectResourceDetectionStrategyMultiplexer.class, new ConfigurationInjectResourceDetectionStrategyMultiplexer() {
+ @Override
+ public @Nullable Resource detectResource(@NotNull SlingHttpServletRequest request) {
+ return null;
+ }
+
+ }, Constants.SERVICE_RANKING, 100);
+ assertSingleConfig(SingleConfigModel.class, context.request(), SingleConfig::stringParam);
+ }
+
+ @Test
+ void testSingleConfigModel_Resource() {
+ assertSingleConfig(SingleConfigModel.class, context.currentResource(), SingleConfig::stringParam);
+ }
+
+ @Test
+ void testSingleConfigValueMapModel_Request() {
+ assertSingleConfig(SingleConfigValueMapModel.class, context.request(), map -> map.get("stringParam", String.class));
+ }
+
+ @Test
+ void testSingleConfigValueMapModel_Resource() {
+ assertSingleConfig(SingleConfigValueMapModel.class, context.currentResource(), map -> map.get("stringParam", String.class));
+ }
+
+ @Test
+ void testSingleConfigAdaptModel_Request() {
+ assertSingleConfig(SingleConfigAdaptModel.class, context.request(), ConfigurationValuesModel::getStringParam);
+ }
+
+ @Test
+ void testSingleConfigAdaptModel_Resource() {
+ assertSingleConfig(SingleConfigAdaptModel.class, context.currentResource(), ConfigurationValuesModel::getStringParam);
+ }
+
+ @Test
+ void testListConfigModel_Request() {
+ assertListConfig(ListConfigModel.class, context.request(), ListConfig::stringParam);
+ }
+
+ @Test
+ void testListConfigModel_Resource() {
+ assertListConfig(ListConfigModel.class, context.currentResource(), ListConfig::stringParam);
+ }
+
+ @Test
+ void testListConfigValueMapModel_Request() {
+ assertListConfig(ListConfigValueMapModel.class, context.request(), map -> map.get("stringParam", String.class));
+ }
+
+ @Test
+ void testListConfigValueMapModel_Resource() {
+ assertListConfig(ListConfigValueMapModel.class, context.currentResource(), map -> map.get("stringParam", String.class));
+ }
+
+ @Test
+ void testListConfigAdaptModel_Request() {
+ assertListConfig(ListConfigAdaptModel.class, context.request(), ConfigurationValuesModel::getStringParam);
+ }
+
+ @Test
+ void testListConfigAdaptModel_Resource() {
+ assertListConfig(ListConfigAdaptModel.class, context.currentResource(), ConfigurationValuesModel::getStringParam);
+ }
+
+ private <T> void assertSingleConfig(Class<? extends SingleConfigGetter<T>> modelClass, Adaptable adaptable, Function<T,String> extractor) {
+ context.registerInjectActivateService(ContextAwareConfigurationInjector.class);
+ SingleConfigGetter<T> model = adaptable.adaptTo(modelClass);
+ assertNotNull(model);
+ T config = model.getConfig();
+ assertEquals("value1", extractor.apply(config));
+ }
+
+ private <T> void assertListConfig(Class<? extends ListConfigGetter<T>> modelClass, Adaptable adaptable, Function<T,String> extractor) {
+ context.registerInjectActivateService(ContextAwareConfigurationInjector.class);
+ ListConfigGetter<T> model = adaptable.adaptTo(modelClass);
+ assertNotNull(model);
+ assertListValues(model.getConfigList(), extractor);
+ assertListValues(ImmutableList.copyOf(model.getConfigCollection()), extractor);
+ assertListValues(ImmutableList.copyOf(model.getConfigArray()), extractor);
+ }
+
+ private <T> void assertListValues(List<T> configList, Function<T,String> extractor) {
+ assertNotNull(configList);
+ assertEquals(2, configList.size());
+ assertEquals("item1", extractor.apply(configList.get(0)));
+ assertEquals("item2", extractor.apply(configList.get(1)));
+ }
+
+ @Test
+ void testInvalid_SingleConfigModel_ResourceResolver() {
+ context.registerInjectActivateService(ContextAwareConfigurationInjector.class);
+ SingleConfigModel model = context.resourceResolver().adaptTo(SingleConfigModel.class);
+ assertNull(model);
+ }
+
+ @Test
+ @SuppressWarnings("null")
+ void testInvalidInjectModel() {
+ context.registerInjectActivateService(ContextAwareConfigurationInjector.class);
+ InvalidInjectModel model = context.request().adaptTo(InvalidInjectModel.class);
+ assertNull(model);
+ }
+
+ @Test
+ @SuppressWarnings("null")
+ void testInvalidAnnotationModel() {
+ context.registerInjectActivateService(ContextAwareConfigurationInjector.class);
+ InvalidAnnotationModel model = context.request().adaptTo(InvalidAnnotationModel.class);
+ assertNull(model);
+ }
+
+ @Test
+ @SuppressWarnings("null")
+ void testInvalidAnnotationListModel() {
+ context.registerInjectActivateService(ContextAwareConfigurationInjector.class);
+ InvalidAnnotationListModel model = context.request().adaptTo(InvalidAnnotationListModel.class);
+ assertNull(model);
+ }
+
+ @Test
+ @SuppressWarnings("null")
+ void testInvalidSetModel() {
+ context.registerInjectActivateService(ContextAwareConfigurationInjector.class);
+ InvalidSetModel model = context.request().adaptTo(InvalidSetModel.class);
+ assertNull(model);
+ }
+
+}