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 895766f3e999997302d645e7f82cdbfdd5268c5c Author: Justin Edelson <jus...@apache.org> AuthorDate: Fri Aug 22 21:39:30 2014 +0000 SLING-3860 - allowing maximum recursion depth to be configured git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/models/impl@1619937 13f79535-47bb-0310-9956-ffa450edef68 --- .../sling/models/impl/ModelAdapterFactory.java | 52 +++++++++++----------- .../sling/models/impl/ThreadInvocationCounter.java | 42 +++++++++++++++++ .../apache/sling/models/impl/ConstructorTest.java | 3 ++ .../sling/models/impl/CustomInjectorTest.java | 3 ++ .../org/apache/sling/models/impl/DefaultTest.java | 3 ++ .../impl/InjectorSpecificAnnotationTest.java | 3 ++ .../sling/models/impl/InvalidAdaptationsTest.java | 2 + .../sling/models/impl/MultipleInjectorTest.java | 3 ++ .../sling/models/impl/OSGiInjectionTest.java | 3 ++ .../sling/models/impl/OptionalPrimitivesTest.java | 4 ++ .../sling/models/impl/PostConstructTest.java | 3 ++ .../sling/models/impl/RequestInjectionTest.java | 3 ++ .../models/impl/ResourceModelClassesTest.java | 2 + .../models/impl/ResourceModelInterfacesTest.java | 3 ++ .../models/impl/ResourcePathInjectionTest.java | 3 ++ .../sling/models/impl/SelfDependencyTest.java | 4 ++ .../java/org/apache/sling/models/impl/ViaTest.java | 3 ++ 17 files changed, 112 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java b/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java index 1880e66..0f51f66 100644 --- a/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java +++ b/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java @@ -32,6 +32,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Dictionary; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; @@ -53,11 +54,13 @@ import org.apache.commons.lang.ClassUtils; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Property; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.ReferencePolicy; import org.apache.sling.api.adapter.Adaptable; import org.apache.sling.api.adapter.AdapterFactory; +import org.apache.sling.commons.osgi.PropertiesUtil; import org.apache.sling.commons.osgi.ServiceUtil; import org.apache.sling.models.annotations.Default; import org.apache.sling.models.annotations.DefaultInjectionStrategy; @@ -80,7 +83,7 @@ import org.osgi.service.component.ComponentContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@Component +@Component(metatype = true) public class ModelAdapterFactory implements AdapterFactory, Runnable { private static class DisposalCallbackRegistryImpl implements DisposalCallbackRegistry { @@ -121,6 +124,11 @@ public class ModelAdapterFactory implements AdapterFactory, Runnable { private static final Logger log = LoggerFactory.getLogger(ModelAdapterFactory.class); + private static final int DEFAULT_MAX_RECURSION_DEPTH = 20; + + @Property(label = "Maximum Recursion Depth", description = "Maximum depth adaptation will be attempted.", intValue = DEFAULT_MAX_RECURSION_DEPTH) + private static final String PROP_MAX_RECURSION_DEPTH = "max.recursion.depth"; + @Reference(name = "injector", referenceInterface = Injector.class, cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, policy = ReferencePolicy.DYNAMIC) private final Map<Object, Injector> injectors = new TreeMap<Object, Injector>(); @@ -138,38 +146,19 @@ public class ModelAdapterFactory implements AdapterFactory, Runnable { private ServiceRegistration jobRegistration; private ServiceRegistration configPrinterRegistration; - - // Use threadlocal to count recursive invocations and break recursing if a max. limit is reached (to avoid cyclic dependencies) - private static final int MAX_RECURSIVE_INOVCATIONS = 20; - private static class ThreadInvocationCounter { - private int count; - public boolean isMaximumReached() { - return count >= MAX_RECURSIVE_INOVCATIONS; - } - public void increase() { - this.count++; - } - public void decrease() { - this.count--; - } - } - - private static final ThreadLocal<ThreadInvocationCounter> INVOCATION_COUNT_THREADLOCAL = new ThreadLocal<ModelAdapterFactory.ThreadInvocationCounter>() { - @Override - protected ThreadInvocationCounter initialValue() { - return new ThreadInvocationCounter(); - } - }; + // Use threadlocal to count recursive invocations and break recursing if a max. limit is reached (to avoid cyclic dependencies) + private ThreadLocal<ThreadInvocationCounter> invocationCountThreadLocal; @SuppressWarnings("unchecked") public <AdapterType> AdapterType getAdapter(Object adaptable, Class<AdapterType> type) { - if (INVOCATION_COUNT_THREADLOCAL.get().isMaximumReached()) { + ThreadInvocationCounter threadInvocationCounter = invocationCountThreadLocal.get(); + if (threadInvocationCounter.isMaximumReached()) { log.error("Adapting {} to {} failed, too much recursive invocations (>={}).", - new Object[] { adaptable, type, MAX_RECURSIVE_INOVCATIONS }); + new Object[] { adaptable, type, threadInvocationCounter.maxRecursionDepth }); return null; }; - INVOCATION_COUNT_THREADLOCAL.get().increase(); + threadInvocationCounter.increase(); try { Model modelAnnotation = type.getAnnotation(Model.class); if (modelAnnotation == null) { @@ -203,7 +192,7 @@ public class ModelAdapterFactory implements AdapterFactory, Runnable { } } } finally { - INVOCATION_COUNT_THREADLOCAL.get().decrease(); + threadInvocationCounter.decrease(); } } @@ -902,6 +891,15 @@ public class ModelAdapterFactory implements AdapterFactory, Runnable { @Activate protected void activate(final ComponentContext ctx) { + Dictionary<?, ?> props = ctx.getProperties(); + final int maxRecursionDepth = PropertiesUtil.toInteger(props.get(PROP_MAX_RECURSION_DEPTH), DEFAULT_MAX_RECURSION_DEPTH); + this.invocationCountThreadLocal = new ThreadLocal<ThreadInvocationCounter>() { + @Override + protected ThreadInvocationCounter initialValue() { + return new ThreadInvocationCounter(maxRecursionDepth); + } + }; + BundleContext bundleContext = ctx.getBundleContext(); this.queue = new ReferenceQueue<Object>(); this.disposalCallbacks = new ConcurrentHashMap<java.lang.ref.Reference<Object>, DisposalCallbackRegistryImpl>(); diff --git a/src/main/java/org/apache/sling/models/impl/ThreadInvocationCounter.java b/src/main/java/org/apache/sling/models/impl/ThreadInvocationCounter.java new file mode 100644 index 0000000..b386aa5 --- /dev/null +++ b/src/main/java/org/apache/sling/models/impl/ThreadInvocationCounter.java @@ -0,0 +1,42 @@ +/* + * 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; + +class ThreadInvocationCounter { + + private int count; + + final int maxRecursionDepth; + + public ThreadInvocationCounter(int maxRecursionDepth) { + this.maxRecursionDepth = maxRecursionDepth; + } + + public boolean isMaximumReached() { + return count >= maxRecursionDepth; + } + + public void increase() { + this.count++; + } + + public void decrease() { + this.count--; + } +} \ No newline at end of file diff --git a/src/test/java/org/apache/sling/models/impl/ConstructorTest.java b/src/test/java/org/apache/sling/models/impl/ConstructorTest.java index 6720a16..1b46255 100644 --- a/src/test/java/org/apache/sling/models/impl/ConstructorTest.java +++ b/src/test/java/org/apache/sling/models/impl/ConstructorTest.java @@ -19,6 +19,8 @@ package org.apache.sling.models.impl; import static org.junit.Assert.*; import static org.mockito.Mockito.*; +import java.util.Hashtable; + import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.models.impl.injectors.RequestAttributeInjector; import org.apache.sling.models.impl.injectors.SelfInjector; @@ -59,6 +61,7 @@ public class ConstructorTest { @Before public void setup() { when(componentCtx.getBundleContext()).thenReturn(bundleContext); + when(componentCtx.getProperties()).thenReturn(new Hashtable<String, Object>()); when(request.getAttribute("attribute")).thenReturn(INT_VALUE); when(request.getAttribute("attribute2")).thenReturn(STRING_VALUE); diff --git a/src/test/java/org/apache/sling/models/impl/CustomInjectorTest.java b/src/test/java/org/apache/sling/models/impl/CustomInjectorTest.java index 046ce00..6179eb1 100644 --- a/src/test/java/org/apache/sling/models/impl/CustomInjectorTest.java +++ b/src/test/java/org/apache/sling/models/impl/CustomInjectorTest.java @@ -19,6 +19,8 @@ package org.apache.sling.models.impl; import static org.junit.Assert.*; import static org.mockito.Mockito.*; +import java.util.Hashtable; + import javax.inject.Inject; import org.apache.sling.models.annotations.Model; @@ -47,6 +49,7 @@ public class CustomInjectorTest { @Before public void setup() { when(componentCtx.getBundleContext()).thenReturn(bundleContext); + when(componentCtx.getProperties()).thenReturn(new Hashtable<String, Object>()); factory = new ModelAdapterFactory(); factory.activate(componentCtx); diff --git a/src/test/java/org/apache/sling/models/impl/DefaultTest.java b/src/test/java/org/apache/sling/models/impl/DefaultTest.java index 01a333f..9ef3c25 100644 --- a/src/test/java/org/apache/sling/models/impl/DefaultTest.java +++ b/src/test/java/org/apache/sling/models/impl/DefaultTest.java @@ -21,6 +21,7 @@ import static org.mockito.Mockito.*; import java.util.Arrays; import java.util.Collections; +import java.util.Hashtable; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ValueMap; @@ -53,6 +54,8 @@ public class DefaultTest { @Before public void setup() { when(componentCtx.getBundleContext()).thenReturn(bundleContext); + when(componentCtx.getProperties()).thenReturn(new Hashtable<String, Object>()); + factory = new ModelAdapterFactory(); factory.activate(componentCtx); factory.bindInjector(new ValueMapInjector(), new ServicePropertiesMap(0, 0)); diff --git a/src/test/java/org/apache/sling/models/impl/InjectorSpecificAnnotationTest.java b/src/test/java/org/apache/sling/models/impl/InjectorSpecificAnnotationTest.java index 2a82d7d..484beaa 100644 --- a/src/test/java/org/apache/sling/models/impl/InjectorSpecificAnnotationTest.java +++ b/src/test/java/org/apache/sling/models/impl/InjectorSpecificAnnotationTest.java @@ -21,6 +21,7 @@ import static org.mockito.Mockito.*; import java.util.Collections; import java.util.HashMap; +import java.util.Hashtable; import java.util.Map; import org.apache.sling.api.SlingHttpServletRequest; @@ -72,6 +73,8 @@ public class InjectorSpecificAnnotationTest { @Before public void setup() { when(componentCtx.getBundleContext()).thenReturn(bundleContext); + when(componentCtx.getProperties()).thenReturn(new Hashtable<String, Object>()); + factory = new ModelAdapterFactory(); factory.activate(componentCtx); diff --git a/src/test/java/org/apache/sling/models/impl/InvalidAdaptationsTest.java b/src/test/java/org/apache/sling/models/impl/InvalidAdaptationsTest.java index 4c545af..4e99178 100644 --- a/src/test/java/org/apache/sling/models/impl/InvalidAdaptationsTest.java +++ b/src/test/java/org/apache/sling/models/impl/InvalidAdaptationsTest.java @@ -20,6 +20,7 @@ import static org.junit.Assert.*; import static org.mockito.Mockito.*; import java.util.Collections; +import java.util.Hashtable; import java.util.Map; import org.apache.sling.api.SlingHttpServletRequest; @@ -51,6 +52,7 @@ public class InvalidAdaptationsTest { @Before public void setup() { when(componentCtx.getBundleContext()).thenReturn(bundleContext); + when(componentCtx.getProperties()).thenReturn(new Hashtable<String, Object>()); factory = new ModelAdapterFactory(); factory.activate(componentCtx); diff --git a/src/test/java/org/apache/sling/models/impl/MultipleInjectorTest.java b/src/test/java/org/apache/sling/models/impl/MultipleInjectorTest.java index 44324c5..640de65 100644 --- a/src/test/java/org/apache/sling/models/impl/MultipleInjectorTest.java +++ b/src/test/java/org/apache/sling/models/impl/MultipleInjectorTest.java @@ -20,6 +20,7 @@ import static org.junit.Assert.*; import static org.mockito.Mockito.*; import java.lang.reflect.AnnotatedElement; +import java.util.Hashtable; import javax.inject.Inject; @@ -64,6 +65,8 @@ public class MultipleInjectorTest { @Before public void setup() { when(componentCtx.getBundleContext()).thenReturn(bundleContext); + when(componentCtx.getProperties()).thenReturn(new Hashtable<String, Object>()); + bindings = new SlingBindings(); factory = new ModelAdapterFactory(); diff --git a/src/test/java/org/apache/sling/models/impl/OSGiInjectionTest.java b/src/test/java/org/apache/sling/models/impl/OSGiInjectionTest.java index df09c52..58b46bf 100644 --- a/src/test/java/org/apache/sling/models/impl/OSGiInjectionTest.java +++ b/src/test/java/org/apache/sling/models/impl/OSGiInjectionTest.java @@ -21,6 +21,7 @@ import static org.mockito.Matchers.*; import static org.mockito.Mockito.*; import java.util.Dictionary; +import java.util.Hashtable; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.Resource; @@ -65,6 +66,8 @@ public class OSGiInjectionTest { @Before public void setup() { when(componentCtx.getBundleContext()).thenReturn(bundleContext); + when(componentCtx.getProperties()).thenReturn(new Hashtable<String, Object>()); + factory = new ModelAdapterFactory(); factory.activate(componentCtx); diff --git a/src/test/java/org/apache/sling/models/impl/OptionalPrimitivesTest.java b/src/test/java/org/apache/sling/models/impl/OptionalPrimitivesTest.java index 0fd45c5..06ef24f 100644 --- a/src/test/java/org/apache/sling/models/impl/OptionalPrimitivesTest.java +++ b/src/test/java/org/apache/sling/models/impl/OptionalPrimitivesTest.java @@ -22,6 +22,8 @@ import static org.junit.Assert.assertNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import java.util.Hashtable; + import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ValueMap; import org.apache.sling.models.impl.injectors.ChildResourceInjector; @@ -51,6 +53,8 @@ public class OptionalPrimitivesTest { @Before public void setup() { when(componentCtx.getBundleContext()).thenReturn(bundleContext); + when(componentCtx.getProperties()).thenReturn(new Hashtable<String, Object>()); + factory = new ModelAdapterFactory(); factory.activate(componentCtx); factory.bindInjector(new ValueMapInjector(), new ServicePropertiesMap(2, 2)); diff --git a/src/test/java/org/apache/sling/models/impl/PostConstructTest.java b/src/test/java/org/apache/sling/models/impl/PostConstructTest.java index 7f54f12..8e6aa75 100644 --- a/src/test/java/org/apache/sling/models/impl/PostConstructTest.java +++ b/src/test/java/org/apache/sling/models/impl/PostConstructTest.java @@ -19,6 +19,8 @@ package org.apache.sling.models.impl; import static org.junit.Assert.*; import static org.mockito.Mockito.*; +import java.util.Hashtable; + import org.apache.sling.api.resource.Resource; import org.apache.sling.models.testmodels.classes.SubClass; import org.junit.Before; @@ -41,6 +43,7 @@ public class PostConstructTest { @Before public void setup() { when(componentCtx.getBundleContext()).thenReturn(bundleContext); + when(componentCtx.getProperties()).thenReturn(new Hashtable<String, Object>()); } @Test diff --git a/src/test/java/org/apache/sling/models/impl/RequestInjectionTest.java b/src/test/java/org/apache/sling/models/impl/RequestInjectionTest.java index 91dd851..4fae168 100644 --- a/src/test/java/org/apache/sling/models/impl/RequestInjectionTest.java +++ b/src/test/java/org/apache/sling/models/impl/RequestInjectionTest.java @@ -19,6 +19,8 @@ package org.apache.sling.models.impl; import static org.junit.Assert.*; import static org.mockito.Mockito.*; +import java.util.Hashtable; + import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.scripting.SlingBindings; import org.apache.sling.api.scripting.SlingScriptHelper; @@ -53,6 +55,7 @@ public class RequestInjectionTest { @Before public void setup() { when(componentCtx.getBundleContext()).thenReturn(bundleContext); + when(componentCtx.getProperties()).thenReturn(new Hashtable<String, Object>()); SlingBindings bindings = new SlingBindings(); bindings.setSling(sling); diff --git a/src/test/java/org/apache/sling/models/impl/ResourceModelClassesTest.java b/src/test/java/org/apache/sling/models/impl/ResourceModelClassesTest.java index 3f020a9..625e5a0 100644 --- a/src/test/java/org/apache/sling/models/impl/ResourceModelClassesTest.java +++ b/src/test/java/org/apache/sling/models/impl/ResourceModelClassesTest.java @@ -22,6 +22,7 @@ import static org.mockito.Mockito.*; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.Hashtable; import java.util.Map; import org.apache.commons.lang.RandomStringUtils; @@ -64,6 +65,7 @@ public class ResourceModelClassesTest { @Before public void setup() { when(componentCtx.getBundleContext()).thenReturn(bundleContext); + when(componentCtx.getProperties()).thenReturn(new Hashtable<String, Object>()); factory = new ModelAdapterFactory(); factory.activate(componentCtx); diff --git a/src/test/java/org/apache/sling/models/impl/ResourceModelInterfacesTest.java b/src/test/java/org/apache/sling/models/impl/ResourceModelInterfacesTest.java index 6999525..0696ff5 100644 --- a/src/test/java/org/apache/sling/models/impl/ResourceModelInterfacesTest.java +++ b/src/test/java/org/apache/sling/models/impl/ResourceModelInterfacesTest.java @@ -21,6 +21,7 @@ import static org.mockito.Mockito.*; import java.util.Collections; import java.util.HashMap; +import java.util.Hashtable; import java.util.Map; import org.apache.commons.lang.RandomStringUtils; @@ -59,6 +60,8 @@ public class ResourceModelInterfacesTest { @Before public void setup() { when(componentCtx.getBundleContext()).thenReturn(bundleContext); + when(componentCtx.getProperties()).thenReturn(new Hashtable<String, Object>()); + factory = new ModelAdapterFactory(); factory.activate(componentCtx); factory.bindInjector(new ValueMapInjector(), new ServicePropertiesMap(2, 2)); diff --git a/src/test/java/org/apache/sling/models/impl/ResourcePathInjectionTest.java b/src/test/java/org/apache/sling/models/impl/ResourcePathInjectionTest.java index 8280584..ee0cea8 100644 --- a/src/test/java/org/apache/sling/models/impl/ResourcePathInjectionTest.java +++ b/src/test/java/org/apache/sling/models/impl/ResourcePathInjectionTest.java @@ -22,6 +22,7 @@ import static org.junit.Assert.*; import static org.mockito.Mockito.*; import java.util.HashMap; +import java.util.Hashtable; import java.util.Map; import org.apache.sling.api.resource.Resource; @@ -78,6 +79,8 @@ public class ResourcePathInjectionTest { ValueMap properties = new ValueMapDecorator(map); when(componentCtx.getBundleContext()).thenReturn(bundleContext); + when(componentCtx.getProperties()).thenReturn(new Hashtable<String, Object>()); + when(adaptable.getResourceResolver()).thenReturn(resourceResolver); when(adaptable.adaptTo(ValueMap.class)).thenReturn(properties); diff --git a/src/test/java/org/apache/sling/models/impl/SelfDependencyTest.java b/src/test/java/org/apache/sling/models/impl/SelfDependencyTest.java index e0e9bad..c2811f9 100644 --- a/src/test/java/org/apache/sling/models/impl/SelfDependencyTest.java +++ b/src/test/java/org/apache/sling/models/impl/SelfDependencyTest.java @@ -22,6 +22,8 @@ import static org.junit.Assert.assertSame; import static org.mockito.Matchers.any; import static org.mockito.Mockito.when; +import java.util.Hashtable; + import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.models.impl.injectors.SelfInjector; import org.apache.sling.models.testmodels.classes.DirectCyclicSelfDependencyModel; @@ -57,6 +59,8 @@ public class SelfDependencyTest { @Before public void setup() { when(componentCtx.getBundleContext()).thenReturn(bundleContext); + when(componentCtx.getProperties()).thenReturn(new Hashtable<String, Object>()); + when(request.adaptTo(any(Class.class))).then(new Answer<Object>() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { diff --git a/src/test/java/org/apache/sling/models/impl/ViaTest.java b/src/test/java/org/apache/sling/models/impl/ViaTest.java index 822e07c..a1c9af4 100644 --- a/src/test/java/org/apache/sling/models/impl/ViaTest.java +++ b/src/test/java/org/apache/sling/models/impl/ViaTest.java @@ -20,6 +20,7 @@ import static org.junit.Assert.*; import static org.mockito.Mockito.*; import java.util.Collections; +import java.util.Hashtable; import org.apache.commons.lang.RandomStringUtils; import org.apache.sling.api.SlingHttpServletRequest; @@ -56,6 +57,8 @@ public class ViaTest { @Before public void setup() { when(componentCtx.getBundleContext()).thenReturn(bundleContext); + when(componentCtx.getProperties()).thenReturn(new Hashtable<String, Object>()); + when(request.getResource()).thenReturn(resource); factory = new ModelAdapterFactory(); factory.activate(componentCtx); -- To stop receiving notification emails like this one, please contact "commits@sling.apache.org" <commits@sling.apache.org>.