You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ss...@apache.org on 2016/11/23 22:29:02 UTC

svn commit: r1771057 - in /sling/trunk/contrib/extensions/contextaware-config: impl/ impl/src/main/java/org/apache/sling/caconfig/management/impl/ impl/src/main/java/org/apache/sling/caconfig/management/impl/console/ impl/src/main/java/org/apache/sling...

Author: sseifert
Date: Wed Nov 23 22:29:02 2016
New Revision: 1771057

URL: http://svn.apache.org/viewvc?rev=1771057&view=rev
Log:
SLING-6115 Context-Aware Config: Web Console Plugin for Configuration Resolution

Added:
    sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/
    sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/ConfigurationResolverWebConsolePlugin.java   (with props)
    sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplNoDefaultTest.java   (with props)
Removed:
    sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/resource/impl/def/WebConsolePlugin.java
Modified:
    sling/trunk/contrib/extensions/contextaware-config/impl/pom.xml
    sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImpl.java
    sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImpl.java
    sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/resource/impl/def/DefaultConfigurationResourceResolvingStrategy.java
    sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationTestUtils.java
    sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImplTest.java
    sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplCustomPersistenceTest.java
    sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/resource/impl/ConfigurationResourceTestUtils.java
    sling/trunk/contrib/extensions/contextaware-config/integration-tests/pom.xml
    sling/trunk/contrib/extensions/contextaware-config/integration-tests/src/main/provisioning/integration-tests.txt

Modified: sling/trunk/contrib/extensions/contextaware-config/impl/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/pom.xml?rev=1771057&r1=1771056&r2=1771057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/pom.xml (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/pom.xml Wed Nov 23 22:29:02 2016
@@ -130,8 +130,14 @@
         <dependency>
             <groupId>org.apache.felix</groupId>
             <artifactId>org.apache.felix.webconsole</artifactId>
-            <version>3.0.0</version>
-            <scope>provided</scope>
+            <version>4.2.0</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.xss</artifactId>
+            <version>1.0.0</version>
+            <scope>compile</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.sling</groupId>

Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImpl.java?rev=1771057&r1=1771056&r2=1771057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImpl.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImpl.java Wed Nov 23 22:29:02 2016
@@ -18,6 +18,7 @@
  */
 package org.apache.sling.caconfig.management.impl;
 
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -31,6 +32,7 @@ import org.apache.sling.api.resource.Res
 import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.api.wrappers.ValueMapDecorator;
+import org.apache.sling.caconfig.impl.def.ConfigurationDefNameConstants;
 import org.apache.sling.caconfig.impl.override.ConfigurationOverrideManager;
 import org.apache.sling.caconfig.management.ConfigurationData;
 import org.apache.sling.caconfig.management.ValueInfo;
@@ -52,6 +54,12 @@ final class ConfigurationDataImpl implem
     private ValueMap valuesCache;
     private ValueMap effectiveValuesCache;
     
+    private static final Set<String> PROPERTIES_TO_IGNORE = new HashSet<>(Arrays.asList(
+            "jcr:primaryType",
+            "sling:resourceType",
+            ConfigurationDefNameConstants.PROPERTY_CONFIG_PROPERTY_INHERIT
+            ));
+    
     @SuppressWarnings("unchecked")
     public ConfigurationDataImpl(ConfigurationMetadata configMetadata,
             Resource resolvedConfigurationResource, Resource writebackConfigurationResource,
@@ -93,6 +101,9 @@ final class ConfigurationDataImpl implem
         if (writebackConfigurationResource != null) {
             return writebackConfigurationResource.getPath();
         }
+        if (resolvedConfigurationResource != null) {
+            return resolvedConfigurationResource.getPath();
+        }
         return null;
     }
 
@@ -106,6 +117,7 @@ final class ConfigurationDataImpl implem
             if (resolvedConfigurationResource != null) {
                 propertyNamesCache.addAll(ResourceUtil.getValueMap(resolvedConfigurationResource).keySet());
             }
+            propertyNamesCache.removeAll(PROPERTIES_TO_IGNORE);
         }
         return propertyNamesCache;
     }
@@ -113,12 +125,12 @@ final class ConfigurationDataImpl implem
     @Override
     public ValueMap getValues() {
         if (valuesCache == null) {
+            Map<String,Object> props = new HashMap<>();
             if (writebackConfigurationResource != null) {
-                valuesCache = ResourceUtil.getValueMap(writebackConfigurationResource);
-            }
-            else {
-                valuesCache = ValueMap.EMPTY;
+                props.putAll( ResourceUtil.getValueMap(writebackConfigurationResource));
             }
+            removeIgnoredProperties(props);
+            valuesCache = new ValueMapDecorator(props);
         }
         return valuesCache;
     }
@@ -137,10 +149,17 @@ final class ConfigurationDataImpl implem
             if (resolvedConfigurationResource != null) {
                 props.putAll(ResourceUtil.getValueMap(resolvedConfigurationResource));
             }
+            removeIgnoredProperties(props);
             effectiveValuesCache = new ValueMapDecorator(props);
         }
         return effectiveValuesCache;
     }
+    
+    private void removeIgnoredProperties(Map<String,Object> props) {
+        for (String propertyName : PROPERTIES_TO_IGNORE) {
+            props.remove(propertyName);
+        }
+    }
 
     @SuppressWarnings("unchecked")
     @Override

Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImpl.java?rev=1771057&r1=1771056&r2=1771057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImpl.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImpl.java Wed Nov 23 22:29:02 2016
@@ -61,24 +61,27 @@ public class ConfigurationManagerImpl im
     @Override
     public ConfigurationData get(Resource resource, String configName) {
         ConfigurationMetadata configMetadata = configurationMetadataProvider.getConfigurationMetadata(configName);
+        Resource configResource = null;
         Iterator<Resource> configResourceInheritanceChain = configurationResourceResolvingStrategy
                 .getResourceInheritanceChain(resource, CONFIGS_PARENT_NAME, configName);
-        ResettableIterator resettableConfigResourceInheritanceChain = new ListIteratorWrapper(configResourceInheritanceChain);
-        Resource configResource = applyPersistenceAndInheritance(resource.getPath(), configName, resettableConfigResourceInheritanceChain);
-        if (configResource != null) {
-            // get writeback resource for "reverse inheritance detection"
-            Resource writebackConfigResource = null;
-            String writebackConfigResourcePath = configurationResourceResolvingStrategy.getResourcePath(resource, CONFIGS_PARENT_NAME, configName);
-            if (writebackConfigResourcePath != null) {
-                writebackConfigResource = configResource.getResourceResolver().getResource(writebackConfigResourcePath);
-                if (writebackConfigResource != null) {
-                    writebackConfigResource = configurationPersistenceStrategy.getResource(writebackConfigResource);
+        if (configResourceInheritanceChain != null) {
+            ResettableIterator resettableConfigResourceInheritanceChain = new ListIteratorWrapper(configResourceInheritanceChain);
+            configResource = applyPersistenceAndInheritance(resource.getPath(), configName, resettableConfigResourceInheritanceChain);
+            if (configResource != null) {
+                // get writeback resource for "reverse inheritance detection"
+                Resource writebackConfigResource = null;
+                String writebackConfigResourcePath = configurationResourceResolvingStrategy.getResourcePath(resource, CONFIGS_PARENT_NAME, configName);
+                if (writebackConfigResourcePath != null) {
+                    writebackConfigResource = configResource.getResourceResolver().getResource(writebackConfigResourcePath);
+                    if (writebackConfigResource != null) {
+                        writebackConfigResource = configurationPersistenceStrategy.getResource(writebackConfigResource);
+                    }
                 }
+                resettableConfigResourceInheritanceChain.reset();
+                return new ConfigurationDataImpl(configMetadata, configResource, writebackConfigResource,
+                        applyPersistence(resettableConfigResourceInheritanceChain),
+                        resource, configName, configurationOverrideManager, false);
             }
-            resettableConfigResourceInheritanceChain.reset();
-            return new ConfigurationDataImpl(configMetadata, configResource, writebackConfigResource,
-                    applyPersistence(resettableConfigResourceInheritanceChain),
-                    resource, configName, configurationOverrideManager, false);
         }
         if (configMetadata != null) {
             // if no config resource found but config metadata exist return empty config data with default values
@@ -97,25 +100,27 @@ public class ConfigurationManagerImpl im
 
         Collection<Iterator<Resource>> configResourceInheritanceChains = configurationResourceResolvingStrategy
                 .getResourceCollectionInheritanceChain(resource, CONFIGS_PARENT_NAME, configName);
-        for (Iterator<Resource> configResourceInheritanceChain : configResourceInheritanceChains) {
-            ResettableIterator resettableConfigResourceInheritanceChain = new ListIteratorWrapper(configResourceInheritanceChain);
-            Resource configResource = applyPersistenceAndInheritance(resource.getPath(), configName, resettableConfigResourceInheritanceChain);
-            if (configResource != null) {
-                // get writeback resource for "reverse inheritance detection"
-                Resource writebackConfigResource = null;
-                if (writebackConfigResourceCollectionParentPath != null) {
-                    resettableConfigResourceInheritanceChain.reset();
-                    Resource untransformedConfigResource = (Resource)resettableConfigResourceInheritanceChain.next();
-                    writebackConfigResource = configResource.getResourceResolver().getResource(
-                            writebackConfigResourceCollectionParentPath + "/" + untransformedConfigResource.getName());
-                    if (writebackConfigResource != null) {
-                        writebackConfigResource = configurationPersistenceStrategy.getResource(writebackConfigResource);
+        if (configResourceInheritanceChains != null) {
+            for (Iterator<Resource> configResourceInheritanceChain : configResourceInheritanceChains) {
+                ResettableIterator resettableConfigResourceInheritanceChain = new ListIteratorWrapper(configResourceInheritanceChain);
+                Resource configResource = applyPersistenceAndInheritance(resource.getPath(), configName, resettableConfigResourceInheritanceChain);
+                if (configResource != null) {
+                    // get writeback resource for "reverse inheritance detection"
+                    Resource writebackConfigResource = null;
+                    if (writebackConfigResourceCollectionParentPath != null) {
+                        resettableConfigResourceInheritanceChain.reset();
+                        Resource untransformedConfigResource = (Resource)resettableConfigResourceInheritanceChain.next();
+                        writebackConfigResource = configResource.getResourceResolver().getResource(
+                                writebackConfigResourceCollectionParentPath + "/" + untransformedConfigResource.getName());
+                        if (writebackConfigResource != null) {
+                            writebackConfigResource = configurationPersistenceStrategy.getResource(writebackConfigResource);
+                        }
                     }
+                    resettableConfigResourceInheritanceChain.reset();
+                    configData.add(new ConfigurationDataImpl(configMetadata, configResource, writebackConfigResource,
+                            applyPersistence(resettableConfigResourceInheritanceChain),
+                            resource, configName, configurationOverrideManager, true));
                 }
-                resettableConfigResourceInheritanceChain.reset();
-                configData.add(new ConfigurationDataImpl(configMetadata, configResource, writebackConfigResource,
-                        applyPersistence(resettableConfigResourceInheritanceChain),
-                        resource, configName, configurationOverrideManager, true));
             }
         }
         return configData;

Added: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/ConfigurationResolverWebConsolePlugin.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/ConfigurationResolverWebConsolePlugin.java?rev=1771057&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/ConfigurationResolverWebConsolePlugin.java (added)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/ConfigurationResolverWebConsolePlugin.java Wed Nov 23 22:29:02 2016
@@ -0,0 +1,331 @@
+/*
+ * 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.caconfig.management.impl.console;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.lang.reflect.Array;
+import java.util.Collection;
+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.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+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.caconfig.management.ConfigurationData;
+import org.apache.sling.caconfig.management.ConfigurationManager;
+import org.apache.sling.caconfig.management.ValueInfo;
+import org.apache.sling.xss.XSSAPI;
+import org.osgi.framework.Constants;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(service=Servlet.class,
+           property={Constants.SERVICE_DESCRIPTION + "=Apache Sling Context-Aware Configuration Resolver Web Console Plugin",
+                   WebConsoleConstants.PLUGIN_LABEL + "=" + ConfigurationResolverWebConsolePlugin.LABEL,
+                   WebConsoleConstants.PLUGIN_TITLE + "=" + ConfigurationResolverWebConsolePlugin.TITLE,
+                   WebConsoleConstants.PLUGIN_CATEGORY + "=Sling"})
+@SuppressWarnings("serial")
+public class ConfigurationResolverWebConsolePlugin extends AbstractWebConsolePlugin {
+
+    public static final String LABEL = "slingcaconfigresolver";
+    public static final String TITLE = "Context-Aware Configuration";
+    
+    private static final Logger log = LoggerFactory.getLogger(ConfigurationResolverWebConsolePlugin.class);
+    
+    @Reference(policyOption = ReferencePolicyOption.GREEDY)
+    private ResourceResolverFactory resolverFactory;
+
+    @Reference(policyOption = ReferencePolicyOption.GREEDY)
+    private ConfigurationManager configurationManager;
+
+    @Reference(policyOption = ReferencePolicyOption.GREEDY)
+    private XSSAPI xss;
+
+    @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.");
+
+        pw.println("<br/>");
+
+        printResolutionTestTool(request, 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 configName = this.getParameter(request, "configName", null);
+        final boolean resourceCollection = BooleanUtils.toBoolean(this.getParameter(request, "resourceCollection", "false"));
+
+        ResourceResolver resolver = null;
+        try {
+            Resource contentResource = null;
+            if (path != null) {
+                resolver = getResolver();
+                if (resolver != null) {
+                    contentResource = resolver.getResource(path);
+                }
+            }
+
+            pw.println("<form method='get'>");
+
+            tableStart(pw, "Test Configuration Resolution", 2);
+            
+            String alertMessage = null;
+            if (path != null) {
+                if (resolver == null) {
+                    alertMessage = "Unable to access repository - please check system configuration.";
+                }
+                else if (contentResource == null) {
+                    alertMessage = "Path does not exist.";
+                }
+            }
+            textField(pw, "Content Path", "path", path, alertMessage);
+            
+            tableRows(pw);
+            textField(pw, "Config Name", "configName", configName);
+            
+            tableRows(pw);
+            checkboxField(pw, "Resource collection", "resourceCollection", resourceCollection);
+            
+            tableRows(pw);
+            pw.println("<td></td>");
+            pw.println("<td><input type='submit' value='Resolve'/></td>");
+            tableEnd(pw);
+
+            pw.println("</form>");
+
+            pw.println("<br/>");
+
+            if (contentResource != null) {
+
+                // resolve configuration
+                Collection<ConfigurationData> configDatas;
+                if (resourceCollection) {
+                    configDatas = configurationManager.getCollection(contentResource, configName);
+                }
+                else {
+                    ConfigurationData configData = configurationManager.get(contentResource, configName);
+                    if (configData != null) {
+                        configDatas = Collections.singletonList(configData);
+                    }
+                    else {
+                        configDatas = Collections.emptyList();
+                    }
+                }
+
+                tableStart(pw, "Result", 6);
+                
+                if (configDatas.size() == 0) {
+                    pw.println("<td colspan='6'>");
+                    alertDiv(pw, "No matching item found.");
+                    pw.println("<br/>&nbsp;</td>");
+                }
+                else {
+                
+                    pw.println("<th>Property</th>");
+                    pw.println("<th>Effective Value</th>");
+                    pw.println("<th>Value</th>");
+                    pw.println("<th>Default</th>");
+                    pw.println("<th>Inherited</th>");
+                    pw.println("<th>Overwritten</th>");
+
+                    for (ConfigurationData data : configDatas) {
+                        tableRows(pw);
+                        pw.println("<td colspan='6' style='background-color:#f3f3f3'>");
+                        pw.print("Path: " + xss.encodeForHTML(data.getResourcePath()));
+                        pw.println("</td>");
+                        
+                        for (String propertyName : data.getPropertyNames()) {
+                            ValueInfo<?> valueInfo = data.getValueInfo(propertyName);
+                            tableRows(pw);
+                            td(pw, propertyName);
+                            td(pw, valueInfo.getEffectiveValue());
+                            td(pw, valueInfo.getValue());
+                            td(pw, valueInfo.isDefault());
+                            
+                            String title = null;
+                            if (valueInfo.isInherited()) {
+                                title = "Source path: " + valueInfo.getConfigSourcePath();
+                            }
+                            td(pw, valueInfo.isInherited(), title);
+
+                            td(pw, valueInfo.isOverridden());
+                        }
+                        
+                   }
+                    
+                }
+                
+                tableEnd(pw);
+            }
+
+        }
+        finally {
+            if (resolver != null) {
+                resolver.close();
+            }
+        }
+    }
+
+    private void info(PrintWriter pw, String text) {
+        pw.print("<p class='statline ui-state-highlight'>");
+        pw.print(xss.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(xss.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 void textField(PrintWriter pw, String label, String fieldName, String value, String... alertMessages) {
+        pw.print("<td style='width:20%'>");
+        pw.print(xss.encodeForHTMLAttr(label));
+        pw.println("</td>");
+        pw.print("<td><input name='");
+        pw.print(xss.encodeForHTMLAttr(fieldName));
+        pw.print("' value='");
+        pw.print(xss.encodeForHTMLAttr(StringUtils.defaultString(value)));
+        pw.print("' style='width:100%'/>");
+        for (String alertMessage : alertMessages) {
+            alertDiv(pw, alertMessage);
+        }
+        pw.println("</td>");
+    }
+    
+    private void checkboxField(PrintWriter pw, String label, String fieldName, boolean checked) {
+        pw.print("<td style='width:20%'>");
+        pw.print(xss.encodeForHTMLAttr(label));
+        pw.println("</td>");
+        pw.print("<td><input type='checkbox' name='");
+        pw.print(xss.encodeForHTMLAttr(fieldName));
+        pw.print("' value='true'");
+        if (checked) {
+            pw.print(" checked");
+        }
+        pw.print("/></td>");
+    }
+    
+    private void alertDiv(PrintWriter pw, String text) {
+        if (StringUtils.isBlank(text)) {
+            return;
+        }
+        pw.println("<div>");
+        pw.println("<span class='ui-icon ui-icon-alert' style='float:left'></span>");
+        pw.print("<span style='float:left'>");
+        pw.print(xss.encodeForHTML(text));
+        pw.println("</span>");
+        pw.println("</div>");
+    }
+    
+    private void td(PrintWriter pw, Object value, String... title) {
+        pw.print("<td");
+        if (title.length > 0 && !StringUtils.isBlank(title[0])) {
+            pw.print(" title='");
+            pw.print(xss.encodeForHTML(title[0]));
+            pw.print("'");
+        }
+        pw.print(">");
+
+        if (value != null) {
+            if (value.getClass().isArray()) {
+                for (int i = 0; i < Array.getLength(value); i++) {
+                    Object itemValue = Array.get(value, i);
+                    pw.print(xss.encodeForHTML(ObjectUtils.defaultIfNull(itemValue, "").toString()));
+                    pw.println("<br>");
+                }
+            }
+            else {
+                pw.print(xss.encodeForHTML(value.toString()));
+            }
+        }
+        
+        if (title.length > 0 && !StringUtils.isBlank(title[0])) {
+            pw.print("<span class='ui-icon ui-icon-info' style='float:left'></span>");
+        }
+        pw.print("</td>");
+    }
+
+    private ResourceResolver getResolver() {
+        try {
+            return resolverFactory.getServiceResourceResolver(null);
+        }
+        catch (final LoginException ex) {
+            log.warn("Unable to get resource resolver - please ensure a system user is configured: {}", ex.getMessage());
+            return null;
+        }
+    }
+
+}

Propchange: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/ConfigurationResolverWebConsolePlugin.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/ConfigurationResolverWebConsolePlugin.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Wed Nov 23 22:29:02 2016
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/console/ConfigurationResolverWebConsolePlugin.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/resource/impl/def/DefaultConfigurationResourceResolvingStrategy.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/resource/impl/def/DefaultConfigurationResourceResolvingStrategy.java?rev=1771057&r1=1771056&r2=1771057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/resource/impl/def/DefaultConfigurationResourceResolvingStrategy.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/resource/impl/def/DefaultConfigurationResourceResolvingStrategy.java Wed Nov 23 22:29:02 2016
@@ -100,10 +100,6 @@ public class DefaultConfigurationResourc
             fieldOption=FieldOption.REPLACE)
     private volatile List<CollectionInheritanceDecider> collectionInheritanceDeciders;
 
-    Config getConfiguration() {
-        return this.config;
-    }
-
     @Activate
     private void activate(final Config config) {
         this.config = config;

Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationTestUtils.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationTestUtils.java?rev=1771057&r1=1771056&r2=1771057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationTestUtils.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationTestUtils.java Wed Nov 23 22:29:02 2016
@@ -37,13 +37,26 @@ public final class ConfigurationTestUtil
      * @param context Sling context
      */
     public static ConfigurationResolver registerConfigurationResolver(SlingContext context) {
-        ConfigurationResourceTestUtils.registerConfigurationResourceResolver(context);
+        ConfigurationResourceTestUtils.registerConfigurationResourceResolver(context);        
         context.registerInjectActivateService(new DefaultConfigurationPersistenceStrategy());
         context.registerInjectActivateService(new ConfigurationPersistenceStrategyMultiplexer());
         context.registerInjectActivateService(new DefaultConfigurationInheritanceStrategy());
         context.registerInjectActivateService(new ConfigurationInheritanceStrategyMultiplexer());
         context.registerInjectActivateService(new ConfigurationOverrideManager());
         return context.registerInjectActivateService(new ConfigurationResolverImpl());
+    }
+    
+    /**
+     * Register all services for {@link ConfigurationResolver}
+     * without the default implementations of the multiplexed services.
+     * @param context Sling context
+     */
+    public static ConfigurationResolver registerConfigurationResolverWithoutDefaultImpl(SlingContext context) {
+        ConfigurationResourceTestUtils.registerConfigurationResourceResolverWithoutDefaultImpl(context);
+        context.registerInjectActivateService(new ConfigurationPersistenceStrategyMultiplexer());
+        context.registerInjectActivateService(new ConfigurationInheritanceStrategyMultiplexer());
+        context.registerInjectActivateService(new ConfigurationOverrideManager());
+        return context.registerInjectActivateService(new ConfigurationResolverImpl());
     }
     
 }

Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImplTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImplTest.java?rev=1771057&r1=1771056&r2=1771057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImplTest.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationDataImplTest.java Wed Nov 23 22:29:02 2016
@@ -161,4 +161,24 @@ public class ConfigurationDataImplTest {
         assertEquals((Integer)5, prop3.getEffectiveValue());
     }
 
+    @Test
+    public void testIgnoreProperties() {
+        Resource resource = context.create().resource("/conf/testIgnoreProps",
+                "prop1", "value1",
+                "prop4", true,
+                "jcr:primaryType", "myType",
+                "sling:resourceType", "my/type");
+
+        ConfigurationData underTest = new ConfigurationDataImpl(null, resource, resource, null,
+                contextResource, "test", configurationOverrideManager, false);
+        
+        assertEquals(ImmutableSet.of("prop1", "prop4"), underTest.getPropertyNames());
+        
+        assertNull(underTest.getValues().get("jcr:primaryType"));
+        assertNull(underTest.getEffectiveValues().get("jcr:primaryType"));
+
+        assertNull(underTest.getValues().get("sling:resourceType"));
+        assertNull(underTest.getEffectiveValues().get("sling:resourceType"));
+    }
+
 }

Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplCustomPersistenceTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplCustomPersistenceTest.java?rev=1771057&r1=1771056&r2=1771057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplCustomPersistenceTest.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplCustomPersistenceTest.java Wed Nov 23 22:29:02 2016
@@ -24,6 +24,9 @@ import org.junit.runner.RunWith;
 import org.mockito.runners.MockitoJUnitRunner;
 import org.osgi.framework.Constants;
 
+/**
+ * Test {@link ConfigurationManagerImpl} with custom persistence.
+ */
 @RunWith(MockitoJUnitRunner.class)
 public class ConfigurationManagerImplCustomPersistenceTest extends ConfigurationManagerImplTest {
     

Added: sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplNoDefaultTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplNoDefaultTest.java?rev=1771057&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplNoDefaultTest.java (added)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplNoDefaultTest.java Wed Nov 23 22:29:02 2016
@@ -0,0 +1,149 @@
+/*
+ * 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.caconfig.management.impl;
+
+import static org.apache.sling.caconfig.resource.impl.def.ConfigurationResourceNameConstants.PROPERTY_CONFIG_REF;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.caconfig.impl.ConfigurationTestUtils;
+import org.apache.sling.caconfig.impl.metadata.ConfigurationMetadataProviderMultiplexer;
+import org.apache.sling.caconfig.management.ConfigurationData;
+import org.apache.sling.caconfig.management.ConfigurationManager;
+import org.apache.sling.caconfig.spi.ConfigurationMetadataProvider;
+import org.apache.sling.caconfig.spi.metadata.ConfigurationMetadata;
+import org.apache.sling.caconfig.spi.metadata.PropertyMetadata;
+import org.apache.sling.testing.mock.sling.junit.SlingContext;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Test {@link ConfigurationManagerImpl} with no default implementation of the multiplexed services.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class ConfigurationManagerImplNoDefaultTest {
+    
+    @Rule
+    public SlingContext context = new SlingContext();
+
+    @Mock
+    private ConfigurationMetadataProvider configurationMetadataProvider;
+    
+    private ConfigurationManager underTest;
+    
+    private Resource contextResourceNoConfig;
+    private ConfigurationMetadata configMetadata;
+    
+    private static final String CONFIG_NAME = "testConfig";
+    private static final String CONFIG_COL_NAME = "testConfigCol";
+   
+    @Before
+    public void setUp() {
+        context.registerService(ConfigurationMetadataProvider.class, configurationMetadataProvider);
+        context.registerInjectActivateService(new ConfigurationMetadataProviderMultiplexer());
+        ConfigurationTestUtils.registerConfigurationResolverWithoutDefaultImpl(context);
+        underTest = context.registerInjectActivateService(new ConfigurationManagerImpl());
+        
+        contextResourceNoConfig = context.create().resource("/content/testNoConfig",
+                PROPERTY_CONFIG_REF, "/conf/testNoConfig");
+        
+        configMetadata = new ConfigurationMetadata(CONFIG_NAME);
+        configMetadata.setPropertyMetadata(ImmutableMap.<String,PropertyMetadata<?>>of(
+                "prop1", new PropertyMetadata<>("prop1", "defValue"),
+                "prop2", new PropertyMetadata<>("prop2", String.class),
+                "prop3", new PropertyMetadata<>("prop3", 5)));
+        when(configurationMetadataProvider.getConfigurationMetadata(CONFIG_NAME)).thenReturn(configMetadata);
+
+        configMetadata = new ConfigurationMetadata(CONFIG_COL_NAME);
+        configMetadata.setPropertyMetadata(ImmutableMap.<String,PropertyMetadata<?>>of(
+                "prop1", new PropertyMetadata<>("prop1", "defValue"),
+                "prop2", new PropertyMetadata<>("prop2", String.class),
+                "prop3", new PropertyMetadata<>("prop3", 5)));
+        when(configurationMetadataProvider.getConfigurationMetadata(CONFIG_COL_NAME)).thenReturn(configMetadata);
+    }
+    
+    protected String getConfigPropertiesPath(String path) {
+        return path;
+    }
+    
+    @Test
+    public void testGet_NoConfigResource() {
+        ConfigurationData configData = underTest.get(contextResourceNoConfig, CONFIG_NAME);
+        assertNotNull(configData);
+
+        assertEquals(ImmutableSet.of("prop1", "prop2", "prop3"), configData.getPropertyNames());
+        assertNull(configData.getValues().get("prop1", String.class));
+        assertEquals((Integer)5, configData.getEffectiveValues().get("prop3", 0));
+
+        assertFalse(configData.getValueInfo("prop1").isInherited());
+        assertFalse(configData.getValueInfo("prop3").isInherited());
+    }
+
+    @Test
+    public void testGet_NoConfigResource_NoConfigMetadata() {
+        when(configurationMetadataProvider.getConfigurationMetadata(CONFIG_NAME)).thenReturn(null);
+
+        ConfigurationData configData = underTest.get(contextResourceNoConfig, CONFIG_NAME);
+        assertNull(configData);
+    }
+
+    @Test
+    public void testGetCollection_NoConfigResources() {
+        List<ConfigurationData> configDatas = ImmutableList.copyOf(underTest.getCollection(contextResourceNoConfig, CONFIG_COL_NAME));
+        assertEquals(0, configDatas.size());
+    }
+
+    @Test
+    public void testGetCollection_NoConfigResources_NoConfigMetadata() {
+        when(configurationMetadataProvider.getConfigurationMetadata(CONFIG_COL_NAME)).thenReturn(null);
+
+        List<ConfigurationData> configDatas = ImmutableList.copyOf(underTest.getCollection(contextResourceNoConfig, CONFIG_COL_NAME));
+        assertEquals(0, configDatas.size());
+    }
+
+    @Test
+    public void testNewCollectionItem() {
+        ConfigurationData newItem = underTest.newCollectionItem(contextResourceNoConfig, CONFIG_COL_NAME);
+        assertNotNull(newItem);
+        assertEquals((Integer)5, newItem.getEffectiveValues().get("prop3", 0));
+    }
+
+    @Test
+    public void testNewCollectionItem_NoConfigMetadata() {
+        when(configurationMetadataProvider.getConfigurationMetadata(CONFIG_COL_NAME)).thenReturn(null);
+
+        ConfigurationData newItem = underTest.newCollectionItem(contextResourceNoConfig, CONFIG_COL_NAME);
+        assertNull(newItem);
+    }
+
+}

Propchange: sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplNoDefaultTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplNoDefaultTest.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Wed Nov 23 22:29:02 2016
@@ -0,0 +1 @@
+LastChangedDate LastChangedRevision LastChangedBy HeadURL Id Author

Propchange: sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplNoDefaultTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/resource/impl/ConfigurationResourceTestUtils.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/resource/impl/ConfigurationResourceTestUtils.java?rev=1771057&r1=1771056&r2=1771057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/resource/impl/ConfigurationResourceTestUtils.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/resource/impl/ConfigurationResourceTestUtils.java Wed Nov 23 22:29:02 2016
@@ -41,4 +41,15 @@ public final class ConfigurationResource
         return context.registerInjectActivateService(new ConfigurationResourceResolverImpl());
     }
     
+    /**
+     * Register all services for {@link ConfigurationResourceResolver}
+     * without the default implementations of the multiplexed services.
+     * @param context Sling context
+     */
+    public static ConfigurationResourceResolver registerConfigurationResourceResolverWithoutDefaultImpl(SlingContext context) {
+        context.registerInjectActivateService(new ContextPathStrategyMultiplexer());
+        context.registerInjectActivateService(new ConfigurationResourceResolvingStrategyMultiplexer());
+        return context.registerInjectActivateService(new ConfigurationResourceResolverImpl());
+    }
+    
 }

Modified: sling/trunk/contrib/extensions/contextaware-config/integration-tests/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/integration-tests/pom.xml?rev=1771057&r1=1771056&r2=1771057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/integration-tests/pom.xml (original)
+++ sling/trunk/contrib/extensions/contextaware-config/integration-tests/pom.xml Wed Nov 23 22:29:02 2016
@@ -246,5 +246,17 @@
             <scope>provided</scope>
         </dependency>
     </dependencies>
-
+    
+    <profiles>
+        <!-- Start on port 8080 and keep running -->
+        <profile>
+            <id>run8080</id>
+            <properties>
+                <launchpad.keep.running>true</launchpad.keep.running>
+                <launchpad.debug>true</launchpad.debug>
+                <http.port>8080</http.port>
+            </properties>            
+        </profile>
+    </profiles>
+    
 </project>

Modified: sling/trunk/contrib/extensions/contextaware-config/integration-tests/src/main/provisioning/integration-tests.txt
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/integration-tests/src/main/provisioning/integration-tests.txt?rev=1771057&r1=1771056&r2=1771057&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/integration-tests/src/main/provisioning/integration-tests.txt (original)
+++ sling/trunk/contrib/extensions/contextaware-config/integration-tests/src/main/provisioning/integration-tests.txt Wed Nov 23 22:29:02 2016
@@ -38,3 +38,17 @@
 
   org.apache.sling.jcr.base.internal.LoginAdminWhitelist
     whitelist.bundles.additional=["org.apache.sling.junit.core"]
+
+  org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended-sling-caconfig
+    user.mapping=[
+      "org.apache.sling.caconfig.impl\=sling-caconfig"
+    ]
+
+[:repoinit]
+    create service user sling-caconfig
+
+    create path (sling:Folder) /conf
+
+    set ACL for sling-caconfig
+        allow   jcr:read    on /
+    end