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/18 23:42:02 UTC
svn commit: r1770448 [1/2] - in
/sling/trunk/contrib/extensions/contextaware-config: impl/
impl/src/main/java/org/apache/sling/caconfig/impl/
impl/src/main/java/org/apache/sling/caconfig/impl/def/
impl/src/main/java/org/apache/sling/caconfig/management...
Author: sseifert
Date: Fri Nov 18 23:42:02 2016
New Revision: 1770448
URL: http://svn.apache.org/viewvc?rev=1770448&view=rev
Log:
SLING-6060 Context-Aware Config: Configuration property override providers
Added:
sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationResourceWrapper.java (with props)
sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/
sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/
sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/ConfigurationOverrideManager.java (with props)
sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OsgiConfigurationOverrideProvider.java (with props)
sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OverrideItem.java (with props)
sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OverrideStringParser.java (with props)
sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/SystemPropertyConfigurationOverrideProvider.java (with props)
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/override/
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/override/impl/
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/override/impl/ConfigurationOverrideManagerTest.java (with props)
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/override/impl/DummyConfigurationOverrideProvider.java (with props)
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/override/impl/OsgiConfigurationOverrideProviderTest.java (with props)
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/override/impl/OverrideItemTest.java (with props)
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/override/impl/OverrideStringParserTest.java (with props)
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/override/impl/SystemPropertyConfigurationOverrideProviderTest.java (with props)
sling/trunk/contrib/extensions/contextaware-config/spi/src/main/java/org/apache/sling/caconfig/spi/ConfigurationOverrideProvider.java (with props)
Removed:
sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/def/ConfigurationResourceWrapper.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/impl/ConfigurationBuilderImpl.java
sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationResolverImpl.java
sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationInheritanceStrategy.java
sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/ValueInfo.java
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/management/impl/ValueInfoImpl.java
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverValueMapTest.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/ConfigurationManagerImplTest.java
sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ValueInfoImplTest.java
sling/trunk/contrib/extensions/contextaware-config/spi/pom.xml
sling/trunk/contrib/extensions/contextaware-config/spi/src/main/java/org/apache/sling/caconfig/spi/ConfigurationMetadataProvider.java
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=1770448&r1=1770447&r2=1770448&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/pom.xml (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/pom.xml Fri Nov 18 23:42:02 2016
@@ -74,19 +74,19 @@
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.commons.osgi</artifactId>
<version>2.4.0</version>
- <scope>provided</scope>
+ <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.caconfig.api</artifactId>
<version>1.0.0</version>
- <scope>provided</scope>
+ <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.caconfig.spi</artifactId>
<version>1.1.1-SNAPSHOT</version>
- <scope>provided</scope>
+ <scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
@@ -110,6 +110,12 @@
<scope>provided</scope>
</dependency>
<dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.commons.json</artifactId>
+ <version>2.0.10</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderImpl.java?rev=1770448&r1=1770447&r2=1770448&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderImpl.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderImpl.java Fri Nov 18 23:42:02 2016
@@ -36,6 +36,7 @@ import org.apache.sling.caconfig.Configu
import org.apache.sling.caconfig.ConfigurationResolver;
import org.apache.sling.caconfig.impl.ConfigurationProxy.ChildResolver;
import org.apache.sling.caconfig.impl.metadata.AnnotationClassParser;
+import org.apache.sling.caconfig.override.impl.ConfigurationOverrideManager;
import org.apache.sling.caconfig.resource.spi.ConfigurationResourceResolvingStrategy;
import org.apache.sling.caconfig.spi.ConfigurationInheritanceStrategy;
import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy;
@@ -47,6 +48,7 @@ class ConfigurationBuilderImpl implement
private final ConfigurationResourceResolvingStrategy configurationResourceResolvingStrategy;
private final ConfigurationPersistenceStrategy configurationPersistenceStrategy;
private final ConfigurationInheritanceStrategy configurationInheritanceStrategy;
+ private final ConfigurationOverrideManager configurationOverrideManager;
private String configName;
@@ -54,12 +56,14 @@ class ConfigurationBuilderImpl implement
final ConfigurationResolver configurationResolver,
final ConfigurationResourceResolvingStrategy configurationResourceResolvingStrategy,
final ConfigurationPersistenceStrategy configurationPersistenceStrategy,
- final ConfigurationInheritanceStrategy configurationInheritanceStrategy) {
+ final ConfigurationInheritanceStrategy configurationInheritanceStrategy,
+ final ConfigurationOverrideManager configurationOverrideManager) {
this.contentResource = resource;
this.configurationResolver = configurationResolver;
this.configurationResourceResolvingStrategy = configurationResourceResolvingStrategy;
this.configurationPersistenceStrategy = configurationPersistenceStrategy;
this.configurationInheritanceStrategy = configurationInheritanceStrategy;
+ this.configurationOverrideManager = configurationOverrideManager;
}
@Override
@@ -159,6 +163,8 @@ class ConfigurationBuilderImpl implement
});
// apply resource inheritance
configResource = configurationInheritanceStrategy.getResource(transformedResources);
+ // apply overrides
+ configResource = configurationOverrideManager.overrideProperties(contentResource.getPath(), name, configResource);
// build name
if (configResource != null && appendResourceName) {
conversionName = conversionName + "/" + configResource.getName();
Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationResolverImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationResolverImpl.java?rev=1770448&r1=1770447&r2=1770448&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationResolverImpl.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationResolverImpl.java Fri Nov 18 23:42:02 2016
@@ -22,6 +22,7 @@ import org.apache.sling.api.resource.Res
import org.apache.sling.caconfig.ConfigurationBuilder;
import org.apache.sling.caconfig.ConfigurationResolver;
import org.apache.sling.caconfig.management.impl.ConfigurationPersistenceStrategyMultiplexer;
+import org.apache.sling.caconfig.override.impl.ConfigurationOverrideManager;
import org.apache.sling.caconfig.resource.impl.ConfigurationResourceResolvingStrategyMultiplexer;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
@@ -31,17 +32,18 @@ public class ConfigurationResolverImpl i
@Reference
private ConfigurationResourceResolvingStrategyMultiplexer configurationResourceResolvingStrategy;
-
@Reference
private ConfigurationPersistenceStrategyMultiplexer configurationPersistenceStrategy;
-
@Reference
private ConfigurationInheritanceStrategyMultiplexer configurationInheritanceStrategy;
+ @Reference
+ private ConfigurationOverrideManager configurationOverrideManager;
@Override
public ConfigurationBuilder get(Resource resource) {
return new ConfigurationBuilderImpl(resource, this,
- configurationResourceResolvingStrategy, configurationPersistenceStrategy, configurationInheritanceStrategy);
+ configurationResourceResolvingStrategy, configurationPersistenceStrategy,
+ configurationInheritanceStrategy, configurationOverrideManager);
}
}
Added: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationResourceWrapper.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationResourceWrapper.java?rev=1770448&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationResourceWrapper.java (added)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationResourceWrapper.java Fri Nov 18 23:42:02 2016
@@ -0,0 +1,61 @@
+/*
+ * 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.impl;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceWrapper;
+import org.apache.sling.api.resource.ValueMap;
+
+/**
+ * Wrapper that returns an enhanced value map for the resource
+ * providing a merged map with all inherited property values.
+ */
+public final class ConfigurationResourceWrapper extends ResourceWrapper {
+
+ private final ValueMap props;
+
+ public ConfigurationResourceWrapper(Resource resource, ValueMap props) {
+ super(unwrap(resource));
+ this.props = props;
+ }
+
+ private static Resource unwrap(Resource resource) {
+ if (resource instanceof ConfigurationResourceWrapper) {
+ return ((ConfigurationResourceWrapper)resource).getResource();
+ }
+ else {
+ return resource;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+ if (type == ValueMap.class) {
+ return (AdapterType)props;
+ }
+ return super.adaptTo(type);
+ }
+
+ @Override
+ public ValueMap getValueMap() {
+ return props;
+ }
+
+}
Propchange: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationResourceWrapper.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/ConfigurationResourceWrapper.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Fri Nov 18 23:42: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/impl/ConfigurationResourceWrapper.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationInheritanceStrategy.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationInheritanceStrategy.java?rev=1770448&r1=1770447&r2=1770448&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationInheritanceStrategy.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/impl/def/DefaultConfigurationInheritanceStrategy.java Fri Nov 18 23:42:02 2016
@@ -26,6 +26,7 @@ import java.util.Map;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.wrappers.ValueMapDecorator;
+import org.apache.sling.caconfig.impl.ConfigurationResourceWrapper;
import org.apache.sling.caconfig.spi.ConfigurationInheritanceStrategy;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.metatype.annotations.AttributeDefinition;
Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/ValueInfo.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/ValueInfo.java?rev=1770448&r1=1770447&r2=1770448&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/ValueInfo.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/ValueInfo.java Fri Nov 18 23:42:02 2016
@@ -74,13 +74,6 @@ public interface ValueInfo<T> {
/**
* @return true if the value is overridden by an configuration override provider.
*/
- // for future use
- //boolean isOverridden();
-
- /**
- * @return true if this value is locked on a higher level and is not allowed to be overridden.
- */
- // for future use
- //boolean isLocked();
+ boolean isOverridden();
}
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=1770448&r1=1770447&r2=1770448&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 Fri Nov 18 23:42:02 2016
@@ -32,6 +32,7 @@ import org.apache.sling.api.resource.Val
import org.apache.sling.api.wrappers.ValueMapDecorator;
import org.apache.sling.caconfig.management.ConfigurationData;
import org.apache.sling.caconfig.management.ValueInfo;
+import org.apache.sling.caconfig.override.impl.ConfigurationOverrideManager;
import org.apache.sling.caconfig.spi.metadata.ConfigurationMetadata;
import org.apache.sling.caconfig.spi.metadata.PropertyMetadata;
@@ -41,20 +42,29 @@ final class ConfigurationDataImpl implem
private final Resource resolvedConfigurationResource;
private final Resource writebackConfigurationResource;
private final List<Resource> configurationResourceInheritanceChain;
+ private final Resource contextResource;
+ private final String configName;
+ private final ConfigurationOverrideManager configurationOverrideManager;
@SuppressWarnings("unchecked")
public ConfigurationDataImpl(ConfigurationMetadata configMetadata,
Resource resolvedConfigurationResource, Resource writebackConfigurationResource,
- Iterator<Resource> configurationResourceInheritanceChain) {
+ Iterator<Resource> configurationResourceInheritanceChain,
+ Resource contextResource, String configName, ConfigurationOverrideManager configurationOverrideManager) {
this.configMetadata = configMetadata;
this.resolvedConfigurationResource = resolvedConfigurationResource;
this.writebackConfigurationResource = writebackConfigurationResource;
this.configurationResourceInheritanceChain = configurationResourceInheritanceChain != null
? IteratorUtils.toList(configurationResourceInheritanceChain) : null;
+ this.contextResource = contextResource;
+ this.configName = configName;
+ this.configurationOverrideManager = configurationOverrideManager;
}
- public ConfigurationDataImpl(ConfigurationMetadata configMetadata) {
- this(configMetadata, null, null, null);
+ public ConfigurationDataImpl(ConfigurationMetadata configMetadata,
+ Resource contextResource, String configName, ConfigurationOverrideManager configurationOverrideManager) {
+ this(configMetadata, null, null, null,
+ contextResource, configName, configurationOverrideManager);
}
@Override
@@ -117,7 +127,10 @@ final class ConfigurationDataImpl implem
propertyMetadata,
resolvedConfigurationResource,
writebackConfigurationResource,
- configurationResourceInheritanceChain);
+ configurationResourceInheritanceChain,
+ contextResource,
+ configName,
+ configurationOverrideManager);
}
}
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=1770448&r1=1770447&r2=1770448&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 Fri Nov 18 23:42:02 2016
@@ -35,6 +35,7 @@ import org.apache.sling.caconfig.impl.Co
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.override.impl.ConfigurationOverrideManager;
import org.apache.sling.caconfig.resource.impl.ConfigurationResourceResolvingStrategyMultiplexer;
import org.apache.sling.caconfig.spi.ConfigurationPersistenceException;
import org.apache.sling.caconfig.spi.metadata.ConfigurationMetadata;
@@ -52,6 +53,8 @@ public class ConfigurationManagerImpl im
private ConfigurationPersistenceStrategyMultiplexer configurationPersistenceStrategy;
@Reference
private ConfigurationInheritanceStrategyMultiplexer configurationInheritanceStrategy;
+ @Reference
+ private ConfigurationOverrideManager configurationOverrideManager;
@SuppressWarnings("unchecked")
@Override
@@ -60,7 +63,7 @@ public class ConfigurationManagerImpl im
Iterator<Resource> configResourceInheritanceChain = configurationResourceResolvingStrategy
.getResourceInheritanceChain(resource, CONFIGS_PARENT_NAME, configName);
ResettableIterator resettableConfigResourceInheritanceChain = new ListIteratorWrapper(configResourceInheritanceChain);
- Resource configResource = applyPersistenceAndInheritance(resettableConfigResourceInheritanceChain);
+ Resource configResource = applyPersistenceAndInheritance(resource.getPath(), configName, resettableConfigResourceInheritanceChain);
if (configResource != null) {
// get writeback resource for "reverse inheritance detection"
Resource writebackConfigResource = null;
@@ -73,11 +76,13 @@ public class ConfigurationManagerImpl im
}
resettableConfigResourceInheritanceChain.reset();
return new ConfigurationDataImpl(configMetadata, configResource, writebackConfigResource,
- applyPersistence(resettableConfigResourceInheritanceChain));
+ applyPersistence(resettableConfigResourceInheritanceChain),
+ resource, configName, configurationOverrideManager);
}
if (configMetadata != null) {
// if no config resource found but config metadata exist return empty config data with default values
- return new ConfigurationDataImpl(configMetadata);
+ return new ConfigurationDataImpl(configMetadata,
+ resource, configName, configurationOverrideManager);
}
return null;
}
@@ -93,7 +98,7 @@ public class ConfigurationManagerImpl im
.getResourceCollectionInheritanceChain(resource, CONFIGS_PARENT_NAME, configName);
for (Iterator<Resource> configResourceInheritanceChain : configResourceInheritanceChains) {
ResettableIterator resettableConfigResourceInheritanceChain = new ListIteratorWrapper(configResourceInheritanceChain);
- Resource configResource = applyPersistenceAndInheritance(resettableConfigResourceInheritanceChain);
+ Resource configResource = applyPersistenceAndInheritance(resource.getPath(), configName, resettableConfigResourceInheritanceChain);
if (configResource != null) {
// get writeback resource for "reverse inheritance detection"
Resource writebackConfigResource = null;
@@ -108,7 +113,8 @@ public class ConfigurationManagerImpl im
}
resettableConfigResourceInheritanceChain.reset();
configData.add(new ConfigurationDataImpl(configMetadata, configResource, writebackConfigResource,
- applyPersistence(resettableConfigResourceInheritanceChain)));
+ applyPersistence(resettableConfigResourceInheritanceChain),
+ resource, configName, configurationOverrideManager));
}
}
return configData;
@@ -128,7 +134,7 @@ public class ConfigurationManagerImpl im
});
}
- private Resource applyPersistenceAndInheritance(Iterator<Resource> configResourceInheritanceChain) {
+ private Resource applyPersistenceAndInheritance(String contextPath, String configName, Iterator<Resource> configResourceInheritanceChain) {
if (configResourceInheritanceChain == null) {
return null;
}
@@ -137,7 +143,10 @@ public class ConfigurationManagerImpl im
Iterator<Resource> transformedConfigResources = applyPersistence(configResourceInheritanceChain);
// apply resource inheritance
- return configurationInheritanceStrategy.getResource(transformedConfigResources);
+ Resource configResource = configurationInheritanceStrategy.getResource(transformedConfigResources);
+
+ // apply overrides
+ return configurationOverrideManager.overrideProperties(contextPath, configName, configResource);
}
@Override
@@ -166,7 +175,8 @@ public class ConfigurationManagerImpl im
public ConfigurationData newCollectionItem(String configName) {
ConfigurationMetadata configMetadata = configurationMetadataProvider.getConfigurationMetadata(configName);
if (configMetadata != null) {
- return new ConfigurationDataImpl(configMetadata);
+ return new ConfigurationDataImpl(configMetadata,
+ null, configName, configurationOverrideManager);
}
return null;
}
Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ValueInfoImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ValueInfoImpl.java?rev=1770448&r1=1770447&r2=1770448&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ValueInfoImpl.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/management/impl/ValueInfoImpl.java Fri Nov 18 23:42:02 2016
@@ -18,13 +18,16 @@
*/
package org.apache.sling.caconfig.management.impl;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.caconfig.management.ValueInfo;
+import org.apache.sling.caconfig.override.impl.ConfigurationOverrideManager;
import org.apache.sling.caconfig.spi.metadata.PropertyMetadata;
final class ValueInfoImpl<T> implements ValueInfo<T> {
@@ -36,10 +39,14 @@ final class ValueInfoImpl<T> implements
private final Resource resolvedConfigurationResource;
private final Resource writebackConfigurationResource;
private final List<Resource> configurationResourceInheritanceChain;
+ private final Resource contextResource;
+ private final String configName;
+ private final ConfigurationOverrideManager configurationOverrideManager;
public ValueInfoImpl(String name, T value, PropertyMetadata<T> propertyMetadata,
Resource resolvedConfigurationResource, Resource writebackConfigurationResource,
- List<Resource> configurationResourceInheritanceChain) {
+ List<Resource> configurationResourceInheritanceChain,
+ Resource contextResource, String configName, ConfigurationOverrideManager configurationOverrideManager) {
this.name = name;
this.value = value;
this.defaultValue = propertyMetadata != null ? propertyMetadata.getDefaultValue() : null;
@@ -47,6 +54,9 @@ final class ValueInfoImpl<T> implements
this.resolvedConfigurationResource = resolvedConfigurationResource;
this.writebackConfigurationResource = writebackConfigurationResource;
this.configurationResourceInheritanceChain = configurationResourceInheritanceChain;
+ this.contextResource = contextResource;
+ this.configName = configName;
+ this.configurationOverrideManager = configurationOverrideManager;
}
@Override
@@ -59,9 +69,18 @@ final class ValueInfoImpl<T> implements
return propertyMetadata;
}
+ @SuppressWarnings("unchecked")
@Override
public T getValue() {
- return value;
+ if (writebackConfigurationResource == null) {
+ return null;
+ }
+ else if (propertyMetadata != null) {
+ return writebackConfigurationResource.getValueMap().get(name, propertyMetadata.getType());
+ }
+ else {
+ return (T)writebackConfigurationResource.getValueMap().get(name);
+ }
}
@Override
@@ -128,4 +147,21 @@ final class ValueInfoImpl<T> implements
}
return getResourceFromInheritanceChain(inheritanceChain);
}
+
+ @Override
+ public boolean isOverridden() {
+ if (contextResource == null) {
+ return false;
+ }
+ Map<String,Object> overrideProperties = configurationOverrideManager.overrideProperties(
+ contextResource.getPath(), configName, Collections.<String,Object>emptyMap());
+ if (overrideProperties != null) {
+ return overrideProperties.containsKey(name)
+ || (getValue() != null && value == null);
+ }
+ else {
+ return false;
+ }
+ }
+
}
Added: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/ConfigurationOverrideManager.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/ConfigurationOverrideManager.java?rev=1770448&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/ConfigurationOverrideManager.java (added)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/ConfigurationOverrideManager.java Fri Nov 18 23:42:02 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.caconfig.override.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.wrappers.ValueMapDecorator;
+import org.apache.sling.caconfig.impl.ConfigurationResourceWrapper;
+import org.apache.sling.caconfig.spi.ConfigurationOverrideProvider;
+import org.apache.sling.commons.osgi.Order;
+import org.apache.sling.commons.osgi.RankedServices;
+import org.apache.sling.commons.osgi.RankedServices.ChangeListener;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
+
+/**
+ * Detects all {@link ConfigurationOverrideProvider} implementations in the container
+ * and consolidates their result based on service ranking.
+ */
+@Component(service = ConfigurationOverrideManager.class,
+reference={
+ @Reference(name="configurationOverrideProvider", service=ConfigurationOverrideProvider.class,
+ bind="bindConfigurationOverrideProvider", unbind="unbindConfigurationOverrideProvider",
+ cardinality=ReferenceCardinality.MULTIPLE,
+ policy=ReferencePolicy.DYNAMIC, policyOption=ReferencePolicyOption.GREEDY)
+})
+public class ConfigurationOverrideManager implements ChangeListener {
+
+ private RankedServices<ConfigurationOverrideProvider> items = new RankedServices<>(Order.DESCENDING, this);
+ private volatile Collection<OverrideItem> allOverrides = Collections.emptyList();
+
+ protected void bindConfigurationOverrideProvider(ConfigurationOverrideProvider item, Map<String, Object> props) {
+ items.bind(item, props);
+ }
+
+ protected void unbindConfigurationOverrideProvider(ConfigurationOverrideProvider item, Map<String, Object> props) {
+ items.unbind(item, props);
+ }
+
+ /**
+ * Override properties for given context path and configuration name.
+ * @param contextPath Path of context resource for which configuration was resolved
+ * @param configName Configuration name
+ * @param properties Resolved configuration properties
+ * @return Overwritten or replaced properties - or null if no override took place
+ */
+ public Map<String,Object> overrideProperties(String contextPath, String configName, Map<String,Object> properties) {
+ if (allOverrides.size() == 0) {
+ return null;
+ }
+ boolean anyMatch = false;
+ Map<String,Object> overrideProperties = new HashMap<>(properties);
+
+ for (OverrideItem override : allOverrides) {
+ if (StringUtils.equals(configName, override.getConfigName()) && override.matchesPath(contextPath)) {
+ if (override.isAllProperties()) {
+ overrideProperties.clear();
+ }
+ overrideProperties.putAll(override.getProperties());
+ anyMatch = true;
+ }
+ }
+
+ if (anyMatch) {
+ return overrideProperties;
+ }
+ else {
+ return null;
+ }
+ }
+
+ /**
+ * Override properties in given configuration resource (if any overrides are defined).
+ * @param contextPath Context path
+ * @param configName Configuration name
+ * @param configResource Resolved configuration resource
+ * @return Resource with overwritten configuration properties - or original configuration resource if no override took place
+ */
+ public Resource overrideProperties(String contextPath, String configName, Resource configResource) {
+ if (configResource == null) {
+ return null;
+ }
+ Map<String,Object> overrideProperties = overrideProperties(contextPath, configName, configResource.getValueMap());
+ if (overrideProperties == null) {
+ return configResource;
+ }
+ return new ConfigurationResourceWrapper(configResource, new ValueMapDecorator(overrideProperties));
+ }
+
+ /**
+ * If a provider is added or removed parse and collect all overrides again (to ensure correct overall order is preserved).
+ */
+ @Override
+ public void changed() {
+ List<OverrideItem> overrides = new ArrayList<>();
+ for (ConfigurationOverrideProvider item : items) {
+ overrides.addAll(OverrideStringParser.parse(item.getOverrideStrings()));
+ }
+ allOverrides = overrides;
+ }
+
+}
Propchange: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/ConfigurationOverrideManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/ConfigurationOverrideManager.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Fri Nov 18 23:42: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/override/impl/ConfigurationOverrideManager.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OsgiConfigurationOverrideProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OsgiConfigurationOverrideProvider.java?rev=1770448&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OsgiConfigurationOverrideProvider.java (added)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OsgiConfigurationOverrideProvider.java Fri Nov 18 23:42:02 2016
@@ -0,0 +1,84 @@
+/*
+ * 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.override.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.sling.caconfig.spi.ConfigurationOverrideProvider;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+
+/**
+ * Provides parameter override map from OSGi factory configuration.
+ */
+@Component(service = ConfigurationOverrideProvider.class, immediate = true)
+@Designate(ocd = OsgiConfigurationOverrideProvider.Config.class, factory = true)
+public final class OsgiConfigurationOverrideProvider implements ConfigurationOverrideProvider {
+
+ @ObjectClassDefinition(name = "Apache Sling Context-Aware OSGi Configuration Override Provider",
+ description = "Allows to override configuration property values from OSGi configurations.")
+ public static @interface Config {
+
+ @AttributeDefinition(name = "Description",
+ description = "This description is used for display in the web console.")
+ String description();
+
+ @AttributeDefinition(name = "Overrides",
+ description = "Override strings - examples:<br>\n"
+ + "{configName}/{propertyName}={propertyJsonValue}<br>\n"
+ + "{configName}={propertyJsonObject}<br>\n"
+ + "[{contextPath}]{configName}/{propertyName}={propertyJsonValue}<br>\n"
+ + "[{contextPath}]{configName}={propertyJsonObject}")
+ String[] overrides();
+
+ @AttributeDefinition(name = "Enabled",
+ description = "Enable this override provider.")
+ boolean enabled() default false;
+
+ @AttributeDefinition(name = "Service Ranking",
+ description = "Priority of configuration override providers (higher = higher priority).")
+ int service_ranking() default 100;
+
+ String webconsole_configurationFactory_nameHint() default "{description}, enabled={enabled}";
+
+ }
+
+ private Collection<String> overrideStrings;
+
+ @Activate
+ void activate(Config config) {
+ List<String> overrides = new ArrayList<>();
+ if (config.enabled()) {
+ overrides.addAll(Arrays.asList(config.overrides()));
+ }
+ this.overrideStrings = overrides;
+ }
+
+ @Override
+ public Collection<String> getOverrideStrings() {
+ return overrideStrings;
+ }
+
+}
Propchange: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OsgiConfigurationOverrideProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OsgiConfigurationOverrideProvider.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Fri Nov 18 23:42: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/override/impl/OsgiConfigurationOverrideProvider.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OverrideItem.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OverrideItem.java?rev=1770448&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OverrideItem.java (added)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OverrideItem.java Fri Nov 18 23:42:02 2016
@@ -0,0 +1,95 @@
+/*
+ * 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.override.impl;
+
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Holds override information provided by override providers.
+ */
+class OverrideItem {
+
+ private final String path;
+ private final Pattern pathPattern;
+ private final String configName;
+ private final Map<String,Object> properties;
+ private final boolean allProperties;
+
+ public OverrideItem(String path, String configName,
+ Map<String, Object> properties, boolean allProperties) {
+ this.path = path;
+ this.pathPattern = toPathPattern(path);
+ this.configName = configName;
+ this.properties = properties;
+ this.allProperties = allProperties;
+ }
+
+ private static Pattern toPathPattern(String path) {
+ if (StringUtils.isBlank(path)) {
+ return null;
+ }
+ return Pattern.compile("^" + Pattern.quote(StringUtils.trim(path)) + "(/.*)?$");
+ }
+
+ /**
+ * @return Path (incl. subtree) to match - or null for all paths
+ */
+ public String getPath() {
+ return path;
+ }
+
+ /**
+ * @param path Path to check
+ * @return true if path matches
+ */
+ public boolean matchesPath(String path) {
+ if (pathPattern == null) {
+ return true;
+ }
+ else {
+ return pathPattern.matcher(path).matches();
+ }
+ }
+
+ /**
+ * @return Configuration name (may contain a relative hierarchy with "/")
+ */
+ public String getConfigName() {
+ return configName;
+ }
+
+ /**
+ * @return Properties map
+ */
+ public Map<String, Object> getProperties() {
+ return properties;
+ }
+
+ /**
+ * @return If true, all properties for this config name should be replaced
+ * with those from the map. Otherwise they are merged.
+ */
+ public boolean isAllProperties() {
+ return allProperties;
+ }
+
+}
Propchange: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OverrideItem.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OverrideItem.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Fri Nov 18 23:42: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/override/impl/OverrideItem.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OverrideStringParser.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OverrideStringParser.java?rev=1770448&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OverrideStringParser.java (added)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OverrideStringParser.java Fri Nov 18 23:42:02 2016
@@ -0,0 +1,273 @@
+/*
+ * 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.override.impl;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang3.ClassUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.caconfig.spi.metadata.PropertyMetadata;
+import org.apache.sling.commons.json.JSONArray;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Parses override configuration strings like these:
+ * <ul>
+ * <li><code>{configName}/{propertyName}={propertyJsonValue}</code></li>
+ * <li><code>{configName}={propertyJsonObject}</code></li>
+ * <li><code>[{contextPath}]{configName}/{propertyName}={propertyJsonValue}</code></li>
+ * <li><code>[{contextPath}]{configName}={propertyJsonObject}</code></li>
+ * </ul>
+ */
+class OverrideStringParser {
+
+ private static final Logger log = LoggerFactory.getLogger(OverrideStringParser.class);
+
+ private static final Pattern OVERRIDE_PATTERN = Pattern.compile("^(\\[([^\\[\\]=]+)\\])?([^\\[\\]=]+)=(.*)$");
+
+ private OverrideStringParser() {
+ // static method sonly
+ }
+
+ /**
+ * Parses a list of override strings from a override provider.
+ * @param overrideStrings Override strings
+ * @return Override objects
+ */
+ public static Collection<OverrideItem> parse(Collection<String> overrideStrings) {
+ List<OverrideItem> result = new ArrayList<>();
+
+ for (String overrideString : overrideStrings) {
+
+ // check if override generic pattern is matched
+ Matcher matcher = OVERRIDE_PATTERN.matcher(StringUtils.defaultString(overrideString));
+ if (!matcher.matches()) {
+ log.warn("Ignore config override string - invalid syntax: {}", overrideString);
+ continue;
+ }
+
+ // get single parts
+ String path = StringUtils.trim(matcher.group(2));
+ String configName = StringUtils.trim(matcher.group(3));
+ String value = StringUtils.trim(StringUtils.defaultString(matcher.group(4)));
+
+ OverrideItem item;
+ try {
+ // check if value is JSON = defines whole parameter map for a config name
+ JSONObject json = toJson(value);
+ if (json != null) {
+ item = new OverrideItem(path, configName, toMap(json), true);
+ }
+ else {
+ // otherwise it defines a key/value pair in a single line
+ String propertyName = StringUtils.substringAfterLast(configName, "/");
+ if (StringUtils.isEmpty(propertyName)) {
+ log.warn("Ignore config override string - missing property name: {}", overrideString);
+ continue;
+ }
+ configName = StringUtils.substringBeforeLast(configName, "/");
+ Map<String,Object> props = new HashMap<>();
+ props.put(propertyName, convertJsonValue(value));
+ item = new OverrideItem(path, configName, props, false);
+ }
+ }
+ catch (JSONException ex) {
+ log.warn("Ignore config override string - invalid JSON syntax ({}): {}", ex.getMessage(), overrideString);
+ continue;
+ }
+
+ // convert arrays
+ convertArrays(item.getProperties());
+
+ // validate item
+ if (!isValid(item, overrideString)) {
+ continue;
+ }
+
+ // if item does not contain a full property set try to merge with existing one
+ if (!item.isAllProperties()) {
+ boolean foundMatchingItem = false;
+ for (OverrideItem existingItem : result) {
+ if (!existingItem.isAllProperties()
+ && StringUtils.equals(item.getPath(), existingItem.getPath())
+ && StringUtils.equals(item.getConfigName(), existingItem.getConfigName())) {
+ existingItem.getProperties().putAll(item.getProperties());
+ foundMatchingItem = true;
+ break;
+ }
+ }
+ if (foundMatchingItem) {
+ continue;
+ }
+ }
+
+ // add item to result
+ result.add(item);
+ }
+
+ return result;
+ }
+
+ /**
+ * Try to convert value to JSON object
+ * @param value Value string
+ * @return JSON object or null if the string does not start with "{"
+ * @throws JSONException when JSON parsing failed
+ */
+ private static JSONObject toJson(String value) throws JSONException {
+ if (!StringUtils.startsWith(value, "{")) {
+ return null;
+ }
+ return new JSONObject(value);
+ }
+
+ /**
+ * Convert JSON object to map.
+ * @param json JSON object
+ * @return Map (keys/values are not validated)
+ */
+ private static Map<String,Object> toMap(JSONObject json) {
+ Map<String,Object> props = new HashMap<>();
+ Iterator<String> keys = json.keys();
+ while (keys.hasNext()) {
+ String key = keys.next();
+ try {
+ props.put(key, json.get(key));
+ }
+ catch (JSONException e) {
+ // should never happen
+ }
+ }
+ return props;
+ }
+
+ /**
+ * Convert single JSON-conformant value object
+ * @param jsonValue JSON value
+ * @return Object
+ * @throws JSONException If JSON-parsing of value failed
+ */
+ private static Object convertJsonValue(String jsonValue) throws JSONException {
+ String jsonString = "{\"value\":" + jsonValue + "}";
+ JSONObject json = toJson(jsonString);
+ return json.opt("value");
+ }
+
+ /**
+ * Convert all JSON arrays in the properties map to Java Array counterparts. Invalid arrays are ignored.
+ * @param props Properties
+ */
+ private static void convertArrays(Map<String,Object> props) {
+ Map<String,Object> convertedProps = new HashMap<>();
+ for (Map.Entry<String, Object> entry : props.entrySet()) {
+ Object value = entry.getValue();
+ if (value.getClass().equals(JSONArray.class)) {
+ JSONArray array = (JSONArray)value;
+ if (array.length() == 0) {
+ convertedProps.put(entry.getKey(), new String[0]);
+ }
+ else {
+ Object firstValue = array.opt(0);
+ if (firstValue != null) {
+ try {
+ Class firstType = firstValue.getClass();
+ Object convertedArray = Array.newInstance(firstType, array.length());
+ for (int i=0; i<array.length(); i++) {
+ Array.set(convertedArray, i, array.opt(i));
+ }
+ convertedProps.put(entry.getKey(), convertedArray);
+ }
+ catch (IllegalArgumentException ex) {
+ // ignore arrays with mixed types - will fail later in validation
+ }
+ }
+ }
+ }
+ }
+ if (!convertedProps.isEmpty()) {
+ props.putAll(convertedProps);
+ }
+ }
+
+ /**
+ * Validate override item and it's properties map.
+ * @param item Override item
+ * @param overrideString Override string
+ * @return true if item is valid
+ */
+ private static boolean isValid(OverrideItem item, String overrideString) {
+ if (item.getPath() != null && (!StringUtils.startsWith(item.getPath(), "/") || StringUtils.contains(item.getPath(), "."))) {
+ log.warn("Ignore config override string - invalid path: {}", overrideString);
+ return false;
+ }
+ if (StringUtils.startsWith(item.getConfigName(), "/") || StringUtils.contains(item.getConfigName(), ".")) {
+ log.warn("Ignore config override string - invalid configName: {}", overrideString);
+ return false;
+ }
+ for (Map.Entry<String, Object> entry : item.getProperties().entrySet()) {
+ String propertyName = entry.getKey();
+ if (StringUtils.isEmpty(propertyName) || StringUtils.contains(propertyName, "/")) {
+ log.warn("Ignore config override string - invalid property name ({}): {}", propertyName, overrideString);
+ return false;
+ }
+ Object value = entry.getValue();
+ if (value == null || !isSupportedType(value)) {
+ log.warn("Ignore config override string - invalid property value ({} - {}): {}", value, value.getClass().getName(), overrideString);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Validate if the given object is not null, and the type is supported for configuration values.
+ * @param value Value
+ * @return true if valid
+ */
+ private static boolean isSupportedType(Object value) {
+ if (value == null) {
+ return false;
+ }
+ Class clazz = value.getClass();
+ if (clazz.isArray()) {
+ clazz = clazz.getComponentType();
+ }
+ for (Class type : PropertyMetadata.SUPPORTED_TYPES) {
+ if (type.equals(clazz )) {
+ return true;
+ }
+ if (type.isPrimitive() && ClassUtils.primitiveToWrapper(type).equals(clazz)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
Propchange: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OverrideStringParser.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/OverrideStringParser.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Fri Nov 18 23:42: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/override/impl/OverrideStringParser.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/SystemPropertyConfigurationOverrideProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/SystemPropertyConfigurationOverrideProvider.java?rev=1770448&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/SystemPropertyConfigurationOverrideProvider.java (added)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/SystemPropertyConfigurationOverrideProvider.java Fri Nov 18 23:42:02 2016
@@ -0,0 +1,89 @@
+/*
+ * 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.override.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.sling.caconfig.spi.ConfigurationOverrideProvider;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+
+/**
+ * Provides parameter override map from system properties.
+ */
+@Component(service = ConfigurationOverrideProvider.class, immediate = true)
+@Designate(ocd = SystemPropertyConfigurationOverrideProvider.Config.class)
+public final class SystemPropertyConfigurationOverrideProvider implements ConfigurationOverrideProvider {
+
+ /**
+ * Prefix for override system property
+ */
+ public static final String SYSTEM_PROPERTY_PREFIX = "sling.config.override.";
+
+ @ObjectClassDefinition(name = "Apache Sling Context-Aware System Property Configuration Override Provider",
+ description = "Allows to override configuration property values from system environment properties.")
+ public static @interface Config {
+
+ @AttributeDefinition(name = "Enabled",
+ description = "Enable this override provider.")
+ boolean enabled() default false;
+
+ @AttributeDefinition(name = "Service Ranking",
+ description = "Priority of configuration override providers (higher = higher priority).")
+ int service_ranking() default 200;
+
+ }
+
+ private Collection<String> overrideStrings;
+
+ @Activate
+ void activate(Config config) {
+ List<String> overrides = new ArrayList<>();
+
+ if (config.enabled()) {
+ Properties properties = System.getProperties();
+ Enumeration<Object> keys = properties.keys();
+ while (keys.hasMoreElements()) {
+ Object keyObject = keys.nextElement();
+ if (keyObject instanceof String) {
+ String key = (String) keyObject;
+ if (StringUtils.startsWith(key, SYSTEM_PROPERTY_PREFIX)) {
+ overrides.add(StringUtils.substringAfter(key, SYSTEM_PROPERTY_PREFIX) + "=" + System.getProperty(key));
+ }
+ }
+ }
+ }
+
+ this.overrideStrings = overrides;
+ }
+
+ @Override
+ public Collection<String> getOverrideStrings() {
+ return overrideStrings;
+ }
+
+}
Propchange: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/SystemPropertyConfigurationOverrideProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: sling/trunk/contrib/extensions/contextaware-config/impl/src/main/java/org/apache/sling/caconfig/override/impl/SystemPropertyConfigurationOverrideProvider.java
------------------------------------------------------------------------------
--- svn:keywords (added)
+++ svn:keywords Fri Nov 18 23:42: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/override/impl/SystemPropertyConfigurationOverrideProvider.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverValueMapTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverValueMapTest.java?rev=1770448&r1=1770447&r2=1770448&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverValueMapTest.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/impl/ConfigurationResolverValueMapTest.java Fri Nov 18 23:42:02 2016
@@ -30,6 +30,8 @@ import org.apache.sling.api.resource.Res
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.caconfig.ConfigurationResolveException;
import org.apache.sling.caconfig.ConfigurationResolver;
+import org.apache.sling.caconfig.override.impl.DummyConfigurationOverrideProvider;
+import org.apache.sling.caconfig.spi.ConfigurationOverrideProvider;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
import org.junit.Before;
import org.junit.Rule;
@@ -102,6 +104,42 @@ public class ConfigurationResolverValueM
}
@Test
+ public void testConfigWithOverride() {
+ context.registerService(ConfigurationOverrideProvider.class, new DummyConfigurationOverrideProvider(
+ "[/content]sampleName={stringParam='override1',intParam=222}"));
+
+ context.build().resource("/conf/content/site1/sling:configs/sampleName",
+ "stringParam", "configValue1",
+ "intParam", 111,
+ "boolParam", true);
+
+ ValueMap props = underTest.get(site1Page1).name("sampleName").asValueMap();
+
+ assertEquals("override1", props.get("stringParam", String.class));
+ assertEquals(222, (int)props.get("intParam", 0));
+ assertEquals(false, props.get("boolParam", false));
+ }
+
+ @Test
+ public void testConfigCollectionWithOverride() {
+ context.registerService(ConfigurationOverrideProvider.class, new DummyConfigurationOverrideProvider(
+ "[/content]sampleList/stringParam='override1'"));
+
+ context.build().resource("/conf/content/site1/sling:configs/sampleList")
+ .siblingsMode()
+ .resource("1", "stringParam", "configValue1.1")
+ .resource("2", "stringParam", "configValue1.2")
+ .resource("3", "stringParam", "configValue1.3");
+
+ Collection<ValueMap> propsList = underTest.get(site1Page1).name("sampleList").asValueMapCollection();
+
+ Iterator<ValueMap> propsIterator = propsList.iterator();
+ assertEquals("override1", propsIterator.next().get("stringParam", String.class));
+ assertEquals("override1", propsIterator.next().get("stringParam", String.class));
+ assertEquals("override1", propsIterator.next().get("stringParam", String.class));
+ }
+
+ @Test
public void testNonExistingContentResource() {
ValueMap props = underTest.get(null).name("sampleName").asValueMap();
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=1770448&r1=1770447&r2=1770448&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 Fri Nov 18 23:42:02 2016
@@ -22,6 +22,7 @@ import org.apache.sling.caconfig.Configu
import org.apache.sling.caconfig.impl.def.DefaultConfigurationInheritanceStrategy;
import org.apache.sling.caconfig.impl.def.DefaultConfigurationPersistenceStrategy;
import org.apache.sling.caconfig.management.impl.ConfigurationPersistenceStrategyMultiplexer;
+import org.apache.sling.caconfig.override.impl.ConfigurationOverrideManager;
import org.apache.sling.caconfig.resource.impl.ConfigurationResourceTestUtils;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
@@ -41,6 +42,7 @@ public final class ConfigurationTestUtil
context.registerInjectActivateService(new ConfigurationPersistenceStrategyMultiplexer());
context.registerInjectActivateService(new DefaultConfigurationInheritanceStrategy());
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=1770448&r1=1770447&r2=1770448&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 Fri Nov 18 23:42:02 2016
@@ -26,20 +26,29 @@ import org.apache.sling.api.resource.Res
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.caconfig.management.ConfigurationData;
import org.apache.sling.caconfig.management.ValueInfo;
+import org.apache.sling.caconfig.override.impl.ConfigurationOverrideManager;
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.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+@RunWith(MockitoJUnitRunner.class)
public class ConfigurationDataImplTest {
@Rule
public SlingContext context = new SlingContext();
+ @Mock
+ private Resource contextResource;
+ @Mock
+ private ConfigurationOverrideManager configurationOverrideManager;
private Resource configResource;
private ConfigurationMetadata configMetadata;
@@ -58,7 +67,8 @@ public class ConfigurationDataImplTest {
@Test
public void testWithResourceMetadata() {
- ConfigurationData underTest = new ConfigurationDataImpl(configMetadata, configResource, configResource, null);
+ ConfigurationData underTest = new ConfigurationDataImpl(configMetadata, configResource, configResource, null,
+ contextResource, "test", configurationOverrideManager);
assertEquals(configResource.getPath(), underTest.getResourcePath());
assertEquals(ImmutableSet.of("prop1", "prop2", "prop3", "prop4"), underTest.getPropertyNames());
@@ -93,7 +103,8 @@ public class ConfigurationDataImplTest {
@Test
public void testWithResourceOnly() {
- ConfigurationData underTest = new ConfigurationDataImpl(null, configResource, configResource, null);
+ ConfigurationData underTest = new ConfigurationDataImpl(null, configResource, configResource, null,
+ contextResource, "test", configurationOverrideManager);
assertEquals(ImmutableSet.of("prop1", "prop4"), underTest.getPropertyNames());
@@ -118,7 +129,8 @@ public class ConfigurationDataImplTest {
@Test
public void testMetadataOnly() {
- ConfigurationData underTest = new ConfigurationDataImpl(configMetadata);
+ ConfigurationData underTest = new ConfigurationDataImpl(configMetadata,
+ contextResource, "test", configurationOverrideManager);
assertEquals(ImmutableSet.of("prop1", "prop2", "prop3"), underTest.getPropertyNames());
Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplTest.java?rev=1770448&r1=1770447&r2=1770448&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplTest.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplTest.java Fri Nov 18 23:42:02 2016
@@ -38,7 +38,9 @@ import org.apache.sling.caconfig.impl.Co
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.override.impl.DummyConfigurationOverrideProvider;
import org.apache.sling.caconfig.spi.ConfigurationMetadataProvider;
+import org.apache.sling.caconfig.spi.ConfigurationOverrideProvider;
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;
@@ -197,6 +199,25 @@ public class ConfigurationManagerImplTes
}
@Test
+ public void testGet_WithOverride() {
+ context.registerService(ConfigurationOverrideProvider.class, new DummyConfigurationOverrideProvider(
+ "[/content]" + CONFIG_NAME + "={prop1='override1'}"));
+
+ ConfigurationData configData = underTest.get(contextResource, CONFIG_NAME);
+ assertNotNull(configData);
+
+ assertEquals(ImmutableSet.of("prop1", "prop2", "prop3"), configData.getPropertyNames());
+ assertEquals("value1", configData.getValues().get("prop1", String.class));
+ assertEquals("override1", configData.getEffectiveValues().get("prop1", String.class));
+ assertEquals((Integer)5, configData.getEffectiveValues().get("prop3", 0));
+
+ assertFalse(configData.getValueInfo("prop1").isInherited());
+ assertTrue(configData.getValueInfo("prop1").isOverridden());
+ assertFalse(configData.getValueInfo("prop3").isInherited());
+ assertFalse(configData.getValueInfo("prop3").isOverridden());
+ }
+
+ @Test
public void testGet_NoConfigResource() {
ConfigurationData configData = underTest.get(contextResourceNoConfig, CONFIG_NAME);
assertNotNull(configData);
@@ -330,6 +351,37 @@ public class ConfigurationManagerImplTes
}
@Test
+ public void testGetCollection_WithOverride() {
+ context.registerService(ConfigurationOverrideProvider.class, new DummyConfigurationOverrideProvider(
+ "[/content]" + CONFIG_COL_NAME + "/prop1='override1'"));
+
+ List<ConfigurationData> configDatas = ImmutableList.copyOf(underTest.getCollection(contextResource, CONFIG_COL_NAME));
+ assertEquals(2, configDatas.size());
+
+ ConfigurationData configData1 = configDatas.get(0);
+ assertEquals(ImmutableSet.of("prop1", "prop2", "prop3"), configData1.getPropertyNames());
+ assertEquals("value1", configData1.getValues().get("prop1", String.class));
+ assertEquals("override1", configData1.getEffectiveValues().get("prop1", String.class));
+ assertEquals((Integer)5, configData1.getEffectiveValues().get("prop3", 0));
+
+ assertFalse(configData1.getValueInfo("prop1").isInherited());
+ assertTrue(configData1.getValueInfo("prop1").isOverridden());
+ assertFalse(configData1.getValueInfo("prop3").isInherited());
+ assertFalse(configData1.getValueInfo("prop3").isOverridden());
+
+ ConfigurationData configData2 = configDatas.get(1);
+ assertEquals(ImmutableSet.of("prop1", "prop2", "prop3", "prop4"), configData2.getPropertyNames());
+ assertNull(configData2.getValues().get("prop1", String.class));
+ assertEquals("override1", configData2.getEffectiveValues().get("prop1", String.class));
+ assertEquals((Integer)5, configData2.getEffectiveValues().get("prop3", 0));
+
+ assertFalse(configData2.getValueInfo("prop1").isInherited());
+ assertTrue(configData2.getValueInfo("prop1").isOverridden());
+ assertFalse(configData2.getValueInfo("prop3").isInherited());
+ assertFalse(configData2.getValueInfo("prop3").isOverridden());
+ }
+
+ @Test
public void testGetCollection_NoConfigResources() {
List<ConfigurationData> configDatas = ImmutableList.copyOf(underTest.getCollection(contextResourceNoConfig, CONFIG_COL_NAME));
assertEquals(0, configDatas.size());
Modified: sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ValueInfoImplTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ValueInfoImplTest.java?rev=1770448&r1=1770447&r2=1770448&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ValueInfoImplTest.java (original)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/management/impl/ValueInfoImplTest.java Fri Nov 18 23:42:02 2016
@@ -24,14 +24,25 @@ import static org.junit.Assert.assertNul
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
+import org.apache.sling.api.resource.Resource;
import org.apache.sling.caconfig.management.ValueInfo;
+import org.apache.sling.caconfig.override.impl.ConfigurationOverrideManager;
import org.apache.sling.caconfig.spi.metadata.PropertyMetadata;
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+@RunWith(MockitoJUnitRunner.class)
public class ValueInfoImplTest {
private PropertyMetadata<String> propertyMetadata;
+
+ @Mock
+ private Resource contextResource;
+ @Mock
+ private ConfigurationOverrideManager configurationOverrideManager;
@Before
public void setUp() {
@@ -40,20 +51,23 @@ public class ValueInfoImplTest {
@Test
public void testValueMetadata() {
- ValueInfo<String> underTest = new ValueInfoImpl<>("name1", "value", propertyMetadata, null, null, null);
+ ValueInfo<String> underTest = new ValueInfoImpl<>("name1", "value", propertyMetadata, null, null, null,
+ contextResource, "test", configurationOverrideManager);
assertEquals("name1", underTest.getName());
assertSame(propertyMetadata, underTest.getPropertyMetadata());
- assertEquals("value", underTest.getValue());
+ assertNull(underTest.getValue());
assertEquals("value", underTest.getEffectiveValue());
assertNull(underTest.getConfigSourcePath());
assertFalse(underTest.isDefault());
assertFalse(underTest.isInherited());
+ assertFalse(underTest.isOverridden());
}
@Test
public void testNoValueMetadata() {
- ValueInfo<String> underTest = new ValueInfoImpl<>("name1", null, propertyMetadata, null, null, null);
+ ValueInfo<String> underTest = new ValueInfoImpl<>("name1", null, propertyMetadata, null, null, null,
+ contextResource, "test", configurationOverrideManager);
assertEquals("name1", underTest.getName());
assertSame(propertyMetadata, underTest.getPropertyMetadata());
@@ -62,19 +76,22 @@ public class ValueInfoImplTest {
assertNull(underTest.getConfigSourcePath());
assertTrue(underTest.isDefault());
assertFalse(underTest.isInherited());
+ assertFalse(underTest.isOverridden());
}
@Test
public void testValueNoMetadata() {
- ValueInfo<String> underTest = new ValueInfoImpl<>("name1", "value", null, null, null, null);
+ ValueInfo<String> underTest = new ValueInfoImpl<>("name1", "value", null, null, null, null,
+ contextResource, "test", configurationOverrideManager);
assertEquals("name1", underTest.getName());
assertNull(underTest.getPropertyMetadata());
- assertEquals("value", underTest.getValue());
+ assertNull(underTest.getValue());
assertEquals("value", underTest.getEffectiveValue());
assertNull(underTest.getConfigSourcePath());
assertFalse(underTest.isDefault());
assertFalse(underTest.isInherited());
+ assertFalse(underTest.isOverridden());
}
}
Added: sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/override/impl/ConfigurationOverrideManagerTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/override/impl/ConfigurationOverrideManagerTest.java?rev=1770448&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/override/impl/ConfigurationOverrideManagerTest.java (added)
+++ sling/trunk/contrib/extensions/contextaware-config/impl/src/test/java/org/apache/sling/caconfig/override/impl/ConfigurationOverrideManagerTest.java Fri Nov 18 23:42:02 2016
@@ -0,0 +1,97 @@
+/*
+ * 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.override.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.util.Map;
+
+import org.apache.sling.caconfig.spi.ConfigurationOverrideProvider;
+import org.apache.sling.testing.mock.sling.junit.SlingContext;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.osgi.framework.Constants;
+
+import com.google.common.collect.ImmutableMap;
+
+public class ConfigurationOverrideManagerTest {
+
+ @Rule
+ public SlingContext context = new SlingContext();
+
+ private ConfigurationOverrideManager underTest;
+
+ @Before
+ public void setUp() {
+ underTest = context.registerInjectActivateService(new ConfigurationOverrideManager());
+ }
+
+ @Test
+ public void testWithNoProviders() {
+ assertOverride("/a/b", "test",
+ ImmutableMap.<String,Object>of("param1", "initialValue"),
+ null);
+ }
+
+ @Test
+ public void testWithMultipleProviders() {
+
+ // 1st provider
+ context.registerService(ConfigurationOverrideProvider.class, new DummyConfigurationOverrideProvider(
+ "test/globalParam1='globalValue1'",
+ "[/a/b]test/param1='value1'"), Constants.SERVICE_RANKING, 200);
+
+ // 2nd provider (may overwrite 1st one)
+ context.registerService(ConfigurationOverrideProvider.class, new DummyConfigurationOverrideProvider(
+ "test/globalParam1='globalValue1a'",
+ "[/a/b/c]test={'param1'='value2'}"), Constants.SERVICE_RANKING, 100);
+
+ assertOverride("/a", "test",
+ ImmutableMap.<String,Object>of("param1", "initialValue"),
+ ImmutableMap.<String,Object>of("param1", "initialValue", "globalParam1", "globalValue1a"));
+
+ assertOverride("/a/b", "test",
+ ImmutableMap.<String,Object>of("param1", "initialValue"),
+ ImmutableMap.<String,Object>of("param1", "value1", "globalParam1", "globalValue1a"));
+
+ assertOverride("/a/b/c", "test",
+ ImmutableMap.<String,Object>of("param1", "initialValue"),
+ ImmutableMap.<String,Object>of("param1", "value2"));
+
+ assertOverride("/a/b/c/d", "test",
+ ImmutableMap.<String,Object>of("param1", "initialValue"),
+ ImmutableMap.<String,Object>of("param1", "value2"));
+
+ assertOverride("/a/b", "test2",
+ ImmutableMap.<String,Object>of("param1", "initialValue"),
+ null);
+ }
+
+ private void assertOverride(String path, String configName, Map<String,Object> input, Map<String,Object> output) {
+ if (output == null) {
+ assertNull(underTest.overrideProperties(path, configName, input));
+ }
+ else {
+ assertEquals(output, underTest.overrideProperties(path, configName, input));
+ }
+ }
+
+}