Author: kwin
Date: Thu Feb 26 12:27:25 2015
New Revision: 1662434
URL: http://svn.apache.org/r1662434
Log:
SLING-4447 provide a SlingModels Sightly UseProvider which throws exceptions in
case a Sling Model cannot be instantiated instead of falling back to the simple
Pojo instantiation.
Added:
sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/sightly/
sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/sightly/ModelFactoryUseProvider.java
Modified:
sling/trunk/bundles/extensions/models/impl/pom.xml
Modified: sling/trunk/bundles/extensions/models/impl/pom.xml
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/pom.xml?rev=1662434&r1=1662433&r2=1662434&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/pom.xml (original)
+++ sling/trunk/bundles/extensions/models/impl/pom.xml Thu Feb 26 12:27:25 2015
@@ -146,5 +146,19 @@
<scope>provided</scope>
<optional>true</optional>
</dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.scripting.sightly</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.commons.classloader</artifactId>
+ <version>1.3.0</version>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
</dependencies>
</project>
Added:
sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/sightly/ModelFactoryUseProvider.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/sightly/ModelFactoryUseProvider.java?rev=1662434&view=auto
==============================================================================
---
sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/sightly/ModelFactoryUseProvider.java
(added)
+++
sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/sightly/ModelFactoryUseProvider.java
Thu Feb 26 12:27:25 2015
@@ -0,0 +1,146 @@
+/*
+ * 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.sightly;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.script.Bindings;
+import javax.servlet.ServletRequest;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.scripting.SlingBindings;
+import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
+import org.apache.sling.models.factory.ModelFactory;
+import
org.apache.sling.scripting.sightly.impl.engine.extension.use.UseProviderUtils;
+import org.apache.sling.scripting.sightly.render.RenderContext;
+import org.apache.sling.scripting.sightly.use.ProviderOutcome;
+import org.apache.sling.scripting.sightly.use.UseProvider;
+import org.osgi.framework.Constants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Sightly {@code UseProvider} which will instantiate a referenced Sling Model.
+ * It will always fail with an exception (i.e. no other {@code UseProvider} is
asked afterwards and the exception is being rethrown)
+ * in case the following two preconditions are fulfilled:
+ * 1. the given identifier specifies a class which can be loaded by the
DynamicClassLoader
+ * 2. the loaded class has a Model annotation
+ * In case any of those preconditions are not fulfilled, the other registered
UseProviders are used!
+ */
+@Component
+@Service
+/*
+ * must have a higher priority than
org.apache.sling.scripting.sightly.impl.engine.extension.use.JavaUseProvider
but lower than
+ *
org.apache.sling.scripting.sightly.impl.engine.extension.use.RenderUnitProvider
to kick in
+ * before the JavaUserProvider but after the RenderUnitProvider
+ */
+@Property(name = Constants.SERVICE_RANKING, intValue = { 95 })
+public class ModelFactoryUseProvider implements UseProvider {
+
+ private static final Logger log =
LoggerFactory.getLogger(ModelFactoryUseProvider.class);
+
+ @Reference
+ ModelFactory modelFactory;
+
+ @Reference
+ private DynamicClassLoaderManager dynamicClassLoaderManager = null;
+
+ @Override
+ public ProviderOutcome provide(final String identifier,
+ final RenderContext renderContext, final Bindings arguments) {
+ final Class<?> cls;
+ try {
+ cls =
dynamicClassLoaderManager.getDynamicClassLoader().loadClass(identifier);
+ } catch(ClassNotFoundException e) {
+ log.debug("Could not find class with the given name {}: {}",
identifier, e.getMessage());
+ // next use provider will be queried
+ return ProviderOutcome.failure();
+ }
+ Bindings globalBindings = renderContext.getBindings();
+ Bindings bindings = UseProviderUtils.merge(globalBindings, arguments);
+ Resource resource = (Resource) bindings.get(SlingBindings.RESOURCE);
+ if (resource == null) {
+ return ProviderOutcome.failure(new IllegalStateException("Could
not get resource from bindings"));
+ }
+ SlingHttpServletRequest request = (SlingHttpServletRequest)
bindings.get(SlingBindings.REQUEST);
+ if (request == null) {
+ return ProviderOutcome.failure(new IllegalStateException("Could
not get request from bindings"));
+ }
+
+ // pass parameters as request attributes
+ Map<String, Object> overrides = setRequestAttributes(request,
arguments);
+ Object obj = null;
+ try {
+ if (!modelFactory.isModelClass(resource, cls)) {
+ log.debug("{} is no Sling Model (because it lacks the
according Model annotation)!");
+ // next use provider will be queried
+ return ProviderOutcome.failure();
+ }
+ // try to instantiate class via Sling Models (first via resource,
then via request)
+ if (modelFactory.canCreateFromAdaptable(resource, cls)) {
+ obj = modelFactory.createModel(resource, cls);
+ } else if (modelFactory.canCreateFromAdaptable(request, cls)) {
+ obj = modelFactory.createModel(request, cls);
+ } else {
+ return ProviderOutcome.failure(new
IllegalStateException("Could not adapt the given Sling Model from neither
resource nor request: " + cls));
+ }
+ } catch (Throwable e) {
+ return ProviderOutcome.failure(e);
+ } finally {
+ resetRequestAttribute(request, overrides);
+ }
+ return ProviderOutcome.notNullOrFailure(obj);
+ }
+
+ private Map<String, Object> setRequestAttributes(final ServletRequest
request,
+ final Bindings arguments) {
+ Map<String, Object> overrides = new HashMap<String, Object>();
+ for (Map.Entry<String, Object> entry : arguments.entrySet()) {
+ String key = entry.getKey();
+ Object value = entry.getValue();
+ Object oldValue = request.getAttribute(key);
+ if (oldValue != null) {
+ overrides.put(key, oldValue);
+ }
+ else {
+ overrides.put(key, null);
+ }
+ request.setAttribute(key, value);
+ }
+ return overrides;
+ }
+
+ private void resetRequestAttribute(final ServletRequest request,
+ final Map<String, Object> overrides) {
+ for (Map.Entry<String, Object> entry : overrides.entrySet()) {
+ String key = entry.getKey();
+ Object value = entry.getValue();
+ if (value == null) {
+ request.removeAttribute(key);
+ }
+ else {
+ request.setAttribute(key, value);
+ }
+ }
+ }
+}