This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-models-provider.git
commit 9fc455ffe88b63a755498ca4e5188028025f3812 Author: Radu Cotescu <[email protected]> AuthorDate: Thu Sep 17 14:07:19 2015 +0000 SLING-5036 - Optimise the ModelsFactoryUseProvider to fail as early as possible if it cannot provide an object * renamed ModelsFactoryUseProvider to SlingModelsUseProvider * delayed all bindings retrievals until they're absolutely necessary * removed bindings merging - models can get their arguments through request attributes if they're adaptable from SlingHttpServletRequest * updated the test setup to take into account the SlingModelsUseProvider (both IT and performance) git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1703629 13f79535-47bb-0310-9956-ffa450edef68 --- ...seProvider.java => SlingModelsUseProvider.java} | 124 +++++++++++---------- 1 file changed, 67 insertions(+), 57 deletions(-) diff --git a/src/main/java/org/apache/sling/scripting/sightly/models/impl/ModelFactoryUseProvider.java b/src/main/java/org/apache/sling/scripting/sightly/models/impl/SlingModelsUseProvider.java similarity index 61% rename from src/main/java/org/apache/sling/scripting/sightly/models/impl/ModelFactoryUseProvider.java rename to src/main/java/org/apache/sling/scripting/sightly/models/impl/SlingModelsUseProvider.java index 6c81d92..cf8fa3d 100644 --- a/src/main/java/org/apache/sling/scripting/sightly/models/impl/ModelFactoryUseProvider.java +++ b/src/main/java/org/apache/sling/scripting/sightly/models/impl/SlingModelsUseProvider.java @@ -1,30 +1,29 @@ -/* +/******************************************************************************* * 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 - * + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> * 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.scripting.sightly.models.impl; - import java.util.HashMap; import java.util.Map; - +import java.util.regex.Pattern; import javax.script.Bindings; -import javax.script.SimpleBindings; import javax.servlet.ServletRequest; import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Properties; import org.apache.felix.scr.annotations.Property; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.Service; @@ -41,83 +40,104 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** + * <p> * Sightly {@link UseProvider} which will instantiate a referenced Sling Model. - * For that it tries to use the {@link ModelFactory#createModel(Object, Class)} first with the adaptable {@link Resource} + * </p> + * <p> + * For that it tries to use the {@link ModelFactory#createModel(Object, Class)} first with the adaptable {@link Resource} * then with the adaptable {@link SlingHttpServletRequest}. * 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: * <ol> - * <li>the given identifier specifies a class which can be loaded by the DynamicClassLoader</li> - * <li>the loaded class has a Model annotation</li> + * <li>the given identifier specifies a class which can be loaded by a {@link org.apache.sling.commons.classloader.DynamicClassLoader}</li> + * <li>the loaded class has a {@link org.apache.sling.models.annotations.Model} annotation</li> * </ol> - * In case any of those preconditions are not fulfilled the other registered UseProviders are used! + * </p> + * <p> + * <p> + * In case any of those preconditions are not fulfilled the other registered {@link UseProvider}s will be queried. + * </p> */ @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 JavaUseProvider but after the RenderUnitProvider - */ -@Property(name = Constants.SERVICE_RANKING, intValue = { 95 }) -public class ModelFactoryUseProvider implements UseProvider { +@Properties({ + @Property( + name = Constants.SERVICE_RANKING, + label = "Service Ranking", + description = + "The Service Ranking value acts as the priority with which this Use Provider is queried to return an Use-object. A" + + "higher value represents a higher priority.", + /** + * Must have a higher priority than {@link org.apache.sling.scripting.sightly.impl.engine.extension.use.JavaUseProvider} but lower + * than {@link org.apache.sling.scripting.sightly.impl.engine.extension.use.RenderUnitProvider} to kick in before the + * JavaUseProvider but after the RenderUnitProvider. + */ + intValue = 95 + ) +}) +public class SlingModelsUseProvider implements UseProvider { + + private static final Logger LOGGER = LoggerFactory.getLogger(SlingModelsUseProvider.class); + private static final Pattern JAVA_PATTERN = Pattern.compile( + "([[\\p{L}&&[^\\p{Lu}]]_$][\\p{L}\\p{N}_$]*\\.)*[\\p{Lu}_$][\\p{L}\\p{N}_$]*"); + - private static final Logger log = LoggerFactory.getLogger(ModelFactoryUseProvider.class); - @Reference - ModelFactory modelFactory; - + private ModelFactory modelFactory = null; + @Reference private DynamicClassLoaderManager dynamicClassLoaderManager = null; - + @Override public ProviderOutcome provide(final String identifier, final RenderContext renderContext, final Bindings arguments) { + if (!JAVA_PATTERN.matcher(identifier).matches()) { + LOGGER.debug("Identifier {} does not match a Java class name pattern.", identifier); + return ProviderOutcome.failure(); + } 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()); + } catch (ClassNotFoundException e) { + LOGGER.debug("Could not find class with the given name {}: {}", identifier, e.getMessage()); // next use provider will be queried return ProviderOutcome.failure(); } if (!modelFactory.isModelClass(cls)) { - log.debug("{} is no Sling Model (because it lacks the according Model annotation or is not being picked up by the Bundle Listener)!"); + LOGGER.debug("{} is not a Sling Model."); // next use provider will be queried return ProviderOutcome.failure(); } Bindings globalBindings = renderContext.getBindings(); - Bindings bindings = 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); + SlingHttpServletRequest request = (SlingHttpServletRequest) globalBindings.get(SlingBindings.REQUEST); if (request == null) { - return ProviderOutcome.failure(new IllegalStateException("Could not get request from bindings")); + 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 { // try to instantiate class via Sling Models (first via request, then via resource) if (modelFactory.canCreateFromAdaptable(request, cls)) { - obj = modelFactory.createModel(request, cls); - } else if (modelFactory.canCreateFromAdaptable(resource, cls)) { - obj = modelFactory.createModel(resource, cls); - } else { - return ProviderOutcome.failure(new IllegalStateException("Could not adapt the given Sling Model from neither resource nor request: " + cls)); + return ProviderOutcome.notNullOrFailure(modelFactory.createModel(request, cls)); + } + Resource resource = (Resource) globalBindings.get(SlingBindings.RESOURCE); + if (resource == null) { + return ProviderOutcome.failure(new IllegalStateException("Could not get resource from bindings.")); } + if (modelFactory.canCreateFromAdaptable(resource, cls)) { + return ProviderOutcome.notNullOrFailure(modelFactory.createModel(resource, cls)); + } + return ProviderOutcome.failure( + new IllegalStateException("Could not adapt the given Sling Model from neither request nor resource: " + 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) { + 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(); @@ -125,8 +145,7 @@ public class ModelFactoryUseProvider implements UseProvider { Object oldValue = request.getAttribute(key); if (oldValue != null) { overrides.put(key, oldValue); - } - else { + } else { overrides.put(key, null); } request.setAttribute(key, value); @@ -134,24 +153,15 @@ public class ModelFactoryUseProvider implements UseProvider { return overrides; } - private void resetRequestAttribute(final ServletRequest request, - final Map<String, Object> 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 { + } else { request.setAttribute(key, value); } } } - - private SimpleBindings merge(Bindings former, Bindings latter) { - SimpleBindings bindings = new SimpleBindings(); - bindings.putAll(former); - bindings.putAll(latter); - return bindings; - } } -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
