Skip to content

Commit 8395e0e

Browse files
committed
XCOMMONS-3289: Allow overwritting xwiki.properties and xwiki.cfg properties via environment variable and Java system properties
1 parent 425422f commit 8395e0e

File tree

16 files changed

+1191
-9
lines changed

16 files changed

+1191
-9
lines changed

xwiki-commons-core/xwiki-commons-configuration/pom.xml

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
<description>XWiki Commons - Configuration - Parent POM</description>
3434
<modules>
3535
<module>xwiki-commons-configuration-api</module>
36+
<module>xwiki-commons-configuration-default</module>
3637
</modules>
3738
</project>
3839

xwiki-commons-core/xwiki-commons-configuration/xwiki-commons-configuration-api/src/main/java/org/xwiki/configuration/ConfigurationSource.java

+22-2
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ default <T> T getProperty(String key, Class<T> valueClass, T defaultValue)
6666
{
6767
if (containsKey(key)) {
6868
return getProperty(key, valueClass);
69-
} else {
70-
return getProperty(key, defaultValue);
7169
}
70+
71+
return defaultValue;
7272
}
7373

7474
/**
@@ -84,6 +84,16 @@ default <T> T getProperty(String key, Class<T> valueClass, T defaultValue)
8484
*/
8585
List<String> getKeys();
8686

87+
/**
88+
* @param prefix the prefix to filter the keys
89+
* @return the list of available keys in the configuration source that start with the passed prefix
90+
* @since 17.4.0RC1
91+
*/
92+
default List<String> getKeys(String prefix)
93+
{
94+
return getKeys().stream().filter(key -> key.startsWith(prefix)).toList();
95+
}
96+
8797
/**
8898
* @param key the key to check
8999
* @return true if the key is present in the configuration source or false otherwise
@@ -95,6 +105,16 @@ default <T> T getProperty(String key, Class<T> valueClass, T defaultValue)
95105
*/
96106
boolean isEmpty();
97107

108+
/**
109+
* @param prefix the prefix to filter the keys
110+
* @return true if the configuration source doesn't have any key or false otherwise
111+
* @since 17.4.0RC1
112+
*/
113+
default boolean isEmpty(String prefix)
114+
{
115+
return getKeys(prefix).isEmpty();
116+
}
117+
98118
/**
99119
* Set a property, this will replace any previously set values.
100120
*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/*
2+
* See the NOTICE file distributed with this work for additional
3+
* information regarding copyright ownership.
4+
*
5+
* This is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU Lesser General Public License as
7+
* published by the Free Software Foundation; either version 2.1 of
8+
* the License, or (at your option) any later version.
9+
*
10+
* This software is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this software; if not, write to the Free
17+
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18+
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19+
*/
20+
package org.xwiki.configuration.internal;
21+
22+
import java.util.ArrayList;
23+
import java.util.LinkedHashSet;
24+
import java.util.List;
25+
import java.util.Set;
26+
27+
import org.xwiki.configuration.ConfigurationSource;
28+
29+
/**
30+
* Base class for composing (aka chaining) several Configuration Sources. The order of sources is important. Sources
31+
* located before other sources take priority.
32+
*
33+
* @version $Id$
34+
* @since 7.4M1
35+
*/
36+
public abstract class AbstractCompositeConfigurationSource extends AbstractConfigurationSource
37+
implements Iterable<ConfigurationSource>
38+
{
39+
@Override
40+
public boolean containsKey(String key)
41+
{
42+
boolean result = false;
43+
44+
for (ConfigurationSource source : this) {
45+
if (source.containsKey(key)) {
46+
result = true;
47+
break;
48+
}
49+
}
50+
51+
return result;
52+
}
53+
54+
@Override
55+
public <T> T getProperty(String key)
56+
{
57+
T result = null;
58+
59+
for (ConfigurationSource source : this) {
60+
if (source.containsKey(key)) {
61+
result = source.<T>getProperty(key);
62+
break;
63+
}
64+
}
65+
66+
return result;
67+
}
68+
69+
@Override
70+
public <T> T getProperty(String key, Class<T> valueClass)
71+
{
72+
T result = null;
73+
74+
for (ConfigurationSource source : this) {
75+
if (source.containsKey(key)) {
76+
result = source.getProperty(key, valueClass);
77+
break;
78+
}
79+
}
80+
81+
// List and Properties must return empty collections and not null values.
82+
if (result == null) {
83+
result = getDefault(valueClass);
84+
}
85+
86+
return result;
87+
}
88+
89+
@Override
90+
public <T> T getProperty(String key, T defaultValue)
91+
{
92+
T result = null;
93+
94+
for (ConfigurationSource source : this) {
95+
if (source.containsKey(key)) {
96+
result = source.<T>getProperty(key, defaultValue);
97+
break;
98+
}
99+
}
100+
101+
if (result == null) {
102+
result = defaultValue;
103+
}
104+
105+
return result;
106+
}
107+
108+
@Override
109+
public List<String> getKeys()
110+
{
111+
// We use a linked hash set in order to keep the keys in the order in which they were defined in the sources.
112+
Set<String> keys = new LinkedHashSet<>();
113+
114+
for (ConfigurationSource source : this) {
115+
keys.addAll(source.getKeys());
116+
}
117+
118+
return new ArrayList<>(keys);
119+
}
120+
121+
@Override
122+
public List<String> getKeys(String prefix)
123+
{
124+
// We use a linked hash set in order to keep the keys in the order in which they were defined in the sources.
125+
Set<String> keys = new LinkedHashSet<>();
126+
127+
for (ConfigurationSource source : this) {
128+
keys.addAll(source.getKeys(prefix));
129+
}
130+
131+
return new ArrayList<>(keys);
132+
}
133+
134+
@Override
135+
public boolean isEmpty()
136+
{
137+
for (ConfigurationSource source : this) {
138+
if (!source.isEmpty()) {
139+
return false;
140+
}
141+
}
142+
143+
return true;
144+
}
145+
146+
@Override
147+
public boolean isEmpty(String prefix)
148+
{
149+
for (ConfigurationSource source : this) {
150+
if (!source.isEmpty(prefix)) {
151+
return false;
152+
}
153+
}
154+
155+
return true;
156+
}
157+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* See the NOTICE file distributed with this work for additional
3+
* information regarding copyright ownership.
4+
*
5+
* This is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU Lesser General Public License as
7+
* published by the Free Software Foundation; either version 2.1 of
8+
* the License, or (at your option) any later version.
9+
*
10+
* This software is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this software; if not, write to the Free
17+
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18+
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19+
*/
20+
package org.xwiki.configuration.internal;
21+
22+
import java.util.ArrayList;
23+
import java.util.Iterator;
24+
import java.util.List;
25+
26+
import org.xwiki.configuration.ConfigurationSource;
27+
28+
/**
29+
* Allows composing (aka chaining) several Configuration Sources. The order of sources is important. Sources located
30+
* before other sources take priority.
31+
*
32+
* @version $Id$
33+
* @since 2.0M1
34+
*/
35+
public class CompositeConfigurationSource extends AbstractCompositeConfigurationSource
36+
{
37+
/**
38+
* The order of sources is important. Sources located before other sources take priority.
39+
*/
40+
protected List<ConfigurationSource> sources = new ArrayList<>();
41+
42+
/**
43+
* @param source the source to add to the list of sources
44+
*/
45+
public void addConfigurationSource(ConfigurationSource source)
46+
{
47+
this.sources.add(source);
48+
}
49+
50+
@Override
51+
public Iterator<ConfigurationSource> iterator()
52+
{
53+
return this.sources.iterator();
54+
}
55+
}

xwiki-commons-core/xwiki-commons-configuration/xwiki-commons-configuration-api/src/main/java/org/xwiki/configuration/internal/ConfigurationSourceDecorator.java

+12
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ public List<String> getKeys()
9090
return executeRead(() -> getWrappedConfigurationSource().getKeys());
9191
}
9292

93+
@Override
94+
public List<String> getKeys(String prefix)
95+
{
96+
return executeRead(() -> getWrappedConfigurationSource().getKeys(prefix));
97+
}
98+
9399
@Override
94100
public boolean containsKey(String key)
95101
{
@@ -102,6 +108,12 @@ public boolean isEmpty()
102108
return executeRead(() -> getWrappedConfigurationSource().isEmpty());
103109
}
104110

111+
@Override
112+
public boolean isEmpty(String prefix)
113+
{
114+
return executeRead(() -> getWrappedConfigurationSource().isEmpty(prefix));
115+
}
116+
105117
@Override
106118
public void setProperties(Map<String, Object> properties) throws ConfigurationSaveException
107119
{

xwiki-commons-core/xwiki-commons-configuration/xwiki-commons-configuration-api/src/main/java/org/xwiki/configuration/internal/MemoryConfigurationSource.java

+12
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,12 @@ public List<String> getKeys()
118118
return new ArrayList<>(this.properties.keySet());
119119
}
120120

121+
@Override
122+
public List<String> getKeys(String prefix)
123+
{
124+
return this.properties.keySet().stream().filter(k -> k.startsWith(prefix)).toList();
125+
}
126+
121127
@Override
122128
public boolean containsKey(String key)
123129
{
@@ -129,4 +135,10 @@ public boolean isEmpty()
129135
{
130136
return this.properties.isEmpty();
131137
}
138+
139+
@Override
140+
public boolean isEmpty(String prefix)
141+
{
142+
return this.properties.keySet().stream().noneMatch(k -> k.startsWith(prefix));
143+
}
132144
}

xwiki-commons-core/xwiki-commons-configuration/xwiki-commons-configuration-api/src/main/java/org/xwiki/configuration/internal/VoidConfigurationSource.java

+12
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ public List<String> getKeys()
6262
return Collections.emptyList();
6363
}
6464

65+
@Override
66+
public List<String> getKeys(String prefix)
67+
{
68+
return Collections.emptyList();
69+
}
70+
6571
@Override
6672
public boolean containsKey(String key)
6773
{
@@ -73,4 +79,10 @@ public boolean isEmpty()
7379
{
7480
return true;
7581
}
82+
83+
@Override
84+
public boolean isEmpty(String prefix)
85+
{
86+
return true;
87+
}
7688
}

0 commit comments

Comments
 (0)