sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jus...@apache.org
Subject svn commit: r1619007 [1/2] - in /sling/trunk/bundles/extensions/models: api/src/main/java/org/apache/sling/models/annotations/ api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ api/src/main/java/org/apache/sling/models/spi/ impl/ ...
Date Tue, 19 Aug 2014 22:51:37 GMT
Author: justin
Date: Tue Aug 19 22:51:36 2014
New Revision: 1619007

URL: http://svn.apache.org/r1619007
Log:
SLING-3716 SLING-3718 - adding support for constructor injection and self injection based on a patch from Stefan Seifert

Added:
    sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/Self.java
      - copied, changed from r1618976, sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/RequestAttribute.java
    sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/spi/AcceptsNullName.java
    sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/ConstructorParameter.java
    sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/MapBackedInvocationHandler.java
    sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/ParameterCountInjectComparator.java
    sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/SelfInjector.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/SelfDependencyTest.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/injectors/BindingsInjectorTest.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/injectors/RequestAttributeInjectorTest.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/injectors/SelfInjectorTest.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/injectors/ValueMapInjectorTest.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/DirectCyclicSelfDependencyModel.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/IndirectCyclicSelfDependencyModelA.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/IndirectCyclicSelfDependencyModelB.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/SelfDependencyModelA.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/SelfDependencyModelB.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/constructorinjection/
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/constructorinjection/BindingsModel.java
      - copied, changed from r1618976, sling/trunk/bundles/extensions/models/integration-tests/src/main/java/org/apache/sling/models/it/models/TestModel.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/constructorinjection/DefaultPrimitivesModel.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/constructorinjection/DefaultStringModel.java
      - copied, changed from r1618976, sling/trunk/bundles/extensions/models/integration-tests/src/main/java/org/apache/sling/models/it/models/TestModel.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/constructorinjection/DefaultWrappersModel.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/constructorinjection/InjectorSpecificAnnotationModel.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/constructorinjection/ListOSGiModel.java
      - copied, changed from r1618976, sling/trunk/bundles/extensions/models/integration-tests/src/main/java/org/apache/sling/models/it/models/TestModel.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/constructorinjection/NoNameModel.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/constructorinjection/SimpleOSGiModel.java
      - copied, changed from r1618976, sling/trunk/bundles/extensions/models/integration-tests/src/main/java/org/apache/sling/models/it/models/TestModel.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/constructorinjection/WithThreeConstructorsOneInjectModel.java
      - copied, changed from r1618976, sling/trunk/bundles/extensions/models/integration-tests/src/main/java/org/apache/sling/models/it/models/TestModel.java
    sling/trunk/bundles/extensions/models/integration-tests/src/main/java/org/apache/sling/models/it/models/ConstructorInjectionTestModel.java
      - copied, changed from r1618976, sling/trunk/bundles/extensions/models/integration-tests/src/main/java/org/apache/sling/models/it/models/TestModel.java
    sling/trunk/bundles/extensions/models/integration-tests/src/main/java/org/apache/sling/models/it/models/FieldInjectionTestModel.java
      - copied, changed from r1618976, sling/trunk/bundles/extensions/models/integration-tests/src/main/java/org/apache/sling/models/it/models/TestModel.java
    sling/trunk/bundles/extensions/models/integration-tests/src/main/java/org/apache/sling/models/it/models/InterfaceInjectionTestModel.java
      - copied, changed from r1618976, sling/trunk/bundles/extensions/models/integration-tests/src/main/java/org/apache/sling/models/it/models/TestModel.java
Removed:
    sling/trunk/bundles/extensions/models/integration-tests/src/main/java/org/apache/sling/models/it/models/TestModel.java
Modified:
    sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Default.java
    sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Filter.java
    sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Optional.java
    sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Required.java
    sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Source.java
    sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Via.java
    sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ChildResource.java
    sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/OSGiService.java
    sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/RequestAttribute.java
    sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ScriptVariable.java
    sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ValueMapValue.java
    sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/package-info.java
    sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/package-info.java
    sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/spi/package-info.java
    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/injectors/OSGiServiceInjector.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ConstructorTest.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/DefaultTest.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/InjectorSpecificAnnotationTest.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/OSGiInjectionTest.java
    sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/RequestInjectionTest.java
    sling/trunk/bundles/extensions/models/integration-tests/src/main/java/org/apache/sling/models/it/SimpleTest.java

Modified: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Default.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Default.java?rev=1619007&r1=1619006&r2=1619007&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Default.java (original)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Default.java Tue Aug 19 22:51:36 2014
@@ -24,7 +24,7 @@ import java.lang.annotation.Target;
 /**
  * Default value for an injection.
  */
-@Target({ ElementType.FIELD, ElementType.METHOD })
+@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
 @Retention(RetentionPolicy.RUNTIME)
 public @interface Default {
 

Modified: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Filter.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Filter.java?rev=1619007&r1=1619006&r2=1619007&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Filter.java (original)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Filter.java Tue Aug 19 22:51:36 2014
@@ -26,7 +26,7 @@ import javax.inject.Qualifier;
 /**
  * Provide a filter on an @Inject.
  */
-@Target({ ElementType.FIELD, ElementType.METHOD })
+@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
 @Retention(RetentionPolicy.RUNTIME)
 @Source("osgi-services")
 @Qualifier

Modified: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Optional.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Optional.java?rev=1619007&r1=1619006&r2=1619007&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Optional.java (original)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Optional.java Tue Aug 19 22:51:36 2014
@@ -24,7 +24,7 @@ import java.lang.annotation.Target;
 /**
  * Marker annotation for optional injections.
  */
-@Target({ ElementType.FIELD, ElementType.METHOD })
+@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
 @Retention(RetentionPolicy.RUNTIME)
 public @interface Optional {
 

Modified: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Required.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Required.java?rev=1619007&r1=1619006&r2=1619007&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Required.java (original)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Required.java Tue Aug 19 22:51:36 2014
@@ -24,7 +24,7 @@ import java.lang.annotation.Target;
 /**
  * Marker annotation for required injections.
  */
-@Target({ ElementType.FIELD, ElementType.METHOD })
+@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
 @Retention(RetentionPolicy.RUNTIME)
 public @interface Required {
 

Modified: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Source.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Source.java?rev=1619007&r1=1619006&r2=1619007&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Source.java (original)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Source.java Tue Aug 19 22:51:36 2014
@@ -28,7 +28,7 @@ import javax.inject.Qualifier;
  * Can also be used as a meta-annotation to declare that some other annotation implies
  * a source.
  */
-@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE })
+@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE })
 @Retention(RetentionPolicy.RUNTIME)
 @Qualifier
 public @interface Source {

Modified: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Via.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Via.java?rev=1619007&r1=1619006&r2=1619007&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Via.java (original)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Via.java Tue Aug 19 22:51:36 2014
@@ -25,7 +25,7 @@ import java.lang.annotation.Target;
  * Indicate that this injection point should be handled using a projected
  * property of the adaptable.
  */
-@Target({ ElementType.FIELD, ElementType.METHOD })
+@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
 @Retention(RetentionPolicy.RUNTIME)
 public @interface Via {
 

Modified: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ChildResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ChildResource.java?rev=1619007&r1=1619006&r2=1619007&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ChildResource.java (original)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ChildResource.java Tue Aug 19 22:51:36 2014
@@ -18,6 +18,7 @@ package org.apache.sling.models.annotati
 
 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;
@@ -27,10 +28,10 @@ import org.apache.sling.models.annotatio
 import org.apache.sling.models.spi.injectorspecific.InjectAnnotation;
 
 /**
- * Annotation to be used on either methods or fields to let Sling Models inject a child resource
+ * Annotation to be used on either methods, fields or constructor parameters to let Sling Models inject a child resource
  *
  */
-@Target({ METHOD, FIELD })
+@Target({ METHOD, FIELD, PARAMETER })
 @Retention(RUNTIME)
 @InjectAnnotation
 @Source("child-resources")

Modified: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/OSGiService.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/OSGiService.java?rev=1619007&r1=1619006&r2=1619007&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/OSGiService.java (original)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/OSGiService.java Tue Aug 19 22:51:36 2014
@@ -18,6 +18,7 @@ package org.apache.sling.models.annotati
 
 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;
@@ -27,10 +28,10 @@ import org.apache.sling.models.annotatio
 import org.apache.sling.models.spi.injectorspecific.InjectAnnotation;
 
 /**
- * Annotation to be used on either methods or fields to let Sling Models inject an OSGi service
+ * Annotation to be used on either methods, fields or constructor parameters to let Sling Models inject an OSGi service
  *
  */
-@Target({ METHOD, FIELD })
+@Target({ METHOD, FIELD, PARAMETER })
 @Retention(RUNTIME)
 @InjectAnnotation
 @Source("osgi-services")

Modified: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/RequestAttribute.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/RequestAttribute.java?rev=1619007&r1=1619006&r2=1619007&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/RequestAttribute.java (original)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/RequestAttribute.java Tue Aug 19 22:51:36 2014
@@ -18,6 +18,7 @@ package org.apache.sling.models.annotati
 
 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;
@@ -27,11 +28,11 @@ import org.apache.sling.models.annotatio
 import org.apache.sling.models.spi.injectorspecific.InjectAnnotation;
 
 /**
- * Annotation to be used on either methods or fields to let Sling Models inject a
+ * Annotation to be used on either methods, fields or constructor parameters to let Sling Models inject a
  * request attribute.
  *
  */
-@Target({ METHOD, FIELD })
+@Target({ METHOD, FIELD, PARAMETER })
 @Retention(RUNTIME)
 @InjectAnnotation
 @Source("request-attributes")

Modified: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ScriptVariable.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ScriptVariable.java?rev=1619007&r1=1619006&r2=1619007&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ScriptVariable.java (original)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ScriptVariable.java Tue Aug 19 22:51:36 2014
@@ -18,6 +18,7 @@ package org.apache.sling.models.annotati
 
 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;
@@ -27,11 +28,11 @@ import org.apache.sling.models.annotatio
 import org.apache.sling.models.spi.injectorspecific.InjectAnnotation;
 
 /**
- * Annotation to be used on either methods or fields to let Sling Models inject a
+ * Annotation to be used on either methods, fields or constructor parameters to let Sling Models inject a
  * script variable (from the {@link org.apache.sling.api.scripting.SlingBindings})
  *
  */
-@Target({ METHOD, FIELD })
+@Target({ METHOD, FIELD, PARAMETER })
 @Retention(RUNTIME)
 @InjectAnnotation
 @Source("script-bindings")

Copied: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/Self.java (from r1618976, sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/RequestAttribute.java)
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/Self.java?p2=sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/Self.java&p1=sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/RequestAttribute.java&r1=1618976&r2=1619007&rev=1619007&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/RequestAttribute.java (original)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/Self.java Tue Aug 19 22:51:36 2014
@@ -18,6 +18,7 @@ package org.apache.sling.models.annotati
 
 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;
@@ -27,26 +28,19 @@ import org.apache.sling.models.annotatio
 import org.apache.sling.models.spi.injectorspecific.InjectAnnotation;
 
 /**
- * Annotation to be used on either methods or fields to let Sling Models inject a
- * request attribute.
- *
+ * Annotation to be used on either methods, fields or constructor parameters to let Sling Models
+ * inject the adaptable itself, or an object that can be adapted from it. 
  */
-@Target({ METHOD, FIELD })
+@Target({ METHOD, FIELD, PARAMETER })
 @Retention(RUNTIME)
 @InjectAnnotation
-@Source("request-attributes")
-public @interface RequestAttribute {
+@Source("self")
+public @interface Self {
 
     /**
-     * Specifies the name of the request attribute. If empty or not set, then the name
-     * is derived from the method or field.
-     */
-    public String name() default "";
-
-    /**
-     * If set to true, the model can be instantiated even if there is no request attribute
-     * with the given name found.
+     * If set to true, the model can be instantiated even if there is no object that can be adapted from the adaptable itself. 
      * Default = false.
      */
     public boolean optional() default false;
+
 }

Modified: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ValueMapValue.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ValueMapValue.java?rev=1619007&r1=1619006&r2=1619007&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ValueMapValue.java (original)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/ValueMapValue.java Tue Aug 19 22:51:36 2014
@@ -18,6 +18,7 @@ package org.apache.sling.models.annotati
 
 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;
@@ -27,10 +28,11 @@ import org.apache.sling.models.annotatio
 import org.apache.sling.models.spi.injectorspecific.InjectAnnotation;
 
 /**
- * Annotation to be used on either methods or fields to let Sling Models inject a value from the ValueMap of the current resource.
+ * Annotation to be used on either methods, fields or constructor parameter to let Sling Models
+ * inject a value from the ValueMap of the current resource.
  *
  */
-@Target({ METHOD, FIELD })
+@Target({ METHOD, FIELD, PARAMETER })
 @Retention(RUNTIME)
 @InjectAnnotation
 @Source("valuemap")

Modified: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/package-info.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/package-info.java?rev=1619007&r1=1619006&r2=1619007&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/package-info.java (original)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/injectorspecific/package-info.java Tue Aug 19 22:51:36 2014
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("1.0.0")
+@Version("1.0.2")
 package org.apache.sling.models.annotations.injectorspecific;
 
 import aQute.bnd.annotation.Version;
\ No newline at end of file

Modified: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/package-info.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/package-info.java?rev=1619007&r1=1619006&r2=1619007&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/package-info.java (original)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/package-info.java Tue Aug 19 22:51:36 2014
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("1.1.0")
+@Version("1.1.2")
 package org.apache.sling.models.annotations;
 
 import aQute.bnd.annotation.Version;
\ No newline at end of file

Added: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/spi/AcceptsNullName.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/spi/AcceptsNullName.java?rev=1619007&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/spi/AcceptsNullName.java (added)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/spi/AcceptsNullName.java Tue Aug 19 22:51:36 2014
@@ -0,0 +1,27 @@
+/*
+ * 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.spi;
+
+/**
+ * Marker interface for an injector to declare that it ignores the name
+ * parameter.
+ *
+ */
+public interface AcceptsNullName {
+}

Modified: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/spi/package-info.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/spi/package-info.java?rev=1619007&r1=1619006&r2=1619007&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/spi/package-info.java (original)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/spi/package-info.java Tue Aug 19 22:51:36 2014
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("1.0.0")
+@Version("1.0.2")
 package org.apache.sling.models.spi;
 
 import aQute.bnd.annotation.Version;
\ No newline at end of file

Modified: sling/trunk/bundles/extensions/models/impl/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/pom.xml?rev=1619007&r1=1619006&r2=1619007&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/pom.xml (original)
+++ sling/trunk/bundles/extensions/models/impl/pom.xml Tue Aug 19 22:51:36 2014
@@ -63,7 +63,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.models.api</artifactId>
-            <version>1.0.2</version>
+            <version>1.0.3-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>

Added: sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/ConstructorParameter.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/ConstructorParameter.java?rev=1619007&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/ConstructorParameter.java (added)
+++ sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/ConstructorParameter.java Tue Aug 19 22:51:36 2014
@@ -0,0 +1,87 @@
+/*
+ * 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 java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Type;
+
+/**
+ * Constructor parameters aren't normally accessible using the
+ * AnnotatedElement. This class acts as a facade to ease
+ * compatibility with field and method injection.
+ */
+class ConstructorParameter implements AnnotatedElement {
+
+    private final Annotation[] annotations;
+    private final Class<?> type;
+    private final Type genericType;
+    private final int parameterIndex;
+
+    ConstructorParameter(Annotation[] annotations, Class<?> type, Type genericType, int parameterIndex) {
+        this.annotations = annotations;
+        this.type = type;
+        this.genericType = genericType;
+        this.parameterIndex = parameterIndex;
+    }
+
+    @Override
+    public boolean isAnnotationPresent(Class<? extends Annotation> paramClass) {
+        return getAnnotation(paramClass) != null;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Annotation> T getAnnotation(Class<T> paramClass) {
+        for (Annotation annotation : this.annotations) {
+            if (paramClass.isInstance(annotation)) {
+                return (T)annotation;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Annotation[] getAnnotations() {
+        return annotations;
+    }
+
+    @Override
+    public Annotation[] getDeclaredAnnotations() {
+        return annotations;
+    }
+
+    public Class<?> getType() {
+        return this.type;
+    }
+
+    public Type getGenericType() {
+        return this.genericType;
+    }
+
+    public int getParameterIndex() {
+        return this.parameterIndex;
+    }
+    
+    @Override
+    public String toString() {
+        return "Parameter" + this.parameterIndex + "[" + this.genericType.toString() + "]";
+    }
+    
+}
\ No newline at end of file

Added: sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/MapBackedInvocationHandler.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/MapBackedInvocationHandler.java?rev=1619007&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/MapBackedInvocationHandler.java (added)
+++ sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/MapBackedInvocationHandler.java Tue Aug 19 22:51:36 2014
@@ -0,0 +1,37 @@
+/*
+ * 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 java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.Map;
+
+class MapBackedInvocationHandler implements InvocationHandler {
+
+    private Map<Method, Object> methods;
+
+    public MapBackedInvocationHandler(Map<Method, Object> methods) {
+        this.methods = methods;
+    }
+
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        return methods.get(method);
+    }
+
+}
\ No newline at end of file

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=1619007&r1=1619006&r2=1619007&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 Tue Aug 19 22:51:36 2014
@@ -32,7 +32,6 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
@@ -69,6 +68,7 @@ import org.apache.sling.models.annotatio
 import org.apache.sling.models.annotations.Via;
 import org.apache.sling.models.spi.DisposalCallback;
 import org.apache.sling.models.spi.DisposalCallbackRegistry;
+import org.apache.sling.models.spi.AcceptsNullName;
 import org.apache.sling.models.spi.Injector;
 import org.apache.sling.models.spi.injectorspecific.InjectAnnotation;
 import org.apache.sling.models.spi.injectorspecific.InjectAnnotationProcessor;
@@ -83,23 +83,6 @@ import org.slf4j.LoggerFactory;
 @Component
 public class ModelAdapterFactory implements AdapterFactory, Runnable {
 
-    /**
-     * Comparator which sorts constructors by the number of parameters
-     * in reverse order (most params to least params).
-     */
-    public class ParameterCountComparator implements Comparator<Constructor<?>> {
-
-        @Override
-        public int compare(Constructor<?> o1, Constructor<?> o2) {
-            return compare(o2.getParameterTypes().length, o1.getParameterTypes().length);
-        }
-
-        public int compare(int x, int y) {
-            return (x < y) ? -1 : ((x == y) ? 0 : 1);
-        }
-
-    }
-
     private static class DisposalCallbackRegistryImpl implements DisposalCallbackRegistry {
 
         private List<DisposalCallback> callbacks = new ArrayList<DisposalCallback>();
@@ -125,20 +108,6 @@ public class ModelAdapterFactory impleme
 
     private ConcurrentMap<java.lang.ref.Reference<Object>, DisposalCallbackRegistryImpl> disposalCallbacks;
 
-    private static class MapBackedInvocationHandler implements InvocationHandler {
-
-        private Map<Method, Object> methods;
-
-        public MapBackedInvocationHandler(Map<Method, Object> methods) {
-            this.methods = methods;
-        }
-
-        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-            return methods.get(method);
-        }
-
-    }
-
     @Override
     public void run() {
         java.lang.ref.Reference<? extends Object> ref = queue.poll();
@@ -169,39 +138,72 @@ public class ModelAdapterFactory impleme
     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;
 
-    @SuppressWarnings("unchecked")
-    public <AdapterType> AdapterType getAdapter(Object adaptable, Class<AdapterType> type) {
-        Model modelAnnotation = type.getAnnotation(Model.class);
-        if (modelAnnotation == null) {
-            return null;
+    private static class ThreadInvocationCounter {
+        private int count;
+        public boolean isMaximumReached() {
+            return count >= MAX_RECURSIVE_INOVCATIONS;
         }
-        boolean isAdaptable = false;
-
-        Class<?>[] declaredAdaptable = modelAnnotation.adaptables();
-        for (Class<?> clazz : declaredAdaptable) {
-            if (clazz.isInstance(adaptable)) {
-                isAdaptable = true;
-            }
+        public void increase() {
+            this.count++;
         }
-        if (!isAdaptable) {
-            return null;
+        public void decrease() {
+            this.count--;
         }
+    }
 
-        if (type.isInterface()) {
-            InvocationHandler handler = createInvocationHandler(adaptable, type, modelAnnotation);
-            if (handler != null) {
-                return (AdapterType) Proxy.newProxyInstance(type.getClassLoader(), new Class<?>[] { type }, handler);
-            } else {
+    private static final ThreadLocal<ThreadInvocationCounter> INVOCATION_COUNT_THREADLOCAL = new ThreadLocal<ModelAdapterFactory.ThreadInvocationCounter>() {
+        @Override
+        protected ThreadInvocationCounter initialValue() {
+            return new ThreadInvocationCounter();
+        }
+    };
+
+    @SuppressWarnings("unchecked")
+    public <AdapterType> AdapterType getAdapter(Object adaptable, Class<AdapterType> type) {
+        if (INVOCATION_COUNT_THREADLOCAL.get().isMaximumReached()) {
+            log.error("Adapting {} to {} failed, too much recursive invocations (>={}).",
+                    new Object[] { adaptable, type, MAX_RECURSIVE_INOVCATIONS });
+            return null;
+        };
+        INVOCATION_COUNT_THREADLOCAL.get().increase();
+        try {
+            Model modelAnnotation = type.getAnnotation(Model.class);
+            if (modelAnnotation == null) {
                 return null;
             }
-        } else {
-            try {
-                return createObject(adaptable, type, modelAnnotation);
-            } catch (Exception e) {
-                log.error("unable to create object", e);
+            boolean isAdaptable = false;
+
+            Class<?>[] declaredAdaptable = modelAnnotation.adaptables();
+            for (Class<?> clazz : declaredAdaptable) {
+                if (clazz.isInstance(adaptable)) {
+                    isAdaptable = true;
+                }
+            }
+            if (!isAdaptable) {
                 return null;
             }
+
+            if (type.isInterface()) {
+                InvocationHandler handler = createInvocationHandler(adaptable, type, modelAnnotation);
+                if (handler != null) {
+                    return (AdapterType) Proxy.newProxyInstance(type.getClassLoader(), new Class<?>[] { type }, handler);
+                } else {
+                    return null;
+                }
+            } else {
+                try {
+                    return createObject(adaptable, type, modelAnnotation);
+                } catch (Exception e) {
+                    log.error("unable to create object", e);
+                    return null;
+                }
+            }
+        } finally {
+            INVOCATION_COUNT_THREADLOCAL.get().decrease();
         }
     }
 
@@ -276,14 +278,28 @@ public class ModelAdapterFactory impleme
             return setMethod((Method) element, methods, value);
         }
     }
+    
+    private static class SetConstructorParameterCallback implements InjectCallback {
+
+        private final List<Object> parameterValues;
 
-    private boolean injectFieldOrMethod(final AnnotatedElement element, final Object adaptable, final Type type,
+        private SetConstructorParameterCallback(List<Object> parameterValues) {
+            this.parameterValues = parameterValues;
+        }
+
+        @Override
+        public boolean inject(AnnotatedElement element, Object value) {
+            return setConstructorParameter((ConstructorParameter)element, parameterValues, value);
+        }
+    }
+
+    private boolean injectElement(final AnnotatedElement element, final Object adaptable, final Type type,
             final Model modelAnnotation, final DisposalCallbackRegistry registry, InjectCallback callback) {
 
         InjectAnnotationProcessor annotationProcessor = null;
         String source = getSource(element);
         boolean wasInjectionSuccessful = false;
-        
+
         // find an appropriate annotation processor
         for (InjectAnnotationProcessorFactory factory : sortedInjectAnnotationProcessorFactories) {
             annotationProcessor = factory.createAnnotationProcessor(adaptable, element);
@@ -292,16 +308,19 @@ public class ModelAdapterFactory impleme
             }
         }
 
+        String name = getName(element, annotationProcessor);
+        Object injectionAdaptable = getAdaptable(adaptable, element, annotationProcessor);
+
         // find the right injector
         for (Injector injector : sortedInjectors) {
             if (source == null || source.equals(injector.getName())) {
-                String name = getName(element, annotationProcessor);
-                Object injectionAdaptable = getAdaptable(adaptable, element, annotationProcessor);
-                if (injectionAdaptable != null) {
-                    Object value = injector.getValue(injectionAdaptable, name, type, element, registry);
-                    if (callback.inject(element, value)) {
-                        wasInjectionSuccessful = true;
-                        break;
+                if (name != null || injector instanceof AcceptsNullName) {
+                    if (injectionAdaptable != null) {
+                        Object value = injector.getValue(injectionAdaptable, name, type, element, registry);
+                        if (callback.inject(element, value)) {
+                            wasInjectionSuccessful = true;
+                            break;
+                        }
                     }
                 }
             }
@@ -324,12 +343,13 @@ public class ModelAdapterFactory impleme
         SetMethodsCallback callback = new SetMethodsCallback(methods);
         MapBackedInvocationHandler handler = new MapBackedInvocationHandler(methods);
 
-        DisposalCallbackRegistryImpl registry = createAndRegisterCallbackRegistry(handler);
+        DisposalCallbackRegistryImpl registry = new DisposalCallbackRegistryImpl();
+        registerCallbackRegistry(handler, registry);
         Set<Method> requiredMethods = new HashSet<Method>();
 
         for (Method method : injectableMethods) {
             Type returnType = mapPrimitiveClasses(method.getGenericReturnType());
-            if (!injectFieldOrMethod(method, adaptable, returnType, modelAnnotation, registry, callback)) {
+            if (!injectElement(method, adaptable, returnType, modelAnnotation, registry, callback)) {
                 requiredMethods.add(method);
             }
         }
@@ -341,11 +361,9 @@ public class ModelAdapterFactory impleme
         return handler;
     }
 
-    private DisposalCallbackRegistryImpl createAndRegisterCallbackRegistry(Object object) {
+    private void registerCallbackRegistry(Object object, DisposalCallbackRegistryImpl registry) {
         PhantomReference<Object> reference = new PhantomReference<Object>(object, queue);
-        DisposalCallbackRegistryImpl registry = new DisposalCallbackRegistryImpl();
         disposalCallbacks.put(reference, registry);
-        return registry;
     }
 
     private String getSource(AnnotatedElement element) {
@@ -380,60 +398,52 @@ public class ModelAdapterFactory impleme
         return null;
     }
 
-    @SuppressWarnings("unchecked")
     private <AdapterType> AdapterType createObject(Object adaptable, Class<AdapterType> type, Model modelAnnotation)
             throws InstantiationException, InvocationTargetException, IllegalAccessException {
-        Set<Field> injectableFields = collectInjectableFields(type);
+        DisposalCallbackRegistryImpl registry = new DisposalCallbackRegistryImpl();
 
-        Constructor<?>[] constructors = type.getConstructors();
-        if (constructors.length == 0) {
-            log.warn("Model class {} does not have a public constructor.", type.getName());
+        Constructor<AdapterType> constructorToUse = getBestMatchingConstructor(adaptable, type);
+        if (constructorToUse == null) {
+            log.warn("Model class {} does not have a usable constructor", type.getName());
             return null;
         }
 
-        // sort the constructor list in order from most params to least params
-        Arrays.sort(constructors, new ParameterCountComparator());
-
-        Constructor<AdapterType> constructorToUse = null;
-        boolean constructorHasParam = false;
-        for (Constructor<?> constructor : constructors) {
-            final Class<?>[] paramTypes = constructor.getParameterTypes();
-            if (paramTypes.length == 1) {
-                Class<?> paramType = constructor.getParameterTypes()[0];
-                if (paramType.isInstance(adaptable)) {
-                    constructorToUse = (Constructor<AdapterType>) constructor;
-                    constructorHasParam = true;
-                    break;
-                }
-            }
-
-            if (constructor.getParameterTypes().length == 0) {
-                constructorToUse = (Constructor<AdapterType>) constructor;
-                constructorHasParam = false;
-                break;
+        final AdapterType object;
+        if (constructorToUse.getParameterTypes().length == 0) {
+            // no parameters for constructor injection? instantiate it right away
+            object = constructorToUse.newInstance();
+        } else {
+            // instantiate with constructor injection
+            // if this fails, make sure resources that may be claimed by injectors are cleared up again
+            try {
+                object = newInstanceWithConstructorInjection(constructorToUse, adaptable, type, modelAnnotation, registry);
+            } catch (InstantiationException ex) {
+                registry.onDisposed();
+                throw ex;
+            } catch (InvocationTargetException ex) {
+                registry.onDisposed();
+                throw ex;
+            } catch (IllegalAccessException ex) {
+                registry.onDisposed();
+                throw ex;
             }
         }
 
-        if (constructorToUse == null) {
-            log.warn("Model class {} does not have a usable constructor", type.getName());
+        if (object == null) {
+            registry.onDisposed();
             return null;
         }
 
-        final AdapterType object;
-        if (constructorHasParam) {
-            object = constructorToUse.newInstance(adaptable);
-        } else {
-            object = constructorToUse.newInstance();
-        }
-        InjectCallback callback = new SetFieldCallback(object);
+        registerCallbackRegistry(object, registry);
 
-        DisposalCallbackRegistryImpl registry = createAndRegisterCallbackRegistry(object);
+        InjectCallback callback = new SetFieldCallback(object);
 
         Set<Field> requiredFields = new HashSet<Field>();
 
+        Set<Field> injectableFields = collectInjectableFields(type);
         for (Field field : injectableFields) {
             Type fieldType = mapPrimitiveClasses(field.getGenericType());
-            if (!injectFieldOrMethod(field, adaptable, fieldType, modelAnnotation, registry, callback)) {
+            if (!injectElement(field, adaptable, fieldType, modelAnnotation, registry, callback)) {
                 requiredFields.add(field);
             }
         }
@@ -453,6 +463,64 @@ public class ModelAdapterFactory impleme
 
     }
 
+    /**
+     * Gets best matching constructor for constructor injection - or default constructor if none is found.
+     * @param adaptable Adaptable instance
+     * @param type Model type
+     * @return Constructor or null if none found
+     */
+    @SuppressWarnings("unchecked")
+    private <AdapterType> Constructor<AdapterType> getBestMatchingConstructor(Object adaptable, Class<AdapterType> type) {
+        Constructor<?>[] constructors = type.getConstructors();
+
+        // sort the constructor list in order from most params to least params, and constructors with @Inject annotation first
+        Arrays.sort(constructors, new ParameterCountInjectComparator());
+
+        for (Constructor<?> constructor : constructors) {
+            // first try to find the constructor with most parameters and @Inject annotation
+            if (constructor.isAnnotationPresent(Inject.class)) {
+                return (Constructor<AdapterType>) constructor;
+            }
+            // compatibility mode for sling models implementation <= 1.0.6:
+            // support constructor without @Inject if it has exactly one parameter matching the adaptable class
+            final Class<?>[] paramTypes = constructor.getParameterTypes();
+            if (paramTypes.length == 1) {
+                Class<?> paramType = constructor.getParameterTypes()[0];
+                if (paramType.isInstance(adaptable)) {
+                    return (Constructor<AdapterType>) constructor;
+                }
+            }
+            // if no constructor for injection found use public constructor without any params
+            if (constructor.getParameterTypes().length == 0) {
+                return (Constructor<AdapterType>) constructor;
+            }
+        }
+        return null;
+    }
+
+    private <AdapterType> AdapterType newInstanceWithConstructorInjection(Constructor<AdapterType> constructor, Object adaptable,
+            Class<AdapterType> type, Model modelAnnotation, DisposalCallbackRegistry registry)
+            throws InstantiationException, InvocationTargetException, IllegalAccessException {
+        Set<ConstructorParameter> requiredParameters = new HashSet<ConstructorParameter>();
+        Type[] parameterTypes = constructor.getGenericParameterTypes();
+        List<Object> paramValues = new ArrayList<Object>(Arrays.asList(new Object[parameterTypes.length]));
+        InjectCallback callback = new SetConstructorParameterCallback(paramValues);
+
+        for (int i = 0; i < parameterTypes.length; i++) {
+            Type genericType = mapPrimitiveClasses(parameterTypes[i]);
+            ConstructorParameter constructorParameter = new ConstructorParameter(
+                    constructor.getParameterAnnotations()[i], constructor.getParameterTypes()[i], genericType, i);
+            if (!injectElement(constructorParameter, adaptable, genericType, modelAnnotation, registry, callback)) {
+                requiredParameters.add(constructorParameter);
+            }
+        }
+        if (!requiredParameters.isEmpty()) {
+            log.warn("Required constructor parameters {} on model class {} were not able to be injected.", requiredParameters, type);
+            return null;
+        }
+        return constructor.newInstance(paramValues.toArray(new Object[paramValues.size()]));
+    }
+
     private boolean isOptional(AnnotatedElement point, Model modelAnnotation, InjectAnnotationProcessor annotationProcessor) {
         if (annotationProcessor != null) {
             Boolean isOptional = annotationProcessor.isOptional();
@@ -582,6 +650,9 @@ public class ModelAdapterFactory impleme
             return getNameFromMethod((Method) element);
         } else if (element instanceof Field) {
             return getNameFromField((Field) element);
+        } else if (element instanceof ConstructorParameter) {
+            // implicit name not supported for constructor parameters - but do not throw exception because class-based injection is still possible
+            return null;
         } else {
             throw new IllegalArgumentException("The given element must be either method or field but is " + element);
         }
@@ -702,6 +773,27 @@ public class ModelAdapterFactory impleme
         }
     }
 
+    private static boolean setConstructorParameter(ConstructorParameter constructorParameter, List<Object> parameterValues, Object value) {
+        if (value != null && constructorParameter.getType() instanceof Class<?>) {
+            Class<?> requestedType = (Class<?>)constructorParameter.getType();
+            if (!isAcceptableType(requestedType, constructorParameter.getGenericType(), value)) {
+                if (value instanceof Adaptable) {
+                    value = ((Adaptable) value).adaptTo(requestedType);
+                    if (value == null) {
+                        return false;
+                    }
+                }
+                else {
+                    return false;
+                }
+            }
+            parameterValues.set(constructorParameter.getParameterIndex(), value);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
     private static boolean isAcceptableType(Class<?> type, Type genericType, Object value) {
         if (type.isInstance(value)) {
             if ((type == Collection.class || type == List.class) && genericType instanceof ParameterizedType &&

Added: sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/ParameterCountInjectComparator.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/ParameterCountInjectComparator.java?rev=1619007&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/ParameterCountInjectComparator.java (added)
+++ sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/ParameterCountInjectComparator.java Tue Aug 19 22:51:36 2014
@@ -0,0 +1,63 @@
+/*
+ * 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 java.lang.reflect.Constructor;
+import java.util.Comparator;
+
+import javax.inject.Inject;
+
+/**
+ * Comparator which sorts constructors by the number of parameters
+ * in reverse order (most params to least params).
+ * If two constructors have the same number of parameters constructors with
+ * @Inject annotation are sorted first.
+ */
+class ParameterCountInjectComparator implements Comparator<Constructor<?>> {
+
+    @Override
+    public int compare(Constructor<?> o1, Constructor<?> o2) {
+        int result = compareParameterCount(o2.getParameterTypes().length, o1.getParameterTypes().length);
+        if (result==0) {
+            return compareInjectAnnotation(o1, o2);
+        }
+        else {
+            return result;
+        }
+    }
+
+    private int compareParameterCount(int x, int y) {
+        return (x < y) ? -1 : ((x == y) ? 0 : 1);
+    }
+
+    private int compareInjectAnnotation(Constructor<?> o1, Constructor<?> o2) {
+        boolean hasInject1 = o1.isAnnotationPresent(Inject.class);
+        boolean hasInject2 = o2.isAnnotationPresent(Inject.class);
+        if (hasInject1 && !hasInject2) {
+            return -1;
+        }
+        else if (hasInject2 && !hasInject1) {
+            return 1;
+        }
+        else {
+            return 0;
+        }
+    }
+    
+}
\ No newline at end of file

Modified: sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/OSGiServiceInjector.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/OSGiServiceInjector.java?rev=1619007&r1=1619006&r2=1619007&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/OSGiServiceInjector.java (original)
+++ sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/OSGiServiceInjector.java Tue Aug 19 22:51:36 2014
@@ -38,6 +38,7 @@ import org.apache.sling.models.annotatio
 import org.apache.sling.models.annotations.injectorspecific.OSGiService;
 import org.apache.sling.models.spi.DisposalCallback;
 import org.apache.sling.models.spi.DisposalCallbackRegistry;
+import org.apache.sling.models.spi.AcceptsNullName;
 import org.apache.sling.models.spi.Injector;
 import org.apache.sling.models.spi.injectorspecific.AbstractInjectAnnotationProcessor;
 import org.apache.sling.models.spi.injectorspecific.InjectAnnotationProcessor;
@@ -53,7 +54,7 @@ import org.slf4j.LoggerFactory;
 @Component
 @Service
 @Property(name = Constants.SERVICE_RANKING, intValue = 5000)
-public class OSGiServiceInjector implements Injector, InjectAnnotationProcessorFactory {
+public class OSGiServiceInjector implements Injector, InjectAnnotationProcessorFactory, AcceptsNullName {
 
     private static final Logger log = LoggerFactory.getLogger(OSGiServiceInjector.class);
 

Added: sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/SelfInjector.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/SelfInjector.java?rev=1619007&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/SelfInjector.java (added)
+++ sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/injectors/SelfInjector.java Tue Aug 19 22:51:36 2014
@@ -0,0 +1,87 @@
+/*
+ * 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.models.annotations.injectorspecific.Self;
+import org.apache.sling.models.spi.DisposalCallbackRegistry;
+import org.apache.sling.models.spi.AcceptsNullName;
+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;
+
+/**
+ * Injects the adaptable object itself.
+ */
+@Component
+@Service
+@Property(name = Constants.SERVICE_RANKING, intValue = 100)
+public class SelfInjector implements Injector, InjectAnnotationProcessorFactory, AcceptsNullName {
+
+    @Override
+    public String getName() {
+        return "self";
+    }
+
+    public Object getValue(Object adaptable, String name, Type type, AnnotatedElement element,
+            DisposalCallbackRegistry callbackRegistry) {
+        // if the @Self annotation is present return the adaptable to be inserted directly or to be adapted from
+        if (element.isAnnotationPresent(Self.class)) {
+            return adaptable;
+        }
+        // otherwise apply class-based injection only if class matches or is a superclass
+        else if (type instanceof Class<?>) {
+            Class<?> requestedClass = (Class<?>)type;
+            if (requestedClass.isAssignableFrom(adaptable.getClass())) {
+                return adaptable;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public InjectAnnotationProcessor createAnnotationProcessor(Object adaptable, AnnotatedElement element) {
+        // check if the element has the expected annotation
+        Self annotation = element.getAnnotation(Self.class);
+        if (annotation != null) {
+            return new SelfAnnotationProcessor(annotation);
+        }
+        return null;
+    }
+
+    private static class SelfAnnotationProcessor extends AbstractInjectAnnotationProcessor {
+
+        private final Self annotation;
+
+        public SelfAnnotationProcessor(Self annotation) {
+            this.annotation = annotation;
+        }
+
+        @Override
+        public Boolean isOptional() {
+            return annotation.optional();
+        }
+    }
+
+}

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=1619007&r1=1619006&r2=1619007&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 Tue Aug 19 22:51:36 2014
@@ -21,11 +21,14 @@ import static org.mockito.Mockito.*;
 
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.models.impl.injectors.RequestAttributeInjector;
+import org.apache.sling.models.impl.injectors.SelfInjector;
 import org.apache.sling.models.testmodels.classes.InvalidConstructorModel;
 import org.apache.sling.models.testmodels.classes.SuperclassConstructorModel;
 import org.apache.sling.models.testmodels.classes.WithOneConstructorModel;
 import org.apache.sling.models.testmodels.classes.WithThreeConstructorsModel;
 import org.apache.sling.models.testmodels.classes.WithTwoConstructorsModel;
+import org.apache.sling.models.testmodels.classes.constructorinjection.NoNameModel;
+import org.apache.sling.models.testmodels.classes.constructorinjection.WithThreeConstructorsOneInjectModel;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -35,6 +38,7 @@ import org.osgi.framework.BundleContext;
 import org.osgi.service.component.ComponentContext;
 
 @RunWith(MockitoJUnitRunner.class)
+@SuppressWarnings("javadoc")
 public class ConstructorTest {
 
     @Mock
@@ -48,15 +52,21 @@ public class ConstructorTest {
     @Mock
     private SlingHttpServletRequest request;
 
+    private static final int INT_VALUE = 42;
+
+    private static final String STRING_VALUE = "myValue";
+
     @Before
     public void setup() {
         when(componentCtx.getBundleContext()).thenReturn(bundleContext);
 
-        when(request.getAttribute("attribute")).thenReturn(42);
+        when(request.getAttribute("attribute")).thenReturn(INT_VALUE);
+        when(request.getAttribute("attribute2")).thenReturn(STRING_VALUE);
 
         factory = new ModelAdapterFactory();
         factory.activate(componentCtx);
         factory.bindInjector(new RequestAttributeInjector(), new ServicePropertiesMap(1, 1));
+        factory.bindInjector(new SelfInjector(), new ServicePropertiesMap(2, 2));
     }
 
     @Test
@@ -64,7 +74,7 @@ public class ConstructorTest {
         WithOneConstructorModel model = factory.getAdapter(request, WithOneConstructorModel.class);
         assertNotNull(model);
         assertEquals(request, model.getRequest());
-        assertEquals(42, model.getAttribute());
+        assertEquals(INT_VALUE, model.getAttribute());
     }
 
     @Test
@@ -72,7 +82,7 @@ public class ConstructorTest {
         WithThreeConstructorsModel model = factory.getAdapter(request, WithThreeConstructorsModel.class);
         assertNotNull(model);
         assertEquals(request, model.getRequest());
-        assertEquals(42, model.getAttribute());
+        assertEquals(INT_VALUE, model.getAttribute());
     }
 
     @Test
@@ -80,7 +90,7 @@ public class ConstructorTest {
         WithTwoConstructorsModel model = factory.getAdapter(request, WithTwoConstructorsModel.class);
         assertNotNull(model);
         assertEquals(request, model.getRequest());
-        assertEquals(42, model.getAttribute());
+        assertEquals(INT_VALUE, model.getAttribute());
     }
 
     @Test
@@ -88,7 +98,7 @@ public class ConstructorTest {
         SuperclassConstructorModel model = factory.getAdapter(request, SuperclassConstructorModel.class);
         assertNotNull(model);
         assertEquals(request, model.getRequest());
-        assertEquals(42, model.getAttribute());
+        assertEquals(INT_VALUE, model.getAttribute());
     }
 
     @Test
@@ -97,4 +107,23 @@ public class ConstructorTest {
         assertNull(model);
     }
 
+    /**
+     * Test model object with three constructors, and make sure that one with @Inject is picked for instantiation.
+     * Test mixing of constructor injection and field injection as well.
+     */
+    @Test
+    public void testThreeConstructorsOneInjectInjection() {
+        WithThreeConstructorsOneInjectModel model = factory.getAdapter(request,
+                WithThreeConstructorsOneInjectModel.class);
+        assertNotNull(model);
+        assertNull(model.getRequest());
+        assertEquals(INT_VALUE, model.getAttribute());
+        assertEquals(STRING_VALUE, model.getAttribute2());
+    }
+
+    @Test
+    public void testNoNameModel() {
+        NoNameModel model = factory.getAdapter(request, NoNameModel.class);
+        assertNull(model);
+    }
 }

Modified: sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/DefaultTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/DefaultTest.java?rev=1619007&r1=1619006&r2=1619007&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/DefaultTest.java (original)
+++ sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/DefaultTest.java Tue Aug 19 22:51:36 2014
@@ -39,6 +39,7 @@ import org.osgi.framework.BundleContext;
 import org.osgi.service.component.ComponentContext;
 
 @RunWith(MockitoJUnitRunner.class)
+@SuppressWarnings("javadoc")
 public class DefaultTest {
 
     @Mock
@@ -58,7 +59,7 @@ public class DefaultTest {
     }
 
     @Test
-    public void testDefaultStringValue() {
+    public void testDefaultStringValueField() {
         ValueMap vm = new ValueMapDecorator(Collections.<String, Object>emptyMap());
 
         Resource res = mock(Resource.class);
@@ -71,7 +72,7 @@ public class DefaultTest {
     }
 
     @Test
-    public void testDefaultStringValueOnInterface() {
+    public void testDefaultStringValueOnInterfaceField() {
         ValueMap vm = new ValueMapDecorator(Collections.<String, Object>singletonMap("first", "first value"));
 
         Resource res = mock(Resource.class);
@@ -85,7 +86,7 @@ public class DefaultTest {
 
 
     @Test
-    public void testDefaultPrimitives() {
+    public void testDefaultPrimitivesField() {
         ValueMap vm = new ValueMapDecorator(Collections.<String, Object>emptyMap());
 
         Resource res = mock(Resource.class);
@@ -103,7 +104,7 @@ public class DefaultTest {
     }
 
     @Test
-    public void testDefaultWrappers() {
+    public void testDefaultWrappersField() {
         ValueMap vm = new ValueMapDecorator(Collections.<String, Object>emptyMap());
 
         Resource res = mock(Resource.class);
@@ -119,4 +120,57 @@ public class DefaultTest {
         assertEquals(Long.valueOf(1L), model.getLongWrapperProperty());
         assertArrayEquals(new Long[] { Long.valueOf(1L), Long.valueOf(1L) }, model.getLongWrapperArrayProperty());
     }
+
+    @Test
+    public void testDefaultStringValueConstructor() {
+        ValueMap vm = new ValueMapDecorator(Collections.<String, Object>emptyMap());
+
+        Resource res = mock(Resource.class);
+        when(res.adaptTo(ValueMap.class)).thenReturn(vm);
+
+        org.apache.sling.models.testmodels.classes.constructorinjection.DefaultStringModel model
+                = factory.getAdapter(res, org.apache.sling.models.testmodels.classes.constructorinjection.DefaultStringModel.class);
+        assertNotNull(model);
+        assertEquals("firstDefault", model.getFirstProperty());
+        assertEquals(2, model.getSecondProperty().length);
+    }
+
+    @Test
+    public void testDefaultPrimitivesConstructor() {
+        ValueMap vm = new ValueMapDecorator(Collections.<String, Object>emptyMap());
+
+        Resource res = mock(Resource.class);
+        when(res.adaptTo(ValueMap.class)).thenReturn(vm);
+
+        org.apache.sling.models.testmodels.classes.constructorinjection.DefaultPrimitivesModel model
+                = factory.getAdapter(res, org.apache.sling.models.testmodels.classes.constructorinjection.DefaultPrimitivesModel.class);
+        assertNotNull(model);
+
+        assertEquals(true, model.getBooleanProperty());
+        // we need to wait for JUnit 4.12 for this assertArrayEquals to be working on primitive boolean arrays, https://github.com/junit-team/junit/issues/86!
+        assertTrue(Arrays.equals(new boolean[] { true, true }, model.getBooleanArrayProperty()));
+
+        assertEquals(1L, model.getLongProperty());
+        assertArrayEquals(new long[] { 1L, 1L }, model.getLongArrayProperty());
+    }
+
+    @Test
+    public void testDefaultWrappersConstructor() {
+        ValueMap vm = new ValueMapDecorator(Collections.<String, Object>emptyMap());
+
+        Resource res = mock(Resource.class);
+        when(res.adaptTo(ValueMap.class)).thenReturn(vm);
+
+        org.apache.sling.models.testmodels.classes.constructorinjection.DefaultWrappersModel model
+                = factory.getAdapter(res, org.apache.sling.models.testmodels.classes.constructorinjection.DefaultWrappersModel.class);
+        assertNotNull(model);
+
+        assertEquals(Boolean.valueOf(true), model.getBooleanWrapperProperty());
+        // we need to wait for JUnit 4.12 for this assertArrayEquals to be working on primitive boolean arrays, https://github.com/junit-team/junit/issues/86!
+        assertTrue(Arrays.equals(new Boolean[] { Boolean.TRUE, Boolean.TRUE }, model.getBooleanWrapperArrayProperty()));
+
+        assertEquals(Long.valueOf(1L), model.getLongWrapperProperty());
+        assertArrayEquals(new Long[] { Long.valueOf(1L), Long.valueOf(1L) }, model.getLongWrapperArrayProperty());
+    }
+
 }

Modified: sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/InjectorSpecificAnnotationTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/InjectorSpecificAnnotationTest.java?rev=1619007&r1=1619006&r2=1619007&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/InjectorSpecificAnnotationTest.java (original)
+++ sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/InjectorSpecificAnnotationTest.java Tue Aug 19 22:51:36 2014
@@ -50,6 +50,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @RunWith(MockitoJUnitRunner.class)
+@SuppressWarnings("javadoc")
 public class InjectorSpecificAnnotationTest {
 
     @Mock
@@ -110,7 +111,7 @@ public class InjectorSpecificAnnotationT
     }
 
     @Test
-    public void testSimpleValueModel() {
+    public void testSimpleValueModelField() {
         Map<String, Object> map = new HashMap<String, Object>();
         map.put("first", "first-value");
         map.put("second", "second-value");
@@ -127,7 +128,7 @@ public class InjectorSpecificAnnotationT
     }
 
     @Test
-    public void testOrderForValueAnnotation() {
+    public void testOrderForValueAnnotationField() {
         // make sure that that the correct injection is used
         // make sure that log is adapted from value map
         // and not coming from request attribute
@@ -149,7 +150,7 @@ public class InjectorSpecificAnnotationT
     }
 
     @Test
-    public void testOSGiService() throws InvalidSyntaxException {
+    public void testOSGiServiceField() throws InvalidSyntaxException {
         ServiceReference ref = mock(ServiceReference.class);
         Logger log = mock(Logger.class);
         when(bundleContext.getServiceReferences(Logger.class.getName(), null)).thenReturn(
@@ -162,7 +163,7 @@ public class InjectorSpecificAnnotationT
     }
 
     @Test
-    public void testScriptVariable() throws InvalidSyntaxException {
+    public void testScriptVariableField() throws InvalidSyntaxException {
         SlingBindings bindings = new SlingBindings();
         SlingScriptHelper helper = mock(SlingScriptHelper.class);
         bindings.setSling(helper);
@@ -174,7 +175,7 @@ public class InjectorSpecificAnnotationT
     }
 
     @Test
-    public void testRequestAttribute() throws InvalidSyntaxException {
+    public void testRequestAttributeField() throws InvalidSyntaxException {
         Object attribute = new Object();
         when(request.getAttribute("attribute")).thenReturn(attribute);
 
@@ -184,7 +185,7 @@ public class InjectorSpecificAnnotationT
     }
 
     @Test
-    public void testChildResource() {
+    public void testChildResourceField() {
         Resource res = mock(Resource.class);
         Resource child = mock(Resource.class);
         when(res.getChild("child1")).thenReturn(child);
@@ -194,4 +195,97 @@ public class InjectorSpecificAnnotationT
         assertNotNull("Could not instanciate model", model);
         assertEquals(child, model.getChildResource());
     }
+
+    @Test
+    public void testSimpleValueModelConstructor() {
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("first", "first-value");
+        map.put("second", "second-value");
+        ValueMap vm = new ValueMapDecorator(map);
+
+        Resource res = mock(Resource.class);
+        when(res.adaptTo(ValueMap.class)).thenReturn(vm);
+        when(request.getResource()).thenReturn(res);
+
+        org.apache.sling.models.testmodels.classes.constructorinjection.InjectorSpecificAnnotationModel model
+                = factory.getAdapter(request, org.apache.sling.models.testmodels.classes.constructorinjection.InjectorSpecificAnnotationModel.class);
+        assertNotNull("Could not instanciate model", model);
+        assertEquals("first-value", model.getFirst());
+        assertEquals("second-value", model.getSecond());
+    }
+
+    @Test
+    public void testOrderForValueAnnotationConstructor() {
+        // make sure that that the correct injection is used
+        // make sure that log is adapted from value map
+        // and not coming from request attribute
+        Logger logFromValueMap = LoggerFactory.getLogger(this.getClass());
+
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("first", "first-value");
+        map.put("log", logFromValueMap);
+        ValueMap vm = new ValueMapDecorator(map);
+
+        Resource res = mock(Resource.class);
+        when(res.adaptTo(ValueMap.class)).thenReturn(vm);
+        when(request.getResource()).thenReturn(res);
+
+        org.apache.sling.models.testmodels.classes.constructorinjection.InjectorSpecificAnnotationModel model
+                = factory.getAdapter(request, org.apache.sling.models.testmodels.classes.constructorinjection.InjectorSpecificAnnotationModel.class);
+        assertNotNull("Could not instanciate model", model);
+        assertEquals("first-value", model.getFirst());
+        assertEquals(logFromValueMap, model.getLog());
+    }
+
+    @Test
+    public void testOSGiServiceConstructor() throws InvalidSyntaxException {
+        ServiceReference ref = mock(ServiceReference.class);
+        Logger log = mock(Logger.class);
+        when(bundleContext.getServiceReferences(Logger.class.getName(), null)).thenReturn(
+                new ServiceReference[] { ref });
+        when(bundleContext.getService(ref)).thenReturn(log);
+
+        org.apache.sling.models.testmodels.classes.constructorinjection.InjectorSpecificAnnotationModel model
+                = factory.getAdapter(request, org.apache.sling.models.testmodels.classes.constructorinjection.InjectorSpecificAnnotationModel.class);
+        assertNotNull("Could not instanciate model", model);
+        assertEquals(log, model.getService());
+    }
+
+    @Test
+    public void testScriptVariableConstructor() throws InvalidSyntaxException {
+        SlingBindings bindings = new SlingBindings();
+        SlingScriptHelper helper = mock(SlingScriptHelper.class);
+        bindings.setSling(helper);
+        when(request.getAttribute(SlingBindings.class.getName())).thenReturn(bindings);
+
+        org.apache.sling.models.testmodels.classes.constructorinjection.InjectorSpecificAnnotationModel model
+                = factory.getAdapter(request, org.apache.sling.models.testmodels.classes.constructorinjection.InjectorSpecificAnnotationModel.class);
+        assertNotNull("Could not instanciate model", model);
+        assertEquals(helper, model.getHelper());
+    }
+
+    @Test
+    public void testRequestAttributeConstructor() throws InvalidSyntaxException {
+        Object attribute = new Object();
+        when(request.getAttribute("attribute")).thenReturn(attribute);
+
+        org.apache.sling.models.testmodels.classes.constructorinjection.InjectorSpecificAnnotationModel model
+                = factory.getAdapter(request, org.apache.sling.models.testmodels.classes.constructorinjection.InjectorSpecificAnnotationModel.class);
+        assertNotNull("Could not instanciate model", model);
+        assertEquals(attribute, model.getRequestAttribute());
+    }
+
+    @Test
+    public void testChildResourceConstructor() {
+        Resource res = mock(Resource.class);
+        Resource child = mock(Resource.class);
+        when(res.getChild("child1")).thenReturn(child);
+        when(request.getResource()).thenReturn(res);
+
+        org.apache.sling.models.testmodels.classes.constructorinjection.InjectorSpecificAnnotationModel model
+                = factory.getAdapter(request, org.apache.sling.models.testmodels.classes.constructorinjection.InjectorSpecificAnnotationModel.class);
+        assertNotNull("Could not instanciate model", model);
+        assertEquals(child, model.getChildResource());
+    }
+
 }

Modified: sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/OSGiInjectionTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/OSGiInjectionTest.java?rev=1619007&r1=1619006&r2=1619007&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/OSGiInjectionTest.java (original)
+++ sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/OSGiInjectionTest.java Tue Aug 19 22:51:36 2014
@@ -47,6 +47,7 @@ import org.osgi.framework.ServiceReferen
 import org.osgi.service.component.ComponentContext;
 
 @RunWith(MockitoJUnitRunner.class)
+@SuppressWarnings("javadoc")
 public class OSGiInjectionTest {
     private ModelAdapterFactory factory;
 
@@ -75,7 +76,7 @@ public class OSGiInjectionTest {
     }
 
     @Test
-    public void testSimpleOSGiModel() throws Exception {
+    public void testSimpleOSGiModelField() throws Exception {
         ServiceReference ref = mock(ServiceReference.class);
         ServiceInterface service = mock(ServiceInterface.class);
         when(bundleContext.getServiceReferences(ServiceInterface.class.getName(), null)).thenReturn(
@@ -93,7 +94,7 @@ public class OSGiInjectionTest {
     }
 
     @Test
-    public void testRequestOSGiModel() throws Exception {
+    public void testRequestOSGiModelField() throws Exception {
         ServiceInterface service = mock(ServiceInterface.class);
 
         SlingHttpServletRequest request = mock(SlingHttpServletRequest.class);
@@ -114,7 +115,7 @@ public class OSGiInjectionTest {
     }
 
     @Test
-    public void testListOSGiModel() throws Exception {
+    public void testListOSGiModelField() throws Exception {
         ServiceReference ref1 = mock(ServiceReference.class);
         ServiceInterface service1 = mock(ServiceInterface.class);
         when(bundleContext.getService(ref1)).thenReturn(service1);
@@ -138,7 +139,7 @@ public class OSGiInjectionTest {
     }
 
     @Test
-    public void testArrayOSGiModel() throws Exception {
+    public void testArrayOSGiModelField() throws Exception {
         ServiceReference ref1 = mock(ServiceReference.class);
         ServiceInterface service1 = mock(ServiceInterface.class);
         when(bundleContext.getService(ref1)).thenReturn(service1);
@@ -162,7 +163,7 @@ public class OSGiInjectionTest {
     }
 
     @Test
-    public void testOptionalArrayOSGiModel() throws Exception {
+    public void testOptionalArrayOSGiModelField() throws Exception {
 
         Resource res = mock(Resource.class);
 
@@ -174,7 +175,7 @@ public class OSGiInjectionTest {
     }
 
     @Test
-    public void testOptionalListOSGiModel() throws Exception {
+    public void testOptionalListOSGiModelField() throws Exception {
         Resource res = mock(Resource.class);
 
         OptionalListOSGiModel model = factory.getAdapter(res, OptionalListOSGiModel.class);
@@ -185,7 +186,7 @@ public class OSGiInjectionTest {
     }
 
     @Test
-    public void testCollectionOSGiModel() throws Exception {
+    public void testCollectionOSGiModelField() throws Exception {
         ServiceReference ref1 = mock(ServiceReference.class);
         ServiceInterface service1 = mock(ServiceInterface.class);
         when(bundleContext.getService(ref1)).thenReturn(service1);
@@ -210,7 +211,7 @@ public class OSGiInjectionTest {
     }
 
     @Test
-    public void testSetOSGiModel() throws Exception {
+    public void testSetOSGiModelField() throws Exception {
         ServiceReference ref1 = mock(ServiceReference.class);
         ServiceInterface service1 = mock(ServiceInterface.class);
         when(bundleContext.getService(ref1)).thenReturn(service1);
@@ -232,4 +233,49 @@ public class OSGiInjectionTest {
         verify(bundleContext).getBundles();
         verifyNoMoreInteractions(res, bundleContext);
     }
+
+    @Test
+    public void testSimpleOSGiModelConstructor() throws Exception {
+        ServiceReference ref = mock(ServiceReference.class);
+        ServiceInterface service = mock(ServiceInterface.class);
+        when(bundleContext.getServiceReferences(ServiceInterface.class.getName(), null)).thenReturn(
+                new ServiceReference[] { ref });
+        when(bundleContext.getService(ref)).thenReturn(service);
+
+        Resource res = mock(Resource.class);
+
+        org.apache.sling.models.testmodels.classes.constructorinjection.SimpleOSGiModel model
+                = factory.getAdapter(res, org.apache.sling.models.testmodels.classes.constructorinjection.SimpleOSGiModel.class);
+        assertNotNull(model);
+        assertNotNull(model.getService());
+        assertEquals(service, model.getService());
+
+        verifyNoMoreInteractions(res);
+    }
+
+    @Test
+    public void testListOSGiModelConstructor() throws Exception {
+        ServiceReference ref1 = mock(ServiceReference.class);
+        ServiceInterface service1 = mock(ServiceInterface.class);
+        when(bundleContext.getService(ref1)).thenReturn(service1);
+        ServiceReference ref2 = mock(ServiceReference.class);
+        ServiceInterface service2 = mock(ServiceInterface.class);
+        when(bundleContext.getService(ref2)).thenReturn(service2);
+
+        when(bundleContext.getServiceReferences(ServiceInterface.class.getName(), null)).thenReturn(
+                new ServiceReference[] { ref1, ref2 });
+
+        Resource res = mock(Resource.class);
+
+        org.apache.sling.models.testmodels.classes.constructorinjection.ListOSGiModel model
+                = factory.getAdapter(res, org.apache.sling.models.testmodels.classes.constructorinjection.ListOSGiModel.class);
+        assertNotNull(model);
+        assertNotNull(model.getServices());
+        assertEquals(2, model.getServices().size());
+        assertEquals(service1, model.getServices().get(0));
+        assertEquals(service2, model.getServices().get(1));
+
+        verifyNoMoreInteractions(res);
+    }
+
 }



Mime
View raw message