Skip to content

Commit 8ab0a06

Browse files
committed
XCOMMONS-3289: Allow overwritting xwiki.properties and xwiki.cfg properties via environment variable and Java system properties
* won't be ready for 17.4.0RC1 * provide an abstract to help support system overwrite
1 parent c41ca5e commit 8ab0a06

File tree

7 files changed

+402
-18
lines changed

7 files changed

+402
-18
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ default <T> T getProperty(String key, Class<T> valueClass, T defaultValue)
8888
/**
8989
* @param prefix the prefix to filter the keys
9090
* @return the list of available keys in the configuration source that start with the passed prefix
91-
* @since 17.4.0RC1
91+
* @since 17.5.0RC1
9292
*/
9393
@Unstable
9494
default List<String> getKeys(String prefix)
@@ -110,7 +110,7 @@ default List<String> getKeys(String prefix)
110110
/**
111111
* @param prefix the prefix to filter the keys
112112
* @return true if the configuration source doesn't have any key or false otherwise
113-
* @since 17.4.0RC1
113+
* @since 17.5.0RC1
114114
*/
115115
@Unstable
116116
default boolean isEmpty(String prefix)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
* Base class to use to implement {@link ConfigurationSource}.
3030
*
3131
* @version $Id$
32-
* @since 3.5M1
32+
* @since 17.5.0RC1
3333
*/
3434
public abstract class AbstractConfigurationSource implements ConfigurationSource
3535
{

xwiki-commons-core/xwiki-commons-configuration/xwiki-commons-configuration-default/src/main/java/org/xwiki/configuration/internal/AbstractPropertiesConfigurationSource.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
* @version $Id$
3232
* @since 17.4.0RC1
3333
*/
34-
public abstract class AbstractPropertiesConfigurationSource implements ConfigurationSource
34+
public abstract class AbstractPropertiesConfigurationSource extends AbstractSystemOverwriteConfigurationSource
3535
{
3636
/**
3737
* Component used for performing type conversions.
@@ -41,7 +41,7 @@ public abstract class AbstractPropertiesConfigurationSource implements Configura
4141

4242
@Override
4343
@SuppressWarnings("unchecked")
44-
public <T> T getProperty(String key, T defaultValue)
44+
public <T> T getPropertyInternal(String key, T defaultValue)
4545
{
4646
T result;
4747
if (containsKey(key)) {
@@ -58,11 +58,17 @@ public <T> T getProperty(String key, T defaultValue)
5858
}
5959

6060
@Override
61-
public <T> T getProperty(String key, Class<T> valueClass)
61+
public <T> T getPropertyInternal(String key, Class<T> valueClass)
6262
{
6363
return getConvertedProperty(key, valueClass, null);
6464
}
6565

66+
@Override
67+
protected <T> T getPropertyInternal(String key, Class<T> valueClass, T defaultValue)
68+
{
69+
return getConvertedProperty(key, valueClass, defaultValue);
70+
}
71+
6672
/**
6773
* @param <T> the value type
6874
* @param key the property key for which we want the value
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
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 jakarta.inject.Inject;
28+
29+
import org.xwiki.component.descriptor.ComponentDescriptor;
30+
import org.xwiki.component.manager.ComponentLookupException;
31+
import org.xwiki.component.manager.ComponentManager;
32+
import org.xwiki.component.phase.Initializable;
33+
import org.xwiki.component.phase.InitializationException;
34+
import org.xwiki.configuration.ConfigurationSource;
35+
36+
/**
37+
* Helper to implement {@link ConfigurationSource}.
38+
*
39+
* @version $Id$
40+
* @since 17.5.0RC1
41+
*/
42+
public abstract class AbstractSystemOverwriteConfigurationSource extends AbstractConfigurationSource
43+
implements Initializable
44+
{
45+
@Inject
46+
protected ComponentDescriptor<AbstractSystemOverwriteConfigurationSource> componentDescriptor;
47+
48+
@Inject
49+
protected ComponentManager componentManager;
50+
51+
/**
52+
* True if it should be possible to overwrite this configuration source using system environment variables or
53+
* properties.
54+
*/
55+
protected boolean systemOverwriteEnabled;
56+
57+
protected ConfigurationSource systemConfigurationSource;
58+
59+
@Override
60+
public void initialize() throws InitializationException
61+
{
62+
if (this.systemOverwriteEnabled) {
63+
try {
64+
this.systemConfigurationSource = this.componentManager.getInstance(ConfigurationSource.class, "system");
65+
} catch (ComponentLookupException e) {
66+
throw new InitializationException("Failed to lookup the system configuration source", e);
67+
}
68+
}
69+
}
70+
71+
/**
72+
* @param key the key
73+
* @return the key to use with the system ConfigurationSource
74+
*/
75+
protected String toSystemOverwriteKey(String key)
76+
{
77+
return this.componentDescriptor.getRoleHint() + "." + key;
78+
}
79+
80+
@Override
81+
public <T> T getProperty(String key)
82+
{
83+
if (this.systemOverwriteEnabled) {
84+
String systemOverwriteKey = toSystemOverwriteKey(key);
85+
if (this.systemConfigurationSource.containsKey(systemOverwriteKey)) {
86+
return this.systemConfigurationSource.getProperty(systemOverwriteKey);
87+
}
88+
}
89+
90+
return getPropertyInternal(key);
91+
}
92+
93+
protected abstract <T> T getPropertyInternal(String key);
94+
95+
@Override
96+
public <T> T getProperty(String key, T defaultValue)
97+
{
98+
if (this.systemOverwriteEnabled) {
99+
String systemOverwriteKey = toSystemOverwriteKey(key);
100+
if (this.systemConfigurationSource.containsKey(systemOverwriteKey)) {
101+
return this.systemConfigurationSource.getProperty(systemOverwriteKey, defaultValue);
102+
}
103+
}
104+
105+
return getPropertyInternal(key, defaultValue);
106+
}
107+
108+
protected abstract <T> T getPropertyInternal(String key, T defaultValue);
109+
110+
@Override
111+
public <T> T getProperty(String key, Class<T> valueClass)
112+
{
113+
if (this.systemOverwriteEnabled) {
114+
String systemOverwriteKey = toSystemOverwriteKey(key);
115+
if (this.systemConfigurationSource.containsKey(systemOverwriteKey)) {
116+
return this.systemConfigurationSource.getProperty(systemOverwriteKey, valueClass);
117+
}
118+
}
119+
120+
return getPropertyInternal(key, valueClass);
121+
}
122+
123+
protected abstract <T> T getPropertyInternal(String key, Class<T> valueClass);
124+
125+
@Override
126+
public <T> T getProperty(String key, Class<T> valueClass, T defaultValue)
127+
{
128+
if (this.systemOverwriteEnabled) {
129+
String systemOverwriteKey = toSystemOverwriteKey(key);
130+
if (this.systemConfigurationSource.containsKey(systemOverwriteKey)) {
131+
return this.systemConfigurationSource.getProperty(systemOverwriteKey, valueClass, defaultValue);
132+
}
133+
}
134+
135+
return getPropertyInternal(key, valueClass, defaultValue);
136+
}
137+
138+
protected abstract <T> T getPropertyInternal(String key, Class<T> valueClass, T defaultValue);
139+
140+
@Override
141+
public List<String> getKeys()
142+
{
143+
if (this.systemOverwriteEnabled) {
144+
Set<String> keys = new LinkedHashSet<>();
145+
146+
// Add current keys
147+
keys.addAll(getKeysInternal());
148+
149+
// Add system ones
150+
keys.addAll(this.systemConfigurationSource.getKeys(toSystemOverwriteKey("")));
151+
152+
return new ArrayList<>(keys);
153+
}
154+
155+
return getKeysInternal();
156+
}
157+
158+
protected abstract List<String> getKeysInternal();
159+
160+
@Override
161+
public List<String> getKeys(String prefix)
162+
{
163+
if (this.systemOverwriteEnabled) {
164+
Set<String> keys = new LinkedHashSet<>();
165+
166+
// Add current keys
167+
keys.addAll(getKeysInternal());
168+
169+
// Add system ones
170+
keys.addAll(this.systemConfigurationSource.getKeys(toSystemOverwriteKey(prefix)));
171+
172+
return new ArrayList<>(keys);
173+
}
174+
175+
return getKeysInternal(prefix);
176+
}
177+
178+
protected abstract List<String> getKeysInternal(String prefix);
179+
180+
@Override
181+
public boolean containsKey(String key)
182+
{
183+
if (this.systemOverwriteEnabled && this.systemConfigurationSource.containsKey(toSystemOverwriteKey(key))) {
184+
return true;
185+
}
186+
187+
return containsKeyInternal(key);
188+
}
189+
190+
protected abstract boolean containsKeyInternal(String key);
191+
192+
@Override
193+
public boolean isEmpty()
194+
{
195+
if (this.systemOverwriteEnabled && !this.systemConfigurationSource.isEmpty(toSystemOverwriteKey(""))) {
196+
return false;
197+
}
198+
199+
return isEmptyInternal();
200+
}
201+
202+
protected abstract boolean isEmptyInternal();
203+
204+
@Override
205+
public boolean isEmpty(String prefix)
206+
{
207+
if (this.systemOverwriteEnabled && !this.systemConfigurationSource.isEmpty(toSystemOverwriteKey(prefix))) {
208+
return false;
209+
}
210+
211+
return isEmptyInternal(prefix);
212+
}
213+
214+
protected abstract boolean isEmptyInternal(String prefix);
215+
}

xwiki-commons-core/xwiki-commons-configuration/xwiki-commons-configuration-default/src/main/java/org/xwiki/configuration/internal/SystemEnvConfigurationSource.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ String getenv(String name)
7474

7575
@SuppressWarnings("unchecked")
7676
@Override
77-
public <T> T getProperty(String key)
77+
public <T> T getPropertyInternal(String key)
7878
{
7979
if (key == null) {
8080
return null;
@@ -84,13 +84,13 @@ public <T> T getProperty(String key)
8484
}
8585

8686
@Override
87-
public List<String> getKeys()
87+
public List<String> getKeysInternal()
8888
{
8989
return getKeys("");
9090
}
9191

9292
@Override
93-
public List<String> getKeys(String prefix)
93+
public List<String> getKeysInternal(String prefix)
9494
{
9595
String encodedPrefix = encode(prefix);
9696
String encodedCompletePrefix = PREFIX + encodedPrefix;
@@ -100,7 +100,7 @@ public List<String> getKeys(String prefix)
100100
}
101101

102102
@Override
103-
public boolean containsKey(String key)
103+
public boolean containsKeyInternal(String key)
104104
{
105105
if (key == null) {
106106
return false;
@@ -110,13 +110,13 @@ public boolean containsKey(String key)
110110
}
111111

112112
@Override
113-
public boolean isEmpty()
113+
public boolean isEmptyInternal()
114114
{
115115
return isEmpty("");
116116
}
117117

118118
@Override
119-
public boolean isEmpty(String prefix)
119+
public boolean isEmptyInternal(String prefix)
120120
{
121121
Map<String, String> env = getenv();
122122

xwiki-commons-core/xwiki-commons-configuration/xwiki-commons-configuration-default/src/main/java/org/xwiki/configuration/internal/SystemPropertiesConfigurationSource.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ void setSystemProperties(Properties properties)
7979

8080
@SuppressWarnings("unchecked")
8181
@Override
82-
public <T> T getProperty(String key)
82+
public <T> T getPropertyInternal(String key)
8383
{
8484
if (key == null) {
8585
return null;
@@ -89,13 +89,13 @@ public <T> T getProperty(String key)
8989
}
9090

9191
@Override
92-
public List<String> getKeys()
92+
public List<String> getKeysInternal()
9393
{
9494
return getKeys("");
9595
}
9696

9797
@Override
98-
public List<String> getKeys(String prefix)
98+
public List<String> getKeysInternal(String prefix)
9999
{
100100
String systemPrefix = toSystemKey(prefix);
101101

@@ -104,7 +104,7 @@ public List<String> getKeys(String prefix)
104104
}
105105

106106
@Override
107-
public boolean containsKey(String key)
107+
public boolean containsKeyInternal(String key)
108108
{
109109
if (key == null) {
110110
return false;
@@ -114,13 +114,13 @@ public boolean containsKey(String key)
114114
}
115115

116116
@Override
117-
public boolean isEmpty()
117+
public boolean isEmptyInternal()
118118
{
119119
return isEmpty("");
120120
}
121121

122122
@Override
123-
public boolean isEmpty(String prefix)
123+
public boolean isEmptyInternal(String prefix)
124124
{
125125
Properties properties = getSystemProperties();
126126

0 commit comments

Comments
 (0)