You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2014/11/28 11:18:09 UTC

svn commit: r1642281 [9/14] - in /sling/trunk/contrib/scripting/sightly: ./ engine/ engine/src/main/antlr4/org/apache/sling/parser/expr/generated/ engine/src/main/antlr4/org/apache/sling/scripting/ engine/src/main/antlr4/org/apache/sling/scripting/sigh...

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/UnitLoader.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/UnitLoader.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/UnitLoader.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/UnitLoader.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,448 @@
+/*******************************************************************************
+ * 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.impl.engine;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import javax.script.Bindings;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.felix.scr.annotations.Activate;
+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;
+import org.apache.sling.api.SlingConstants;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.PersistenceException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.api.scripting.SlingBindings;
+import org.apache.sling.scripting.sightly.SightlyException;
+import org.apache.sling.scripting.sightly.impl.compiled.CompilationOutput;
+import org.apache.sling.scripting.sightly.impl.compiled.JavaClassBackend;
+import org.apache.sling.scripting.sightly.impl.compiler.SightlyJavaCompilerService;
+import org.apache.sling.scripting.sightly.impl.compiler.SightlyParsingException;
+import org.apache.sling.scripting.sightly.impl.compiler.SightlyCompilerService;
+import org.apache.sling.scripting.sightly.impl.compiler.util.GlobalShadowCheckBackend;
+import org.apache.sling.scripting.sightly.impl.engine.compiled.JavaClassTemplate;
+import org.apache.sling.scripting.sightly.impl.engine.compiled.SourceIdentifier;
+import org.apache.sling.scripting.sightly.impl.engine.runtime.RenderContextImpl;
+import org.apache.sling.scripting.sightly.impl.engine.runtime.RenderUnit;
+import org.apache.sling.scripting.sightly.impl.engine.runtime.SightlyRenderException;
+import org.apache.sling.settings.SlingSettingsService;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventConstants;
+import org.osgi.service.event.EventHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Create rendering units from resources.
+ */
+@Component
+@Service({UnitLoader.class, EventHandler.class})
+@Properties({
+        @Property(
+                name = EventConstants.EVENT_TOPIC,
+                value = {SlingConstants.TOPIC_RESOURCE_ADDED, SlingConstants.TOPIC_RESOURCE_CHANGED, SlingConstants.TOPIC_RESOURCE_REMOVED}
+        ),
+        @Property(
+                name = EventConstants.EVENT_FILTER,
+                value = "(|(" + SlingConstants.PROPERTY_PATH + "=/apps/**/*." + SightlyScriptEngineFactory.EXTENSION + ")(" +
+                        SlingConstants.PROPERTY_PATH + "=/libs/**/*." + SightlyScriptEngineFactory.EXTENSION + "))"
+        )
+})
+public class UnitLoader implements EventHandler {
+
+    public static final String DEFAULT_REPO_BASE_PATH = "/var/classes";
+    private static final Logger log = LoggerFactory.getLogger(UnitLoader.class);
+    private static final String CLASS_NAME_PREFIX = "SightlyJava_";
+    private static final String MAIN_TEMPLATE_PATH = "templates/compiled_unit_template.txt";
+    private static final String CHILD_TEMPLATE_PATH = "templates/subtemplate.txt";
+
+    private static final String NT_FOLDER = "nt:folder";
+    private static final String NT_FILE = "nt:file";
+    private static final String NT_RESOURCE = "nt:resource";
+    private static final String JCR_PRIMARY_TYPE = "jcr:primaryType";
+    private static final String JCR_CONTENT = "jcr:content";
+    private static final String JCR_DATA = "jcr:data";
+    private static final String JCR_LASTMODIFIED = "jcr:lastModified";
+    private static final String JCR_ENCODING = "jcr:encoding";
+
+    private String mainTemplate;
+    private String childTemplate;
+    private Map<String, Long> slyScriptsMap = new ConcurrentHashMap<String, Long>();
+
+    private final Map<String, Lock> activeWrites = new HashMap<String, Lock>();
+
+    @Reference
+    private SightlyCompilerService sightlyCompilerService = null;
+
+    @Reference
+    private SightlyJavaCompilerService sightlyJavaCompilerService = null;
+
+    @Reference
+    private SightlyEngineConfiguration sightlyEngineConfiguration = null;
+
+    @Reference
+    private ResourceResolverFactory rrf = null;
+
+    @Reference
+    private SlingSettingsService slingSettings = null;
+
+    private static long getLastModifiedDate(ResourceResolver resolver, String path) {
+        try {
+            Resource ntResource = getNtResource(resolver, path);
+            if (ntResource != null) {
+                ValueMap ntResourceProperties = ntResource.adaptTo(ValueMap.class);
+                /**
+                 * make sure to use 0L for the default value; otherwise we get an Integer
+                 * overflow due to the long value stored in JCR
+                 */
+                return ntResourceProperties.get(JCR_LASTMODIFIED, 0L);
+            }
+        } catch (Exception e) {
+            log.error("Error while reading last modification date: ", e);
+        }
+        return 0L;
+    }
+
+    private static Resource getNtResource(ResourceResolver resolver, String path) {
+        Resource resource = resolver.getResource(path);
+        if (resource != null) {
+            if (path.endsWith(JCR_CONTENT) && resource.isResourceType(NT_RESOURCE)) {
+                return resource;
+            } else {
+                Resource ntResource = resource.getChild(JCR_CONTENT);
+                if (ntResource != null && ntResource.isResourceType(NT_RESOURCE)) {
+                    return ntResource;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Create a render unit from the given resource
+     *
+     * @param scriptResource the resource
+     * @param bindings       the bindings
+     * @param renderContext  the rendering context
+     * @return the render unit
+     */
+    public RenderUnit createUnit(Resource scriptResource, Bindings bindings, RenderContextImpl renderContext) {
+        Lock lock = null;
+        ResourceResolver adminResolver = null;
+        try {
+            SourceIdentifier sourceIdentifier = obtainIdentifier(scriptResource);
+            adminResolver = rrf.getAdministrativeResourceResolver(null);
+            Object obj;
+            ValueMap templateProperties = adminResolver.getResource(scriptResource.getPath()).getChild(JCR_CONTENT).adaptTo(ValueMap.class);
+            String encoding = templateProperties.get(JCR_ENCODING, sightlyEngineConfiguration.getEncoding());
+            SlingHttpServletResponse response = (SlingHttpServletResponse) bindings.get(SlingBindings.RESPONSE);
+            response.setCharacterEncoding(encoding);
+            if (needsUpdate(adminResolver, sourceIdentifier)) {
+                synchronized (activeWrites) {
+                    String sourceFullPath = sourceIdentifier.getSourceFullPath();
+                    lock = activeWrites.get(sourceFullPath);
+                    if (lock == null) {
+                        lock = new ReentrantLock();
+                        activeWrites.put(sourceFullPath, lock);
+                    }
+                    lock.lock();
+                }
+                createClass(adminResolver, sourceIdentifier, bindings, encoding, renderContext);
+                Resource javaClassResource = adminResolver.getResource(sourceIdentifier.getSourceFullPath());
+                obj = sightlyJavaCompilerService.compileSource(javaClassResource, sourceIdentifier.getFullyQualifiedName());
+            } else {
+                Resource javaClassResource = adminResolver.getResource(sourceIdentifier.getSourceFullPath());
+                obj = sightlyJavaCompilerService.getInstance(javaClassResource, sourceIdentifier.getFullyQualifiedName());
+            }
+            if (!(obj instanceof RenderUnit)) {
+                throw new SightlyRenderException("Class is not a RenderUnit instance");
+            }
+            return (RenderUnit) obj;
+        } catch (LoginException e) {
+            throw new SightlyRenderException("Unable to create a RenderUnit.", e);
+        } finally {
+            if (adminResolver != null) {
+                adminResolver.close();
+            }
+            if (lock != null) {
+                lock.unlock();
+            }
+        }
+    }
+
+    @Override
+    public void handleEvent(Event event) {
+        String path = (String) event.getProperty(SlingConstants.PROPERTY_PATH);
+        String topic = event.getTopic();
+        if (SlingConstants.TOPIC_RESOURCE_ADDED.equals(topic) || SlingConstants.TOPIC_RESOURCE_CHANGED.equals(topic)) {
+            slyScriptsMap.put(path, Calendar.getInstance().getTimeInMillis());
+        } else if (SlingConstants.TOPIC_RESOURCE_REMOVED.equals(topic)) {
+            slyScriptsMap.remove(path);
+        }
+    }
+
+    @Activate
+    @SuppressWarnings("unused")
+    protected void activate(ComponentContext componentContext) {
+        mainTemplate = resourceFile(componentContext, MAIN_TEMPLATE_PATH);
+        childTemplate = resourceFile(componentContext, CHILD_TEMPLATE_PATH);
+        String basePath =
+                DEFAULT_REPO_BASE_PATH + "/" + slingSettings.getSlingId() + "/sightly/";
+        ResourceResolver adminResolver = null;
+        try {
+            adminResolver = rrf.getAdministrativeResourceResolver(null);
+            Resource basePathResource;
+            if ((basePathResource = adminResolver.getResource(basePath)) != null) {
+                for (Resource resource : basePathResource.getChildren()) {
+                    if (!resource.getName().equals(sightlyEngineConfiguration.getEngineVersion())) {
+                        adminResolver.delete(resource);
+                    }
+                }
+                if (adminResolver.hasChanges()) {
+                    adminResolver.commit();
+                }
+            }
+        } catch (Exception e) {
+            log.error("Cannot delete stale Sightly Java classes.", e);
+        } finally {
+            if (adminResolver != null) {
+                adminResolver.close();
+            }
+        }
+    }
+
+    private synchronized void writeSource(ResourceResolver resolver, String sourceFullPath, String source) {
+        try {
+            String sourceParentPath = ResourceUtil.getParent(sourceFullPath);
+            Map<String, Object> sourceFolderProperties = new HashMap<String, Object>();
+            sourceFolderProperties.put(JCR_PRIMARY_TYPE, NT_FOLDER);
+            createResource(resolver, sourceParentPath, sourceFolderProperties, NT_FOLDER, true, false);
+
+            Map<String, Object> sourceFileProperties = new HashMap<String, Object>();
+            sourceFileProperties.put(JCR_PRIMARY_TYPE, NT_FILE);
+            createResource(resolver, sourceFullPath, sourceFileProperties, null, false, false);
+
+            Map<String, Object> ntResourceProperties = new HashMap<String, Object>();
+            ntResourceProperties.put(JCR_PRIMARY_TYPE, NT_RESOURCE);
+            ntResourceProperties.put(JCR_DATA, new ByteArrayInputStream(source.getBytes()));
+            ntResourceProperties.put(JCR_LASTMODIFIED, Calendar.getInstance());
+            createResource(resolver, sourceFullPath + "/" + JCR_CONTENT, ntResourceProperties, NT_RESOURCE, true, true);
+            log.debug("Successfully written Java source file to repository: {}", sourceFullPath);
+        } catch (PersistenceException e) {
+            log.error("Repository error while writing Java source file: " + sourceFullPath, e);
+        }
+    }
+
+    private SourceIdentifier obtainIdentifier(Resource resource) {
+        String basePath =
+                DEFAULT_REPO_BASE_PATH + "/" + slingSettings.getSlingId() + "/sightly/" + sightlyEngineConfiguration.getEngineVersion();
+        return new SourceIdentifier(resource, CLASS_NAME_PREFIX, basePath);
+    }
+
+    private void createClass(ResourceResolver resolver, SourceIdentifier identifier, Bindings bindings, String encoding,
+                             RenderContextImpl renderContext) {
+        String scriptSource = null;
+        try {
+            Resource scriptResource = resolver.getResource(identifier.getResource().getPath());
+            if (scriptResource != null) {
+                scriptSource = IOUtils.toString(scriptResource.adaptTo(InputStream.class), encoding);
+                String javaSourceCode = obtainResultSource(scriptSource, identifier, bindings, renderContext);
+                writeSource(resolver, identifier.getSourceFullPath(), javaSourceCode);
+            }
+        } catch (SightlyParsingException e) {
+            String offendingInput = e.getOffendingInput();
+            if (StringUtils.isNotEmpty(offendingInput)) {
+                offendingInput = StringEscapeUtils.unescapeHtml(offendingInput.trim());
+                int errorLine = getLineWhereErrorOccurred(scriptSource, offendingInput);
+                throw new SightlyParsingException("Parsing error in template " + identifier.getResource().getPath() + " at line " +
+                        errorLine + ":\n" + offendingInput + "\n");
+            } else {
+                throw e;
+            }
+
+        } catch (IOException e) {
+            throw new SightlyRenderException(e);
+        }
+    }
+
+    private String obtainResultSource(String scriptSource, SourceIdentifier identifier, Bindings bindings, RenderContextImpl renderContext) {
+        JavaClassTemplate classTemplate = newMainTemplate();
+        classTemplate.setClassName(identifier.getClassName());
+        classTemplate.setPackageName(identifier.getPackageName());
+        CompilationOutput compilationOutput = obtainOutput(scriptSource, bindings, renderContext);
+        processCompilationResult(compilationOutput, classTemplate);
+        return classTemplate.toString();
+    }
+
+    private CompilationOutput obtainOutput(String source, Bindings bindings, RenderContextImpl renderContext) {
+        JavaClassBackend backend = new JavaClassBackend();
+        sightlyCompilerService.compile(source, new GlobalShadowCheckBackend(backend, bindings.keySet()), renderContext);
+        return backend.build();
+    }
+
+    private void processCompilationResult(CompilationOutput result, JavaClassTemplate mainTemplate) {
+        mainTemplate.writeMainBody(result.getMainBody());
+        for (Map.Entry<String, CompilationOutput> entry : result.getSubTemplates().entrySet()) {
+            JavaClassTemplate childTemplate = newChildTemplate();
+            processCompilationResult(entry.getValue(), childTemplate);
+            mainTemplate.writeSubTemplate(entry.getKey(), childTemplate.toString());
+        }
+    }
+
+    private JavaClassTemplate newMainTemplate() {
+        return new JavaClassTemplate(mainTemplate);
+    }
+
+    private JavaClassTemplate newChildTemplate() {
+        return new JavaClassTemplate(childTemplate);
+    }
+
+    private String resourceFile(ComponentContext componentContext, String path) {
+        InputStream inputStream = null;
+        try {
+            URL url = componentContext.getBundleContext().getBundle().getEntry(path);
+            if (url == null) {
+                throw new SightlyException("No bundle resource resides at " + path);
+            }
+            inputStream = componentContext.getBundleContext().getBundle().getEntry(path).openStream();
+            return IOUtils.toString(inputStream);
+        } catch (IOException e) {
+            throw new SightlyException("Java class templates could not be found");
+        } finally {
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (IOException e) {
+                    log.error("Error when closing bundle resource stream", e);
+                }
+            }
+        }
+    }
+
+    private int getLineWhereErrorOccurred(String documentFragment, String offendingInput) {
+        int offendingInputIndex = documentFragment.indexOf(offendingInput);
+        String textBeforeError = documentFragment.substring(0, offendingInputIndex);
+        int line = 0;
+        int newLine = 0;
+        while (textBeforeError.length() > 0 && newLine != -1) {
+            newLine = textBeforeError.indexOf("\n");
+            if (newLine != -1) {
+                line++;
+                textBeforeError = textBeforeError.substring(newLine + 1, textBeforeError.length());
+            }
+        }
+        return ++line;
+    }
+
+    private boolean needsUpdate(ResourceResolver resolver, SourceIdentifier sourceIdentifier) {
+        if (sightlyEngineConfiguration.isDevMode()) {
+            return true;
+        }
+        String javaPath = sourceIdentifier.getSourceFullPath();
+        String slyPath = sourceIdentifier.getResource().getPath();
+        Long javaFileDate = getLastModifiedDate(resolver, javaPath);
+        if (javaFileDate != 0) {
+
+            Long slyScriptChangeDate = slyScriptsMap.get(slyPath);
+            if (slyScriptChangeDate != null) {
+                if (slyScriptChangeDate < javaFileDate) {
+                    return false;
+                }
+            } else {
+                slyScriptsMap.put(slyPath, Calendar.getInstance().getTimeInMillis());
+            }
+            return true;
+        }
+        slyScriptsMap.put(slyPath, Calendar.getInstance().getTimeInMillis());
+        return true;
+    }
+
+    private Resource createResource(ResourceResolver resolver, String path, Map<String, Object> resourceProperties, String intermediateType,
+                                    boolean autoCommit, boolean forceOverwrite) throws PersistenceException {
+        Resource rsrc = resolver.getResource(path);
+        if (rsrc == null || forceOverwrite) {
+            final int lastPos = path.lastIndexOf('/');
+            final String name = path.substring(lastPos + 1);
+
+            final Resource parentResource;
+            if (lastPos == 0) {
+                parentResource = resolver.getResource("/");
+            } else {
+                final String parentPath = path.substring(0, lastPos);
+                Map<String, Object> parentProperties = new HashMap<String, Object>();
+                parentProperties.put(JCR_PRIMARY_TYPE, intermediateType);
+                parentResource = createResource(resolver, parentPath, parentProperties, intermediateType, autoCommit, false);
+            }
+            if (autoCommit) {
+                resolver.refresh();
+            }
+            if (forceOverwrite) {
+                Resource resource = resolver.getResource(parentResource, name);
+                if (resource != null) {
+                    resolver.delete(resource);
+                }
+            }
+            try {
+                rsrc = resolver.create(parentResource, name, resourceProperties);
+                if (autoCommit) {
+                    resolver.commit();
+                    resolver.refresh();
+                    rsrc = resolver.getResource(parentResource, name);
+                }
+            } catch (PersistenceException pe) {
+                resolver.revert();
+                resolver.refresh();
+                rsrc = resolver.getResource(parentResource, name);
+                if (rsrc == null) {
+                    rsrc = resolver.create(parentResource, name, resourceProperties);
+                }
+            } finally {
+                if (autoCommit) {
+                    resolver.commit();
+                    resolver.refresh();
+                    rsrc = resolver.getResource(parentResource, name);
+                }
+            }
+        }
+        return rsrc;
+    }
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/UnitLoader.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/compiled/JavaClassTemplate.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/compiled/JavaClassTemplate.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/compiled/JavaClassTemplate.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/compiled/JavaClassTemplate.java Fri Nov 28 10:18:01 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.impl.engine.compiled;
+
+/**
+ * Template for generated Java classes.
+ */
+public class JavaClassTemplate {
+
+
+    private String classTemplate;
+
+    private static final String MAIN_BODY = "MainBody";
+    private static final String CLASS_NAME = "ClassName";
+    private static final String PACKAGE_NAME = "PackageName";
+    private static final String TEMPLATE_INIT = "SubTemplateMapInit";
+    private static final String NAME = "Name";
+
+    private StringBuilder templateInitBuilder = new StringBuilder();
+
+    public JavaClassTemplate(String template) {
+        this.classTemplate = template;
+    }
+
+    public void writeMainBody(String content) {
+        setPart(MAIN_BODY, content);
+    }
+
+    public void writeSubTemplate(String name, String content) {
+        templateInitBuilder.append(insertPart(NAME, content, name));
+    }
+
+    public void setClassName(String name) {
+        setPart(CLASS_NAME, name);
+    }
+
+    public void setPackageName(String name) {
+        setPart(PACKAGE_NAME, name);
+    }
+
+    @Override
+    public String toString() {
+        return insertPart(TEMPLATE_INIT, classTemplate, templateInitBuilder.toString());
+    }
+
+    private void setPart(String partName, String content) {
+        classTemplate = insertPart(partName, classTemplate, content);
+    }
+
+    private String insertPart(String partName, String original, String content) {
+        String id = "##" + partName + "##";
+        return original.replace(id, content);
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/compiled/JavaClassTemplate.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/compiled/SourceIdentifier.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/compiled/SourceIdentifier.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/compiled/SourceIdentifier.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/compiled/SourceIdentifier.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * 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.impl.engine.compiled;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceUtil;
+
+/**
+ * Identifies a Java source file in a JCR repository.
+ */
+public class SourceIdentifier {
+
+    private final String className;
+    private final Resource resource;
+    private final String packageName;
+    private final String sourceFileName;
+    private final String sourceFullPath;
+    private final String fullyQualifiedName;
+
+    public SourceIdentifier(Resource resource, String classNamePrefix, String basePath) {
+        this.resource = resource;
+        this.className = buildClassName(resource, classNamePrefix);
+        this.packageName = buildPackageName(resource);
+        this.sourceFileName = buildSourceFileName(this.className);
+        this.sourceFullPath = buildSourceFullPath(resource, basePath, this.sourceFileName);
+        this.fullyQualifiedName = buildFullyQualifiedName(packageName, className);
+    }
+
+    public String getClassName() {
+        return className;
+    }
+
+    public Resource getResource() {
+        return resource;
+    }
+
+    public String getPackageName() {
+        return packageName;
+    }
+
+    public String getSourceFileName() {
+        return sourceFileName;
+    }
+
+    public String getSourceFullPath() {
+        return sourceFullPath;
+    }
+
+    public String getFullyQualifiedName() {
+        return fullyQualifiedName;
+    }
+
+    private String buildFullyQualifiedName(String packageName, String className) {
+        return packageName + "." + className;
+    }
+
+    private String buildClassName(Resource resource, String classNamePrefix) {
+        String scriptName = ResourceUtil.getName(resource.getPath());
+        scriptName = scriptName.substring(0, scriptName.lastIndexOf(getExtension(scriptName)));
+        String className = classNamePrefix + scriptName;
+        return className.replaceAll("-", "_").replaceAll("\\.", "_");
+    }
+
+    private String buildPackageName(Resource resource) {
+        return ResourceUtil.getParent(resource.getPath())
+                .replaceAll("/", ".")
+                .substring(1)
+                .replaceAll("-", "_");
+    }
+
+    private String buildSourceFileName(String className) {
+        return className + ".java";
+    }
+
+    private String buildSourceFullPath(Resource resource, String basePath, String sourceFileName) {
+        String sourceParentPath = basePath + ResourceUtil.getParent(resource.getPath());
+        return sourceParentPath + "/" + sourceFileName;
+    }
+
+    private String getExtension(String scriptName) {
+        if (StringUtils.isEmpty(scriptName)) {
+            return null;
+        }
+        int lastDotIndex = scriptName.lastIndexOf('.');
+        return scriptName.substring(lastDotIndex);
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/compiled/SourceIdentifier.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/ExtensionUtils.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/ExtensionUtils.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/ExtensionUtils.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/ExtensionUtils.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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.impl.engine.extension;
+
+import org.apache.sling.scripting.sightly.extension.RuntimeExtension;
+import org.apache.sling.scripting.sightly.extension.RuntimeExtensionException;
+
+/**
+ * Helper class for {@link RuntimeExtension} implementations.
+ */
+public class ExtensionUtils {
+
+    /**
+     * Helper method for checking if the number of arguments passed to a {@link RuntimeExtension} are equal to what the extension requires.
+     *
+     * @param extensionName the name of the extension
+     * @param arguments     the arguments array
+     * @param count         the expected number or arguments
+     * @throws RuntimeExtensionException if the number of supplied arguments differs from what's expected
+     */
+    public static void checkArgumentCount(String extensionName, Object[] arguments, int count) {
+        if (arguments.length != count) {
+            throw new RuntimeExtensionException(String.format("Extension %s requires %d arguments", extensionName, count));
+        }
+    }
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/ExtensionUtils.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/I18nRuntimeExtension.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/I18nRuntimeExtension.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/I18nRuntimeExtension.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/I18nRuntimeExtension.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * 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.impl.engine.extension;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import javax.script.Bindings;
+
+import org.apache.commons.lang.StringUtils;
+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.Service;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.scripting.SlingBindings;
+import org.apache.sling.api.scripting.SlingScriptHelper;
+import org.apache.sling.i18n.ResourceBundleProvider;
+import org.apache.sling.scripting.sightly.extension.ExtensionInstance;
+import org.apache.sling.scripting.sightly.extension.RuntimeExtension;
+import org.apache.sling.scripting.sightly.impl.filter.I18nFilter;
+import org.apache.sling.scripting.sightly.render.RenderContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component
+@Service(RuntimeExtension.class)
+@Properties({
+        @Property(name = RuntimeExtension.SCR_PROP_NAME, value = I18nFilter.FUNCTION)
+})
+public class I18nRuntimeExtension implements RuntimeExtension {
+
+    private static final Logger LOG = LoggerFactory.getLogger(I18nRuntimeExtension.class);
+
+    @Override
+    public ExtensionInstance provide(final RenderContext renderContext) {
+
+        return new ExtensionInstance() {
+            @Override
+            public Object call(Object... arguments) {
+                ExtensionUtils.checkArgumentCount(I18nFilter.FUNCTION, arguments, 3);
+                String text = renderContext.toString(arguments[0]);
+                String locale = renderContext.toString(arguments[1]);
+                String hint = renderContext.toString(arguments[2]);
+                return get(text, locale, hint);
+            }
+
+            private String get(String text, String locale, String hint) {
+                final Bindings bindings = renderContext.getBindings();
+                final SlingScriptHelper slingScriptHelper = (SlingScriptHelper) bindings.get(SlingBindings.SLING);
+                final SlingHttpServletRequest request = (SlingHttpServletRequest) bindings.get(SlingBindings.REQUEST);
+                final ResourceBundleProvider resourceBundleProvider = slingScriptHelper.getService(ResourceBundleProvider.class);
+                if (resourceBundleProvider != null) {
+                    String key = text;
+                    if (StringUtils.isNotEmpty(hint)) {
+                        key += " ((" + hint + "))";
+                    }
+                    if (StringUtils.isEmpty(locale)) {
+                        Enumeration<Locale> requestLocales = request.getLocales();
+                        while (requestLocales.hasMoreElements()) {
+                            Locale l = requestLocales.nextElement();
+                            ResourceBundle resourceBundle = resourceBundleProvider.getResourceBundle(l);
+                            if (resourceBundle != null && resourceBundle.containsKey(key)) {
+                                return resourceBundle.getString(key);
+                            }
+                        }
+                    } else {
+                        Locale l = new Locale(locale);
+                        ResourceBundle resourceBundle = resourceBundleProvider.getResourceBundle(l);
+                        if (resourceBundle != null && resourceBundle.containsKey(key)) {
+                            return resourceBundle.getString(key);
+                        }
+                    }
+                }
+                LOG.warn("No translation found for string '{}' using expression provided locale '{}' or default locale '{}'",
+                        new String[] {text, locale, resourceBundleProvider.getDefaultLocale().getLanguage()});
+                return text;
+            }
+
+        };
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/I18nRuntimeExtension.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/IncludeRuntimeExtension.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/IncludeRuntimeExtension.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/IncludeRuntimeExtension.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/IncludeRuntimeExtension.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * 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.impl.engine.extension;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Map;
+
+import javax.script.Bindings;
+import javax.servlet.Servlet;
+
+import org.apache.commons.lang.StringUtils;
+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.Service;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.scripting.SlingBindings;
+import org.apache.sling.api.scripting.SlingScriptHelper;
+import org.apache.sling.api.servlets.ServletResolver;
+import org.apache.sling.scripting.sightly.extension.ExtensionInstance;
+import org.apache.sling.scripting.sightly.extension.RuntimeExtension;
+import org.apache.sling.scripting.sightly.impl.engine.runtime.SightlyRenderException;
+import org.apache.sling.scripting.sightly.impl.plugin.IncludePlugin;
+import org.apache.sling.scripting.sightly.render.RenderContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component
+@Service(RuntimeExtension.class)
+@Properties({
+        @Property(name = RuntimeExtension.SCR_PROP_NAME, value = IncludePlugin.FUNCTION)
+})
+@SuppressWarnings("unused")
+/**
+ * Runtime support for including resources in a Sightly script through {@code data-sly-include}. For more details check the implementation
+ * of the {@link org.apache.sling.scripting.sightly.impl.plugin.IncludePlugin}.
+ */
+public class IncludeRuntimeExtension implements RuntimeExtension {
+
+    private static final Logger LOG = LoggerFactory.getLogger(IncludeRuntimeExtension.class);
+    private static final String OPTION_FILE = "file";
+    private static final String OPTION_PREPEND_PATH = "prependPath";
+    private static final String OPTION_APPEND_PATH = "appendPath";
+
+
+    @Override
+    public ExtensionInstance provide(final RenderContext renderContext) {
+
+        return new ExtensionInstance() {
+
+            private final Bindings bindings = renderContext.getBindings();
+
+            @Override
+            public Object call(Object... arguments) {
+                ExtensionUtils.checkArgumentCount(IncludePlugin.FUNCTION, arguments, 2);
+                String originalPath = renderContext.toString(arguments[0]);
+                Map options = (Map) arguments[1];
+                String path = buildPath(originalPath, options);
+                if (path == null) {
+                    throw new SightlyRenderException("Path for include is empty");
+                }
+                StringWriter output = new StringWriter();
+                includeScript(path, new PrintWriter(output));
+                return output.toString();
+
+            }
+
+            private String buildPath(String path, Map options) {
+                if (StringUtils.isEmpty(path)) {
+                    path = (String) options.get(OPTION_FILE);
+                }
+                if (StringUtils.isEmpty(path)) {
+                    return null;
+                }
+                String prependPath = (String) options.get(OPTION_PREPEND_PATH);
+                String appendPath = (String) options.get(OPTION_APPEND_PATH);
+                if (StringUtils.isNotEmpty(prependPath)) {
+                    path = prependPath + path;
+                }
+                if (StringUtils.isNotEmpty(appendPath)) {
+                    path = path + appendPath;
+                }
+                return path;
+            }
+
+            private void includeScript(String script, PrintWriter out) {
+                if (StringUtils.isEmpty(script)) {
+                    LOG.error("Script path cannot be empty");
+                } else {
+                    SlingScriptHelper slingScriptHelper = (SlingScriptHelper) bindings.get(SlingBindings.SLING);
+                    ServletResolver servletResolver = slingScriptHelper.getService(ServletResolver.class);
+                    if (servletResolver != null) {
+                        SlingHttpServletRequest request = (SlingHttpServletRequest) bindings.get(SlingBindings.REQUEST);
+                        Servlet servlet = servletResolver.resolveServlet(request.getResource(), script);
+                        if (servlet != null) {
+                            try {
+                                SlingHttpServletResponse response = (SlingHttpServletResponse) bindings.get(SlingBindings.RESPONSE);
+                                PrintWriterResponseWrapper resWrapper = new PrintWriterResponseWrapper(out, response);
+                                servlet.service(request, resWrapper);
+                            } catch (Exception e) {
+                                LOG.error("Failed to include script {}", script, e);
+                            }
+                        } else {
+                            LOG.error("Failed to locate script {}", script);
+                        }
+                    } else {
+                        LOG.error("Sling ServletResolver service is unavailable, failed to include {}", script);
+                    }
+                }
+            }
+        };
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/IncludeRuntimeExtension.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/PrintWriterResponseWrapper.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/PrintWriterResponseWrapper.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/PrintWriterResponseWrapper.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/PrintWriterResponseWrapper.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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.impl.engine.extension;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.wrappers.SlingHttpServletResponseWrapper;
+
+/**
+ * Wrapper response to redirect the output into a specified print writer
+ */
+public class PrintWriterResponseWrapper extends SlingHttpServletResponseWrapper {
+
+    private final PrintWriter writer;
+
+    /**
+     * Create a wrapper for the supplied wrappedRequest
+     *
+     * @param writer - the base writer
+     * @param wrappedResponse - the wrapped response
+     */
+    public PrintWriterResponseWrapper(PrintWriter writer, SlingHttpServletResponse wrappedResponse) {
+        super(wrappedResponse);
+        this.writer = writer;
+    }
+
+    @Override
+    public PrintWriter getWriter() throws IOException {
+        return writer;
+    }
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/PrintWriterResponseWrapper.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/ResourceRuntimeExtension.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/ResourceRuntimeExtension.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/ResourceRuntimeExtension.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/ResourceRuntimeExtension.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,241 @@
+/*******************************************************************************
+ * 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.impl.engine.extension;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.script.Bindings;
+import javax.servlet.RequestDispatcher;
+
+import org.apache.commons.lang.StringUtils;
+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.Service;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.request.RequestDispatcherOptions;
+import org.apache.sling.api.resource.NonExistingResource;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.api.resource.SyntheticResource;
+import org.apache.sling.api.scripting.SlingBindings;
+import org.apache.sling.scripting.sightly.extension.ExtensionInstance;
+import org.apache.sling.scripting.sightly.extension.RuntimeExtension;
+import org.apache.sling.scripting.sightly.impl.plugin.ResourcePlugin;
+import org.apache.sling.scripting.sightly.render.RenderContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Runtime support for including resources in a Sightly script through {@code data-sly-resource}. For more details check the implementation
+ * of the {@link org.apache.sling.scripting.sightly.impl.plugin.ResourcePlugin}.
+ */
+@Component
+@Service(RuntimeExtension.class)
+@Properties(
+        @Property(name = RuntimeExtension.SCR_PROP_NAME, value = ResourcePlugin.FUNCTION)
+)
+@SuppressWarnings("unused")
+public class ResourceRuntimeExtension implements RuntimeExtension {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ResourceRuntimeExtension.class);
+    private static final String OPTION_RESOURCE_TYPE = "resourceType";
+    private static final String OPTION_PATH = "path";
+    private static final String OPTION_PREPEND_PATH = "prependPath";
+    private static final String OPTION_APPEND_PATH = "appendPath";
+    private static final String OPTION_SELECTORS = "selectors";
+    private static final String OPTION_REMOVE_SELECTORS = "removeSelectors";
+    private static final String OPTION_ADD_SELECTORS = "addSelectors";
+    private static final String OPTION_REPLACE_SELECTORS = "replaceSelectors";
+
+    @Override
+    public ExtensionInstance provide(final RenderContext renderContext) {
+        return new ExtensionInstance() {
+
+            private final Bindings bindings = renderContext.getBindings();
+
+            @Override
+            @SuppressWarnings("unchecked")
+            public Object call(Object... arguments) {
+                ExtensionUtils.checkArgumentCount(ResourcePlugin.FUNCTION, arguments, 2);
+                return provideResource(arguments[0], (Map<String, Object>) arguments[1]);
+            }
+
+            private String provideResource(Object pathObj, Map<String, Object> options) {
+                Map<String, Object> opts = new HashMap<String, Object>(options);
+                String path = buildPath(pathObj, opts);
+                String resourceType = getAndRemoveOption(opts, OPTION_RESOURCE_TYPE);
+                handleSelectors(path, opts);
+                String dispatcherOptions = createDispatcherOptions(opts);
+                StringWriter writer = new StringWriter();
+                PrintWriter printWriter = new PrintWriter(writer);
+                includeResource(printWriter, path, dispatcherOptions, resourceType);
+                return writer.toString();
+            }
+
+            private void handleSelectors(String path, Map<String, Object> options) {
+                String selectors = getAndRemoveOption(options, OPTION_SELECTORS);
+                if (StringUtils.isNotEmpty(selectors)) {
+                    // handle the selectors option
+                    options.put(OPTION_ADD_SELECTORS, selectors);
+                    options.put(OPTION_REPLACE_SELECTORS, " ");
+                } else {
+                    if (options.containsKey(OPTION_REMOVE_SELECTORS)) {
+                        String removeSelectors = getAndRemoveOption(options, OPTION_REMOVE_SELECTORS);
+                        if (StringUtils.isEmpty(removeSelectors)) {
+                            options.put(OPTION_REPLACE_SELECTORS, " ");
+                        } else {
+                            String currentSelectors = getSelectorsFromPath(path);
+                            if (StringUtils.isEmpty(currentSelectors)) {
+                                currentSelectors = ((SlingHttpServletRequest) bindings.get(SlingBindings.REQUEST)).getRequestPathInfo()
+                                        .getSelectorString();
+                            }
+                            if (StringUtils.isNotEmpty(currentSelectors)) {
+                                options.put(OPTION_REPLACE_SELECTORS, " ");
+                                String addSelectors = currentSelectors.replace(removeSelectors, "").replaceAll("\\.\\.", "\\.");
+                                if (addSelectors.startsWith(".")) {
+                                    addSelectors = addSelectors.substring(1);
+                                }
+                                if (addSelectors.endsWith(".")) {
+                                    addSelectors = addSelectors.substring(0, addSelectors.length() - 1);
+                                }
+                                options.put(OPTION_ADD_SELECTORS, addSelectors);
+                            }
+                        }
+                    }
+                }
+            }
+
+            private String buildPath(Object pathObj, Map<String, Object> options) {
+                String path = coerceString(pathObj);
+                String prependPath = getAndRemoveOption(options, OPTION_PREPEND_PATH);
+                String appendPath = getAndRemoveOption(options, OPTION_APPEND_PATH);
+                if (StringUtils.isEmpty(path)) {
+                    path = getOption(options, OPTION_PATH);
+                }
+                if (StringUtils.isNotEmpty(prependPath)) {
+                    path = prependPath + "/" + path;
+                }
+                if (StringUtils.isNotEmpty(appendPath)) {
+                    path = path + "/" + appendPath;
+                }
+
+                return path;
+            }
+
+            private String createDispatcherOptions(Map<String, Object> options) {
+                if (options == null || options.isEmpty()) {
+                    return null;
+                }
+                StringBuilder buffer = new StringBuilder();
+                boolean hasPreceding = false;
+                for (Map.Entry<String, Object> option : options.entrySet()) {
+                    if (hasPreceding) {
+                        buffer.append(", ");
+                    }
+                    String key = option.getKey();
+                    buffer.append(key).append("=");
+                    String strVal = coerceString(option.getValue());
+                    if (strVal == null) {
+                        strVal = "";
+                    }
+                    buffer.append(strVal);
+                    hasPreceding = true;
+                }
+                return buffer.toString();
+            }
+
+            private String coerceString(Object obj) {
+                if (obj instanceof String) {
+                    return (String) obj;
+                }
+                return null;
+            }
+
+            private String getOption(Map<String, Object> options, String property) {
+                return (String) options.get(property);
+            }
+
+            private String getAndRemoveOption(Map<String, Object> options, String property) {
+                return (String) options.remove(property);
+            }
+
+            private String getSelectorsFromPath(String path) {
+                String filePath;
+                if (path.contains("/")) {
+                    filePath = path.substring(path.lastIndexOf('/') + 1, path.length());
+                } else {
+                    filePath = path;
+                }
+                String[] parts = filePath.split("\\.");
+                if (parts.length > 2) {
+                    StringBuilder sb = new StringBuilder();
+                    for (int i = 1; i < parts.length - 1; i++) {
+                        sb.append(parts[i]);
+                        if (i != parts.length - 2) {
+                            sb.append(".");
+                        }
+                    }
+                    if (sb.length() > 0) {
+                        return sb.toString();
+                    }
+                }
+                return null;
+            }
+
+            private void includeResource(PrintWriter out, String script, String dispatcherOptions, String resourceType) {
+                if (StringUtils.isEmpty(script)) {
+                    LOG.error("Script path cannot be empty");
+                } else {
+                    SlingHttpServletResponse customResponse = new PrintWriterResponseWrapper(out,
+                            (SlingHttpServletResponse) bindings.get(SlingBindings.RESPONSE));
+                    SlingHttpServletRequest request = (SlingHttpServletRequest) bindings.get(SlingBindings.REQUEST);
+                    script = normalizePath(request, script);
+
+                    Resource includeRes = request.getResourceResolver().resolve(script);
+                    if (includeRes instanceof NonExistingResource || includeRes.isResourceType(Resource.RESOURCE_TYPE_NON_EXISTING)) {
+                        includeRes = new SyntheticResource(request.getResourceResolver(), script, resourceType);
+                    }
+                    try {
+                        RequestDispatcherOptions opts = new RequestDispatcherOptions(dispatcherOptions);
+                        if (StringUtils.isNotEmpty(resourceType)) {
+                            opts.setForceResourceType(resourceType);
+                        }
+                        RequestDispatcher dispatcher = request.getRequestDispatcher(includeRes, opts);
+                        dispatcher.include(request, customResponse);
+                    } catch (Exception e) {
+                        LOG.error("Failed to include resource {}", script, e);
+                    }
+                }
+            }
+
+            private String normalizePath(SlingHttpServletRequest request, String path) {
+                if (!path.startsWith("/")) {
+                    path = request.getResource().getPath() + "/" + path;
+                }
+                return ResourceUtil.normalize(path);
+            }
+
+        };
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/ResourceRuntimeExtension.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/XSSRuntimeExtension.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/XSSRuntimeExtension.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/XSSRuntimeExtension.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/XSSRuntimeExtension.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,239 @@
+/*******************************************************************************
+ * 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.impl.engine.extension;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import javax.script.Bindings;
+
+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.Service;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.scripting.sightly.extension.ExtensionInstance;
+import org.apache.sling.scripting.sightly.extension.RuntimeExtension;
+import org.apache.sling.scripting.sightly.extension.RuntimeExtensionException;
+import org.apache.sling.scripting.sightly.impl.compiler.CompilerException;
+import org.apache.sling.scripting.sightly.impl.filter.XSSFilter;
+import org.apache.sling.scripting.sightly.impl.html.MarkupUtils;
+import org.apache.sling.scripting.sightly.impl.plugin.MarkupContext;
+import org.apache.sling.scripting.sightly.render.RenderContext;
+import org.apache.sling.xss.XSSAPI;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Runtime support for XSS filtering
+ */
+@Component
+@Service(RuntimeExtension.class)
+@Properties(
+        @Property(name = RuntimeExtension.SCR_PROP_NAME, value = XSSFilter.FUNCTION_NAME)
+)
+public class XSSRuntimeExtension implements RuntimeExtension {
+
+    private static final Set<String> elementNameWhiteList = new HashSet<String>();
+    private static final Logger LOG = LoggerFactory.getLogger(XSSRuntimeExtension.class);
+    private static final Pattern VALID_ATTRIBUTE = Pattern.compile("^[a-zA-Z_:][\\-a-zA-Z0-9_:\\.]*$");
+
+    @Override
+    public ExtensionInstance provide(final RenderContext renderContext) {
+
+        final XSSAPI xssapi = obtainAPI(renderContext.getBindings());
+
+        return new ExtensionInstance() {
+            @Override
+            public Object call(Object... arguments) {
+                if (arguments.length < 2) {
+                    throw new RuntimeExtensionException(
+                            String.format("Extension %s requires at least %d arguments", XSSFilter.FUNCTION_NAME, 2));
+                }
+                Object original = arguments[0];
+                Object option = arguments[1];
+                Object hint = null;
+                if (arguments.length >= 3) {
+                    hint = arguments[2];
+                }
+                MarkupContext markupContext = null;
+                if (option != null && option instanceof String) {
+                    String name = (String) option;
+                    markupContext = MarkupContext.lookup(name);
+                }
+                if (markupContext == MarkupContext.UNSAFE) {
+                    return original;
+                }
+                if (markupContext == null) {
+                    LOG.warn("Expression context {} is invalid, expression will be replaced by the empty string", option);
+                    return "";
+                }
+                String text = renderContext.toString(original);
+                return applyXSSFilter(text, hint, markupContext);
+            }
+
+            private String applyXSSFilter(String text, Object hint, MarkupContext xssContext) {
+                if (xssContext.equals(MarkupContext.ATTRIBUTE) && hint instanceof String) {
+                    String attributeName = (String) hint;
+                    MarkupContext attrMarkupContext = getAttributeMarkupContext(attributeName);
+                    return applyXSSFilter(text, attrMarkupContext);
+                }
+                return applyXSSFilter(text, xssContext);
+            }
+
+            private String applyXSSFilter(String text, MarkupContext xssContext) {
+                switch (xssContext) {
+                    case ATTRIBUTE:
+                        return xssapi.encodeForHTMLAttr(text);
+                    case COMMENT:
+                    case TEXT:
+                        return xssapi.encodeForHTML(text);
+                    case ATTRIBUTE_NAME:
+                        return escapeAttributeName(text);
+                    case NUMBER:
+                        return xssapi.getValidLong(text, 0).toString();
+                    case URI:
+                        return xssapi.getValidHref(text);
+                    case SCRIPT_TOKEN:
+                    case SCRIPT_COMMENT:
+                        return xssapi.getValidJSToken(text, "");
+                    case STYLE_TOKEN:
+                        return xssapi.getValidStyleToken(text, "");
+                    case SCRIPT_STRING:
+                        return xssapi.encodeForJSString(text);
+                    case ELEMENT_NAME:
+                        return escapeElementName(text);
+                    case HTML:
+                        return xssapi.filterHTML(text);
+                }
+                return text; //todo: apply the rest of XSS filters
+            }
+        };
+    }
+
+    private String escapeElementName(String original) {
+        original = original.trim();
+        if (elementNameWhiteList.contains(original.toLowerCase())) {
+            return original;
+        }
+        return "";
+    }
+
+    private XSSAPI obtainAPI(Bindings bindings) {
+        SlingHttpServletRequest request = (SlingHttpServletRequest) bindings.get("request");
+        if (request == null) {
+            throw new CompilerException("Cannot obtain request from bindings");
+        }
+        return request.adaptTo(XSSAPI.class);
+    }
+
+    private MarkupContext getAttributeMarkupContext(String attributeName) {
+        if ("src".equalsIgnoreCase(attributeName) || "href".equalsIgnoreCase(attributeName)) {
+            return MarkupContext.URI;
+        }
+        return MarkupContext.ATTRIBUTE;
+    }
+
+    private String escapeAttributeName(String attributeName) {
+        if (attributeName == null) {
+            return null;
+        }
+        attributeName = attributeName.trim();
+        if (matchPattern(VALID_ATTRIBUTE, attributeName) && !MarkupUtils.isSensitiveAttribute(attributeName)) {
+            return attributeName;
+        }
+        return null;
+    }
+
+    private boolean matchPattern(Pattern pattern, String str) {
+        return pattern.matcher(str).matches();
+    }
+
+    static {
+        elementNameWhiteList.add("section");
+        elementNameWhiteList.add("nav");
+        elementNameWhiteList.add("article");
+        elementNameWhiteList.add("aside");
+        elementNameWhiteList.add("h1");
+        elementNameWhiteList.add("h2");
+        elementNameWhiteList.add("h3");
+        elementNameWhiteList.add("h4");
+        elementNameWhiteList.add("h5");
+        elementNameWhiteList.add("h6");
+        elementNameWhiteList.add("header");
+        elementNameWhiteList.add("footer");
+        elementNameWhiteList.add("address");
+        elementNameWhiteList.add("main");
+        elementNameWhiteList.add("p");
+        elementNameWhiteList.add("pre");
+        elementNameWhiteList.add("blockquote");
+        elementNameWhiteList.add("ol");
+        elementNameWhiteList.add("li");
+        elementNameWhiteList.add("dl");
+        elementNameWhiteList.add("dt");
+        elementNameWhiteList.add("dd");
+        elementNameWhiteList.add("figure");
+        elementNameWhiteList.add("figcaption");
+        elementNameWhiteList.add("div");
+        elementNameWhiteList.add("a");
+        elementNameWhiteList.add("em");
+        elementNameWhiteList.add("strong");
+        elementNameWhiteList.add("small");
+        elementNameWhiteList.add("s");
+        elementNameWhiteList.add("cite");
+        elementNameWhiteList.add("q");
+        elementNameWhiteList.add("dfn");
+        elementNameWhiteList.add("abbbr");
+        elementNameWhiteList.add("data");
+        elementNameWhiteList.add("time");
+        elementNameWhiteList.add("code");
+        elementNameWhiteList.add("var");
+        elementNameWhiteList.add("samp");
+        elementNameWhiteList.add("kbd");
+        elementNameWhiteList.add("sub");
+        elementNameWhiteList.add("sup");
+        elementNameWhiteList.add("i");
+        elementNameWhiteList.add("b");
+        elementNameWhiteList.add("u");
+        elementNameWhiteList.add("mark");
+        elementNameWhiteList.add("ruby");
+        elementNameWhiteList.add("rt");
+        elementNameWhiteList.add("rp");
+        elementNameWhiteList.add("bdi");
+        elementNameWhiteList.add("bdo");
+        elementNameWhiteList.add("span");
+        elementNameWhiteList.add("br");
+        elementNameWhiteList.add("wbr");
+        elementNameWhiteList.add("ins");
+        elementNameWhiteList.add("del");
+        elementNameWhiteList.add("table");
+        elementNameWhiteList.add("caption");
+        elementNameWhiteList.add("colgroup");
+        elementNameWhiteList.add("col");
+        elementNameWhiteList.add("tbody");
+        elementNameWhiteList.add("thead");
+        elementNameWhiteList.add("tfoot");
+        elementNameWhiteList.add("tr");
+        elementNameWhiteList.add("td");
+        elementNameWhiteList.add("th");
+    }
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/XSSRuntimeExtension.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/ClassUseProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/ClassUseProvider.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/ClassUseProvider.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/ClassUseProvider.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * 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.impl.engine.extension.use;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.script.Bindings;
+import javax.servlet.ServletRequest;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.scripting.SlingBindings;
+import org.apache.sling.api.scripting.SlingScriptHelper;
+import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
+import org.apache.sling.scripting.sightly.render.RenderContext;
+import org.apache.sling.scripting.sightly.use.ProviderOutcome;
+import org.apache.sling.scripting.sightly.use.UseProvider;
+import org.osgi.framework.Constants;
+
+/**
+ * Interprets the identifier as a class name and tries to load that class
+ * using a dynamic class loader
+ */
+@Component(
+        metatype = true,
+        label = "Apache Sling Scripting Sightly Class Use Provider",
+        description = "The Class Use Provider is responsible for instantiating Use-API objects that are adaptable from Resource or " +
+                "SlingHttpServletRequest."
+)
+@Service(UseProvider.class)
+@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.",
+                intValue = 80,
+                propertyPrivate = false
+        )
+})
+public class ClassUseProvider implements UseProvider {
+
+    @Override
+    public ProviderOutcome provide(String identifier, RenderContext renderContext, Bindings arguments) {
+        Bindings globalBindings = renderContext.getBindings();
+        Bindings bindings = UseProviderUtils.merge(globalBindings, arguments);
+        SlingScriptHelper sling = (SlingScriptHelper) bindings.get(SlingBindings.SLING);
+        Resource resource = (Resource) bindings.get(SlingBindings.RESOURCE);
+        final SlingHttpServletRequest request = (SlingHttpServletRequest) bindings.get(SlingBindings.REQUEST);
+        Map<String, Object> overrides = setRequestAttributes(request, arguments);
+        
+        DynamicClassLoaderManager classLoaderManager = sling.getService(DynamicClassLoaderManager.class);
+        Object obj;
+        try {
+            Class<?> cls = classLoaderManager.getDynamicClassLoader().loadClass(identifier);
+            obj = resource.adaptTo(cls);
+            if (obj == null) {
+                obj = request.adaptTo(cls);
+            }
+        } catch (ClassNotFoundException e) {
+            obj = null;
+        } finally {
+            resetRequestAttribute(request, overrides);
+        }
+        return ProviderOutcome.notNullOrFailure(obj);
+    }
+
+    private Map<String, Object> setRequestAttributes(ServletRequest request, Bindings arguments) {
+        Map<String, Object> overrides = new HashMap<String, Object>();
+        for (Map.Entry<String, Object> entry : arguments.entrySet()) {
+            String key = entry.getKey();
+            Object value = entry.getValue();
+            Object oldValue = request.getAttribute(key);
+            if (oldValue != null) {
+                overrides.put(key, oldValue);
+            } else {
+                overrides.put(key, NULL);
+            }
+            request.setAttribute(key, value);
+        }
+        return overrides;
+    }
+
+    private void resetRequestAttribute(ServletRequest request, Map<String, Object> overrides) {
+        for (Map.Entry<String, Object> entry : overrides.entrySet()) {
+            String key = entry.getKey();
+            Object value = entry.getValue();
+            if (value == NULL) {
+                request.removeAttribute(key);
+            } else {
+                request.setAttribute(key, value);
+            }
+        }
+    }
+
+    private static final Object NULL = new Object();
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/ClassUseProvider.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/PojoUseProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/PojoUseProvider.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/PojoUseProvider.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/PojoUseProvider.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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.impl.engine.extension.use;
+
+import javax.script.Bindings;
+
+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;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.api.scripting.SlingScriptHelper;
+import org.apache.sling.scripting.sightly.ResourceResolution;
+import org.apache.sling.scripting.sightly.impl.compiler.SightlyJavaCompilerService;
+import org.apache.sling.scripting.sightly.pojo.Use;
+import org.apache.sling.scripting.sightly.render.RenderContext;
+import org.apache.sling.scripting.sightly.use.ProviderOutcome;
+import org.apache.sling.scripting.sightly.use.UseProvider;
+import org.osgi.framework.Constants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Provider which instantiates POJOs.
+ */
+@Component(
+        metatype = true,
+        label = "Apache Sling Scripting Sightly POJO Use Provider",
+        description = "The POJO Use Provider is responsible for instantiating Use-API objects that optionally can implement the org" +
+                ".apache.sling.scripting.sightly.use.Use interface."
+)
+@Service(UseProvider.class)
+@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.",
+                intValue = 90,
+                propertyPrivate = false
+        )
+})
+public class PojoUseProvider implements UseProvider {
+
+    private final Logger LOG = LoggerFactory.getLogger(PojoUseProvider.class);
+
+    @Reference
+    private SightlyJavaCompilerService sightlyJavaCompilerService = null;
+
+    @Override
+    public ProviderOutcome provide(String identifier, RenderContext renderContext, Bindings arguments) {
+        Bindings globalBindings = renderContext.getBindings();
+        Bindings bindings = UseProviderUtils.merge(globalBindings, arguments);
+        SlingScriptHelper sling = UseProviderUtils.getHelper(bindings);
+        ResourceResolverFactory rrf = sling.getService(ResourceResolverFactory.class);
+        ResourceResolver adminResolver = null;
+        try {
+            adminResolver = rrf.getAdministrativeResourceResolver(null);
+            Resource resource = ResourceResolution.resolveComponentForRequest(adminResolver, sling.getRequest());
+            Object result = sightlyJavaCompilerService.getInstance(resource, identifier);
+            if (result instanceof Use) {
+                ((Use) result).init(bindings);
+            }
+            return ProviderOutcome.notNullOrFailure(result);
+        } catch (Exception e) {
+            LOG.error(String.format("Can't instantiate %s POJO.", identifier), e);
+            return ProviderOutcome.failure();
+        } finally {
+            if (adminResolver != null) {
+                adminResolver.close();
+            }
+        }
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/PojoUseProvider.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain