Author: cziegeler
Date: Fri Jul 22 06:16:52 2016
New Revision: 1753753

URL: http://svn.apache.org/viewvc?rev=1753753&view=rev
Log:
Configuration Prototype

Added:
    sling/whiteboard/cziegeler/sling-conf/
    sling/whiteboard/cziegeler/sling-conf/pom.xml   (with props)
    sling/whiteboard/cziegeler/sling-conf/src/
    sling/whiteboard/cziegeler/sling-conf/src/main/
    sling/whiteboard/cziegeler/sling-conf/src/main/java/
    sling/whiteboard/cziegeler/sling-conf/src/main/java/org/
    sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/
    sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/
    sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/
    
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/ConfigResolver.java
   (with props)
    
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/impl/
    
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/impl/ConfigResolverImpl.java
   (with props)
    
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/impl/WebConsolePlugin.java
   (with props)
    
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/package-info.java
   (with props)
    
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/
    
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/Preference.java
   (with props)
    
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/Preferences.java
   (with props)
    
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/PreferencesResolver.java
   (with props)
    
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/
    
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferenceImpl.java
   (with props)
    
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesAdapterFactory.java
   (with props)
    
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesImpl.java
   (with props)
    
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesResolverImpl.java
   (with props)
    
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/package-info.java
   (with props)

Added: sling/whiteboard/cziegeler/sling-conf/pom.xml
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/sling-conf/pom.xml?rev=1753753&view=auto
==============================================================================
--- sling/whiteboard/cziegeler/sling-conf/pom.xml (added)
+++ sling/whiteboard/cziegeler/sling-conf/pom.xml Fri Jul 22 06:16:52 2016
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>sling</artifactId>
+        <version>27-SNAPSHOT</version>
+        <relativePath/>
+    </parent>
+
+    <artifactId>org.apache.sling.config</artifactId>
+    <packaging>bundle</packaging>
+    <version>0.0.1-SNAPSHOT</version>
+
+    <name>Apache Sling Configuration</name>
+    <description>
+        Manage content releated configurations
+    </description>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-scr-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <configuration>
+                    <excludePackageNames>
+                        
org.apache.sling.config.impl:org.apache.sling.config.preferences.impl
+                    </excludePackageNames>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.cmpn</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.api</artifactId>
+            <version>2.11.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.xss</artifactId>
+            <version>1.0.8</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.webconsole</artifactId>
+            <version>3.0.0</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- Testing -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+    </dependencies>
+</project>

Propchange: sling/whiteboard/cziegeler/sling-conf/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/whiteboard/cziegeler/sling-conf/pom.xml
------------------------------------------------------------------------------
    svn:keywords = Id

Added: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/ConfigResolver.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/ConfigResolver.java?rev=1753753&view=auto
==============================================================================
--- 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/ConfigResolver.java
 (added)
+++ 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/ConfigResolver.java
 Fri Jul 22 06:16:52 2016
@@ -0,0 +1,65 @@
+/*
+ * 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.config;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.sling.api.resource.Resource;
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * Service to lookup and access content related configurations in the
+ * resource tree. This service provides the base for more specific
+ * configurations like the preferences.
+ */
+@ProviderType
+public interface ConfigResolver {
+
+    /**
+     * Standard name for the reference property used to lookup configurations.
+     * For example, a string property on /content pointing to /config/foo.
+     *
+     * <p>
+     * This is a single string property containing an absolute path.
+     */
+    String PROPERTY_CONFIG = "sling:config";
+
+    List<String> getResolvePaths(Resource resource);
+
+    /**
+     * Retrieves a configuration {@link Resource} for the given content 
resource
+     * and name using the resource resolver behind the given resource.
+     *
+     * @param resource a content resource.
+     * @param name The name of the configuration. This is a relative path.
+     * @return a configuration resource or {@code null}.
+     */
+    Resource resolve(Resource resource, String name);
+
+    /**
+     * Retrieves a list of child configuration {@link Resource} for the given 
content
+     * resource and name using the resource resolver behind the given resource.
+     *
+     * @param resource a content resource.
+     * @param name The name of the configuration. This is a relative path.
+     * @return a collection of configuration resources. The collection might 
be empty.
+     */
+    Collection<Resource> resolveChildren(Resource resource, String name);
+}

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/ConfigResolver.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/ConfigResolver.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/impl/ConfigResolverImpl.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/impl/ConfigResolverImpl.java?rev=1753753&view=auto
==============================================================================
--- 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/impl/ConfigResolverImpl.java
 (added)
+++ 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/impl/ConfigResolverImpl.java
 Fri Jul 22 06:16:52 2016
@@ -0,0 +1,282 @@
+/*
+ * 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.config.impl;
+
+
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.config.ConfigResolver;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(service=ConfigResolver.class)
+@Designate(ocd=ConfigResolverImpl.Config.class)
+public class ConfigResolverImpl implements ConfigResolver {
+
+    @ObjectClassDefinition(name="Apache Sling Config Resolver",
+                           description="Standardized access to configurations 
in the resource tree.")
+    public static @interface Config {
+
+        @AttributeDefinition(name="Allowed paths",
+                             description = "Whitelist of paths where 
configurations can reside in.")
+        String[] allowedPaths() default {"/config", "/apps", "/libs"};
+
+        @AttributeDefinition(name="Fallback paths",
+                description = "Global fallback configurations, ordered from 
most specific (checked first) to least specific.")
+        String[] fallbackPaths() default {"/config/global", "/apps", "/libs"};
+    }
+
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    private volatile Config configuration;
+
+    // for SCR
+    public ConfigResolverImpl() {
+        // nothing to do
+    }
+
+    // for unit testing
+    public ConfigResolverImpl(final String[] allowedPaths, final String[] 
fallbackPaths) {
+        this.configuration = new Config() {
+
+            @Override
+            public Class<? extends Annotation> annotationType() {
+                return null;
+            }
+
+            @Override
+            public String[] allowedPaths() {
+                return allowedPaths;
+            }
+
+            @Override
+            public String[] fallbackPaths() {
+                return fallbackPaths;
+            }
+
+        };
+    }
+
+    Config getConfiguration() {
+        return this.configuration;
+    }
+
+    @Activate
+    private void activate(final Config config) {
+        this.configuration = config;
+    }
+
+    @Deactivate
+    private void deactivate() {
+        this.configuration = null;
+    }
+
+
+    @Override
+    public List<String> getResolvePaths(final Resource contentResource) {
+        final List<String> refs = new ArrayList<String>();
+
+        // find property reference
+        String ref = this.findConfigRef(contentResource);
+
+        if (ref == null) {
+            // nothing found so far, check if we are in a configured tree 
itself
+            if (isAllowedConfigPath(contentResource.getPath())) {
+                ref = contentResource.getPath();
+            }
+        }
+
+        if ( ref != null ) {
+            refs.add(ref);
+        }
+
+        // finally add the global fallbacks
+        if ( this.configuration.fallbackPaths() != null ) {
+            for(final String path : this.configuration.fallbackPaths()) {
+                logger.debug("[{}] fallback config => {}", refs.size(), path);
+                refs.add(path);
+            }
+        }
+
+        return refs;
+    }
+
+    /**
+     * Check the name.
+     * A name must not be null and relative.
+     * @param name The name
+     * @return {@code true} if it is valid
+     */
+    private boolean checkName(final String name) {
+        if (name == null || name.isEmpty() || name.startsWith("/") || 
name.contains("../") ) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public Resource resolve(final Resource contentResource, final String name) 
{
+        if (contentResource == null || !checkName(name)) {
+            return null;
+        }
+        logger.debug("Searching {} for resource {}", name, 
contentResource.getPath());
+
+        // strategy: find first item among all configured paths
+        int idx = 1;
+        for (final String path : getResolvePaths(contentResource)) {
+            final Resource item = 
contentResource.getResourceResolver().getResource(path + "/" + name);
+            if (item != null) {
+                logger.debug("Resolved config item at [{}]: {}", idx, 
item.getPath());
+
+                return item;
+            }
+            idx++;
+        }
+
+        logger.debug("Could not resolve any config item for '{}' (or no 
permissions to read it)", name);
+
+        // nothing found
+        return null;
+    }
+
+    @Override
+    public Collection<Resource> resolveChildren(final Resource 
contentResource, final String name) {
+        if (contentResource == null || !checkName(name)) {
+            return Collections.emptyList();
+        }
+        if (logger.isTraceEnabled()) {
+            logger.trace("- searching for list '{}'", name);
+        }
+
+        final Set<String> names = new HashSet<String>();
+        final List<Resource> result = new ArrayList<Resource>();
+        int idx = 1;
+        for (String path : this.getResolvePaths(contentResource)) {
+            Resource item = 
contentResource.getResourceResolver().getResource(path + "/" + name);
+            if (item != null) {
+                if (logger.isTraceEnabled()) {
+                    logger.trace("+ resolved config item at [{}]: {}", idx, 
item.getPath());
+                }
+
+                for (Resource child : item.getChildren()) {
+                    if ( !child.getName().contains(":") && 
!names.contains(child.getName()) ) {
+                        result.add(child);
+                        names.add(child.getName());
+                    }
+                }
+
+            } else {
+                if (logger.isTraceEnabled()) {
+                    logger.trace("- no item '{}' under config '{}'", name, 
path);
+                }
+            }
+            idx++;
+        }
+
+        if (logger.isTraceEnabled()) {
+            logger.trace("- final list has {} items", result.size());
+        }
+
+        return result;
+    }
+
+   private String findConfigRef(final Resource startResource) {
+        // start at resource, go up
+        Resource resource = startResource;
+        while (resource != null) {
+            String ref = getReference(resource);
+            if (ref != null) {
+                // if absolute path found we are (probably) done
+                if (ref.startsWith("/")) {
+                    // combine full path if relativeRef is present
+                    ref = ResourceUtil.normalize(ref);
+
+                    if (ref != null && !isAllowedConfigPath(ref)) {
+                        logger.warn("Ignoring reference to {} from {} - not in 
allowed paths.", ref, resource.getPath());
+                        ref = null;
+                    }
+
+                    if (ref != null && isFallbackConfigPath(ref)) {
+                        logger.warn("Ignoring reference to {} from {} - 
already a fallback path.", ref, resource.getPath());
+                        ref = null;
+                    }
+
+                    if (ref != null) {
+                        return ref;
+                    }
+
+                } else {
+                    logger.error("Invalid relative reference found for {} : 
{}. This entry is ignored", resource.getPath(), ref);
+                }
+            }
+            // if getParent() returns null, stop
+            resource = resource.getParent();
+        }
+
+        // if hit root and nothing found, return null
+        return null;
+    }
+
+    private String getReference(final Resource resource) {
+        final String ref = 
resource.getValueMap().get(ConfigResolver.PROPERTY_CONFIG, String.class);
+        logger.trace("Reference '{}' found at {}", ref, resource.getPath());
+
+        return ref;
+    }
+
+    private boolean isAllowedConfigPath(String path) {
+        if (this.configuration.allowedPaths() == null) {
+            return false;
+        }
+        for (String pattern : this.configuration.allowedPaths()) {
+            if (logger.isTraceEnabled()) {
+                logger.trace("- checking if '{}' starts with {}", path, 
pattern);
+            }
+            if (path.equals(pattern) || path.startsWith(pattern + "/")) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isFallbackConfigPath(final String ref) {
+        if ( this.configuration.fallbackPaths() != null ) {
+            for(final String name : this.configuration.fallbackPaths()) {
+                if ( name.equals(ref) ) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/impl/ConfigResolverImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/impl/ConfigResolverImpl.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/impl/WebConsolePlugin.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/impl/WebConsolePlugin.java?rev=1753753&view=auto
==============================================================================
--- 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/impl/WebConsolePlugin.java
 (added)
+++ 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/impl/WebConsolePlugin.java
 Fri Jul 22 06:16:52 2016
@@ -0,0 +1,279 @@
+/*
+ * 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.config.impl;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Collections;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.felix.webconsole.AbstractWebConsolePlugin;
+import org.apache.felix.webconsole.WebConsoleConstants;
+import org.apache.sling.api.resource.LoginException;
+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.config.ConfigResolver;
+import org.apache.sling.xss.XSSAPI;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+@Component(service=Servlet.class,
+           property={"org.osgi.framework.Constants.SERVICE_DESCRIPTION=Apache 
Sling Web Console Plugin for configurations",
+                   WebConsoleConstants.PLUGIN_LABEL + "=" + 
WebConsolePlugin.LABEL,
+                   WebConsoleConstants.PLUGIN_TITLE + "=" + 
WebConsolePlugin.TITLE})
+@SuppressWarnings("serial")
+public class WebConsolePlugin extends AbstractWebConsolePlugin {
+
+    public static final String LABEL = "configresolver";
+    public static final String TITLE = "Config Resolver";
+
+    @Reference
+    private ResourceResolverFactory resolverFactory;
+
+    @Reference
+    private ConfigResolver configResolver;
+
+    @Reference
+    private XSSAPI xssAPI;
+
+    @Override
+    public String getLabel() {
+        return LABEL;
+    }
+
+    @Override
+    public String getTitle() {
+        return TITLE;
+    }
+
+    @Override
+    protected void renderContent(HttpServletRequest request, 
HttpServletResponse response)
+        throws ServletException, IOException {
+
+        final PrintWriter pw = response.getWriter();
+
+        info(pw, "Configurations are managed in the resource tree. Use this 
tool to test configuration resolutions.");
+
+        printConfiguration(pw);
+
+        pw.println("<br/>");
+
+        printResolutionTestTool(request, pw);
+    }
+
+    private void printConfiguration(final PrintWriter pw) {
+        final ConfigResolverImpl configResolverImpl = (ConfigResolverImpl) 
configResolver;
+        tableStart(pw, "Configuration", 2);
+        pw.println("<tr>");
+        pw.println("<td style='width:20%'>Allowed paths</td>");
+        pw.print("<td>");
+        
pw.print(xssAPI.encodeForHTML(Arrays.toString(configResolverImpl.getConfiguration().allowedPaths())));
+        pw.println("</td>");
+        pw.println("</tr>");
+        pw.println("<tr>");
+        pw.println("<td style='width:20%'>Fallback paths</td>");
+        pw.print("<td>");
+        
pw.print(xssAPI.encodeForHTML(Arrays.toString(configResolverImpl.getConfiguration().fallbackPaths())));
+        pw.println("</td>");
+        pw.println("</tr>");
+        pw.println("<tr>");
+        pw.println("<td></td>");
+        pw.println("<td>");
+        pw.print("<form method='get' action='${appRoot}/configMgr/");
+        pw.print(ConfigResolverImpl.class.getName());
+        pw.println("'>");
+        pw.println("<input type='submit' value='Configure'/>");
+        pw.println("</form>");
+        pw.println("</td>");
+        pw.println("</tr>");
+        tableEnd(pw);
+    }
+
+    private String getParameter(final HttpServletRequest request, final String 
name, final String defaultValue) {
+        String value = request.getParameter(name);
+        if ( value != null && !value.trim().isEmpty() ) {
+            return value.trim();
+        }
+        return defaultValue;
+    }
+
+    private void printResolutionTestTool(HttpServletRequest request, 
PrintWriter pw) {
+        final String path = this.getParameter(request, "path", null);
+        final String item = this.getParameter(request, "item", ".");
+        final String user = this.getParameter(request, "user", null);
+
+        ResourceResolver resolver = null;
+        try {
+            Resource content = null;
+            if (path != null) {
+                resolver = getResolver(user);
+                if (resolver != null) {
+                    content = resolver.getResource(path);
+                }
+            }
+
+            pw.println("<form method='get'>");
+
+            tableStart(pw, "Test Configuration Resolution", 2);
+            pw.println("<td style='width:20%'>Content Path</td>");
+            pw.print("<td><input name='path' value='");
+            pw.print(xssAPI.encodeForHTMLAttr(path));
+            pw.println("' style='width:100%'/>");
+            if (resolver != null && content == null) {
+                pw.println("<div>");
+                pw.println("<span class='ui-icon ui-icon-alert' 
style='float:left'></span>");
+                pw.println("<span style='float:left'>Path does not 
exist.</span>");
+                pw.println("</div>");
+            }
+            pw.println("</td>");
+
+            tableRows(pw);
+            pw.println("<td>Item</td>");
+            pw.print("<td><input name='item' value='");
+            pw.print(xssAPI.encodeForHTMLAttr(item));
+            pw.println("' style='width:100%'/></td>");
+            tableRows(pw);
+
+            pw.println("<td>User</td>");
+            pw.println("<td><input name='user' value='");
+            pw.print(xssAPI.encodeForHTMLAttr(user));
+            pw.println("' style='width:50%'/>");
+            if (path != null && resolver == null) {
+                pw.println("<div>");
+                pw.println("<span class='ui-icon ui-icon-alert' 
style='float:left'></span>");
+                pw.println("<span style='float:left'>User does not 
exist.</span>");
+                pw.println("</div>");
+            }
+            pw.println("</td>");
+            tableRows(pw);
+
+            pw.println("<td></td>");
+            pw.println("<td><input type='submit' value='Resolve'/></td>");
+            tableEnd(pw);
+
+            pw.println("</form>");
+
+            pw.println("<br/>");
+
+            if (content != null) {
+
+                final Resource confRsrc = configResolver.resolve(content, 
item);
+
+                tableStart(pw, "Resolved", 2);
+                pw.println("<td style='width:20%'>Code</td>");
+                pw.println("<td>");
+                pw.print("<code>resolve(\"");
+                pw.print(xssAPI.encodeForHTML(content.getPath()));
+                pw.print("\", \"");
+                pw.print(xssAPI.encodeForHTML(item));
+                pw.println("\")</code>");
+                pw.println("<br/>&nbsp;");
+                pw.println("</td>");
+                tableRows(pw);
+
+                pw.println("<td style='width:20%'>Item</td>");
+                if (confRsrc != null) {
+                    pw.print("<td>");
+                    pw.print(xssAPI.encodeForHTML(confRsrc.getPath()));
+                    pw.println("<br/>&nbsp;</td>");
+                } else {
+                    pw.println("<td>");
+                    pw.println("<div>");
+                    pw.println("<span class='ui-icon ui-icon-alert' 
style='float:left'></span>");
+                    pw.println("<span style='float:left'>No matching item 
found.</span>");
+                    pw.println("</div>");
+                    pw.println("<br/>&nbsp;</td>");
+                }
+                tableRows(pw);
+
+                pw.println("<td>Config paths</td>");
+
+                pw.println("<td>");
+                for (String p : configResolver.getResolvePaths(content)) {
+                    if (confRsrc != null && confRsrc.getPath().startsWith(p + 
"/")) {
+                        pw.print("<b>");
+                        pw.print(xssAPI.encodeForHTML(p));
+                        pw.println("</b>");
+                    } else {
+                        pw.println(xssAPI.encodeForHTML(p));
+                    }
+                    pw.println("<br/>");
+                }
+                pw.println("</td>");
+
+                tableEnd(pw);
+            }
+
+        } finally {
+            if (resolver != null && user != null) {
+                resolver.close();
+            }
+        }
+    }
+
+    private void info(PrintWriter pw, String text) {
+        pw.print("<p class='statline ui-state-highlight'>");
+        pw.print(xssAPI.encodeForHTML(text));
+        pw.println("</p>");
+    }
+
+    private void tableStart(PrintWriter pw, String title, int colspan) {
+        pw.println("<table class='nicetable ui-widget'>");
+        pw.println("<thead class='ui-widget-header'>");
+        pw.println("<tr>");
+        pw.print("<th colspan=");
+        pw.print(String.valueOf(colspan));
+        pw.print(">");
+        pw.print(xssAPI.encodeForHTML(title));
+        pw.println("</th>");
+        pw.println("</tr>");
+        pw.println("</thead>");
+        pw.println("<tbody class='ui-widget-content'>");
+        pw.println("<tr>");
+    }
+
+    private void tableEnd(PrintWriter pw) {
+        pw.println("</tr>");
+        pw.println("</tbody>");
+        pw.println("</table>");
+    }
+
+    private void tableRows(PrintWriter pw) {
+        pw.println("</tr>");
+        pw.println("<tr>");
+    }
+
+    private ResourceResolver getResolver(final String user) {
+        ResourceResolver requestResolver = 
resolverFactory.getThreadResourceResolver();
+        if ( user == null ) {
+            return requestResolver;
+        }
+        try {
+            return 
requestResolver.clone(Collections.singletonMap(ResourceResolverFactory.USER_IMPERSONATION,
 (Object)user));
+        } catch (final LoginException e) {
+            return null;
+        }
+    }
+}

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/impl/WebConsolePlugin.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/impl/WebConsolePlugin.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/package-info.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/package-info.java?rev=1753753&view=auto
==============================================================================
--- 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/package-info.java
 (added)
+++ 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/package-info.java
 Fri Jul 22 06:16:52 2016
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
[email protected]("1.0.0")
+package org.apache.sling.config;
+

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/package-info.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/Preference.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/Preference.java?rev=1753753&view=auto
==============================================================================
--- 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/Preference.java
 (added)
+++ 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/Preference.java
 Fri Jul 22 06:16:52 2016
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.config.preferences;
+
+import org.apache.sling.api.resource.ValueMap;
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * This is a read only value map which also has a name.
+ */
+@ProviderType
+public interface Preference extends ValueMap {
+
+    /**
+     * Get the name of the value map.
+     * @return The name.
+     */
+    String getName();
+}

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/Preference.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/Preference.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/Preferences.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/Preferences.java?rev=1753753&view=auto
==============================================================================
--- 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/Preferences.java
 (added)
+++ 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/Preferences.java
 Fri Jul 22 06:16:52 2016
@@ -0,0 +1,60 @@
+/*
+ * 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.config.preferences;
+
+import java.util.Collection;
+
+import org.apache.sling.api.resource.ValueMap;
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * Provides access to preferences.
+ */
+@ProviderType
+public interface Preferences {
+
+    /**
+     * Returns preferences values for the given preference item which is a 
relative path.
+     *
+     * <p>
+     * The itemName must be a relative path and is looked up beneath the 
resolved preferences tree.
+     * For example, if the original resource from which this Preferences 
object was created,
+     * points to preferences at "/preferences/sling/ch", and an item path like 
"dam/presets/pdf"
+     * is requested, this will return a value map for the resource at 
"/preferences/sling/ch/dam/presets/pdf".
+     * Note that itemName should be a fixed name specific to the application 
preferences.
+     *
+     * <p>
+     * If no preference resource can be found, an empty value map will be 
returned.
+     *
+     * @param itemName a relative path to an item within a specific 
preferences tree
+     * @return a value map for a configuration resource; an empty map if 
nothing is found or
+     *         the provided path is invalid. The map is read-only.
+     */
+    Preference get(String itemName);
+
+    /**
+     * Returns a list of {@link ValueMap}s for a list of items beneath the 
given preferences item. The
+     * resulting list returns value maps of all resources found at all 
possible preferences paths.
+     *
+     * @param parentItemName a relative path to an item within a specific 
preferences tree
+     * @return a merged list of value maps. An empty list if nothing is found 
or the provided path is invalid.
+     *         The list is unmodifiable.
+     */
+    Collection<Preference> getChildren(String parentItemName);
+}

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/Preferences.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/Preferences.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/PreferencesResolver.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/PreferencesResolver.java?rev=1753753&view=auto
==============================================================================
--- 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/PreferencesResolver.java
 (added)
+++ 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/PreferencesResolver.java
 Fri Jul 22 06:16:52 2016
@@ -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.config.preferences;
+
+import org.apache.sling.api.resource.Resource;
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * Service to lookup and access preferences in the resource tree.
+ */
+@ProviderType
+public interface PreferencesResolver {
+
+    /**
+     * Retrieves a {@link Preferences} for the given resource using the 
resource resolver
+     * behind the given resource.
+     *
+     * @param resource a content resource for which a preferences should be 
resolved
+     * @return a preferences (never null)
+     */
+    Preferences resolve(Resource resource);
+}

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/PreferencesResolver.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/PreferencesResolver.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferenceImpl.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferenceImpl.java?rev=1753753&view=auto
==============================================================================
--- 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferenceImpl.java
 (added)
+++ 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferenceImpl.java
 Fri Jul 22 06:16:52 2016
@@ -0,0 +1,128 @@
+/*
+ * 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.config.preferences.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.config.preferences.Preference;
+
+/**
+ * This is an extension of a value map providing a read-only view
+ * and a name.
+ */
+public class PreferenceImpl implements Preference {
+
+    private final String name;
+
+    private final ValueMap delegatee;
+
+    public PreferenceImpl(final String name, final ValueMap original) {
+        this.name = name;
+        this.delegatee = original;
+    }
+
+    @Override
+    public String getName() {
+        return this.name;
+    }
+
+    @Override
+    public <T> T get(final String name, final Class<T> type) {
+        return delegatee.get(name, type);
+    }
+
+    @Override
+    public <T> T get(final String name, final T defaultValue) {
+        return delegatee.get(name, defaultValue);
+    }
+
+    @Override
+    public int size() {
+        return delegatee.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return delegatee.isEmpty();
+    }
+
+    @Override
+    public boolean containsKey(final Object key) {
+        return delegatee.containsKey(key);
+    }
+
+    @Override
+    public boolean containsValue(final Object value) {
+        return delegatee.containsValue(value);
+    }
+
+    @Override
+    public Object get(final Object key) {
+        return delegatee.get(key);
+    }
+
+    @Override
+    public Object put(final String key, final Object value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Object remove(final Object key) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putAll(final Map<? extends String, ? extends Object> m) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void clear() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Set<String> keySet() {
+        return Collections.unmodifiableSet(delegatee.keySet());
+    }
+
+    @Override
+    public Collection<Object> values() {
+        return Collections.unmodifiableCollection(delegatee.values());
+    }
+
+    @Override
+    public Set<java.util.Map.Entry<String, Object>> entrySet() {
+        return Collections.unmodifiableMap(this).entrySet();
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        return delegatee.equals(o);
+    }
+
+    @Override
+    public int hashCode() {
+        return delegatee.hashCode();
+    }
+}

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferenceImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferenceImpl.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesAdapterFactory.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesAdapterFactory.java?rev=1753753&view=auto
==============================================================================
--- 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesAdapterFactory.java
 (added)
+++ 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesAdapterFactory.java
 Fri Jul 22 06:16:52 2016
@@ -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.config.preferences.impl;
+
+import org.apache.sling.api.adapter.AdapterFactory;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.config.preferences.Preferences;
+import org.apache.sling.config.preferences.PreferencesResolver;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+@Component(service=AdapterFactory.class,
+           property={"adapters=org.apache.sling.preferences.Preferences",
+                     "adaptables=org.apache.sling.api.resource.Resource"})
+public class PreferencesAdapterFactory implements AdapterFactory {
+
+    @Reference
+    private PreferencesResolver resolver;
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <AdapterType> AdapterType getAdapter(final Object adaptable, final 
Class<AdapterType> type) {
+        if (adaptable instanceof Resource && type == Preferences.class) {
+            return (AdapterType) resolver.resolve((Resource) adaptable);
+        }
+        return null;
+    }
+}

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesAdapterFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesAdapterFactory.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesImpl.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesImpl.java?rev=1753753&view=auto
==============================================================================
--- 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesImpl.java
 (added)
+++ 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesImpl.java
 Fri Jul 22 06:16:52 2016
@@ -0,0 +1,103 @@
+/*
+ * 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.config.preferences.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.config.ConfigResolver;
+import org.apache.sling.config.preferences.Preference;
+import org.apache.sling.config.preferences.Preferences;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ */
+public class PreferencesImpl implements Preferences {
+
+    private static final Logger log = 
LoggerFactory.getLogger(PreferencesImpl.class);
+
+    private static final String NAME = "sling:preferences";
+
+    /** Original resource under e.g. /content that */
+    private final Resource originalResource;
+
+    private final ConfigResolver configResolver;
+
+    private volatile List<String> resolvedPaths;
+
+    public PreferencesImpl(final Resource originalResource, final 
ConfigResolver configResolver) {
+        log.debug("Preferences requested for {}", originalResource != null ? 
originalResource.getPath() : "null");
+        this.originalResource = originalResource;
+        this.configResolver = configResolver;
+    }
+
+    /**
+     * Check the name.
+     * A name must not be null and relative.
+     * @param name The name
+     * @return {@code true} if it is valid
+     */
+    private boolean checkName(final String name) {
+        if (name == null || name.isEmpty() || name.startsWith("/") || 
name.contains("../") ) {
+            return false;
+        }
+        return true;
+    }
+
+    List<String> getResolvedPaths() {
+        if ( this.resolvedPaths == null ) {
+            this.resolvedPaths = 
this.configResolver.getResolvePaths(this.originalResource);
+        }
+        return this.resolvedPaths;
+    }
+
+    @Override
+    public Preference get(final String itemName) {
+        Resource res = null;
+        if ( this.originalResource != null && checkName(itemName) ) {
+            for(final String path : this.getResolvedPaths() ) {
+                res = 
this.originalResource.getResourceResolver().getResource(path + '/' + NAME + '/' 
+ itemName);
+                if ( res != null ) {
+                    break;
+                }
+            }
+        }
+        if (res == null) {
+            return new PreferenceImpl(itemName, ValueMap.EMPTY);
+        } else {
+            return new PreferenceImpl(itemName, res.getValueMap());
+        }
+    }
+
+    @Override
+    public List<Preference> getChildren(final String parentItemName) {
+        final List<Preference> maps = new ArrayList<Preference>();
+
+        if ( this.originalResource != null && checkName(parentItemName) ) {
+            for(final Resource rsrc : 
this.configResolver.resolveChildren(originalResource, NAME + '/' + 
parentItemName)) {
+                maps.add(new PreferenceImpl(parentItemName + '/' + 
rsrc.getName(), rsrc.getValueMap()));
+            }
+        }
+
+        return maps;
+    }
+}

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesImpl.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesResolverImpl.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesResolverImpl.java?rev=1753753&view=auto
==============================================================================
--- 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesResolverImpl.java
 (added)
+++ 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesResolverImpl.java
 Fri Jul 22 06:16:52 2016
@@ -0,0 +1,39 @@
+/*
+ * 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.config.preferences.impl;
+
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.config.ConfigResolver;
+import org.apache.sling.config.preferences.Preferences;
+import org.apache.sling.config.preferences.PreferencesResolver;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+@Component(service=PreferencesResolver.class)
+public class PreferencesResolverImpl implements PreferencesResolver {
+
+    @Reference
+    private ConfigResolver configResolver;
+
+    @Override
+    public Preferences resolve(final Resource contentResource) {
+        return new PreferencesImpl(contentResource, configResolver);
+    }
+}

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesResolverImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/impl/PreferencesResolverImpl.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/package-info.java
URL: 
http://svn.apache.org/viewvc/sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/package-info.java?rev=1753753&view=auto
==============================================================================
--- 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/package-info.java
 (added)
+++ 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/package-info.java
 Fri Jul 22 06:16:52 2016
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
[email protected]("1.0.0")
+package org.apache.sling.config.preferences;
+

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
sling/whiteboard/cziegeler/sling-conf/src/main/java/org/apache/sling/config/preferences/package-info.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url


Reply via email to