You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ju...@apache.org on 2017/03/01 14:58:55 UTC

svn commit: r1784960 - in /sling/trunk/bundles/extensions/models/impl: ./ src/main/java/org/apache/sling/models/impl/ src/main/java/org/apache/sling/models/impl/model/ src/test/java/org/apache/sling/models/impl/

Author: justin
Date: Wed Mar  1 14:58:55 2017
New Revision: 1784960

URL: http://svn.apache.org/viewvc?rev=1784960&view=rev
Log:
SLING-6584 - synchronize setAccessible calls

Modified:
    sling/trunk/bundles/extensions/models/impl/pom.xml
    sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
    sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/model/InjectableField.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ConstructorTest.java

Modified: sling/trunk/bundles/extensions/models/impl/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/pom.xml?rev=1784960&r1=1784959&r2=1784960&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/pom.xml (original)
+++ sling/trunk/bundles/extensions/models/impl/pom.xml Wed Mar  1 14:58:55 2017
@@ -125,7 +125,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.models.api</artifactId>
-            <version>1.3.3-SNAPSHOT</version>
+            <version>1.3.2</version>
             <scope>provided</scope>
         </dependency>
         <dependency>

Modified: sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java?rev=1784960&r1=1784959&r2=1784960&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java (original)
+++ sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java Wed Mar  1 14:58:55 2017
@@ -799,23 +799,9 @@ public class ModelAdapterFactory impleme
     }
 
     private RuntimeException setField(InjectableField injectableField, Object createdObject, Object value) {
-        Field field = injectableField.getField();
-        Result<Object> result = adaptIfNecessary(value, field.getType(), field.getGenericType());
+        Result<Object> result = adaptIfNecessary(value, injectableField.getFieldType(), injectableField.getFieldGenericType());
         if (result.wasSuccessful()) {
-            boolean accessible = field.isAccessible();
-            try {
-                if (!accessible) {
-                    field.setAccessible(true);
-                }
-                field.set(createdObject, result.getValue());
-            } catch (Exception e) {
-                return new ModelClassException("Could not inject field due to reflection issues", e);
-            } finally {
-                if (!accessible) {
-                    field.setAccessible(false);
-                }
-            }
-            return null;
+            return injectableField.set(createdObject, result);
         } else {
             return result.getThrowable();
         }

Modified: sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/model/InjectableField.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/model/InjectableField.java?rev=1784960&r1=1784959&r2=1784960&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/model/InjectableField.java (original)
+++ sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/model/InjectableField.java Wed Mar  1 14:58:55 2017
@@ -19,9 +19,12 @@
 package org.apache.sling.models.impl.model;
 
 import java.lang.reflect.Field;
+import java.lang.reflect.Type;
 
 import org.apache.sling.models.annotations.DefaultInjectionStrategy;
+import org.apache.sling.models.factory.ModelClassException;
 import org.apache.sling.models.impl.ReflectionUtil;
+import org.apache.sling.models.impl.Result;
 import org.apache.sling.models.spi.injectorspecific.StaticInjectAnnotationProcessorFactory;
 
 public class InjectableField extends AbstractInjectableElement {
@@ -32,13 +35,35 @@ public class InjectableField extends Abs
         super(field, ReflectionUtil.mapPrimitiveClasses(field.getGenericType()), field.getName(), processorFactories, defaultInjectionStrategy);
         this.field = field;
     }
-    
-    public Field getField() {
-        return field;
+
+    public RuntimeException set(Object createdObject, Result<Object> result) {
+        synchronized (field) {
+            boolean accessible = field.isAccessible();
+            try {
+                if (!accessible) {
+                    field.setAccessible(true);
+                }
+                field.set(createdObject, result.getValue());
+            } catch (Exception e) {
+                return new ModelClassException("Could not inject field due to reflection issues", e);
+            } finally {
+                if (!accessible) {
+                    field.setAccessible(false);
+                }
+            }
+        }
+        return null;
     }
 
     public boolean isPrimitive() {
         return false;
     }
 
+    public Class<?> getFieldType() {
+        return field.getType();
+    }
+
+    public Type getFieldGenericType() {
+        return field.getGenericType();
+    }
 }

Modified: sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ConstructorTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ConstructorTest.java?rev=1784960&r1=1784959&r2=1784960&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ConstructorTest.java (original)
+++ sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ConstructorTest.java Wed Mar  1 14:58:55 2017
@@ -19,7 +19,14 @@ package org.apache.sling.models.impl;
 import static org.junit.Assert.*;
 import static org.mockito.Mockito.*;
 
+import java.util.ArrayList;
 import java.util.Hashtable;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.models.factory.ModelClassException;
@@ -131,6 +138,49 @@ public class ConstructorTest {
     }
 
     @Test
+    public void testMultiThreadedConstructorInjection() throws InterruptedException, ExecutionException {
+
+        class ModelCreator implements Callable<String> {
+            @Override
+            public String call() throws Exception {
+                try {
+                    WithOneConstructorModel model = factory.getAdapter(request, WithOneConstructorModel.class);
+                    if (model == null) {
+                        return "Expected model not null";
+                    }
+                    if (!request.equals(model.getRequest())) {
+                        return "Expected same request";
+                    }
+                    if (INT_VALUE != model.getAttribute()) {
+                        return "Expected same value for attribute";
+                    }
+                } catch (Throwable e) {
+                    return "Exception not expected: " + e;
+                }
+                return null;
+            }
+        }
+
+        int tries = 10000;
+        int threads = 10;
+
+        ExecutorService executorService = Executors.newFixedThreadPool(threads);
+        List<ModelCreator> modelCreators = new ArrayList<>(tries);
+        for (int i = 0; i < tries; i++) {
+            modelCreators.add(new ModelCreator());
+        }
+        List<Future<String>> futures = executorService.invokeAll(modelCreators);
+        executorService.shutdown();
+
+        for (Future<String> f : futures) {
+            String res = f.get();
+            if (res != null) {
+                fail(res);
+            }
+        }
+    }
+
+    @Test
     public void testNoNameModel() {
         NoNameModel model = factory.getAdapter(request, NoNameModel.class);
         assertNull(model);