You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2014/11/14 15:05:03 UTC

svn commit: r1639641 [2/15] - in /sling/trunk/contrib/scripting/sightly: ./ engine/ engine/src/ engine/src/main/ engine/src/main/antlr4/ engine/src/main/antlr4/org/ engine/src/main/antlr4/org/apache/ engine/src/main/antlr4/org/apache/sling/ engine/src/...

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/ObjectModel.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/ObjectModel.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/ObjectModel.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/ObjectModel.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * 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.scripting.sightly.api;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Defines the dynamic queries that values must support
+ * in Sightly
+ */
+public interface ObjectModel {
+
+    String PROPERTY_ACCESS = "resolveProperty";
+    String COLLECTION_COERCE = "coerceToCollection";
+    String NUMERIC_COERCE = "coerceNumeric";
+    String STRING_COERCE = "coerceToString";
+    String BOOLEAN_COERCE = "coerceToBoolean";
+
+    String STRICT_EQ = "strictEq";
+    String LEQ = "leq";
+    String LT = "lt";
+
+    /**
+     * Retrieve the specified property from the given object
+     * @param target - the target object
+     * @param property - the property name
+     * @return - the value of the property or null if the object has no such property
+     */
+    Object resolveProperty(Object target, Object property);
+
+    /**
+     * Convert the given object to a string.
+     * @param target - the target object
+     * @return - the string representation of the object
+     */
+    String coerceToString(Object target);
+
+    /**
+     * Convert the given object to a boolean value
+     * @param object - the target object
+     * @return - the boolean representation of that object
+     */
+    boolean coerceToBoolean(Object object);
+
+    /**
+     * Coerce the object to a numeric value
+     * @param object - the target object
+     * @return - the numeric representation
+     */
+    Number coerceNumeric(Object object);
+
+    /**
+     * Force the conversion of the object to a collection
+     * @param object - the target object
+     * @return the collection representation of the object
+     */
+    Collection<Object> coerceToCollection(Object object);
+
+    /**
+     * Force the conversion of the target object to a map
+     *
+     * @param object - the target object
+     * @return - a map representation of the object. Default is an empty map
+     */
+    Map coerceToMap(Object object);
+
+    /**
+     * Check whether the left argument equals the right one
+     * @param left the left argument
+     * @param right the right argument
+     * @return true if arguments are equal
+     */
+    boolean strictEq(Object left, Object right);
+
+    /**
+     * Check if left < right
+     * @param left the left argument
+     * @param right the right argument
+     * @return true if left < right
+     */
+    boolean lt(Object left, Object right);
+
+    /**
+     * Check if left < right
+     * @param left the left argument
+     * @param right the right argument
+     * @return true if left < right
+     */
+    boolean leq(Object left, Object right);
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/ProviderOutcome.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/ProviderOutcome.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/ProviderOutcome.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/ProviderOutcome.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * 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.scripting.sightly.api;
+
+/**
+ * Result returned by a use provider
+ */
+public final class ProviderOutcome {
+
+    private boolean success;
+    private Object result;
+
+    private static final ProviderOutcome FAILURE = new ProviderOutcome(false, null);
+
+    /**
+     * Create a successful outcome
+     * @param result the result
+     * @return a successful result
+     */
+    public static ProviderOutcome success(Object result) {
+        return new ProviderOutcome(true, result);
+    }
+
+    /**
+     * Create a failed outcome
+     * @return a failed outcome
+     */
+    public static ProviderOutcome failure() {
+        return FAILURE;
+    }
+
+    /**
+     * If the given obj is not null return a successful outcome, with the given result.
+     * Otherwise, return failure
+     * @param obj the result
+     * @return an outcome based on whether the parameter is null or not
+     */
+    public static ProviderOutcome notNullOrFailure(Object obj) {
+        return (obj == null) ? failure() : success(obj);
+    }
+
+    private ProviderOutcome(boolean success, Object result) {
+        this.success = success;
+        this.result = result;
+    }
+
+    /**
+     * Check if the outcome has been successful
+     * @return the outcome success status
+     */
+    public boolean isSuccess() {
+        return success;
+    }
+
+    /**
+     * Check whether the outcome is a failure
+     * @return the outcome failure status
+     */
+    public boolean isFailure() {
+        return !isSuccess();
+    }
+
+    /**
+     * Get the result in this outcome
+     *
+     * @return the result of the container
+     * @throws java.lang.UnsupportedOperationException if the outcome is a failure
+     */
+    public Object getResult() {
+        if (!success) {
+            throw new UnsupportedOperationException("Outcome has not been successful");
+        }
+        return result;
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/Record.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/Record.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/Record.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/Record.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * 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.scripting.sightly.api;
+
+import java.util.Set;
+
+/**
+ * A key-value immutable object understood by the Sightly runtime
+ * @param <T> the type of values for this record
+ */
+public interface Record<T> {
+
+    /**
+     * Get the value of the specified property
+     * @param name the name of the property
+     * @return the value of the property or null if this record does not
+     * have the specified property
+     */
+    T get(String name);
+
+    /**
+     * Get the set of properties for this record
+     * @return this record's properties
+     */
+    Set<String> properties();
+
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/RenderContext.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/RenderContext.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/RenderContext.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/RenderContext.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * 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.scripting.sightly.api;
+
+import java.util.Map;
+
+import javax.script.Bindings;
+import javax.script.SimpleBindings;
+
+/**
+ * Rendering context for Sightly rendering units.
+ * @see RenderUnit
+ */
+public class RenderContext {
+
+    private final StackedWriter writer;
+    private final Bindings bindings;
+    private final ObjectModel objectModel;
+    private final SightlyRuntime runtime;
+    private final UnitLocator unitLocator;
+
+    public RenderContext(StackedWriter writer, Bindings bindings, ObjectModel objectModel, SightlyRuntime runtime, UnitLocator unitLocator) {
+        this.writer = writer;
+        this.bindings = bindings;
+        this.objectModel = objectModel;
+        this.runtime = runtime;
+        this.unitLocator = unitLocator;
+    }
+
+    /**
+     * Get the writer where the content should be written
+     * @return - a stacked writer
+     */
+    public StackedWriter getWriter() {
+        return writer;
+    }
+
+    /**
+     * Provide the bindings for this script
+     * @return - the list of global bindings available to the script
+     */
+    public Bindings getBindings() {
+        return bindings;
+    }
+
+    /**
+     * Get an instance of the objectModel object model
+     * @return - a objectModel object model instance
+     */
+    public ObjectModel getObjectModel() {
+        return objectModel;
+    }
+
+    /**
+     * Get the available Sightly runtime
+     * @return - an instance of the Sightly runtime
+     */
+    public SightlyRuntime getRuntime() {
+        return runtime;
+    }
+
+    /**
+     * Get the unit locator
+     * @return - a unit locator
+     */
+    public UnitLocator getUnitLocator() {
+        return unitLocator;
+    }
+
+    /**
+     * Create a new render context with different bindings
+     * @param newBindings - the new set of bindings
+     * @return - the new render context
+     */
+    public RenderContext withBindings(Bindings newBindings) {
+        return new RenderContext(this.writer, newBindings, this.objectModel, this.runtime, this.unitLocator);
+    }
+
+    /**
+     * Create a new render context with additional bindings
+     * @param additionalBindings - a dictionary of variables
+     * @return - the new render context
+     */
+    public RenderContext withAddedBindings(Map additionalBindings) {
+        Bindings newBindings = new SimpleBindings();
+        newBindings.putAll(this.bindings);
+        //noinspection unchecked
+        newBindings.putAll(additionalBindings);
+        return withBindings(newBindings);
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/RenderUnit.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/RenderUnit.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/RenderUnit.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/RenderUnit.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * 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.scripting.sightly.api;
+
+import javax.script.Bindings;
+
+/**
+ * Basic unit of rendering. This also extends the record interface.
+ * The properties for a unit are the sub-units
+ */
+public interface RenderUnit extends Record<RenderUnit> {
+
+    /**
+     * Render the main script template
+     * @param renderContext - the rendering context
+     * @param arguments - the arguments for this unit
+     */
+    void render(RenderContext renderContext, Bindings arguments);
+
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/ResourceResolution.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/ResourceResolution.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/ResourceResolution.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/ResourceResolution.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * 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.scripting.sightly.api;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.sling.api.SlingConstants;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.jcr.resource.JcrResourceConstants;
+
+/**
+ * Utility class which used by the Sightly engine & extensions
+ * to resolve resources
+ */
+public class ResourceResolution {
+
+    /**
+     * Maximum number of iterations that can be performed when searching for a resource in
+     * the resource superType chain
+     */
+    private static final int RECURSION_LIMIT = 100;
+
+    /**
+     * Resolve the resource with the given path relative to the base resource, using the
+     * resource super type logic
+     * @param resourceResolver The resource resolver to be used
+     * @param base the base resource. It can be null if path is absolute
+     * @param path the path to the resource
+     * @return the retrieved resource or null if no resource was found
+     * @throws java.lang.UnsupportedOperationException if the resource is not in the resource resolver's search path
+     * @throws java.lang.IllegalStateException if the number of steps necessary to search for the resource on the resource
+     * superType chain has reached the maximum limit
+     * @throws java.lang.IllegalArgumentException if a null componentResource is provided but the path is not absolute
+     */
+    public static Resource resolveComponentRelative(ResourceResolver resourceResolver, Resource base, String path) {
+        Resource componentResource = null;
+        if (base != null) {
+            if ("nt:file".equals(base.getResourceType())) {
+                componentResource = retrieveParent(resourceResolver, base);
+            } else {
+                componentResource = base;
+            }
+        }
+        return resolveComponent(resourceResolver, componentResource, path);
+    }
+
+    public static Resource resolveComponentForRequest(ResourceResolver resolver, SlingHttpServletRequest request) {
+        String resourceType = request.getResource().getResourceType();
+        if (StringUtils.isNotEmpty(resourceType)) {
+            if (resourceType.startsWith("/")) {
+                return resolver.getResource(resourceType);
+            }
+            for (String searchPath : resolver.getSearchPath()) {
+                String componentPath = ResourceUtil.normalize(searchPath + "/" + resourceType);
+                Resource componentResource = resolver.getResource(componentPath);
+                if (componentResource != null) {
+                    return componentResource;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Resolve the resource in the specified component
+     * @param resourceResolver The resource resolver to be used
+     * @param componentResource The resource for the component. It can be null if path is absolute
+     * @param path the path to the resource
+     * @return the retrieved resource or null if no resource was found
+     * @throws java.lang.UnsupportedOperationException if the resource is not in the resource resolver's search path
+     * @throws java.lang.IllegalStateException if more than {@link ResourceResolution#RECURSION_LIMIT} steps were
+     * necessary to search for the resource on the resource superType chain
+     * @throws java.lang.IllegalArgumentException if a null componentResource is provided but the path is not absolute
+     */
+    private static Resource resolveComponent(ResourceResolver resourceResolver, Resource componentResource, String path) {
+        if (resourceResolver == null || path == null) {
+            throw new NullPointerException("Arguments cannot be null");
+        }
+        Resource resource = null;
+        if (isAbsolutePath(path)) {
+            resource = resourceResolver.getResource(path);
+        }
+        if (resource == null) {
+            if (componentResource == null) {
+                throw new IllegalArgumentException("Argument cannot be null if path is not absolute: " + path);
+            }
+            resource = recursiveResolution(resourceResolver, componentResource, path);
+        }
+        if (resource == null) {
+            resource = locateInSearchPath(resourceResolver, path);
+        }
+        return resource != null ? searchPathChecked(resourceResolver, resource) : null;
+    }
+
+    private static Resource recursiveResolution(ResourceResolver resourceResolver, Resource componentResource, String path) {
+        for (int iteration = 0; iteration < RECURSION_LIMIT; iteration++) {
+            Resource resource = resourceResolver.getResource(componentResource, path);
+            if (resource != null) {
+                return resource;
+            }
+            componentResource = findSuperComponent(resourceResolver, componentResource);
+            if (componentResource == null) {
+                return null;
+            }
+        }
+        //at this point we have reached recursion limit
+        throw new IllegalStateException("Searching for resource in component chain took more than " +
+                RECURSION_LIMIT + " steps");
+    }
+
+    private static Resource locateInSearchPath(ResourceResolver resourceResolver, String path) {
+        for (String searchPath : resourceResolver.getSearchPath()) {
+            String fullPath = searchPath + path;
+            Resource resource = resourceResolver.getResource(fullPath);
+            if (resource != null && resource.getPath().startsWith(searchPath)) { //prevent path traversal attack
+                return resource;
+            }
+        }
+        return null;
+    }
+
+    private static boolean isInSearchPath(ResourceResolver resourceResolver, Resource resource) {
+        String resourcePath = resource.getPath();
+        for (String path : resourceResolver.getSearchPath()) {
+            if (resourcePath.startsWith(path)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static Resource findSuperComponent(ResourceResolver resourceResolver, Resource base) {
+        String superType = resourceResolver.getParentResourceType(base);
+        if (superType == null) {
+            return null;
+        }
+        return resourceResolver.getResource(superType);
+    }
+
+    private static Resource searchPathChecked(ResourceResolver resourceResolver, Resource resource) {
+        if (!isInSearchPath(resourceResolver, resource)) {
+            throw new UnsupportedOperationException("Access to resource " + resource.getPath() + " is denied, since the resource does not reside on the search path");
+        }
+        return resource;
+    }
+
+    private static Resource retrieveParent(ResourceResolver resourceResolver, Resource resource) {
+        String parentPath = ResourceUtil.getParent(resource.getPath());
+        if (parentPath == null) {
+            return null;
+        }
+        return resourceResolver.getResource(parentPath);
+    }
+
+    private static boolean isAbsolutePath(String path) {
+        return path.startsWith("/");
+    }
+
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/RuntimeExtension.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/RuntimeExtension.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/RuntimeExtension.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/RuntimeExtension.java Fri Nov 14 14:04:56 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.scripting.sightly.api;
+
+/**
+ * Extensions provided to the Sightly runtime
+ */
+public interface RuntimeExtension {
+
+    /**
+     * Provide an instance of this extension
+     * @param renderContext - the runtime context
+     * @return an extension instance
+     */
+    ExtensionInstance provide(RenderContext renderContext);
+
+    /**
+     * The name of this extension
+     * @return - the name of the extension
+     */
+    String name();
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/RuntimeExtensionComponent.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/RuntimeExtensionComponent.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/RuntimeExtensionComponent.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/RuntimeExtensionComponent.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * 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.scripting.sightly.api;
+
+import java.util.Dictionary;
+
+import org.osgi.service.component.ComponentContext;
+
+/**
+ * Component-based implementation for extensions
+ */
+public abstract class RuntimeExtensionComponent implements RuntimeExtension {
+
+    public static final String SCR_PROP_NAME = "org.apache.sling.scripting.sightly.rtextension.name";
+
+    private String name;
+
+    @Override
+    public String name() {
+        return name;
+    }
+
+    @SuppressWarnings("UnusedDeclaration")
+    protected void activate(ComponentContext componentContext) {
+        Dictionary properties = componentContext.getProperties();
+        name = (String) properties.get(SCR_PROP_NAME);
+    }
+
+    protected void checkArgumentCount(Object[] arguments, int count) {
+        if (arguments.length != count) {
+            throw new RuntimeExtensionException(String.format("Extension %s requires %d arguments", name(), count));
+        }
+    }
+
+    protected void checkArguments(Object[] arguments, Class<?> ... classes) {
+        checkArgumentCount(arguments, classes.length);
+        for (int i = 0; i < arguments.length; i++) {
+            Object arg = arguments[i];
+            Class<?> cls = classes[i];
+            if (!(cls.isAssignableFrom(arg.getClass()))) {
+                throw new RuntimeExtensionException(String.format("Argument on position %d is not of expected type %s",
+                        i, cls.getCanonicalName()));
+            }
+        }
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/RuntimeExtensionException.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/RuntimeExtensionException.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/RuntimeExtensionException.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/RuntimeExtensionException.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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.scripting.sightly.api;
+
+/**
+ * Exception thrown by runtime extensions
+ * @see RuntimeExtension
+ */
+public class RuntimeExtensionException extends RuntimeException {
+
+    public RuntimeExtensionException() {
+    }
+
+    public RuntimeExtensionException(String message) {
+        super(message);
+    }
+
+    public RuntimeExtensionException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public RuntimeExtensionException(Throwable cause) {
+        super(cause);
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/SightlyEngineException.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/SightlyEngineException.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/SightlyEngineException.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/SightlyEngineException.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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.scripting.sightly.api;
+
+/**
+ * Exceptions caused by the Sightly engine
+ */
+public class SightlyEngineException extends RuntimeException {
+
+    public SightlyEngineException() {
+    }
+
+    public SightlyEngineException(String message) {
+        super(message);
+    }
+
+    public SightlyEngineException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public SightlyEngineException(Throwable cause) {
+        super(cause);
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/SightlyParsingException.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/SightlyParsingException.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/SightlyParsingException.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/SightlyParsingException.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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.scripting.sightly.api;
+
+/**
+ * The runtime {@code SightlyParsingException} is thrown during the parsing stage for any grammar offending input.
+ */
+public class SightlyParsingException extends RuntimeException {
+
+    private String offendingInput;
+
+    public SightlyParsingException() {
+    }
+
+    public SightlyParsingException(String message) {
+        super(message);
+    }
+
+    public SightlyParsingException(String message, String offendingInput) {
+        super(message);
+        this.offendingInput = offendingInput;
+    }
+
+    public SightlyParsingException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public SightlyParsingException(String message, String offendingInput, Throwable cause) {
+        super(message, cause);
+        this.offendingInput = offendingInput;
+    }
+
+    public SightlyParsingException(Throwable cause) {
+        super(cause);
+    }
+
+    public String getOffendingInput() {
+        return offendingInput;
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/SightlyRenderException.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/SightlyRenderException.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/SightlyRenderException.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/SightlyRenderException.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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.scripting.sightly.api;
+
+/**
+ * Exceptions generated by Sightly during runtime
+ */
+public class SightlyRenderException extends RuntimeException {
+
+    public SightlyRenderException() {
+    }
+
+    public SightlyRenderException(String message) {
+        super(message);
+    }
+
+    public SightlyRenderException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public SightlyRenderException(Throwable cause) {
+        super(cause);
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/SightlyRuntime.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/SightlyRuntime.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/SightlyRuntime.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/SightlyRuntime.java Fri Nov 14 14:04:56 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.scripting.sightly.api;
+
+/**
+ * Runtime interface provided to Sightly scripts
+ */
+public interface SightlyRuntime {
+
+    /**
+     * Call the specified function name with the given arguments
+     * @param functionName - the name of the called function
+     * @param arguments - 0 or more arguments passed to the function
+     * @return - the object returned by the function
+     * @throws SightlyRenderException - if the function was
+     * not defined
+     */
+    Object call(String functionName, Object ... arguments);
+
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/SightlyUseException.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/SightlyUseException.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/SightlyUseException.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/SightlyUseException.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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.scripting.sightly.api;
+
+/**
+ * Exception raised by the use resolving mechanism
+ */
+public class SightlyUseException extends RuntimeException {
+    public SightlyUseException() {
+    }
+
+    public SightlyUseException(String message) {
+        super(message);
+    }
+
+    public SightlyUseException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public SightlyUseException(Throwable cause) {
+        super(cause);
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/StackedWriter.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/StackedWriter.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/StackedWriter.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/StackedWriter.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * 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.scripting.sightly.api;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Stack;
+
+/**
+ * Text writing utility which allows stacking of temporary buffers
+ */
+public class StackedWriter extends Writer {
+
+    private final PrintWriter baseWriter;
+    private final Stack<StringWriter> writerStack = new Stack<StringWriter>();
+    private PrintWriter current;
+
+    public StackedWriter(PrintWriter baseWriter) {
+        this.baseWriter = baseWriter;
+        this.current = baseWriter;
+    }
+
+    @Override
+    public void write(char[] cbuf, int off, int len) throws IOException {
+        current.write(cbuf, off, len);
+    }
+
+    @Override
+    public void write(String text) {
+        current.write(text);
+    }
+
+    @Override
+    public void flush() throws IOException {
+        current.flush();
+    }
+
+    @Override
+    public void close() throws IOException {
+        if (writerStack.size() != 1) {
+            throw new UnsupportedOperationException("Stack is not empty");
+        }
+        current.close();
+    }
+
+    public void push() {
+        StringWriter writer = new StringWriter();
+        writerStack.push(writer);
+        current = new PrintWriter(writer);
+    }
+
+    public String pop() {
+        String output = null;
+        if (!writerStack.isEmpty()) {
+            StringWriter writer = writerStack.pop();
+            output = writer.toString();
+        }
+        if (writerStack.isEmpty()) {
+            current = baseWriter;
+        } else {
+            current = new PrintWriter(writerStack.peek());
+        }
+        return output;
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/UnitLocator.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/UnitLocator.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/UnitLocator.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/UnitLocator.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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.scripting.sightly.api;
+
+/**
+ * Locates rendering units
+ */
+public interface UnitLocator {
+
+    /**
+     * Locate the given rendering unit
+     * @param path - the path of the unit
+     * @return - the rendering unit, or null if the path could not be resolved to a valid
+     * rendering unit
+     */
+    RenderUnit locate(String path);
+
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/Use.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/Use.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/Use.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/Use.java Fri Nov 14 14:04:56 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.scripting.sightly.api;
+
+import javax.script.Bindings;
+
+public interface Use {
+
+    public void init(Bindings bindings);
+
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/UseProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/UseProvider.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/UseProvider.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/UseProvider.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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.scripting.sightly.api;
+
+import javax.script.Bindings;
+
+/**
+ * Provides instances for the use API. Providers are tried in the order
+ * of their priority until one is found which can provide a non-null instance
+ */
+public interface UseProvider extends Comparable<UseProvider> {
+
+    int DEFAULT_PRIORITY = 0;
+
+    /**
+     * Provide an instance based on the given identifier
+     * @param identifier the identifier of the dependency
+     * @param renderContext the current rendering context
+     * @param arguments Specific arguments provided by the use plugin
+     * @return a container with the instance that corresponds to the identifier. If the identifier cannot be
+     * handled by this provider, a failed outcome is returned
+     */
+    ProviderOutcome provide(String identifier, RenderContext renderContext, Bindings arguments);
+
+    /**
+     * The priority with which this use provider should be selected. Use 0 if you don't care
+     * @return the (possibly negative) priority of this provider
+     */
+    int priority();
+
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/UseProviderComponent.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/UseProviderComponent.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/UseProviderComponent.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/api/UseProviderComponent.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * 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.scripting.sightly.api;
+
+import javax.script.Bindings;
+import javax.script.SimpleBindings;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.osgi.service.component.ComponentContext;
+
+/**
+ * Component-based use provider
+ */
+public abstract class UseProviderComponent implements UseProvider {
+
+    public static final String PRIORITY = "org.apache.sling.scripting.sightly.api.use.priority";
+
+    private int priority = DEFAULT_PRIORITY;
+
+    @Override
+    public int priority() {
+        return priority;
+    }
+
+    @Override
+    public int compareTo(UseProvider o) {
+        if (this.priority < o.priority()) {
+            return -1;
+        } else if (this.priority == o.priority()) {
+            return  0;
+        }
+        return 1;
+    }
+
+    @Activate
+    protected void activate(ComponentContext componentContext) {
+        priority = PropertiesUtil.toInteger(componentContext.getProperties().get(PRIORITY), DEFAULT_PRIORITY);
+    }
+
+    /**
+     * Combine to bindings objects. Priority goes to latter bindings
+     * @param former First map of bindings
+     * @param latter Second, with greater visibility, map of bindings
+     * @return the merging of the two maps
+     */
+    protected Bindings merge(Bindings former, Bindings latter) {
+        Bindings bindings = new SimpleBindings();
+        bindings.putAll(former);
+        bindings.putAll(latter);
+        return bindings;
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/common/Dynamic.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/common/Dynamic.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/common/Dynamic.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/common/Dynamic.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * 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.scripting.sightly.common;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.sling.scripting.sightly.api.ObjectModel;
+
+/**
+ * Extends the object model by providing implementations for all Sightly
+ * operators.
+ */
+public class Dynamic implements ObjectModel {
+
+    private final ObjectModel model;
+
+    public Dynamic(ObjectModel model) {
+        this.model = model;
+    }
+
+    @Override
+    public Object resolveProperty(Object target, Object property) {
+        return model.resolveProperty(target, property);
+    }
+
+    @Override
+    public String coerceToString(Object target) {
+        return model.coerceToString(target);
+    }
+
+    @Override
+    public boolean coerceToBoolean(Object object) {
+        return model.coerceToBoolean(object);
+    }
+
+    @Override
+    public Collection<Object> coerceToCollection(Object object) {
+        return model.coerceToCollection(object);
+    }
+
+    @Override
+    public Number coerceNumeric(Object object) {
+        if (object instanceof Number) {
+            return (Number) object;
+        }
+        return 0;
+    }
+
+    @Override
+    public Map coerceToMap(Object object) {
+        return model.coerceToMap(object);
+    }
+
+    @Override
+    public boolean strictEq(Object left, Object right) {
+        return model.strictEq(left, right);
+    }
+
+    public boolean eq(Object left, Object right) {
+        if (left == null) {
+            return right == null;
+        }
+        return left.equals(right);
+    }
+
+    @Override
+    public boolean lt(Object left, Object right) {
+        return model.lt(left, right);
+    }
+
+    @Override
+    public boolean leq(Object left, Object right) {
+        return model.leq(left, right);
+    }
+
+    public Object and(Object left, Object right) {
+        if (coerceToBoolean(left)) {
+            return right;
+        }
+        return left;
+    }
+
+
+    public Object or(Object left, Object right) {
+        if (coerceToBoolean(left)) {
+            return left;
+        }
+        return right;
+    }
+
+
+    public Object not(Object obj) {
+        return !coerceToBoolean(obj);
+    }
+
+
+    public Object concatenate(Object left, Object right) {
+        return coerceToString(left) + coerceToString(right);
+    }
+
+
+    public Object isWhiteSpace(Object object) {
+        return StringUtils.isWhitespace(coerceToString(object));
+    }
+
+
+    public int length(Object object) {
+        return coerceToCollection(object).size();
+    }
+
+
+
+
+    public Number add(Object left, Object right) {
+        return adjust(coerceDouble(left) + coerceDouble(right));
+    }
+
+
+    public Number sub(Object left, Object right) {
+        return adjust(coerceDouble(left) - coerceDouble(right));
+    }
+
+
+    public Number mult(Object left, Object right) {
+        return adjust(coerceDouble(left) * coerceDouble(right));
+    }
+
+
+    public int iDiv(Object left, Object right) {
+        return coerceInt(left) / coerceInt(right);
+    }
+
+
+    public int rem(Object left, Object right) {
+        return coerceInt(left) % coerceInt(right);
+    }
+
+
+    public Number div(Object left, Object right) {
+        return adjust(coerceDouble(left) / coerceDouble(right));
+    }
+
+
+    public boolean neq(Object left, Object right) {
+        return !eq(left, right);
+    }
+
+    public boolean strictNeq(Object left, Object right) {
+        return !strictEq(left, right);
+    }
+
+    public boolean gt(Object left, Object right) {
+        return !leq(left, right);
+    }
+
+
+    public boolean geq(Object left, Object right) {
+        return !lt(left, right);
+    }
+
+    public boolean isCollection(Object obj) {
+        return (obj instanceof Collection) || (obj instanceof Object[])
+                || (obj instanceof Iterable)
+                || (obj instanceof Iterator);
+    }
+
+    private double coerceDouble(Object object) {
+        if (object instanceof Number) {
+            return ((Number) object).doubleValue();
+        }
+        return 0;
+    }
+
+    private int coerceInt(Object object) {
+        return coerceNumeric(object).intValue();
+    }
+
+    private Number adjust(double x) {
+        if (Math.floor(x) == x) {
+            return (int)x;
+        }
+        return x;
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/common/ObjectModelImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/common/ObjectModelImpl.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/common/ObjectModelImpl.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/common/ObjectModelImpl.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,406 @@
+/*******************************************************************************
+ * 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.scripting.sightly.common;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.adapter.Adaptable;
+import org.apache.sling.api.resource.ValueMap;
+
+import org.apache.sling.scripting.sightly.api.ObjectModel;
+import org.apache.sling.scripting.sightly.api.Record;
+import org.apache.sling.scripting.sightly.api.SightlyRenderException;
+
+/**
+ * Default implementation for the object model
+ */
+@Component
+@Service(ObjectModel.class)
+public class ObjectModelImpl implements ObjectModel {
+
+    private static final String TO_STRING_METHOD = "toString";
+
+    @Override
+    public Object resolveProperty(Object target, Object property) {
+        if (property instanceof Number) {
+            return getIndex(target, ((Number) property).intValue());
+        }
+        return getProperty(target, property);
+    }
+
+    @Override
+    public String coerceToString(Object target) {
+        return objectToString(target);
+    }
+
+    @Override
+    public boolean coerceToBoolean(Object object) {
+        return toBoolean(object);
+    }
+
+    @Override
+    public Collection<Object> coerceToCollection(Object object) {
+        return obtainCollection(object);
+    }
+
+    @Override
+    public Map coerceToMap(Object object) {
+        if (object instanceof Map) {
+            return (Map) object;
+        }
+        return Collections.emptyMap();
+    }
+
+
+    @Override
+    public Number coerceNumeric(Object object) {
+        if (object instanceof Number) {
+            return (Number) object;
+        }
+        return 0;
+    }
+
+    @Override
+    public boolean strictEq(Object left, Object right) {
+        if (left instanceof Number && right instanceof Number) {
+            return ((Number) left).doubleValue() == ((Number) right).doubleValue();
+        }
+        if (left instanceof String && right instanceof String) {
+            return left.equals(right);
+        }
+        if (left instanceof Boolean && right instanceof Boolean) {
+            return left.equals(right);
+        }
+        if (left == null && right == null) {
+            return true;
+        }
+        if (left == null || right == null) {
+            Object notNull = (left != null) ? left : right;
+            if (notNull instanceof String || notNull instanceof Boolean || notNull instanceof Number) {
+                return false;
+            }
+        }
+        throw new UnsupportedOperationException("Invalid types in comparison. Equality is supported for String, Number & Boolean types");
+    }
+
+    public boolean lt(Object left, Object right) {
+        if (left instanceof Number && right instanceof Number) {
+            return ((Number) left).doubleValue() < ((Number) right).doubleValue();
+        }
+        throw new UnsupportedOperationException("Invalid types in comparison. Comparison is supported for Number types only");
+    }
+
+
+    public boolean leq(Object left, Object right) {
+        if (left instanceof Number && right instanceof Number) {
+            return ((Number) left).doubleValue() <= ((Number) right).doubleValue();
+        }
+        throw new UnsupportedOperationException("Invalid types in comparison. Comparison is supported for Number types only");
+    }
+
+    @SuppressWarnings("unchecked")
+    private Collection<Object> obtainCollection(Object obj) {
+        if (obj == null) {
+            return Collections.emptyList();
+        }
+        if (obj instanceof Object[]) {
+            return Arrays.asList((Object[]) obj);
+        }
+        if (obj instanceof Collection) {
+            return (Collection<Object>) obj;
+        }
+        if (obj instanceof Map) {
+            return ((Map) obj).keySet();
+        }
+        if (obj instanceof Record) {
+            return ((Record) obj).properties();
+        }
+        if (obj instanceof Enumeration) {
+            return Collections.list((Enumeration<Object>) obj);
+        }
+        if (obj instanceof Iterator) {
+            return fromIterator((Iterator<Object>) obj);
+        }
+        return Collections.emptyList();
+    }
+
+    private Collection<Object> fromIterator(Iterator<Object> iterator) {
+        ArrayList<Object> result = new ArrayList<Object>();
+        while (iterator.hasNext()) {
+            result.add(iterator.next());
+        }
+        return result;
+    }
+
+    private boolean toBoolean(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+
+        if (obj instanceof Number) {
+            Number number = (Number) obj;
+            //todo should we consider precision issues?
+            return !(number.doubleValue() == 0.0);
+        }
+
+        String s = obj.toString().trim();
+        if ("".equals(s)) {
+            return false;
+        } else if ("true".equalsIgnoreCase(s) || "false".equalsIgnoreCase(s)) {
+            return Boolean.parseBoolean(s);
+        }
+
+        if (obj instanceof Collection) {
+            return ((Collection) obj).size() > 0;
+        }
+
+        if (obj instanceof Map) {
+            return ((Map) obj).size() > 0;
+        }
+
+        if (obj instanceof Iterable<?>) {
+            return ((Iterable<?>) obj).iterator().hasNext();
+        }
+
+        if (obj instanceof Iterator<?>) {
+            return ((Iterator<?>) obj).hasNext();
+        }
+
+        if (obj instanceof Object[]) {
+            return ((Object[]) obj).length > 0;
+        }
+
+        return true;
+    }
+
+    private Object getProperty(Object target, Object propertyObj) {
+        String property = coerceToString(propertyObj);
+        if (StringUtils.isEmpty(property)) {
+            throw new IllegalArgumentException("Invalid property name");
+        }
+        if (target == null) {
+            return null;
+        }
+        Object result = null;
+        if (target instanceof Map) {
+            result = getMapProperty((Map) target, property);
+        }
+        if (result == null && target instanceof Record) {
+            result = ((Record) target).get(property);
+        }
+        if (result == null) {
+            result = getObjectProperty(target, property);
+        }
+        if (result == null && target instanceof Adaptable) {
+            result = getValueMapProperty(((Adaptable) target).adaptTo(ValueMap.class), property);
+        }
+        return result;
+    }
+
+    private Object getIndex(Object obj, int index) {
+        if (obj instanceof Map) {
+            Map map = (Map) obj;
+            if (map.containsKey(index)) {
+                return map.get(index);
+            }
+        }
+        Collection collection = coerceToCollection(obj);
+        if (collection instanceof List) {
+            return getIndexSafe((List) collection, index);
+        }
+        return null;
+    }
+
+    private Object getIndexSafe(List list, int index) {
+        if (index < 0 || index >= list.size()) {
+            return null;
+        }
+        return list.get(index);
+    }
+
+    private Object getValueMapProperty(ValueMap valueMap, String property) {
+        if (valueMap == null) {
+            return null;
+        }
+        return valueMap.get(property);
+    }
+
+    private Object getMapProperty(Map map, String property) {
+        return map.get(property);
+    }
+
+    private Object getObjectProperty(Object obj, String property) {
+        Object result = getObjectNoArgMethod(obj, property);
+        if (result != null) return result;
+        return getField(obj, property);
+    }
+
+    private Object getField(Object obj, String property) {
+        if (obj instanceof Object[] && "length".equals(property)) {
+            // Working around this limitation: http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getFields%28%29
+            return ((Object[]) obj).length;
+        }
+        Class<?> cls = obj.getClass();
+        try {
+            Field field = cls.getDeclaredField(property);
+            return field.get(obj);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    private Object getObjectNoArgMethod(Object obj, String property) {
+        Class<?> cls = obj.getClass();
+        Method method = findMethod(cls, property);
+        if (method != null) {
+            try {
+                method = extractMethodInheritanceChain(cls, method);
+                return method.invoke(obj);
+            } catch (Exception e) {
+                throw new SightlyRenderException(e);
+            }
+        }
+        return null;
+    }
+
+    private Method findMethod(Class<?> cls, String baseName) {
+        Method method;
+        String capitalized = StringUtils.capitalize(baseName);
+        method = tryMethod(cls, "get" + capitalized);
+        if (method != null) return method;
+        method = tryMethod(cls, "is" + capitalized);
+        if (method != null) return method;
+        method = tryMethod(cls, baseName);
+        return method;
+    }
+
+
+    private Method tryMethod(Class<?> cls, String name) {
+        try {
+            Method m = cls.getMethod(name);
+            Class<?> declaringClass = m.getDeclaringClass();
+            return (isMethodAllowed(m)) ? m : null;
+        } catch (NoSuchMethodException e) {
+            return null;
+        }
+    }
+
+    private boolean isMethodAllowed(Method method) {
+        Class<?> declaringClass = method.getDeclaringClass();
+        //methods of the Object.class are forbidden (except toString, which is allowed)
+        return declaringClass != Object.class || TO_STRING_METHOD.equals(method.getName());
+    }
+
+
+    private String objectToString(Object obj) {
+        String output = "";
+        if (obj != null) {
+            if (obj instanceof String) {
+                output = (String) obj;
+            } else if (isPrimitive(obj)) {
+                output = obj.toString();
+            } else {
+                Collection<?> col = obtainCollection(obj);
+                if (col != null) {
+                    output = collectionToString(col);
+                }
+            }
+        }
+        return output;
+    }
+
+    private static final Set<Class<?>> primitiveClasses = primitiveClasses();
+
+    private boolean isPrimitive(Object obj) {
+        return primitiveClasses.contains(obj.getClass());
+    }
+
+    private String collectionToString(Collection<?> col) {
+        StringBuilder builder = new StringBuilder();
+        String prefix = "";
+        for (Object o : col) {
+            builder.append(prefix).append(objectToString(o));
+            prefix = ",";
+        }
+        return builder.toString();
+    }
+
+    private static Set<Class<?>> primitiveClasses() {
+        Set<Class<?>> set = new HashSet<Class<?>>();
+        set.add(Boolean.class);
+        set.add(Character.class);
+        set.add(Byte.class);
+        set.add(Short.class);
+        set.add(Integer.class);
+        set.add(Long.class);
+        set.add(Float.class);
+        set.add(Double.class);
+        set.add(Void.class);
+        return set;
+    }
+
+    private static Method extractMethodInheritanceChain(Class type, Method m) {
+        if (m == null || Modifier.isPublic(type.getModifiers())) {
+            return m;
+        }
+        Class[] inf = type.getInterfaces();
+        Method mp;
+        for (Class<?> iface : inf) {
+            try {
+                mp = iface.getMethod(m.getName(), (Class[]) m.getParameterTypes());
+                mp = extractMethodInheritanceChain(mp.getDeclaringClass(), mp);
+                if (mp != null) {
+                    return mp;
+                }
+            } catch (NoSuchMethodException e) {
+                // do nothing
+            }
+        }
+        Class<?> sup = type.getSuperclass();
+        if (sup != null) {
+            try {
+                mp = sup.getMethod(m.getName(), (Class[]) m.getParameterTypes());
+                mp = extractMethodInheritanceChain(mp.getDeclaringClass(), mp);
+                if (mp != null) {
+                    return mp;
+                }
+            } catch (NoSuchMethodException e) {
+                // do nothing
+            }
+        }
+        return null;
+    }
+
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/common/SightlyRuntimeImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/common/SightlyRuntimeImpl.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/common/SightlyRuntimeImpl.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/common/SightlyRuntimeImpl.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * 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.scripting.sightly.common;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.scripting.sightly.api.ExtensionInstance;
+import org.apache.sling.scripting.sightly.api.RuntimeExtension;
+import org.apache.sling.scripting.sightly.api.RenderContext;
+import org.apache.sling.scripting.sightly.api.SightlyRenderException;
+import org.apache.sling.scripting.sightly.api.SightlyRuntime;
+import org.apache.sling.scripting.sightly.api.ExtensionInstance;
+
+/**
+ * Implementation for apache runtime
+ */
+public class SightlyRuntimeImpl implements SightlyRuntime {
+
+    private final Map<String, RuntimeExtension> mapping;
+    private final Map<String, ExtensionInstance> instanceCache = new HashMap<String, ExtensionInstance>();
+    private RenderContext renderContext;
+
+    public SightlyRuntimeImpl(Map<String, RuntimeExtension> mapping) {
+        this.mapping = mapping;
+    }
+
+    @Override
+    public Object call(String functionName, Object... arguments) {
+        ExtensionInstance instance;
+        instance = instanceCache.get(functionName);
+        if (instance == null) {
+            instance = createInstance(functionName);
+            instanceCache.put(functionName, instance);
+        }
+        return instance.call(arguments);
+    }
+
+    public RenderContext getRenderContext() {
+        return renderContext;
+    }
+
+    public void setRenderContext(RenderContext renderContext) {
+        this.renderContext = renderContext;
+    }
+
+    private ExtensionInstance createInstance(String name) {
+        RuntimeExtension extension = mapping.get(name);
+        if (extension == null) {
+            throw new SightlyRenderException("Runtime extension is not available: " + name);
+        }
+        return extension.provide(renderContext);
+    }
+}