This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.models.impl-1.1.0 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-models-impl.git
commit a6b32c144322c49ff20c34af0111ef985339f556 Author: Justin Edelson <[email protected]> AuthorDate: Fri Aug 22 15:50:07 2014 +0000 SLING-3877 - adding a resource path injector. also did some minor refactoring to avoid code duplication between injectors. git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/models/impl@1619848 13f79535-47bb-0310-9956-ffa450edef68 --- .../models/impl/injectors/AbstractInjector.java | 53 ++++++++++ .../impl/injectors/ResourcePathInjector.java | 117 +++++++++++++++++++++ .../impl/injectors/ResourceResolverInjector.java | 10 +- .../models/impl/injectors/ValueMapInjector.java | 16 +-- .../models/impl/ResourcePathInjectionTest.java | 107 +++++++++++++++++++ .../testmodels/classes/ResourcePathModel.java | 62 +++++++++++ 6 files changed, 343 insertions(+), 22 deletions(-) diff --git a/src/main/java/org/apache/sling/models/impl/injectors/AbstractInjector.java b/src/main/java/org/apache/sling/models/impl/injectors/AbstractInjector.java new file mode 100644 index 0000000..a472d14 --- /dev/null +++ b/src/main/java/org/apache/sling/models/impl/injectors/AbstractInjector.java @@ -0,0 +1,53 @@ +/* + * 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.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.adapter.Adaptable; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.resource.ValueMap; + +/** + * Abstract base class for injectors to consolidate common functionality. + */ +abstract class AbstractInjector { + + protected ResourceResolver getResourceResolver(Object adaptable) { + ResourceResolver resolver = null; + if (adaptable instanceof Resource) { + resolver = ((Resource) adaptable).getResourceResolver(); + } else if (adaptable instanceof SlingHttpServletRequest) { + resolver = ((SlingHttpServletRequest) adaptable).getResourceResolver(); + } + return resolver; + } + + protected ValueMap getValueMap(Object adaptable) { + if (adaptable instanceof ValueMap) { + return (ValueMap) adaptable; + } else if (adaptable instanceof Adaptable) { + ValueMap map = ((Adaptable) adaptable).adaptTo(ValueMap.class); + return map; + } else { + return null; + } + } + +} diff --git a/src/main/java/org/apache/sling/models/impl/injectors/ResourcePathInjector.java b/src/main/java/org/apache/sling/models/impl/injectors/ResourcePathInjector.java new file mode 100644 index 0000000..3bc08b9 --- /dev/null +++ b/src/main/java/org/apache/sling/models/impl/injectors/ResourcePathInjector.java @@ -0,0 +1,117 @@ +/* + * 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 java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Type; + +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Property; +import org.apache.felix.scr.annotations.Service; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.resource.ValueMap; +import org.apache.sling.models.annotations.Path; +import org.apache.sling.models.annotations.injectorspecific.ResourcePath; +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.AbstractInjectAnnotationProcessor; +import org.apache.sling.models.spi.injectorspecific.InjectAnnotationProcessor; +import org.apache.sling.models.spi.injectorspecific.InjectAnnotationProcessorFactory; +import org.osgi.framework.Constants; + +@Component +@Service +@Property(name = Constants.SERVICE_RANKING, intValue = 2500) +public class ResourcePathInjector extends AbstractInjector implements Injector, AcceptsNullName, + InjectAnnotationProcessorFactory { + + @Override + public String getName() { + return "resource-path"; + } + + @Override + public Object getValue(Object adaptable, String name, Type declaredType, AnnotatedElement element, + DisposalCallbackRegistry callbackRegistry) { + String resourcePath = null; + Path pathAnnotation = element.getAnnotation(Path.class); + if (pathAnnotation != null) { + resourcePath = pathAnnotation.value(); + } else { + ResourcePath resourcePathAnnotation = element.getAnnotation(ResourcePath.class); + if (resourcePathAnnotation != null) { + resourcePath = resourcePathAnnotation.path(); + if (resourcePath.isEmpty()) { + resourcePath = null; + } + } + + if (resourcePath == null && name != null) { + // try to get from value map + ValueMap map = getValueMap(adaptable); + resourcePath = map.get(name, String.class); + } + } + + if (resourcePath != null) { + ResourceResolver resolver = getResourceResolver(adaptable); + if (resolver != null) { + return resolver.getResource(resourcePath); + } + } + + return null; + } + + @Override + public InjectAnnotationProcessor createAnnotationProcessor(Object adaptable, AnnotatedElement element) { + // check if the element has the expected annotation + ResourcePath annotation = element.getAnnotation(ResourcePath.class); + if (annotation != null) { + return new ResourcePathAnnotationProcessor(annotation, adaptable); + } + return null; + } + + private static class ResourcePathAnnotationProcessor extends AbstractInjectAnnotationProcessor { + + private final ResourcePath annotation; + + public ResourcePathAnnotationProcessor(ResourcePath annotation, Object adaptable) { + this.annotation = annotation; + } + + @Override + public String getName() { + // since null is not allowed as default value in annotations, the empty string means, the default should be + // used! + if (annotation.name().isEmpty()) { + return null; + } + return annotation.name(); + } + + @Override + public Boolean isOptional() { + return annotation.optional(); + } + } + +} diff --git a/src/main/java/org/apache/sling/models/impl/injectors/ResourceResolverInjector.java b/src/main/java/org/apache/sling/models/impl/injectors/ResourceResolverInjector.java index a84bd89..58c992e 100644 --- a/src/main/java/org/apache/sling/models/impl/injectors/ResourceResolverInjector.java +++ b/src/main/java/org/apache/sling/models/impl/injectors/ResourceResolverInjector.java @@ -24,8 +24,6 @@ import java.lang.reflect.Type; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Property; import org.apache.felix.scr.annotations.Service; -import org.apache.sling.api.SlingHttpServletRequest; -import org.apache.sling.api.resource.Resource; import org.apache.sling.models.spi.DisposalCallbackRegistry; import org.apache.sling.models.spi.Injector; import org.osgi.framework.Constants; @@ -33,7 +31,7 @@ import org.osgi.framework.Constants; @Component @Service @Property(name = Constants.SERVICE_RANKING, intValue = 900) -public class ResourceResolverInjector implements Injector { +public class ResourceResolverInjector extends AbstractInjector implements Injector { private static final String NAME_RESOURCE_RESOLVER = "resourceResolver"; @@ -46,11 +44,7 @@ public class ResourceResolverInjector implements Injector { public Object getValue(Object adaptable, String name, Type declaredType, AnnotatedElement element, DisposalCallbackRegistry callbackRegistry) { if (NAME_RESOURCE_RESOLVER.equals(name)) { - if (adaptable instanceof Resource) { - return ((Resource) adaptable).getResourceResolver(); - } else if (adaptable instanceof SlingHttpServletRequest) { - return ((SlingHttpServletRequest) adaptable).getResourceResolver(); - } + return getResourceResolver(adaptable); } return null; } diff --git a/src/main/java/org/apache/sling/models/impl/injectors/ValueMapInjector.java b/src/main/java/org/apache/sling/models/impl/injectors/ValueMapInjector.java index 9c4a123..bda12b6 100644 --- a/src/main/java/org/apache/sling/models/impl/injectors/ValueMapInjector.java +++ b/src/main/java/org/apache/sling/models/impl/injectors/ValueMapInjector.java @@ -30,7 +30,6 @@ import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Property; import org.apache.felix.scr.annotations.Service; import org.apache.sling.api.SlingHttpServletRequest; -import org.apache.sling.api.adapter.Adaptable; import org.apache.sling.api.resource.ValueMap; import org.apache.sling.models.annotations.injectorspecific.ValueMapValue; import org.apache.sling.models.spi.DisposalCallbackRegistry; @@ -45,7 +44,7 @@ import org.slf4j.LoggerFactory; @Component @Service @Property(name = Constants.SERVICE_RANKING, intValue = 2000) -public class ValueMapInjector implements Injector, InjectAnnotationProcessorFactory { +public class ValueMapInjector extends AbstractInjector implements Injector, InjectAnnotationProcessorFactory { private static final Logger log = LoggerFactory.getLogger(ValueMapInjector.class); @@ -56,7 +55,7 @@ public class ValueMapInjector implements Injector, InjectAnnotationProcessorFact public Object getValue(Object adaptable, String name, Type type, AnnotatedElement element, DisposalCallbackRegistry callbackRegistry) { - ValueMap map = getMap(adaptable); + ValueMap map = getValueMap(adaptable); if (map == null) { return null; } else if (type instanceof Class<?>) { @@ -112,17 +111,6 @@ public class ValueMapInjector implements Injector, InjectAnnotationProcessorFact } } - private ValueMap getMap(Object adaptable) { - if (adaptable instanceof ValueMap) { - return (ValueMap) adaptable; - } else if (adaptable instanceof Adaptable) { - ValueMap map = ((Adaptable) adaptable).adaptTo(ValueMap.class); - return map; - } else { - return null; - } - } - private Object unwrapArray(Object wrapperArray, Class<?> primitiveType) { int length = Array.getLength(wrapperArray); Object primitiveArray = Array.newInstance(primitiveType, length); diff --git a/src/test/java/org/apache/sling/models/impl/ResourcePathInjectionTest.java b/src/test/java/org/apache/sling/models/impl/ResourcePathInjectionTest.java new file mode 100644 index 0000000..8280584 --- /dev/null +++ b/src/test/java/org/apache/sling/models/impl/ResourcePathInjectionTest.java @@ -0,0 +1,107 @@ +/* + * 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; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import java.util.HashMap; +import java.util.Map; + +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.api.wrappers.ValueMapDecorator; +import org.apache.sling.models.impl.injectors.ResourcePathInjector; +import org.apache.sling.models.impl.injectors.SelfInjector; +import org.apache.sling.models.impl.injectors.ValueMapInjector; +import org.apache.sling.models.testmodels.classes.ResourcePathModel; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.osgi.framework.BundleContext; +import org.osgi.service.component.ComponentContext; + +@RunWith(MockitoJUnitRunner.class) +public class ResourcePathInjectionTest { + + @Mock + private ComponentContext componentCtx; + + @Mock + private BundleContext bundleContext; + + private ModelAdapterFactory factory; + + @Mock + private Resource adaptable; + + @Mock + private Resource byPathResource; + + @Mock + private Resource byPathResource2; + + @Mock + private Resource byPropertyValueResource; + + @Mock + private Resource byPropertyValueResource2; + + @Mock + private ResourceResolver resourceResolver; + + @Before + public void setup() { + Map<String, Object> map = new HashMap<String, Object>(); + map.put("propertyContainingAPath", "/some/other/path"); + map.put("anotherPropertyContainingAPath", "/some/other/path2"); + + ValueMap properties = new ValueMapDecorator(map); + + when(componentCtx.getBundleContext()).thenReturn(bundleContext); + when(adaptable.getResourceResolver()).thenReturn(resourceResolver); + when(adaptable.adaptTo(ValueMap.class)).thenReturn(properties); + + when(resourceResolver.getResource("/some/path")).thenReturn(byPathResource); + when(resourceResolver.getResource("/some/path2")).thenReturn(byPathResource2); + when(resourceResolver.getResource("/some/other/path")).thenReturn(byPropertyValueResource); + when(resourceResolver.getResource("/some/other/path2")).thenReturn(byPropertyValueResource2); + + factory = new ModelAdapterFactory(); + factory.activate(componentCtx); + factory.bindInjector(new SelfInjector(), new ServicePropertiesMap(1, Integer.MAX_VALUE)); + factory.bindInjector(new ValueMapInjector(), new ServicePropertiesMap(2, 2000)); + factory.bindInjector(new ResourcePathInjector(), new ServicePropertiesMap(3, 2500)); + factory.bindInjectAnnotationProcessorFactory(new ResourcePathInjector(), new ServicePropertiesMap(3, 2500)); + } + + @Test + public void testPathInjection() { + ResourcePathModel model = factory.getAdapter(adaptable, ResourcePathModel.class); + assertNotNull(model); + assertEquals(byPathResource, model.getFromPath()); + assertEquals(byPropertyValueResource, model.getByDerefProperty()); + assertEquals(byPathResource2, model.getFromPath2()); + assertEquals(byPropertyValueResource2, model.getByDerefProperty2()); + } + +} \ No newline at end of file diff --git a/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathModel.java b/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathModel.java new file mode 100644 index 0000000..d18d4fe --- /dev/null +++ b/src/test/java/org/apache/sling/models/testmodels/classes/ResourcePathModel.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The 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.testmodels.classes; + +import javax.inject.Inject; +import javax.inject.Named; + +import org.apache.sling.api.resource.Resource; +import org.apache.sling.models.annotations.Model; +import org.apache.sling.models.annotations.Path; +import org.apache.sling.models.annotations.injectorspecific.ResourcePath; + +@Model(adaptables = Resource.class) +public class ResourcePathModel { + + @Inject + @Path("/some/path") + private Resource fromPath; + + @Inject + @Named("propertyContainingAPath") + private Resource derefProperty; + + @ResourcePath(path = "/some/path2") + private Resource fromPath2; + + @ResourcePath(name = "anotherPropertyContainingAPath") + private Resource derefProperty2; + + public Resource getFromPath() { + return fromPath; + } + + public Resource getByDerefProperty() { + return derefProperty; + } + + public Resource getFromPath2() { + return fromPath2; + } + + public Resource getByDerefProperty2() { + return derefProperty2; + } + +} -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
