You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by an...@apache.org on 2019/08/23 18:45:24 UTC
[sling-org-apache-sling-models-impl] 01/01: SLING-8655 - Updated
dependency on API,
provided Externalized Path Injector (with default Provider) and an unit test
This is an automated email from the ASF dual-hosted git repository.
andysch pushed a commit to branch issues/SLING-8655
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-models-impl.git
commit bb865a6c60acdf7f9d2addd774def6fa2d3575d2
Author: Andreas Schaefer <sc...@iMac.local>
AuthorDate: Fri Aug 23 11:45:08 2019 -0700
SLING-8655 - Updated dependency on API, provided Externalized Path Injector (with default Provider) and an unit test
---
pom.xml | 2 +-
.../impl/injectors/ExternalizedPathInjector.java | 113 ++++++++++++++++++
.../injectors/ExternalizedPathInjectorTest.java | 128 +++++++++++++++++++++
3 files changed, 242 insertions(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 5b8b548..a663fd3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -110,7 +110,7 @@
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.models.api</artifactId>
- <version>1.3.6</version>
+ <version>1.3.9-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<!-- OSGi annotations -->
diff --git a/src/main/java/org/apache/sling/models/impl/injectors/ExternalizedPathInjector.java b/src/main/java/org/apache/sling/models/impl/injectors/ExternalizedPathInjector.java
new file mode 100644
index 0000000..9aded00
--- /dev/null
+++ b/src/main/java/org/apache/sling/models/impl/injectors/ExternalizedPathInjector.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 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.impl.injectors;
+
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.models.annotations.ExternalizePath;
+import org.apache.sling.models.annotations.injectorspecific.ExternalizedPathProvider;
+import org.apache.sling.models.spi.DisposalCallbackRegistry;
+import org.apache.sling.models.spi.Injector;
+import org.jetbrains.annotations.NotNull;
+import org.osgi.framework.Constants;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+@Component(
+ property=Constants.SERVICE_RANKING+":Integer=1000",
+ service={
+ Injector.class
+ }
+)
+public class ExternalizedPathInjector
+ extends AbstractInjector
+ implements Injector
+{
+ List<ExternalizedPathProvider> providerList = new ArrayList<>();
+
+ @Reference(policy = ReferencePolicy.DYNAMIC, cardinality = ReferenceCardinality.OPTIONAL)
+ void bindExternalizedPathProvider(ExternalizedPathProvider provider) {
+ providerList.add(provider);
+ // The providers are sorted so that the one with the highest priority is the first entry
+ Collections.sort(
+ providerList,
+ Comparator.comparingInt(ExternalizedPathProvider::getPriority).reversed()
+ );
+ }
+
+ void unbindExternalizedPathProvider(ExternalizedPathProvider provider) {
+ providerList.remove(provider);
+ }
+
+ public ExternalizedPathInjector() {
+ bindExternalizedPathProvider(new DefaultExternalizedPathProvider());
+ }
+
+ @Override
+ public @NotNull String getName() {
+ return "externalize-path";
+ }
+
+ @Override
+ public Object getValue(@NotNull Object adaptable, String name, @NotNull Type type, @NotNull AnnotatedElement element,
+ @NotNull DisposalCallbackRegistry callbackRegistry) {
+ if (adaptable == ObjectUtils.NULL) {
+ return null;
+ }
+ if (element.isAnnotationPresent(ExternalizePath.class)) {
+ ValueMap properties = getValueMap(adaptable);
+ if(properties != ObjectUtils.NULL) {
+ String imagePath = properties.get(name, String.class);
+ if(imagePath != null) {
+ ExternalizedPathProvider provider = providerList.get(0);
+ return provider.externalize(adaptable, imagePath);
+ }
+ }
+ }
+ return null;
+ }
+
+ /** Fallback Implementation of the Externalized Path Provider that uses the Resource Resolver's map function **/
+ private class DefaultExternalizedPathProvider
+ implements ExternalizedPathProvider
+ {
+ @Override
+ public int getPriority() {
+ return FALLBACK_PRIORITY;
+ }
+
+ @Override
+ public String externalize(@NotNull Object adaptable, String sourcePath) {
+ String answer = sourcePath;
+ ResourceResolver resourceResolver = getResourceResolver(adaptable);
+ if(sourcePath != null && resourceResolver != null) {
+ answer = resourceResolver.map(sourcePath);
+ }
+ return answer;
+ }
+ }
+}
diff --git a/src/test/java/org/apache/sling/models/impl/injectors/ExternalizedPathInjectorTest.java b/src/test/java/org/apache/sling/models/impl/injectors/ExternalizedPathInjectorTest.java
new file mode 100644
index 0000000..2f40e01
--- /dev/null
+++ b/src/test/java/org/apache/sling/models/impl/injectors/ExternalizedPathInjectorTest.java
@@ -0,0 +1,128 @@
+package org.apache.sling.models.impl.injectors;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.models.annotations.ExternalizePath;
+import org.apache.sling.models.annotations.injectorspecific.ExternalizedPathProvider;
+import org.apache.sling.models.spi.DisposalCallbackRegistry;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Test;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Type;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ExternalizedPathInjectorTest {
+
+ @Test
+ public void testNoResolveInjection() {
+ String imagePath = "/content/test/image/test-image.jpg";
+
+ ExternalizedPathInjector injector = new ExternalizedPathInjector();
+ Resource adaptable = mock(Resource.class);
+ ValueMap valueMap = mock(ValueMap.class);
+ when(adaptable.adaptTo(eq(ValueMap.class))).thenReturn(valueMap);
+ String name = "imagePath";
+ when(valueMap.get(eq(name), eq(String.class))).thenReturn(imagePath);
+ Type type = String.class;
+ AnnotatedElement element = mock(AnnotatedElement.class);
+ when(element.isAnnotationPresent(eq(ExternalizePath.class))).thenReturn(true);
+ DisposalCallbackRegistry callbackRegistry = mock(DisposalCallbackRegistry.class);
+ ResourceResolver resourceResolver = mock(ResourceResolver.class);
+ when(adaptable.getResourceResolver()).thenReturn(resourceResolver);
+ when(resourceResolver.map(imagePath)).thenReturn(imagePath);
+
+ Object value = injector.getValue(adaptable, name, type, element, callbackRegistry);
+ assertEquals("No Mapping was expected", imagePath, value);
+ }
+
+ @Test
+ public void testResolveInjection() {
+ String imagePath = "/content/test/image/test-image.jpg";
+ String mappedImagePath = "/image/test-image.jpg";
+
+ ExternalizedPathInjector injector = new ExternalizedPathInjector();
+ Resource adaptable = mock(Resource.class);
+ ValueMap valueMap = mock(ValueMap.class);
+ when(adaptable.adaptTo(eq(ValueMap.class))).thenReturn(valueMap);
+ String name = "imagePath";
+ when(valueMap.get(eq(name), eq(String.class))).thenReturn(imagePath);
+ Type type = String.class;
+ AnnotatedElement element = mock(AnnotatedElement.class);
+ when(element.isAnnotationPresent(eq(ExternalizePath.class))).thenReturn(true);
+ DisposalCallbackRegistry callbackRegistry = mock(DisposalCallbackRegistry.class);
+ ResourceResolver resourceResolver = mock(ResourceResolver.class);
+ when(adaptable.getResourceResolver()).thenReturn(resourceResolver);
+ when(resourceResolver.map(imagePath)).thenReturn(mappedImagePath);
+
+ Object value = injector.getValue(adaptable, name, type, element, callbackRegistry);
+ assertEquals("Mapping was expected", mappedImagePath, value);
+ }
+
+ @Test
+ public void testCustomProviderInjection() {
+ String imagePath = "/content/test/image/test-image.jpg";
+ String from = "/content/test/image/";
+ String to1 = "/image1/";
+ String to2 = "/image2/";
+ String to3 = "/image3/";
+ String mappedImagePath = "/image/test-image.jpg";
+ String mappedImagePath1 = "/image1/test-image.jpg";
+ String mappedImagePath2 = "/image2/test-image.jpg";
+ String mappedImagePath3 = "/image3/test-image.jpg";
+
+ ExternalizedPathInjector injector = new ExternalizedPathInjector();
+ Resource adaptable = mock(Resource.class);
+ ValueMap valueMap = mock(ValueMap.class);
+ when(adaptable.adaptTo(eq(ValueMap.class))).thenReturn(valueMap);
+ String name = "imagePath";
+ when(valueMap.get(eq(name), eq(String.class))).thenReturn(imagePath);
+ Type type = String.class;
+ AnnotatedElement element = mock(AnnotatedElement.class);
+ when(element.isAnnotationPresent(eq(ExternalizePath.class))).thenReturn(true);
+ DisposalCallbackRegistry callbackRegistry = mock(DisposalCallbackRegistry.class);
+ ResourceResolver resourceResolver = mock(ResourceResolver.class);
+ when(adaptable.getResourceResolver()).thenReturn(resourceResolver);
+ when(resourceResolver.map(imagePath)).thenReturn(mappedImagePath);
+
+ TestExternalizedPathProvider provider1 = new TestExternalizedPathProvider(100, from, to1);
+ injector.bindExternalizedPathProvider(provider1);
+ TestExternalizedPathProvider provider3 = new TestExternalizedPathProvider(300, from, to3);
+ injector.bindExternalizedPathProvider(provider3);
+ TestExternalizedPathProvider provider2 = new TestExternalizedPathProvider(200, from, to2);
+ injector.bindExternalizedPathProvider(provider2);
+
+ Object value = injector.getValue(adaptable, name, type, element, callbackRegistry);
+ assertEquals("Wrong Provider was selected", mappedImagePath3, value);
+ }
+
+ private class TestExternalizedPathProvider
+ implements ExternalizedPathProvider
+ {
+ private int priority;
+ private String from = "/";
+ private String to = "/";
+
+ public TestExternalizedPathProvider(int priority, String from, String to) {
+ this.priority = priority;
+ this.from = from;
+ this.to = to;
+ }
+ @Override
+ public int getPriority() { return priority; }
+
+ @Override
+ public String externalize(@NotNull Object adaptable, String sourcePath) {
+ String answer = sourcePath;
+ if(sourcePath.startsWith(from)) {
+ answer = to + sourcePath.substring(from.length());
+ }
+ return answer;
+ }
+ }
+}