Author: kwin
Date: Tue Dec  9 14:46:28 2014
New Revision: 1644069

URL: http://svn.apache.org/r1644069
Log:
SLING-4161 support Sling Validation by a new field on the Model annotation

The dependency to Sling Validation is optional (i.e. Sling Models still work 
even if  Sling Validation is not deployed)

Added:
    
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/ValidationStrategy.java
    
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidResourceException.java
    
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidValidationModelException.java
    
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/ModelClassException.java
    
sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/validation/
    
sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/validation/ModelValidation.java
    
sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/validation/ModelValidationImpl.java
Removed:
    
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidModelException.java
Modified:
    sling/trunk/bundles/extensions/models/api/pom.xml
    
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Model.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/factory/ModelFactory.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/Result.java
    
sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/AdapterFactoryTest.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/InvalidAdaptationsTest.java
    
sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/PostConstructTest.java

Modified: sling/trunk/bundles/extensions/models/api/pom.xml
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/pom.xml?rev=1644069&r1=1644068&r2=1644069&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/pom.xml (original)
+++ sling/trunk/bundles/extensions/models/api/pom.xml Tue Dec  9 14:46:28 2014
@@ -49,6 +49,7 @@
                 <configuration>
                    <instructions>
                         
<Export-Package>org.apache.sling.models.*,javax.inject;version=0</Export-Package>
+                        
<DynamicImport-Package>org.apache.sling.validation.api.*</DynamicImport-Package>
                    </instructions>
                 </configuration>
             </plugin>
@@ -61,5 +62,18 @@
             <version>1</version>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.validation.api</artifactId>
+            <version>1.0.0-SNAPSHOT</version>
+            <scope>provided</scope>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+            <version>2.5</version>
+            <scope>provided</scope>
+        </dependency>
     </dependencies>
 </project>

Modified: 
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Model.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Model.java?rev=1644069&r1=1644068&r2=1644069&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Model.java
 (original)
+++ 
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/Model.java
 Tue Dec  9 14:46:28 2014
@@ -50,5 +50,14 @@ public @interface Model {
      * @return Condition that is displayed in the felix console adapter plugin
      */
     public String condition() default "";
+    
+    /**
+     * 
+     * @return {@link ValidationStrategy.DISABLED} in case the model should 
not be validated through Sling Validation (default),
+     *  {@link ValidationStrategy.REQUIRED} in case the model should be 
validated and if no appropriate Sling Validation Model exists it is considered 
invalid or
+     *  {@link ValidationStrategy.OPTIONAL} in case the model should be 
validated only in case an appropriate Sling Validation Model is found.
+     * @see <a 
href="http://sling.apache.org/documentation/bundles/validation.html";>Sling 
Validation</a>
+     */
+    public ValidationStrategy validation() default ValidationStrategy.DISABLED;
 
 }

Added: 
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/ValidationStrategy.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/ValidationStrategy.java?rev=1644069&view=auto
==============================================================================
--- 
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/ValidationStrategy.java
 (added)
+++ 
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/annotations/ValidationStrategy.java
 Tue Dec  9 14:46:28 2014
@@ -0,0 +1,24 @@
+/*
+ * 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.annotations;
+
+/** 
+ * Used by the {@link Model} annotation.
+ */
+public enum ValidationStrategy {
+    DISABLED, REQUIRED, OPTIONAL
+}

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=1644069&r1=1644068&r2=1644069&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 Dec  9 14:46:28 2014
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("1.1.3")
+@Version("1.2.0")
 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/factory/InvalidResourceException.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidResourceException.java?rev=1644069&view=auto
==============================================================================
--- 
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidResourceException.java
 (added)
+++ 
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidResourceException.java
 Tue Dec  9 14:46:28 2014
@@ -0,0 +1,68 @@
+/*
+ * 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.factory;
+
+import java.util.List;
+import java.util.Map.Entry;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.sling.validation.api.ValidationResult;
+
+/**
+ * Thrown in case Sling Validation detected an invalid resource upon which the 
model should be instanciated.
+ * @see <a 
href="http://sling.apache.org/documentation/bundles/validation.html";>Sling 
Validation</a>
+ * @see ModelFactory
+ */
+public class InvalidResourceException extends RuntimeException {
+    private static final long serialVersionUID = 366657841414210438L;
+    private final ValidationResult result;
+    private final String path;
+
+    public InvalidResourceException(ValidationResult result, String path) {
+        if (result.isValid()) {
+            throw new IllegalArgumentException("Could not create a validator 
exception from a valid validation result!");
+        }
+        this.path = path;
+        this.result = result;
+    }
+    
+    /**
+     * 
+     * @return the underlying {@link ValidationResult}
+     */
+    public ValidationResult getResult() {
+        return result;
+    }
+    
+    /**
+     * 
+     * @return the path of the resource which was considered invalid
+     */
+    public String getPath() {
+        return path;
+    }
+
+    @Override
+    public String getMessage() {
+        StringBuilder builder = new StringBuilder("Validation errors for ");
+        builder.append("'" + path +"':");
+        for (Entry<String, List<String>> entry : 
result.getFailureMessages().entrySet()) {
+            builder.append("\n" + entry.getKey() + ":" + 
StringUtils.join(entry.getValue(), "\n\t"));
+        }
+        return builder.toString();
+    }
+}

Added: 
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidValidationModelException.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidValidationModelException.java?rev=1644069&view=auto
==============================================================================
--- 
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidValidationModelException.java
 (added)
+++ 
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidValidationModelException.java
 Tue Dec  9 14:46:28 2014
@@ -0,0 +1,38 @@
+/*
+ * 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.factory;
+
+/**
+ * Thrown in case an invalid Sling validation model was found or no validation 
model was found at all 
+ * (although it would be required through {@link 
org.apache.sling.models.annotations.ValidationStrategy.REQUIRED}).
+ * Usually just wraps a {@link 
org.apache.sling.validation.api.exceptions.SlingValidationException}
+ * @see <a 
href="http://sling.apache.org/documentation/bundles/validation.html";>Sling 
Validation</a>
+ * @see ModelFactory
+ */
+public class InvalidValidationModelException extends RuntimeException {
+
+    private static final long serialVersionUID = 1115037385798809055L;
+
+    public InvalidValidationModelException(String message) {
+        super(message);
+    }
+
+    public InvalidValidationModelException(Throwable cause) {
+        super(cause);
+    }
+
+}

Added: 
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/ModelClassException.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/ModelClassException.java?rev=1644069&view=auto
==============================================================================
--- 
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/ModelClassException.java
 (added)
+++ 
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/ModelClassException.java
 Tue Dec  9 14:46:28 2014
@@ -0,0 +1,35 @@
+/*
+ * 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.factory;
+
+/**
+ * Exception which is triggered when the Model class could not be instantiated 
due to
+ * not having a model annotation, some reflection error, invalid constructors 
or 
+ * because some exception within the post construct method was triggered.
+ * 
+ * @see ModelFactory
+ */
+public final class ModelClassException extends RuntimeException {
+
+    private static final long serialVersionUID = 4323592065808565135L;
+
+    public ModelClassException(String message) {
+        super(message);
+    }
+}

Modified: 
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/ModelFactory.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/ModelFactory.java?rev=1644069&r1=1644068&r2=1644069&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/ModelFactory.java
 (original)
+++ 
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/ModelFactory.java
 Tue Dec  9 14:46:28 2014
@@ -18,6 +18,7 @@
  */
 package org.apache.sling.models.factory;
 
+
 /**
  * The ModelFactory instantiates Sling Model classes similar to adaptTo but is 
allowed to throw an exception in case
  * instantiation fails for some reason.
@@ -31,19 +32,21 @@ public interface ModelFactory {
      * @return a new instance for the required model (never null)
      * @throws MissingElementsException in case no injector was able to inject 
some required values with the given types
      * @throws InvalidAdaptableException in case the given class cannot be 
instantiated from the given adaptable (different adaptable on the model 
annotation)
-     * @throws InvalidModelException in case the model could not be 
instanciated because model annotation was missing, reflection failed, no valid 
constructor was found or post-construct has thrown an error
+     * @throws ModelClassException in case the model could not be instanciated 
because model annotation was missing, reflection failed, no valid constructor 
was found or post-construct has thrown an error
+     * @throws InvalidValidationModelException in case an invalid validation 
model was found
+     * @throws InvalidResourceException in case the resource (for the Sling 
Model) could not be validated through Sling Validation
      */
     public <ModelType> ModelType createModel(Object adaptable, 
Class<ModelType> type) throws MissingElementsException,
-            InvalidAdaptableException, InvalidModelException;
+            InvalidAdaptableException, ModelClassException, 
InvalidValidationModelException, InvalidResourceException;
 
     /**
      * 
      * @param adaptable the adaptable to check
      * @param type the class to check
      * @return false in case the given class can not be created from the given 
adaptable
-     * @throws InvalidModelException in case no class with the Model 
annotation adapts to the requested type
+     * @throws ModelClassException in case no class with the Model annotation 
adapts to the requested type
      */
-    public boolean canCreateFromAdaptable(Object adaptable, Class<?> type) 
throws InvalidModelException;
+    public boolean canCreateFromAdaptable(Object adaptable, Class<?> type) 
throws ModelClassException;
 
     /**
      * 

Modified: sling/trunk/bundles/extensions/models/impl/pom.xml
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/pom.xml?rev=1644069&r1=1644068&r2=1644069&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/pom.xml (original)
+++ sling/trunk/bundles/extensions/models/impl/pom.xml Tue Dec  9 14:46:28 2014
@@ -54,6 +54,7 @@
                         <Embed-Dependency>
                             *;scope=compile,
                             
org.osgi.compendium;inline="org/osgi/util/tracker/*"</Embed-Dependency>
+                        
<DynamicImport-Package>org.apache.sling.validation.api.*</DynamicImport-Package>
                     </instructions>
                 </configuration>
             </plugin>
@@ -138,5 +139,12 @@
             <version>1.8.3</version>
             <scope>compile</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.validation.api</artifactId>
+            <version>1.0.0-SNAPSHOT</version>
+            <scope>provided</scope>
+            <optional>true</optional>
+        </dependency>
     </dependencies>
 </project>

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=1644069&r1=1644068&r2=1644069&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 Dec  9 14:46:28 2014
@@ -52,15 +52,21 @@ import org.apache.felix.scr.annotations.
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.apache.felix.scr.annotations.ReferencePolicy;
+import org.apache.felix.scr.annotations.ReferencePolicyOption;
 import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.adapter.Adaptable;
 import org.apache.sling.api.adapter.AdapterFactory;
+import org.apache.sling.api.resource.Resource;
 import org.apache.sling.commons.osgi.PropertiesUtil;
 import org.apache.sling.commons.osgi.ServiceUtil;
 import org.apache.sling.models.annotations.Model;
+import org.apache.sling.models.annotations.ValidationStrategy;
 import org.apache.sling.models.factory.InvalidAdaptableException;
-import org.apache.sling.models.factory.InvalidModelException;
+import org.apache.sling.models.factory.InvalidResourceException;
+import org.apache.sling.models.factory.InvalidValidationModelException;
 import org.apache.sling.models.factory.MissingElementsException;
+import org.apache.sling.models.factory.ModelClassException;
 import org.apache.sling.models.factory.ModelFactory;
 import org.apache.sling.models.impl.Result.FailureType;
 import org.apache.sling.models.impl.model.ConstructorParameter;
@@ -69,6 +75,7 @@ import org.apache.sling.models.impl.mode
 import org.apache.sling.models.impl.model.InjectableMethod;
 import org.apache.sling.models.impl.model.ModelClass;
 import org.apache.sling.models.impl.model.ModelClassConstructor;
+import org.apache.sling.models.impl.validation.ModelValidation;
 import org.apache.sling.models.spi.AcceptsNullName;
 import org.apache.sling.models.spi.DisposalCallback;
 import org.apache.sling.models.spi.DisposalCallbackRegistry;
@@ -157,6 +164,9 @@ public class ModelAdapterFactory impleme
     @Reference(name = "implementationPicker", referenceInterface = 
ImplementationPicker.class,
             cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, policy = 
ReferencePolicy.DYNAMIC)
     private final Map<Object, ImplementationPicker> implementationPickers = 
new TreeMap<Object, ImplementationPicker>();
+    
+    @Reference(cardinality=ReferenceCardinality.OPTIONAL_UNARY, 
policyOption=ReferencePolicyOption.GREEDY)
+    private ModelValidation modelValidation;
 
     ModelPackageBundleListener listener;
 
@@ -177,21 +187,21 @@ public class ModelAdapterFactory impleme
 
     @Override
     public <ModelType> ModelType createModel(Object adaptable, 
Class<ModelType> type) throws MissingElementsException,
-            InvalidAdaptableException, InvalidModelException {
+            InvalidAdaptableException, InvalidValidationModelException, 
InvalidResourceException {
         Result<ModelType> result = internalCreateModel(adaptable, type);
         result.throwException(log);
         return result.getModel();
     }
 
     @Override
-    public boolean canCreateFromAdaptable(Object adaptable, Class<?> 
modelClass) throws InvalidModelException {
+    public boolean canCreateFromAdaptable(Object adaptable, Class<?> 
modelClass) throws ModelClassException {
         return innerCanCreateFromAdaptable(adaptable, modelClass);
     }
 
-    private boolean innerCanCreateFromAdaptable(Object adaptable, Class<?> 
requestedType) throws InvalidModelException {
+    private boolean innerCanCreateFromAdaptable(Object adaptable, Class<?> 
requestedType) throws ModelClassException {
         ModelClass<?> modelClass = 
getImplementationTypeForAdapterType(requestedType, adaptable);
         if (!modelClass.hasModelAnnotation()) {
-            throw new InvalidModelException(String.format("Model class '%s' 
does not have a model annotation", modelClass));
+            throw new ModelClassException(String.format("Model class '%s' does 
not have a model annotation", modelClass));
         }
 
         Class<?>[] declaredAdaptable = 
modelClass.getModelAnnotation().adaptables();
@@ -261,19 +271,24 @@ public class ModelAdapterFactory impleme
             }
             if (!isAdaptable) {
                 result.addFailure(FailureType.ADAPTABLE_DOES_NOT_MATCH, 
modelClass.getType());
-            } else if (modelClass.getType().isInterface()) {
-                InvocationHandler handler = createInvocationHandler(adaptable, 
modelClass, result);
-                if (handler != null) {
-                    ModelType model = (ModelType) 
Proxy.newProxyInstance(modelClass.getType().getClassLoader(), new Class<?>[] { 
modelClass.getType() }, handler);
-                    result.setModel(model);
-                }
             } else {
-                try {
-                    ModelType model = createObject(adaptable, modelClass, 
result);
-                    result.setModel(model);
+                if (!validateModel(modelAnnotation, adaptable, result)) {
                     return result;
-                } catch (Exception e) {
-                    result.addFailure(FailureType.OTHER, "Unable to create 
object", e);
+                }
+                if (modelClass.getType().isInterface()) {
+                    InvocationHandler handler = 
createInvocationHandler(adaptable, modelClass, result);
+                    if (handler != null) {
+                        ModelType model = (ModelType) 
Proxy.newProxyInstance(modelClass.getType().getClassLoader(), new Class<?>[] { 
modelClass.getType() }, handler);
+                        result.setModel(model);
+                    }
+                } else {
+                    try {
+                        ModelType model = createObject(adaptable, modelClass, 
result);
+                        result.setModel(model);
+                        return result;
+                    } catch (Exception e) {
+                        result.addFailure(FailureType.OTHER, "Unable to create 
object", e);
+                    }
                 }
             }
             return result;
@@ -281,6 +296,30 @@ public class ModelAdapterFactory impleme
             threadInvocationCounter.decrease();
         }
     }
+    
+    private <ModelType> boolean validateModel(Model modelAnnotation, Object 
adaptable, Result<ModelType> result) {
+        if (modelAnnotation.validation() != ValidationStrategy.DISABLED) {
+            if (modelValidation == null) {
+                result.addFailure(FailureType.VALIDATION_NOT_AVAILABLE);
+                return false;
+            }
+            Resource resource = null;
+            if (adaptable instanceof SlingHttpServletRequest) {
+                resource = ((SlingHttpServletRequest)adaptable).getResource();
+            } else if (adaptable instanceof Resource) {
+                resource = (Resource)adaptable;
+            }
+            if (resource != null) {
+                if (!modelValidation.validate(resource, 
modelAnnotation.validation() == ValidationStrategy.REQUIRED, result)) {
+                    return false;
+                }
+            } else {
+                
result.addFailureWithParameters(FailureType.ADAPTABLE_NOT_USABLE_FOR_VALIDATION,
 adaptable.getClass().getName());
+                return false;
+            }
+        }
+        return true;
+    }
 
     private static interface InjectCallback {
         /**

Modified: 
sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/Result.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/Result.java?rev=1644069&r1=1644068&r2=1644069&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/Result.java
 (original)
+++ 
sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/Result.java
 Tue Dec  9 14:46:28 2014
@@ -24,13 +24,13 @@ import java.util.List;
 import java.util.Set;
 
 import org.apache.sling.models.factory.InvalidAdaptableException;
-import org.apache.sling.models.factory.InvalidModelException;
+import org.apache.sling.models.factory.ModelClassException;
 import org.apache.sling.models.factory.MissingElementsException;
 import org.slf4j.Logger;
 
 public class Result<ModelType> {
 
-    enum FailureType {
+    public enum FailureType {
         ADAPTABLE_DOES_NOT_MATCH("Adaptable is not acceptable for the model 
class"),
         FAILED_CALLING_POST_CONSTRUCT("Failure calling post-construct method"),
         NO_MODEL_ANNOTATION("Provided Adapter class does not have a Model 
annotation"),
@@ -38,7 +38,12 @@ public class Result<ModelType> {
         OTHER("Unclassified problem"),
         MISSING_METHODS("Required methods %s on model %s were not able to be 
injected."),
         MISSING_FIELDS("Required fields %s on model %s were not able to be 
injected."),
-        MISSING_CONSTRUCTOR_PARAMS("Required constructor parameters %s on 
model %s were not able to be injected.");
+        MISSING_CONSTRUCTOR_PARAMS("Required constructor parameters %s on 
model %s were not able to be injected."), 
+        ADAPTABLE_NOT_USABLE_FOR_VALIDATION("Can not call Sling Validation in 
case the adaptable is neiter SlingHttpServletRequest or Resource (adaptable 
is'%s')"),
+        VALIDATION_NOT_AVAILABLE("Sling Validation Bundle is not there, 
therefore no validation can be performed."),
+        VALIDATION_MODEL_NOT_FOUND("Sling Validation model could not be 
found"),
+        VALIDATION_MODEL_INVALID("Sling Validation model is invalid"),
+        VALIDATION_RESULT_RESOURCE_INVALID("Model is invalid according to 
Sling Validation");
 
         private String message;
 
@@ -95,13 +100,19 @@ public class Result<ModelType> {
                 case FAILED_CALLING_POST_CONSTRUCT:
                 case NO_MODEL_ANNOTATION:
                 case NO_USABLE_CONSTRUCTOR:
-                    e = new InvalidModelException(msg);
+                case VALIDATION_NOT_AVAILABLE:
+                case ADAPTABLE_NOT_USABLE_FOR_VALIDATION:
+                    e = new ModelClassException(msg);
                     break;
                 case MISSING_CONSTRUCTOR_PARAMS:
                 case MISSING_FIELDS:
                 case MISSING_METHODS:
                     e = new MissingElementsException(failureType.message, 
missingElements, clazz);
                     break;
+                case VALIDATION_MODEL_NOT_FOUND:
+                case VALIDATION_RESULT_RESOURCE_INVALID:
+                case VALIDATION_MODEL_INVALID:
+                    throw (RuntimeException)failureException;
                 default:
                     e = new RuntimeException(msg);
                     break;
@@ -130,6 +141,12 @@ public class Result<ModelType> {
             failure.log(log);
         }
     }
+    
+    public void addFailure(FailureType type) {
+        Failure f = new Failure();
+        f.failureType = type;
+        failures.add(f);
+    }
 
     public void addFailure(FailureType type, Class<?> clazz) {
         Failure f = new Failure();
@@ -152,6 +169,13 @@ public class Result<ModelType> {
         f.clazz = clazz;
         failures.add(f);
     }
+    
+    public void addFailureWithParameters(FailureType type, Object... 
parameters) {
+        Failure f = new Failure();
+        f.failureType = type;
+        f.failureMessage = String.format(type.message, parameters);
+        failures.add(f);
+    }
 
     public void addFailure(FailureType type, String msg) {
         Failure f = new Failure();

Added: 
sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/validation/ModelValidation.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/validation/ModelValidation.java?rev=1644069&view=auto
==============================================================================
--- 
sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/validation/ModelValidation.java
 (added)
+++ 
sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/validation/ModelValidation.java
 Tue Dec  9 14:46:28 2014
@@ -0,0 +1,32 @@
+/*
+ * 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.validation;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.impl.Result;
+
+public interface ModelValidation {
+
+    /**
+     * Calls the Sling Validation for the given resource.
+     * @param resource
+     * @param required if {@code true} validation fails even if no appropriate 
validation model could be found.
+     * @return {@code true} if validation was successful, otherwise {@code 
false}
+     */
+    public abstract <ModelType> boolean validate(Resource resource, boolean 
required, Result<ModelType> result);
+
+}

Added: 
sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/validation/ModelValidationImpl.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/validation/ModelValidationImpl.java?rev=1644069&view=auto
==============================================================================
--- 
sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/validation/ModelValidationImpl.java
 (added)
+++ 
sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/validation/ModelValidationImpl.java
 Tue Dec  9 14:46:28 2014
@@ -0,0 +1,75 @@
+/*
+ * 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.validation;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.factory.InvalidResourceException;
+import org.apache.sling.models.factory.InvalidValidationModelException;
+import org.apache.sling.models.impl.Result;
+import org.apache.sling.models.impl.Result.FailureType;
+import org.apache.sling.validation.api.ValidationModel;
+import org.apache.sling.validation.api.ValidationResult;
+import org.apache.sling.validation.api.ValidationService;
+import org.apache.sling.validation.api.exceptions.SlingValidationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Service
+@Component
+public class ModelValidationImpl implements ModelValidation {
+
+    @Reference
+    private ValidationService validation;
+    
+    private static final Logger log = 
LoggerFactory.getLogger(ModelValidationImpl.class);
+    
+    @Override
+    public <ModelType> boolean validate(Resource resource, boolean required, 
Result<ModelType> result) {
+        try {
+            ValidationModel validationModel = 
validation.getValidationModel(resource);
+            if (validationModel == null) {
+                String error = String.format("Could not find validation model 
for resource '%s' with type '%s'", resource.getPath(), 
resource.getResourceType());
+                if (required) {
+                    result.addFailure(FailureType.VALIDATION_MODEL_NOT_FOUND, 
new InvalidValidationModelException(error));
+                    return false;
+                } else {
+                    log.warn(error);
+                }
+            } else {
+                try {
+                    ValidationResult validationResult = 
validation.validate(resource, validationModel);
+                    if (!validationResult.isValid()) {
+                        
result.addFailure(FailureType.VALIDATION_RESULT_RESOURCE_INVALID, new 
InvalidResourceException(validationResult, resource.getPath()));
+                        return false;
+                    } 
+                } catch (SlingValidationException e) {
+                    result.addFailure(FailureType.VALIDATION_MODEL_INVALID, 
new InvalidValidationModelException(e));
+                    return false;
+                }
+            }
+        } catch (IllegalStateException e) {
+            result.addFailure(FailureType.VALIDATION_MODEL_INVALID, new 
SlingValidationException(e.getMessage(), e));
+        }
+        
+        return true;
+    }
+
+    
+}

Modified: 
sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/AdapterFactoryTest.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/AdapterFactoryTest.java?rev=1644069&r1=1644068&r2=1644069&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/AdapterFactoryTest.java
 (original)
+++ 
sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/AdapterFactoryTest.java
 Tue Dec  9 14:46:28 2014
@@ -29,7 +29,7 @@ import org.apache.sling.api.wrappers.Val
 import org.apache.sling.models.annotations.Model;
 import org.apache.sling.models.annotations.injectorspecific.Self;
 import org.apache.sling.models.factory.InvalidAdaptableException;
-import org.apache.sling.models.factory.InvalidModelException;
+import org.apache.sling.models.factory.ModelClassException;
 import org.apache.sling.models.factory.MissingElementsException;
 import org.apache.sling.models.impl.injectors.SelfInjector;
 import org.apache.sling.models.impl.injectors.ValueMapInjector;
@@ -85,12 +85,12 @@ public class AdapterFactoryTest {
         Assert.assertFalse(factory.canCreateFromAdaptable(request, 
DefaultStringModel.class));
     }
 
-    @Test(expected = InvalidModelException.class)
+    @Test(expected = ModelClassException.class)
     public void testCanCreateFromAdaptableWithInvalidModel() {
         factory.canCreateFromAdaptable(resource, 
InvalidModelWithMissingAnnotation.class);
     }
 
-    @Test(expected = InvalidModelException.class)
+    @Test(expected = ModelClassException.class)
     public void testCreateFromNonModelClass() {
         factory.createModel(resource, InvalidModelWithMissingAnnotation.class);
     }

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=1644069&r1=1644068&r2=1644069&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 Dec  9 14:46:28 2014
@@ -22,7 +22,7 @@ import static org.mockito.Mockito.*;
 import java.util.Hashtable;
 
 import org.apache.sling.api.SlingHttpServletRequest;
-import org.apache.sling.models.factory.InvalidModelException;
+import org.apache.sling.models.factory.ModelClassException;
 import org.apache.sling.models.impl.injectors.RequestAttributeInjector;
 import org.apache.sling.models.impl.injectors.SelfInjector;
 import org.apache.sling.models.testmodels.classes.InvalidConstructorModel;
@@ -110,7 +110,7 @@ public class ConstructorTest {
         assertNull(model);
     }
 
-    @Test(expected = InvalidModelException.class)
+    @Test(expected = ModelClassException.class)
     public void testInvalidConstructorInjectorException() {
         factory.createModel(request, InvalidConstructorModel.class);
     }

Modified: 
sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/InvalidAdaptationsTest.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/InvalidAdaptationsTest.java?rev=1644069&r1=1644068&r2=1644069&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/InvalidAdaptationsTest.java
 (original)
+++ 
sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/InvalidAdaptationsTest.java
 Tue Dec  9 14:46:28 2014
@@ -29,7 +29,7 @@ import org.apache.sling.api.resource.Val
 import org.apache.sling.api.wrappers.ValueMapDecorator;
 import org.apache.sling.models.annotations.Model;
 import org.apache.sling.models.factory.InvalidAdaptableException;
-import org.apache.sling.models.factory.InvalidModelException;
+import org.apache.sling.models.factory.ModelClassException;
 import org.apache.sling.models.impl.injectors.ChildResourceInjector;
 import org.apache.sling.models.impl.injectors.ValueMapInjector;
 import org.junit.Before;
@@ -72,7 +72,7 @@ public class InvalidAdaptationsTest {
         assertNull(factory.getAdapter(res, NonModel.class));
     }
 
-    @Test(expected = InvalidModelException.class)
+    @Test(expected = ModelClassException.class)
     public void testNonModelClassException() {
         Map<String, Object> emptyMap = Collections.<String, Object> emptyMap();
 

Modified: 
sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/PostConstructTest.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/PostConstructTest.java?rev=1644069&r1=1644068&r2=1644069&view=diff
==============================================================================
--- 
sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/PostConstructTest.java
 (original)
+++ 
sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/PostConstructTest.java
 Tue Dec  9 14:46:28 2014
@@ -22,7 +22,7 @@ import static org.mockito.Mockito.*;
 import java.util.Hashtable;
 
 import org.apache.sling.api.resource.Resource;
-import org.apache.sling.models.factory.InvalidModelException;
+import org.apache.sling.models.factory.ModelClassException;
 import org.apache.sling.models.testmodels.classes.FailingPostConstuctModel;
 import org.apache.sling.models.testmodels.classes.SubClass;
 import 
org.apache.sling.models.testmodels.classes.SubClassOverriddenPostConstruct;
@@ -81,7 +81,7 @@ public class PostConstructTest {
         boolean thrown = false;
         try {
             factory.createModel(resource, FailingPostConstuctModel.class);
-        } catch (InvalidModelException e) {
+        } catch (ModelClassException e) {
             assertTrue(e.getMessage().contains("post-construct"));
             assertEquals("FAIL", e.getCause().getMessage());
             thrown = true;


Reply via email to