diff --git a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/pom.xml b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/pom.xml index f1e2e6866c04..d6ed0dff6fee 100644 --- a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/pom.xml +++ b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/pom.xml @@ -42,6 +42,11 @@ xwiki-commons-configuration-api ${commons.version} + + org.xwiki.commons + xwiki-commons-configuration-default + ${commons.version} + org.xwiki.commons xwiki-commons-environment-api @@ -107,7 +112,6 @@ org/xwiki/configuration/internal/AbstractDocumentConfigurationSource.java, org/xwiki/configuration/internal/AllConfigurationSource.java, org/xwiki/configuration/internal/CommonsConfigurationSource.java, - org/xwiki/configuration/internal/CompositeConfigurationSource.java, org/xwiki/configuration/internal/DefaultConfigurationSource.java diff --git a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/CommonsConfigurationSource.java b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/AbstractCommonsConfigurationSource.java similarity index 75% rename from xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/CommonsConfigurationSource.java rename to xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/AbstractCommonsConfigurationSource.java index 8f77200adea0..a6b74bd257f2 100644 --- a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/CommonsConfigurationSource.java +++ b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/AbstractCommonsConfigurationSource.java @@ -25,11 +25,9 @@ import java.util.Properties; import java.util.concurrent.locks.ReentrantReadWriteLock; -import javax.inject.Inject; - import org.apache.commons.configuration2.Configuration; +import org.xwiki.component.phase.Initializable; import org.xwiki.configuration.ConfigurationSource; -import org.xwiki.properties.ConverterManager; /** * Wrap a Commons Configuration instance into a XWiki {@link ConfigurationSource}. This allows us to reuse the @@ -39,18 +37,19 @@ * @version $Id$ * @since 1.6M1 */ -public class CommonsConfigurationSource implements ConfigurationSource +public abstract class AbstractCommonsConfigurationSource extends AbstractPropertiesConfigurationSource + implements Initializable { - /** - * Component used for performing type conversions. - */ - @Inject - protected ConverterManager converterManager; - protected final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); private Configuration configuration; + protected AbstractCommonsConfigurationSource() + { + // Enable system overwrite + this.systemOverwriteEnabled = true; + } + protected Configuration getConfiguration() { return this.configuration; @@ -63,25 +62,7 @@ protected void setConfiguration(Configuration configuration) @Override @SuppressWarnings("unchecked") - public T getProperty(String key, T defaultValue) - { - T result; - if (containsKey(key)) { - if (defaultValue != null) { - return getProperty(key, (Class) defaultValue.getClass()); - } else { - return getProperty(key); - } - } else { - result = defaultValue; - } - - return result; - } - - @Override - @SuppressWarnings("unchecked") - public T getProperty(String key) + protected T getPropertyInternal(String key) { this.lock.readLock().lock(); @@ -94,9 +75,9 @@ public T getProperty(String key) @Override @SuppressWarnings("unchecked") - public T getProperty(String key, Class valueClass) + protected T getPropertyInternal(String key, Class valueClass) { - T result = null; + T result; try { if (String.class == valueClass) { @@ -106,10 +87,7 @@ public T getProperty(String key, Class valueClass) } else if (Properties.class.isAssignableFrom(valueClass)) { result = (T) getProperties(key); } else { - Object value = getProperty(key); - if (value != null) { - result = this.converterManager.convert(valueClass, value); - } + result = getConvertedProperty(key, valueClass, null); } } catch (org.apache.commons.configuration2.ex.ConversionException | org.xwiki.properties.converter.ConversionException e) { @@ -154,15 +132,35 @@ private Properties getProperties(String key) } @Override - public List getKeys() + protected boolean containsKeyInternal(String key) + { + this.lock.readLock().lock(); + + try { + return getConfiguration().containsKey(key); + } finally { + this.lock.readLock().unlock(); + } + } + + @Override + protected List getKeysInternal() + { + return getKeysInternal(""); + } + + @Override + protected List getKeysInternal(String prefix) { this.lock.readLock().lock(); try { List keysList = new ArrayList<>(); - Iterator keys = getConfiguration().getKeys(); - while (keys.hasNext()) { - keysList.add(keys.next()); + for (Iterator keys = getConfiguration().getKeys(); keys.hasNext();) { + String key = keys.next(); + if (key.startsWith(prefix)) { + keysList.add(key); + } } return keysList; @@ -172,24 +170,31 @@ public List getKeys() } @Override - public boolean containsKey(String key) + protected boolean isEmptyInternal() { this.lock.readLock().lock(); try { - return getConfiguration().containsKey(key); + return getConfiguration().isEmpty(); } finally { this.lock.readLock().unlock(); } } @Override - public boolean isEmpty() + protected boolean isEmptyInternal(String prefix) { this.lock.readLock().lock(); try { - return getConfiguration().isEmpty(); + for (Iterator keys = getConfiguration().getKeys(); keys.hasNext();) { + String key = keys.next(); + if (key.startsWith(prefix)) { + return false; + } + } + + return true; } finally { this.lock.readLock().unlock(); } diff --git a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/AbstractCompositeConfigurationSource.java b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/AbstractCompositeConfigurationSource.java deleted file mode 100644 index 63b6eefae467..000000000000 --- a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/AbstractCompositeConfigurationSource.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package org.xwiki.configuration.internal; - -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -import org.xwiki.configuration.ConfigurationSource; - -/** - * Base class for composing (aka chaining) several Configuration Sources. The order of sources is important. Sources - * located before other sources take priority. - * - * @version $Id$ - * @since 7.4M1 - */ -public abstract class AbstractCompositeConfigurationSource extends AbstractConfigurationSource - implements Iterable -{ - @Override - public boolean containsKey(String key) - { - boolean result = false; - - for (ConfigurationSource source : this) { - if (source.containsKey(key)) { - result = true; - break; - } - } - - return result; - } - - @Override - public T getProperty(String key) - { - T result = null; - - for (ConfigurationSource source : this) { - if (source.containsKey(key)) { - result = source.getProperty(key); - break; - } - } - - return result; - } - - @Override - public T getProperty(String key, Class valueClass) - { - T result = null; - - for (ConfigurationSource source : this) { - if (source.containsKey(key)) { - result = source.getProperty(key, valueClass); - break; - } - } - - // List and Properties must return empty collections and not null values. - if (result == null) { - result = getDefault(valueClass); - } - - return result; - } - - @Override - public T getProperty(String key, T defaultValue) - { - T result = null; - - for (ConfigurationSource source : this) { - if (source.containsKey(key)) { - result = source.getProperty(key, defaultValue); - break; - } - } - - if (result == null) { - result = defaultValue; - } - - return result; - } - - @Override - public List getKeys() - { - // We use a linked hash set in order to keep the keys in the order in which they were defined in the sources. - Set keys = new LinkedHashSet(); - - for (ConfigurationSource source : this) { - keys.addAll(source.getKeys()); - } - - return new ArrayList(keys); - } - - @Override - public boolean isEmpty() - { - boolean result = true; - - for (ConfigurationSource source : this) { - if (!source.isEmpty()) { - result = false; - break; - } - } - - return result; - } -} diff --git a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/AbstractDocumentConfigurationSource.java b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/AbstractDocumentConfigurationSource.java index 200c277d43c8..d690527c0670 100644 --- a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/AbstractDocumentConfigurationSource.java +++ b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/AbstractDocumentConfigurationSource.java @@ -37,7 +37,6 @@ import org.xwiki.cache.CacheManager; import org.xwiki.cache.config.CacheConfiguration; import org.xwiki.component.phase.Disposable; -import org.xwiki.component.phase.Initializable; import org.xwiki.component.phase.InitializationException; import org.xwiki.configuration.ConfigurationSaveException; import org.xwiki.model.reference.DocumentReference; @@ -70,8 +69,8 @@ * @version $Id$ * @since 2.0M2 */ -public abstract class AbstractDocumentConfigurationSource extends AbstractConfigurationSource - implements Initializable, Disposable +public abstract class AbstractDocumentConfigurationSource extends AbstractSystemOverwriteConfigurationSource + implements Disposable { /** * Represents no value (ie the default value will be used) in xproperties. @@ -132,6 +131,8 @@ protected String getCacheKeyPrefix() @Override public void initialize() throws InitializationException { + super.initialize(); + // Initialize cache try { this.cache = this.cacheManager.createNewCache(new CacheConfiguration(getCacheId())); @@ -195,7 +196,7 @@ protected WikiReference getCurrentWikiReference() } @Override - public boolean containsKey(String key) + protected boolean containsKeyInternal(String key) { XWikiContext xcontext = this.xcontextProvider.get(); @@ -254,8 +255,7 @@ protected void setBaseProperty(String propertyName, Object propertyValue, BaseOb // Convert boolean into integer if the target property is of boolean type, since booleans are implemented // as integer in xproperties. Object normalizedPropertyValue = propertyValue; - if (baseClass.get(propertyName) instanceof BooleanClass && propertyValue instanceof Boolean) - { + if (baseClass.get(propertyName) instanceof BooleanClass && propertyValue instanceof Boolean) { normalizedPropertyValue = ((Boolean) propertyValue) ? 1 : 0; } @@ -263,7 +263,13 @@ protected void setBaseProperty(String propertyName, Object propertyValue, BaseOb } @Override - public List getKeys() + protected List getKeysInternal() + { + return getKeys(""); + } + + @Override + protected List getKeysInternal(String prefix) { List keys = Collections.emptyList(); @@ -280,7 +286,7 @@ public List getKeys() for (String key : properties) { // We need to check if the key really have a value as otherwise it does not really make sense to // return it - if (containsKey(key)) { + if (key.startsWith(prefix) && containsKey(key)) { keys.add(key); } } @@ -294,12 +300,10 @@ public List getKeys() } @Override - public T getProperty(String key, T defaultValue) + protected T getPropertyInternal(String key, T defaultValue) { T result = getPropertyValue(key, defaultValue != null ? (Class) defaultValue.getClass() : null); - // Make sure we don't return null values for List and Properties (they must return empty elements - // when using the typed API). if (result == null) { result = defaultValue; } @@ -308,7 +312,7 @@ public T getProperty(String key, T defaultValue) } @Override - public T getProperty(String key, Class valueClass) + protected T getPropertyInternal(String key, Class valueClass) { T result = getPropertyValue(key, valueClass); @@ -321,9 +325,19 @@ public T getProperty(String key, Class valueClass) return result; } + @Override + protected T getPropertyInternal(String key, Class valueClass, T defaultValue) + { + if (containsKey(key)) { + return getPropertyInternal(key, valueClass); + } + + return defaultValue; + } + @Override @SuppressWarnings("unchecked") - public T getProperty(String key) + protected T getPropertyInternal(String key) { return (T) getPropertyValue(key, null); } @@ -354,8 +368,9 @@ protected T getPropertyValue(String key, Class valueClass) // Void.TYPE is used to keep track of fields that don't exist this.cache.set(cacheKey, result == null ? Void.TYPE : result); } catch (XWikiException e) { - this.logger.error("Failed to access configuration value for property [{}]. Ignoring by returning " - + "null", key, e); + this.logger.error( + "Failed to access configuration value for property [{}]. Ignoring by returning " + "null", key, + e); } } } @@ -369,11 +384,17 @@ protected T getPropertyValue(String key, Class valueClass) } @Override - public boolean isEmpty() + protected boolean isEmptyInternal() { return getKeys().isEmpty(); } + @Override + protected boolean isEmptyInternal(String prefix) + { + return getKeys(prefix).isEmpty(); + } + @Override public void setProperty(String key, Object value) throws ConfigurationSaveException { @@ -397,13 +418,14 @@ public void setProperties(Map properties) throws ConfigurationSa setBaseProperty(entry.getKey(), entry.getValue(), baseObject, baseClass); setPropertyNames.add(entry.getKey()); } - xcontext.getWiki().saveDocument(modifiedDocument, String.format("Set properties: %s", - StringUtils.join(setPropertyNames, ',')), xcontext); + xcontext.getWiki().saveDocument(modifiedDocument, + String.format("Set properties: %s", StringUtils.join(setPropertyNames, ',')), xcontext); } } catch (Exception e) { - throw new ConfigurationSaveException(String.format("Failed to set properties [%s] in document [%s]'s [%s] " - + "xobject", getPropertyListAsString(properties), getFailsafeClassReference(), - getFailsafeClassReference()), e); + throw new ConfigurationSaveException( + String.format("Failed to set properties [%s] in document [%s]'s [%s] " + "xobject", + getPropertyListAsString(properties), getFailsafeClassReference(), getFailsafeClassReference()), + e); } } diff --git a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/AbstractSpacesConfigurationSource.java b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/AbstractSpacesConfigurationSource.java index b7cb75d7190d..e05c2d6677f8 100644 --- a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/AbstractSpacesConfigurationSource.java +++ b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/AbstractSpacesConfigurationSource.java @@ -163,6 +163,17 @@ public List getKeys() } } + @Override + public List getKeys(String prefix) + { + XWikiDocument currentDocument = setCurrentDocument(getDocument()); + try { + return getSpaceConfigurationSource().getKeys(prefix); + } finally { + setCurrentDocument(currentDocument); + } + } + @Override public boolean containsKey(String key) { @@ -184,6 +195,17 @@ public boolean isEmpty() setCurrentDocument(currentDocument); } } + + @Override + public boolean isEmpty(String prefix) + { + XWikiDocument currentDocument = setCurrentDocument(getDocument()); + try { + return getSpaceConfigurationSource().isEmpty(prefix); + } finally { + setCurrentDocument(currentDocument); + } + } } @Override diff --git a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/AbstractWikisConfigurationSource.java b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/AbstractWikisConfigurationSource.java index 1585175ca5cd..f2eba7aa4f1e 100644 --- a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/AbstractWikisConfigurationSource.java +++ b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/AbstractWikisConfigurationSource.java @@ -61,37 +61,49 @@ private class WikiConfigurationSource implements ConfigurationSource @Override public boolean containsKey(String key) { - return getFromWiki(() -> AbstractWikisConfigurationSource.super.containsKey(key)); + return getFromWiki(() -> AbstractWikisConfigurationSource.super.containsKeyInternal(key)); } @Override public List getKeys() { - return getFromWiki(() -> AbstractWikisConfigurationSource.super.getKeys()); + return getFromWiki(() -> AbstractWikisConfigurationSource.super.getKeysInternal()); + } + + @Override + public List getKeys(String prefix) + { + return getFromWiki(() -> AbstractWikisConfigurationSource.super.getKeysInternal(prefix)); } @Override public T getProperty(String key) { - return getFromWiki(() -> AbstractWikisConfigurationSource.super.getProperty(key)); + return getFromWiki(() -> AbstractWikisConfigurationSource.super.getPropertyInternal(key)); } @Override public T getProperty(String key, T defaultValue) { - return getFromWiki(() -> AbstractWikisConfigurationSource.super.getProperty(key, defaultValue)); + return getFromWiki(() -> AbstractWikisConfigurationSource.super.getPropertyInternal(key, defaultValue)); } @Override public T getProperty(String key, Class valueClass) { - return getFromWiki(() -> AbstractWikisConfigurationSource.super.getProperty(key, valueClass)); + return getFromWiki(() -> AbstractWikisConfigurationSource.super.getPropertyInternal(key, valueClass)); } @Override public boolean isEmpty() { - return getFromWiki(() -> AbstractWikisConfigurationSource.super.isEmpty()); + return getFromWiki(() -> AbstractWikisConfigurationSource.super.isEmptyInternal()); + } + + @Override + public boolean isEmpty(String prefix) + { + return getFromWiki(() -> AbstractWikisConfigurationSource.super.isEmptyInternal(prefix)); } private T getFromWiki(Supplier supplier) @@ -119,41 +131,53 @@ protected DocumentReference getDocumentReference() } @Override - public boolean containsKey(String key) + protected boolean containsKeyInternal(String key) { return getConfigurationSource().containsKey(key); } @Override - public List getKeys() + protected List getKeysInternal() { return getConfigurationSource().getKeys(); } @Override - public T getProperty(String key) + protected List getKeysInternal(String prefix) + { + return getConfigurationSource().getKeys(prefix); + } + + @Override + protected T getPropertyInternal(String key) { return getConfigurationSource().getProperty(key); } @Override - public T getProperty(String key, T defaultValue) + protected T getPropertyInternal(String key, T defaultValue) { return getConfigurationSource().getProperty(key, defaultValue); } @Override - public T getProperty(String key, Class valueClass) + protected T getPropertyInternal(String key, Class valueClass) { return getConfigurationSource().getProperty(key, valueClass); } @Override - public boolean isEmpty() + protected boolean isEmptyInternal() { return getConfigurationSource().isEmpty(); } + @Override + protected boolean isEmptyInternal(String prefix) + { + return getConfigurationSource().isEmpty(prefix); + } + private ConfigurationSource getConfigurationSource() { CompositeConfigurationSource compositeConfigSource = new CompositeConfigurationSource(); diff --git a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/CompositeConfigurationSource.java b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/CompositeConfigurationSource.java deleted file mode 100644 index a208585087e0..000000000000 --- a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/CompositeConfigurationSource.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * - * This is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this software; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA, or see the FSF site: http://www.fsf.org. - */ -package org.xwiki.configuration.internal; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.xwiki.configuration.ConfigurationSource; - -/** - * Allows composing (aka chaining) several Configuration Sources. The order of sources is important. Sources located - * before other sources take priority. - * - * @version $Id$ - * @since 2.0M1 - */ -public class CompositeConfigurationSource extends AbstractCompositeConfigurationSource -{ - /** - * The order of sources is important. Sources located before other sources take priority. - */ - protected List sources = new ArrayList(); - - public void addConfigurationSource(ConfigurationSource source) - { - this.sources.add(source); - } - - @Override - public Iterator iterator() - { - return this.sources.iterator(); - } -} diff --git a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/PermanentConfigurationSource.java b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/PermanentConfigurationSource.java index c1ccf884f0d4..b69491d29e00 100644 --- a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/PermanentConfigurationSource.java +++ b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/PermanentConfigurationSource.java @@ -37,7 +37,6 @@ import org.apache.commons.configuration2.ex.ConfigurationException; import org.apache.commons.io.FileUtils; import org.xwiki.component.annotation.Component; -import org.xwiki.component.phase.Initializable; import org.xwiki.component.phase.InitializationException; import org.xwiki.configuration.ConfigurationSaveException; import org.xwiki.environment.Environment; @@ -53,7 +52,7 @@ @Component @Named("permanent") @Singleton -public class PermanentConfigurationSource extends CommonsConfigurationSource implements Initializable +public class PermanentConfigurationSource extends AbstractCommonsConfigurationSource { private static final String XWIKI_PROPERTIES_FILE = "configuration.properties"; @@ -68,6 +67,8 @@ public class PermanentConfigurationSource extends CommonsConfigurationSource imp @Override public void initialize() throws InitializationException { + super.initialize(); + setConfiguration(loadConfiguration()); } diff --git a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/RestrictedConfigurationSource.java b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/RestrictedConfigurationSource.java index 38012689b99b..2a750c3d1d8d 100644 --- a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/RestrictedConfigurationSource.java +++ b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/RestrictedConfigurationSource.java @@ -34,7 +34,7 @@ *
  • xwiki properties file (xwiki.properties)
  • * * If you need to use a Configuration source that can find its configuration in the wiki you should consider using - * either {@link DefaultConfigurationSource} or {@link AllConfigurationSource}. + * either {@link SystemConfigurationSource} or {@link AllConfigurationSource}. * * @version $Id$ * @since 4.1M2 diff --git a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/XWikiPropertiesConfigurationSource.java b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/XWikiPropertiesConfigurationSource.java index eb9e848f85d6..3d9b3d2ea811 100644 --- a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/XWikiPropertiesConfigurationSource.java +++ b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/main/java/org/xwiki/configuration/internal/XWikiPropertiesConfigurationSource.java @@ -34,7 +34,6 @@ import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler; import org.slf4j.Logger; import org.xwiki.component.annotation.Component; -import org.xwiki.component.phase.Initializable; import org.xwiki.component.phase.InitializationException; import org.xwiki.environment.Environment; @@ -47,7 +46,7 @@ @Component @Named("xwikiproperties") @Singleton -public class XWikiPropertiesConfigurationSource extends CommonsConfigurationSource implements Initializable +public class XWikiPropertiesConfigurationSource extends AbstractCommonsConfigurationSource { private static final String XWIKI_PROPERTIES_FILE = "xwiki.properties"; @@ -68,6 +67,8 @@ public class XWikiPropertiesConfigurationSource extends CommonsConfigurationSour @Override public void initialize() throws InitializationException { + super.initialize(); + setConfiguration(loadConfiguration()); } diff --git a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/CommonsConfigurationSourceTest.java b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/CommonsConfigurationSourceTest.java index e3af8dc53756..824e27e9dfa3 100644 --- a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/CommonsConfigurationSourceTest.java +++ b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/CommonsConfigurationSourceTest.java @@ -20,6 +20,7 @@ package org.xwiki.configuration.internal; import java.awt.Color; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Properties; @@ -34,6 +35,7 @@ import org.xwiki.properties.ConverterManager; import org.xwiki.test.annotation.AllComponents; import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectMockComponents; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -42,7 +44,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; /** - * Unit tests for {@link CommonsConfigurationSource}. + * Unit tests for {@link AbstractCommonsConfigurationSource}. * * @version $Id$ * @since 2.0M1 @@ -51,14 +53,19 @@ @AllComponents class CommonsConfigurationSourceTest { - private Configuration configuration; + public static class TestCommonsConfigurationSource extends AbstractCommonsConfigurationSource + { - private CommonsConfigurationSource source; + } + + @InjectMockComponents + private TestCommonsConfigurationSource source; + + private Configuration configuration; @BeforeEach void setUp(ComponentManager componentManager) throws Exception { - this.source = new CommonsConfigurationSource(); ConverterManager converterManager = componentManager.getInstance(ConverterManager.class); ReflectionUtils.setFieldValue(this.source, "converterManager", converterManager); this.configuration = new BaseConfiguration(); @@ -103,8 +110,8 @@ void stringPropertyWhenConversionError() this.configuration.setProperty("string", "value"); // Try to retrieve a String property as a Boolean - Exception exception = assertThrows(ConversionException.class, - () -> this.source.getProperty("string", Boolean.class)); + Exception exception = + assertThrows(ConversionException.class, () -> this.source.getProperty("string", Boolean.class)); assertEquals("Key [string] is not compatible with type [java.lang.Boolean]", exception.getMessage()); } @@ -114,8 +121,8 @@ void booleanPropertyWhenConversionError() this.configuration.setProperty("property", ""); // Try to retrieve a String property as a Color - Exception exception = assertThrows(ConversionException.class, - () -> this.source.getProperty("property", Color.class)); + Exception exception = + assertThrows(ConversionException.class, () -> this.source.getProperty("property", Color.class)); assertEquals("Key [property] is not compatible with type [java.awt.Color]", exception.getMessage()); } @@ -157,7 +164,7 @@ void testListPropertyWhenArrayList() this.configuration.setProperty("list", "value"); List expected = Arrays.asList("value"); - assertEquals(expected, this.source.getProperty("list", Arrays.asList("default"))); + assertEquals(expected, this.source.getProperty("list", new ArrayList<>(Arrays.asList("default")))); } @Test @@ -179,10 +186,30 @@ void propertiesProperty() @Test void isEmpty() { - assertTrue(this.configuration.isEmpty()); + assertTrue(this.source.isEmpty()); this.configuration.addProperty("properties", "key2=value2"); - assertFalse(this.configuration.isEmpty()); + assertFalse(this.source.isEmpty()); + assertTrue(this.source.isEmpty("k")); + + this.configuration.addProperty("key", "value"); + + assertFalse(this.source.isEmpty("k")); + } + + @Test + void getKeys() + { + assertEquals(List.of(), this.source.getKeys()); + + this.configuration.addProperty("properties", "key2=value2"); + + assertEquals(List.of("properties"), this.source.getKeys()); + assertEquals(List.of(), this.source.getKeys("k")); + + this.configuration.addProperty("key", "value"); + + assertEquals(List.of("key"), this.source.getKeys("k")); } } diff --git a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/CompositeConfigurationSourceTest.java b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/CompositeConfigurationSourceTest.java index def946e030c7..4febc5078e2f 100644 --- a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/CompositeConfigurationSourceTest.java +++ b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/CompositeConfigurationSourceTest.java @@ -23,14 +23,15 @@ import java.util.List; import java.util.Properties; -import org.apache.commons.configuration2.Configuration; -import org.apache.commons.configuration2.PropertiesConfiguration; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.xwiki.component.util.ReflectionUtils; -import org.xwiki.properties.ConverterManager; -import org.xwiki.test.jmock.AbstractComponentTestCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.xwiki.test.annotation.AllComponents; +import org.xwiki.test.junit5.mockito.ComponentTest; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * Unit tests for {@link CompositeConfigurationSource}. @@ -38,123 +39,112 @@ * @version $Id$ * @since 2.0M1 */ -public class CompositeConfigurationSourceTest extends AbstractComponentTestCase +@ComponentTest +@AllComponents +class CompositeConfigurationSourceTest { - private CompositeConfigurationSource composite; + private MapConfigurationSource config1 = new MapConfigurationSource(); - private Configuration config1; + private MapConfigurationSource config2 = new MapConfigurationSource(); - private Configuration config2; + private CompositeConfigurationSource composite; - @Override - @Before - public void setUp() throws Exception + @BeforeEach + void beforeEach() { - super.setUp(); this.composite = new CompositeConfigurationSource(); - ConverterManager converterManager = getComponentManager().getInstance(ConverterManager.class); - - CommonsConfigurationSource source1 = new CommonsConfigurationSource(); - ReflectionUtils.setFieldValue(source1, "converterManager", converterManager); - this.config1 = new PropertiesConfiguration(); - source1.setConfiguration(this.config1); - this.composite.addConfigurationSource(source1); - - CommonsConfigurationSource source2 = new CommonsConfigurationSource(); - ReflectionUtils.setFieldValue(source2, "converterManager", converterManager); - this.config2 = new PropertiesConfiguration(); - source2.setConfiguration(this.config2); - this.composite.addConfigurationSource(source2); + this.composite.addConfigurationSource(this.config1); + this.composite.addConfigurationSource(this.config2); } @Test - public void testContainsKey() + void testContainsKey() { - config1.setProperty("key1", "value1"); - config1.setProperty("key3", "value3"); - config2.setProperty("key2", "value2"); - config2.setProperty("key3", "value3"); - - Assert.assertTrue(composite.containsKey("key1")); - Assert.assertTrue(composite.containsKey("key2")); - Assert.assertTrue(composite.containsKey("key3")); - Assert.assertFalse(composite.containsKey("unknown")); + this.config1.setProperty("key1", "value1"); + this.config1.setProperty("key3", "value3"); + this.config2.setProperty("key2", "value2"); + this.config2.setProperty("key3", "value3"); + + assertTrue(this.composite.containsKey("key1")); + assertTrue(this.composite.containsKey("key2")); + assertTrue(this.composite.containsKey("key3")); + assertFalse(this.composite.containsKey("unknown")); } @Test - public void testGetProperty() + void testGetProperty() { - config1.setProperty("key1", "value1"); - config1.setProperty("key3", "value3"); - config2.setProperty("key2", "value2"); - config2.setProperty("key3", "value3"); - - Assert.assertEquals("value1", composite.getProperty("key1")); - Assert.assertEquals("value2", composite.getProperty("key2")); - Assert.assertEquals("value3", composite.getProperty("key3")); - Assert.assertNull(composite.getProperty("unknown")); + this.config1.setProperty("key1", "value1"); + this.config1.setProperty("key3", "value3"); + this.config2.setProperty("key2", "value2"); + this.config2.setProperty("key3", "value3"); + + assertEquals("value1", this.composite.getProperty("key1")); + assertEquals("value2", this.composite.getProperty("key2")); + assertEquals("value3", this.composite.getProperty("key3")); + assertNull(this.composite.getProperty("unknown")); } @Test - public void testGetPropertyWithClass() + void testGetPropertyWithClass() { - config1.setProperty("key1", "value1"); - config1.setProperty("key3", "value3"); - config2.setProperty("key2", "value2"); - config2.setProperty("key3", "value3"); - - Assert.assertEquals("value1", composite.getProperty("key1", String.class)); - Assert.assertEquals("value2", composite.getProperty("key2", String.class)); - Assert.assertEquals("value3", composite.getProperty("key3", String.class)); - Assert.assertNull(composite.getProperty("unknown", String.class)); + this.config1.setProperty("key1", "value1"); + this.config1.setProperty("key3", "value3"); + this.config2.setProperty("key2", "value2"); + this.config2.setProperty("key3", "value3"); + + assertEquals("value1", this.composite.getProperty("key1", String.class)); + assertEquals("value2", this.composite.getProperty("key2", String.class)); + assertEquals("value3", this.composite.getProperty("key3", String.class)); + assertNull(this.composite.getProperty("unknown", String.class)); } @Test - public void testGetPropertyWithDefaultValue() + void testGetPropertyWithDefaultValue() { - config1.setProperty("key1", "value1"); - config1.setProperty("key3", "value3"); - config2.setProperty("key2", "value2"); - config2.setProperty("key3", "value3"); - - Assert.assertEquals("value1", composite.getProperty("key1", "default")); - Assert.assertEquals("value2", composite.getProperty("key2", "default")); - Assert.assertEquals("value3", composite.getProperty("key3", "default")); - Assert.assertEquals("default", composite.getProperty("unknown", "default")); + this.config1.setProperty("key1", "value1"); + this.config1.setProperty("key3", "value3"); + this.config2.setProperty("key2", "value2"); + this.config2.setProperty("key3", "value3"); + + assertEquals("value1", this.composite.getProperty("key1", "default")); + assertEquals("value2", this.composite.getProperty("key2", "default")); + assertEquals("value3", this.composite.getProperty("key3", "default")); + assertEquals("default", this.composite.getProperty("unknown", "default")); } @Test - public void testGetKeys() + void testGetKeys() { - config1.setProperty("key1", "value1"); - config2.setProperty("key2", "value2"); + this.config1.setProperty("key1", "value1"); + this.config2.setProperty("key2", "value2"); List expected = Arrays.asList("key1", "key2"); - Assert.assertEquals(expected, composite.getKeys()); + assertEquals(expected, this.composite.getKeys()); } @Test - public void testIsEmpty() + void testIsEmpty() { - Assert.assertTrue(composite.isEmpty()); + assertTrue(this.composite.isEmpty()); - config2.setProperty("key", "value"); - Assert.assertFalse(composite.isEmpty()); + this.config2.setProperty("key", "value"); + assertFalse(this.composite.isEmpty()); } @Test - public void testGetPropertiesAndListsWhenEmpty() + void testGetPropertiesAndListsWhenEmpty() { - Assert.assertTrue(composite.getProperty("unknown", Properties.class).isEmpty()); - Assert.assertTrue(composite.getProperty("unknown", List.class).isEmpty()); + assertTrue(this.composite.getProperty("unknown", Properties.class).isEmpty()); + assertTrue(this.composite.getProperty("unknown", List.class).isEmpty()); } @Test - public void testTypeConversionsWhenDefaultValuesAreNotUsed() + void testTypeConversionsWhenDefaultValuesAreNotUsed() { - config1.setProperty("key1", "true"); + this.config1.setProperty("key1", "true"); // Default value is not used since the property exists and is converted to boolean automatically - Assert.assertTrue(composite.getProperty("key1", false)); + assertTrue(this.composite.getProperty("key1", false)); } } diff --git a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/DefaultConfigurationSourceTest.java b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/DefaultConfigurationSourceTest.java index 11b983c0c696..43a2e41d3a60 100644 --- a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/DefaultConfigurationSourceTest.java +++ b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/DefaultConfigurationSourceTest.java @@ -32,7 +32,7 @@ import static org.mockito.Mockito.*; /** - * Unit tests for {@link DefaultConfigurationSource}. + * Unit tests for {@link SystemConfigurationSource}. * * @version $Id$ * @since 6.1M2 diff --git a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/PermanentConfigurationSourceTest.java b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/PermanentConfigurationSourceTest.java index afa91f9d4794..fea9d79f9df7 100644 --- a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/PermanentConfigurationSourceTest.java +++ b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/PermanentConfigurationSourceTest.java @@ -21,7 +21,6 @@ import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.Map; @@ -29,8 +28,11 @@ import javax.inject.Inject; +import jakarta.inject.Named; + import org.junit.jupiter.api.Test; import org.xwiki.configuration.ConfigurationSaveException; +import org.xwiki.configuration.ConfigurationSource; import org.xwiki.environment.Environment; import org.xwiki.properties.ConverterManager; import org.xwiki.test.TestEnvironment; @@ -55,17 +57,21 @@ class PermanentConfigurationSourceTest @Inject private Environment environment; + @MockComponent + @Named("system") + private ConfigurationSource configurationSource; + @InjectMockComponents private PermanentConfigurationSource configuration; @MockComponent private ConverterManager converter; - private void assertEqualProperties(Map expect) throws FileNotFoundException, IOException + private void assertEqualProperties(Map expect) throws IOException { Properties properties = new Properties(); try (InputStream stream = - new FileInputStream(new File(environment.getPermanentDirectory(), "configuration.properties"))) { + new FileInputStream(new File(this.environment.getPermanentDirectory(), "configuration.properties"))) { properties.load(stream); } @@ -73,7 +79,7 @@ private void assertEqualProperties(Map expect) throws FileNotFou } @Test - void initialize() throws FileNotFoundException, IOException + void initialize() throws IOException { File file = new File(this.environment.getPermanentDirectory(), "configuration.properties"); @@ -84,7 +90,7 @@ void initialize() throws FileNotFoundException, IOException } @Test - void setProperty() throws ConfigurationSaveException, FileNotFoundException, IOException + void setProperty() throws ConfigurationSaveException, IOException { this.configuration.setProperty("prop1", "value1"); @@ -106,7 +112,7 @@ void setProperty() throws ConfigurationSaveException, FileNotFoundException, IOE } @Test - void setProperties() throws ConfigurationSaveException, FileNotFoundException, IOException + void setProperties() throws ConfigurationSaveException, IOException { when(this.converter.convert(String.class, this)).thenReturn("OK"); diff --git a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/SpacePreferencesConfigurationSourceTest.java b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/SpacePreferencesConfigurationSourceTest.java index 9c933bfbaaaa..fd7dfbbe66af 100644 --- a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/SpacePreferencesConfigurationSourceTest.java +++ b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/SpacePreferencesConfigurationSourceTest.java @@ -19,8 +19,7 @@ */ package org.xwiki.configuration.internal; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.when; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -32,8 +31,15 @@ import org.xwiki.test.junit5.mockito.InjectMockComponents; import org.xwiki.test.junit5.mockito.MockComponent; +import com.xpn.xwiki.XWikiException; import com.xpn.xwiki.test.junit5.mockito.OldcoreTest; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.when; + /** * Unit tests for {@link SpacePreferencesConfigurationSource}. * @@ -74,8 +80,37 @@ protected LocalDocumentReference getClassReference() @Test void getPropertyForStringWhenExists() throws Exception { + assertNull(this.source.getProperty("key", String.class)); + setStringProperty(SPACE_DOCUMENT, "key", "value"); assertEquals("value", this.source.getProperty("key", String.class)); } + + @Test + void getKeys() throws XWikiException + { + assertEquals(List.of(), this.source.getKeys()); + assertEquals(List.of(), this.source.getKeys("prefix")); + + setStringProperty(SPACE_DOCUMENT, "key", "value"); + setStringProperty(SPACE_DOCUMENT, "prefixkey", "value2"); + + assertEquals(List.of("prefixkey", "key"), this.source.getKeys()); + assertEquals(List.of("prefixkey"), this.source.getKeys("prefix")); + } + + @Test + void isEmpty() throws XWikiException + { + assertTrue(this.source.isEmpty()); + assertTrue(this.source.isEmpty("prefix")); + + setStringProperty(SPACE_DOCUMENT, "key", "value"); + setStringProperty(SPACE_DOCUMENT, "prefixkey", "value2"); + + assertFalse(this.source.isEmpty()); + assertFalse(this.source.isEmpty("prefix")); + assertTrue(this.source.isEmpty("otherprefix")); + } } diff --git a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/SpacesConfigurationSourceTest.java b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/SpacesConfigurationSourceTest.java index 0cc4d3e41010..cc3d22e64ab5 100644 --- a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/SpacesConfigurationSourceTest.java +++ b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/SpacesConfigurationSourceTest.java @@ -19,13 +19,11 @@ */ package org.xwiki.configuration.internal; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import javax.inject.Named; import javax.inject.Provider; @@ -49,8 +47,6 @@ import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.when; /** @@ -61,17 +57,30 @@ @ComponentTest class SpacesConfigurationSourceTest { + private static final WikiReference WIKI_REFERENCE = new WikiReference("wiki"); + + private static final SpaceReference SPACE_REFERENCE = new SpaceReference("space1", WIKI_REFERENCE); + + private static final SpaceReference SUBSPACE_REFERENCE = new SpaceReference("space2", SPACE_REFERENCE); + @InjectMockComponents private SpacesConfigurationSource spacesSource; @MockComponent private Provider xcontextProvider; - + @MockComponent @Named("space") private ConfigurationSource spaceConfiguration; - - private Map> spacesPreferences = new HashMap<>(); + + private final MapConfigurationSource spaceMap = new MapConfigurationSource(); + + private final MapConfigurationSource subSpaceMap = new MapConfigurationSource(); + + private final MapConfigurationSource noMap = new MapConfigurationSource(); + + private final Map spaceConfigurations = + Map.of(SPACE_REFERENCE, this.spaceMap, SUBSPACE_REFERENCE, this.subSpaceMap); private XWikiContext xcontext; @@ -80,91 +89,75 @@ void before() { this.xcontext = new XWikiContext(); when(this.xcontextProvider.get()).thenReturn(this.xcontext); - when(this.spaceConfiguration.getProperty(any(), same(String.class))).then((Answer) invocation -> { - Map spacePreferences = getSpacePreferences(); - if (spacePreferences != null) { - return spacePreferences.get(invocation.getArgument(0)); - } - return null; + + when(this.spaceConfiguration.getProperty(any())).then((Answer) invocation -> { + return getSpaceConfiguration().getProperty(invocation.getArgument(0)); }); - when(spaceConfiguration.getProperty(any())).then(invocation -> { - Map spacePreferences = getSpacePreferences(); - if (spacePreferences != null) { - return spacePreferences.get(invocation.getArgument(0)); - } - return null; + when(this.spaceConfiguration.getProperty(any(), any(Object.class))).then((Answer) invocation -> { + return getSpaceConfiguration().getProperty(invocation.getArgument(0), invocation.getArgument(1)); }); - when(spaceConfiguration.getProperty(any(), anyString())).then(invocation -> { - Map spacePreferences = getSpacePreferences(); - if (spacePreferences != null) { - String key = invocation.getArgument(0); - if (spacePreferences.containsKey(key)) { - return spacePreferences.get(key); - } - } - return invocation.getArgument(1); + when(this.spaceConfiguration.getProperty(any(), any(Class.class))).then((Answer) invocation -> { + return getSpaceConfiguration().getProperty(invocation.getArgument(0), invocation.>getArgument(1)); }); - when(spaceConfiguration.containsKey(any())).then((Answer) invocation -> { - Map spacePreferences = getSpacePreferences(); - if (spacePreferences != null) { - return spacePreferences.containsKey(invocation.getArgument(0)); - } - return false; + when(this.spaceConfiguration.getProperty(any(), any(), any())).then((Answer) invocation -> { + return getSpaceConfiguration().getProperty(invocation.getArgument(0), invocation.getArgument(1), + invocation.getArgument(2)); }); - when(spaceConfiguration.getKeys()).then((Answer>) invocation -> { - Map spacePreferences = getSpacePreferences(); - if (spacePreferences != null) { - return new ArrayList<>(spacePreferences.keySet()); - } - return Collections.emptyList(); + when(this.spaceConfiguration.containsKey(any())).then((Answer) invocation -> { + return getSpaceConfiguration().containsKey(invocation.getArgument(0)); }); - when(spaceConfiguration.isEmpty()).then((Answer) invocation -> { - Map spacePreferences = getSpacePreferences(); - if (spacePreferences != null) { - return spacePreferences.isEmpty(); - } - return true; + when(this.spaceConfiguration.getKeys()).then((Answer>) invocation -> { + return getSpaceConfiguration().getKeys(); + }); + when(this.spaceConfiguration.getKeys(any())).then((Answer>) invocation -> { + return getSpaceConfiguration().getKeys(invocation.getArgument(0)); + }); + when(this.spaceConfiguration.isEmpty()).then((Answer) invocation -> { + return getSpaceConfiguration().isEmpty(); }); + when(this.spaceConfiguration.isEmpty(any())).then((Answer) invocation -> { + return getSpaceConfiguration().isEmpty(invocation.getArgument(0)); + }); + + this.spaceMap.setProperty("pref", "prefvalue1"); + this.spaceMap.setProperty("pref1", "pref1value1"); + this.subSpaceMap.setProperty("pref", "prefvalue2"); + this.subSpaceMap.setProperty("pref2", "pref2value2"); } - private Map getSpacePreferences() + private ConfigurationSource getSpaceConfiguration() { - if (xcontext.getDoc() != null) { - return spacesPreferences.get(xcontext.getDoc().getDocumentReference().getParent().getName()); + if (this.xcontext.getDoc() != null) { + MapConfigurationSource map = + this.spaceConfigurations.get(this.xcontext.getDoc().getDocumentReference().getParent()); + if (map != null) { + return map; + } } - return null; + return this.noMap; + } + + private void switchTo(SpaceReference reference) + { + this.xcontext.setDoc(new XWikiDocument(new DocumentReference("document", reference))); } + private void assertKeys(Set expected, List actual) + { + assertEquals(expected, new HashSet<>(actual)); + } + @Test void containsKey() { - WikiReference wikiReference = new WikiReference("wiki"); - SpaceReference space1Reference = new SpaceReference("space1", wikiReference); - SpaceReference space2Reference = new SpaceReference("space2", space1Reference); - - Map space1Preferences = new LinkedHashMap<>(); - space1Preferences.put("pref", "prefvalue1"); - space1Preferences.put("pref1", "pref1value1"); - Map space2Preferences = new LinkedHashMap<>(); - space2Preferences.put("pref", "prefvalue2"); - space2Preferences.put("pref2", "pref2value2"); - this.spacesPreferences.put(space1Reference.getName(), space1Preferences); - this.spacesPreferences.put(space2Reference.getName(), space2Preferences); - - // Tests - - assertTrue(this.spacesSource.isEmpty()); assertFalse(this.spacesSource.containsKey("nopref")); - assertEquals(Arrays.asList(), this.spacesSource.getKeys()); assertNull(this.spacesSource.getProperty("nopref")); assertNull(this.spacesSource.getProperty("nopref", String.class)); assertEquals("defaultvalue", this.spacesSource.getProperty("nopref", "defaultvalue")); - this.xcontext.setDoc(new XWikiDocument(new DocumentReference("document", space1Reference))); - assertFalse(this.spacesSource.isEmpty()); + switchTo(SPACE_REFERENCE); assertFalse(this.spacesSource.containsKey("nopref")); - assertEquals(Arrays.asList("pref", "pref1"), this.spacesSource.getKeys()); assertNull(this.spacesSource.getProperty("nopref")); assertNull(this.spacesSource.getProperty("nopref", String.class)); assertEquals("defaultvalue", this.spacesSource.getProperty("nopref", "defaultvalue")); @@ -178,10 +171,8 @@ void containsKey() assertFalse(this.spacesSource.containsKey("pref2")); assertNull(this.spacesSource.getProperty("pref2")); - this.xcontext.setDoc(new XWikiDocument(new DocumentReference("document", space2Reference))); - assertFalse(this.spacesSource.isEmpty()); + switchTo(SUBSPACE_REFERENCE); assertFalse(this.spacesSource.containsKey("nopref")); - assertEquals(Arrays.asList("pref", "pref2", "pref1"), this.spacesSource.getKeys()); assertNull(this.spacesSource.getProperty("nopref")); assertNull(this.spacesSource.getProperty("nopref", String.class)); assertEquals("defaultvalue", this.spacesSource.getProperty("nopref", "defaultvalue")); @@ -195,4 +186,41 @@ void containsKey() assertTrue(this.spacesSource.containsKey("pref2")); assertEquals("pref2value2", this.spacesSource.getProperty("pref2")); } + + @Test + void isEmpty() + { + assertTrue(this.spacesSource.isEmpty()); + assertTrue(this.spacesSource.isEmpty("pref1")); + assertTrue(this.spacesSource.isEmpty("other")); + + switchTo(SPACE_REFERENCE); + assertFalse(this.spacesSource.isEmpty()); + assertFalse(this.spacesSource.isEmpty("pref1")); + assertTrue(this.spacesSource.isEmpty("other")); + + switchTo(SUBSPACE_REFERENCE); + assertFalse(this.spacesSource.isEmpty()); + assertFalse(this.spacesSource.isEmpty("pref2")); + assertTrue(this.spacesSource.isEmpty("other")); + } + + @Test + void getKeys() + { + assertKeys(Set.of(), this.spacesSource.getKeys()); + assertEquals(Arrays.asList(), this.spacesSource.getKeys()); + assertEquals(Arrays.asList(), this.spacesSource.getKeys("pref")); + assertEquals(Arrays.asList(), this.spacesSource.getKeys("other")); + + switchTo(SPACE_REFERENCE); + assertKeys(Set.of("pref", "pref1"), this.spacesSource.getKeys()); + assertKeys(Set.of("pref1"), this.spacesSource.getKeys("pref1")); + assertKeys(Set.of(), this.spacesSource.getKeys("other")); + + switchTo(SUBSPACE_REFERENCE); + assertKeys(Set.of("pref", "pref2", "pref1"), this.spacesSource.getKeys()); + assertKeys(Set.of("pref2"), this.spacesSource.getKeys("pref2")); + assertKeys(Set.of(), this.spacesSource.getKeys("other")); + } } diff --git a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/WikiPreferencesConfigurationSourceTest.java b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/WikiPreferencesConfigurationSourceTest.java index c425ae073ad6..67438c339ff6 100644 --- a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/WikiPreferencesConfigurationSourceTest.java +++ b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/WikiPreferencesConfigurationSourceTest.java @@ -94,6 +94,8 @@ void getProperty() throws Exception assertEquals("default", this.source.getProperty("key", "default")); assertNull(this.source.getProperty("key")); assertNull(this.source.getProperty("key", Integer.class)); + assertNull(this.source.getProperty("key", Void.TYPE)); + assertEquals("default", this.source.getProperty("key", String.class, "default")); // Validate result for simple String key @@ -102,6 +104,7 @@ void getProperty() throws Exception assertEquals("value", this.source.getProperty("key", String.class)); assertEquals("value", this.source.getProperty("key", "default")); + assertEquals("value", this.source.getProperty("key", String.class, "default")); assertEquals("value", this.source.getProperty("key")); // Validate result for non existing key @@ -180,15 +183,23 @@ void containsKey() throws XWikiException void isEmpty() throws XWikiException { assertTrue(this.source.isEmpty()); + assertTrue(this.source.isEmpty("prefix")); setStringProperty(new DocumentReference(CURRENT_WIKI, WikiPreferencesConfigurationSource.CLASS_SPACE_NAME, WikiPreferencesConfigurationSource.CLASS_PAGE_NAME), "key", "value"); assertFalse(this.source.isEmpty()); + assertTrue(this.source.isEmpty("prefix")); + + setStringProperty(new DocumentReference(CURRENT_WIKI, WikiPreferencesConfigurationSource.CLASS_SPACE_NAME, + WikiPreferencesConfigurationSource.CLASS_PAGE_NAME), "prefixkey", "value"); + + assertFalse(this.source.isEmpty()); + assertFalse(this.source.isEmpty("prefix")); } @Test - void setProperty() throws Exception + void setProperties() throws Exception { DocumentReference reference = new DocumentReference(CURRENT_WIKI, WikiPreferencesConfigurationSource.CLASS_SPACE_NAME, WikiPreferencesConfigurationSource.CLASS_PAGE_NAME); @@ -203,14 +214,17 @@ void setProperty() throws Exception BaseClass baseClass = document.getXClass(); baseClass.addTextField("textKey", "Text Key", 30); baseClass.addBooleanField("booleanKey", "Boolean Key"); + baseClass.addTextField("othertextKey", "Text Key", 30); this.oldcore.getSpyXWiki().saveDocument(document, this.oldcore.getXWikiContext()); Map properties = new HashMap<>(); properties.put("textKey", "value"); properties.put("booleanKey", true); this.source.setProperties(properties); + this.source.setProperty("othertextKey", "othervalue"); assertEquals("value", this.source.getProperty("textKey")); + assertEquals("othervalue", this.source.getProperty("othertextKey")); // Simulate the conversion from Integer to Boolean when(this.converterManager.convert(Boolean.class, 1)).thenReturn(true); diff --git a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/WikisConfigurationSourceTest.java b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/WikisConfigurationSourceTest.java index 6b81dc3c6a71..cbc293a9f935 100644 --- a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/WikisConfigurationSourceTest.java +++ b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/WikisConfigurationSourceTest.java @@ -139,11 +139,20 @@ void getProperty() void isEmpty() throws Exception { assertFalse(this.wikisConfigSource.isEmpty()); + assertTrue(this.wikisConfigSource.isEmpty("prefix")); + assertFalse(this.wikisConfigSource.isEmpty("co")); + assertFalse(this.wikisConfigSource.isEmpty("en")); removeConfigObject(SUBWIKI_CONFIG_DOCREF); assertFalse(this.wikisConfigSource.isEmpty()); + assertTrue(this.wikisConfigSource.isEmpty("prefix")); + assertFalse(this.wikisConfigSource.isEmpty("co")); + assertFalse(this.wikisConfigSource.isEmpty("en")); removeConfigObject(MAINWIKI_CONFIG_DOCREF); assertTrue(this.wikisConfigSource.isEmpty()); + assertTrue(this.wikisConfigSource.isEmpty("prefix")); + assertTrue(this.wikisConfigSource.isEmpty("co")); + assertTrue(this.wikisConfigSource.isEmpty("en")); } } diff --git a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/XWikiPropertiesConfigurationSourceTest.java b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/XWikiPropertiesConfigurationSourceTest.java index 2ee08ed725b4..c69d05a6e44d 100644 --- a/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/XWikiPropertiesConfigurationSourceTest.java +++ b/xwiki-platform-core/xwiki-platform-configuration/xwiki-platform-configuration-default/src/test/java/org/xwiki/configuration/internal/XWikiPropertiesConfigurationSourceTest.java @@ -22,16 +22,27 @@ import java.util.Arrays; import java.util.Properties; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; +import jakarta.inject.Named; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.xwiki.component.manager.ComponentLookupException; import org.xwiki.configuration.ConfigurationSource; import org.xwiki.environment.Environment; -import org.xwiki.test.mockito.MockitoComponentMockingRule; +import org.xwiki.properties.ConverterManager; +import org.xwiki.test.LogLevel; +import org.xwiki.test.annotation.ComponentList; +import org.xwiki.test.junit5.LogCaptureExtension; +import org.xwiki.test.junit5.mockito.ComponentTest; +import org.xwiki.test.junit5.mockito.InjectComponentManager; +import org.xwiki.test.junit5.mockito.MockComponent; +import org.xwiki.test.mockito.MockitoComponentManager; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.verify; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertSame; import static org.mockito.Mockito.when; /** @@ -40,40 +51,57 @@ * @version $Id$ * @since 3.0M1 */ -public class XWikiPropertiesConfigurationSourceTest +@ComponentTest +@ComponentList(XWikiPropertiesConfigurationSource.class) +class XWikiPropertiesConfigurationSourceTest { - @Rule - public MockitoComponentMockingRule mocker = - new MockitoComponentMockingRule<>(XWikiPropertiesConfigurationSource.class); - + @MockComponent private Environment environment; - @Before - public void before() throws ComponentLookupException + @MockComponent + @Named("system") + private ConfigurationSource configurationSource; + + @MockComponent + private ConverterManager converterManager; + + @InjectComponentManager + private MockitoComponentManager componentManager; + + @RegisterExtension + LogCaptureExtension logCapture = new LogCaptureExtension(LogLevel.DEBUG); + + private ConfigurationSource getConfiguration() throws ComponentLookupException { - this.environment = this.mocker.getInstance(Environment.class); + // We cannot use @InjectMockComponents because some test need to customize the input of the initialization + return this.componentManager.getInstance(ConfigurationSource.class, "xwikiproperties"); } @Test - public void testInitializeWhenNoPropertiesFile() throws Exception + void testInitializeWhenNoPropertiesFile() throws ComponentLookupException { // Verifies that we can get a property from the source (i.e. that it's correctly initialized) - this.mocker.getComponentUnderTest().getProperty("key"); + getConfiguration().getProperty("key"); - verify(this.mocker.getMockedLogger()).debug( - "No configuration file [{}] found. Using default configuration values.", "/WEB-INF/xwiki.properties"); + ILoggingEvent logEvent = this.logCapture.getLogEvent(0); + assertSame(Level.DEBUG, logEvent.getLevel()); + assertEquals("No configuration file [{}] found. Using default configuration values.", logEvent.getMessage()); + assertEquals("/WEB-INF/xwiki.properties", logEvent.getArgumentArray()[0]); } @Test - public void testListParsing() throws ComponentLookupException + void testListParsing() throws ComponentLookupException { - when(environment.getResource("/WEB-INF/xwiki.properties")) + when(this.environment.getResource("/WEB-INF/xwiki.properties")) .thenReturn(getClass().getResource("/xwiki.properties")); - assertEquals(Arrays.asList("value1", "value2"), - this.mocker.getComponentUnderTest().getProperty("listProperty")); + ConfigurationSource configuration = getConfiguration(); - Properties properties = this.mocker.getComponentUnderTest().getProperty("propertiesProperty", Properties.class); + assertEquals(Arrays.asList("value1", "value2"), configuration.getProperty("listProperty")); + + Properties properties = configuration.getProperty("propertiesProperty", Properties.class); assertEquals("value1", properties.get("prop1")); + + this.logCapture.ignoreAllMessages(); } } diff --git a/xwiki-platform-core/xwiki-platform-mail/xwiki-platform-mail-general/src/main/java/org/xwiki/mail/internal/configuration/AbstractMailConfigClassDocumentConfigurationSource.java b/xwiki-platform-core/xwiki-platform-mail/xwiki-platform-mail-general/src/main/java/org/xwiki/mail/internal/configuration/AbstractMailConfigClassDocumentConfigurationSource.java index 32e1869ad15a..ab8fd05bd4c5 100644 --- a/xwiki-platform-core/xwiki-platform-mail/xwiki-platform-mail-general/src/main/java/org/xwiki/mail/internal/configuration/AbstractMailConfigClassDocumentConfigurationSource.java +++ b/xwiki-platform-core/xwiki-platform-mail/xwiki-platform-mail-general/src/main/java/org/xwiki/mail/internal/configuration/AbstractMailConfigClassDocumentConfigurationSource.java @@ -46,18 +46,18 @@ public abstract class AbstractMailConfigClassDocumentConfigurationSource new LocalDocumentReference(MAIL_SPACE, "MailConfig"); @Override - public T getProperty(String key, T defaultValue) + protected T getPropertyInternal(String key, T defaultValue) { T result; if (defaultValue != null) { try { if (getBaseObject() == null) { // No Mail.GeneralMailConfigClass xobject in the Mail.MailConfig document, use the default value! - result = super.getProperty(key, defaultValue); + result = super.getPropertyInternal(key, defaultValue); } else { // A Mail.GeneralMailConfigClass xobject exists in the Mail.MailConfig document, always use the // value from it. - result = super.getProperty(key, (Class) defaultValue.getClass()); + result = super.getPropertyInternal(key, (Class) defaultValue.getClass()); } } catch (XWikiException e) { this.logger.warn("Failed to access configuration property [{}]. Returning null. Root cause: [{}]", key, @@ -65,7 +65,7 @@ public T getProperty(String key, T defaultValue) result = null; } } else { - result = super.getProperty(key); + result = super.getPropertyInternal(key); } return result; } diff --git a/xwiki-platform-core/xwiki-platform-mail/xwiki-platform-mail-general/src/test/java/org/xwiki/mail/internal/configuration/GeneralMailConfigClassDocumentConfigurationSourceTest.java b/xwiki-platform-core/xwiki-platform-mail/xwiki-platform-mail-general/src/test/java/org/xwiki/mail/internal/configuration/GeneralMailConfigClassDocumentConfigurationSourceTest.java index 63ff1e5109af..7c681e0a2387 100644 --- a/xwiki-platform-core/xwiki-platform-mail/xwiki-platform-mail-general/src/test/java/org/xwiki/mail/internal/configuration/GeneralMailConfigClassDocumentConfigurationSourceTest.java +++ b/xwiki-platform-core/xwiki-platform-mail/xwiki-platform-mail-general/src/test/java/org/xwiki/mail/internal/configuration/GeneralMailConfigClassDocumentConfigurationSourceTest.java @@ -44,13 +44,13 @@ import static org.mockito.Mockito.*; /** - * Unit tests for {@link org.xwiki.mail.internal.configuration.GeneralMailConfigClassDocumentConfigurationSource}. + * Unit tests for {@link GeneralMailConfigClassDocumentConfigurationSource}. * * @version $Id$ * @since 12.4RC1 */ @ComponentTest -public class GeneralMailConfigClassDocumentConfigurationSourceTest +class GeneralMailConfigClassDocumentConfigurationSourceTest { @InjectMockComponents private GeneralMailConfigClassDocumentConfigurationSource source; diff --git a/xwiki-platform-core/xwiki-platform-oldcore/pom.xml b/xwiki-platform-core/xwiki-platform-oldcore/pom.xml index 10366bd78d44..34475c7d5873 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/pom.xml +++ b/xwiki-platform-core/xwiki-platform-oldcore/pom.xml @@ -293,7 +293,7 @@ org.xwiki.commons - xwiki-commons-configuration-api + xwiki-commons-configuration-default ${commons.version} diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/XWikiCfgConfigurationSource.java b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/XWikiCfgConfigurationSource.java index 8c737f14282d..a5aa70470fba 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/XWikiCfgConfigurationSource.java +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/internal/XWikiCfgConfigurationSource.java @@ -22,6 +22,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.InputStream; +import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.Properties; @@ -36,9 +37,8 @@ import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.xwiki.component.annotation.Component; -import org.xwiki.component.phase.Initializable; import org.xwiki.component.phase.InitializationException; -import org.xwiki.configuration.ConfigurationSource; +import org.xwiki.configuration.internal.AbstractSystemOverwriteConfigurationSource; import org.xwiki.environment.Environment; import org.xwiki.properties.ConverterManager; @@ -51,7 +51,7 @@ @Component @Named(XWikiCfgConfigurationSource.ROLEHINT) @Singleton -public class XWikiCfgConfigurationSource implements ConfigurationSource, Initializable +public class XWikiCfgConfigurationSource extends AbstractSystemOverwriteConfigurationSource { /** * The name of the JDNI variable. @@ -76,6 +76,14 @@ public class XWikiCfgConfigurationSource implements ConfigurationSource, Initial private String configurationLocation; + /** + * Enabled system configuration overwrite. + */ + public XWikiCfgConfigurationSource() + { + this.systemOverwriteEnabled = true; + } + /** * @return the location where to find the configuration */ @@ -99,6 +107,8 @@ public static String getConfigPath() @Override public void initialize() throws InitializationException { + super.initialize(); + this.configurationLocation = getConfigPath(); try (InputStream xwikicfgis = loadConfiguration()) { @@ -174,7 +184,7 @@ public Properties getProperties() // ConfigurationSource @Override - public T getProperty(String key, T defaultValue) + public T getPropertyInternal(String key, T defaultValue) { String value = getProperty(key); @@ -186,7 +196,7 @@ public T getProperty(String key, T defaultValue) } @Override - public T getProperty(String key, Class valueClass) + public T getPropertyInternal(String key, Class valueClass) { String value = getProperty(key); @@ -194,29 +204,71 @@ public T getProperty(String key, Class valueClass) } @Override - public T getProperty(String key) + protected T getPropertyInternal(String key, Class valueClass, T defaultValue) + { + String value = getProperty(key); + + if (value == null) { + return defaultValue; + } + + return convert(value, valueClass, defaultValue); + } + + @Override + public T getPropertyInternal(String key) { return (T) StringUtils.trim(this.properties.getProperty(key)); } @Override - public List getKeys() + public List getKeysInternal() { return EnumerationUtils.toList((Enumeration) this.properties.propertyNames()); } @Override - public boolean containsKey(String key) + public List getKeysInternal(String prefix) + { + List keyList = new ArrayList<>(); + + for (Enumeration keys = (Enumeration) this.properties.propertyNames(); keys + .hasMoreElements();) { + String key = keys.nextElement(); + + if (key.startsWith(prefix)) { + keyList.add(key); + } + } + + return keyList; + } + + @Override + public boolean containsKeyInternal(String key) { return this.properties.containsKey(key); } @Override - public boolean isEmpty() + public boolean isEmptyInternal() { return this.properties.isEmpty(); } + @Override + public boolean isEmptyInternal(String prefix) + { + for (Enumeration keys = (Enumeration) this.properties.propertyNames(); keys + .hasMoreElements();) { + if (keys.nextElement().startsWith(prefix)) { + return false; + } + } + + return true; + } + /** * @param properties change the internal {@link Properties} instance */ diff --git a/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/main/java/org/xwiki/user/internal/DefaultUserConfiguration.java b/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/main/java/org/xwiki/user/internal/DefaultUserConfiguration.java index 6c0bfcd14921..08adcc445096 100644 --- a/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/main/java/org/xwiki/user/internal/DefaultUserConfiguration.java +++ b/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/main/java/org/xwiki/user/internal/DefaultUserConfiguration.java @@ -25,7 +25,6 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.commons.lang3.StringUtils; import org.xwiki.component.annotation.Component; import org.xwiki.configuration.ConfigurationSource; import org.xwiki.user.UserConfiguration; @@ -79,12 +78,8 @@ public String getUserQualifierProperty() private Properties getPreferencesFor(String userName) { Properties properties = new Properties(); - // Note: We miss a CS API to get only keys matching a pattern so we have to iterate over all of them... - for (String key : this.xwikiPropertiesSource.getKeys()) { - String preferenceKey = StringUtils.substringAfter(key, PREFIX + "preferences." + userName + "."); - if (!StringUtils.isEmpty(preferenceKey)) { - properties.setProperty(preferenceKey, this.xwikiPropertiesSource.getProperty(key)); - } + for (String key : this.xwikiPropertiesSource.getKeys(PREFIX + "preferences." + userName + ".")) { + properties.setProperty(key, this.xwikiPropertiesSource.getProperty(key)); } return properties; } diff --git a/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/main/java/org/xwiki/user/internal/DefaultUserProperties.java b/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/main/java/org/xwiki/user/internal/DefaultUserProperties.java index b3a5324eb16f..6e9ab236185a 100644 --- a/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/main/java/org/xwiki/user/internal/DefaultUserProperties.java +++ b/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/main/java/org/xwiki/user/internal/DefaultUserProperties.java @@ -177,6 +177,12 @@ public List getKeys() return getConfigurationSource().getKeys(); } + @Override + public List getKeys(String prefix) + { + return getConfigurationSource().getKeys(prefix); + } + @Override public boolean containsKey(String key) { @@ -189,6 +195,12 @@ public boolean isEmpty() return getConfigurationSource().isEmpty(); } + @Override + public boolean isEmpty(String prefix) + { + return getConfigurationSource().isEmpty(prefix); + } + @Override public T getProperty(String key, Class valueClass, T defaultValue) { diff --git a/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/main/java/org/xwiki/user/internal/GuestConfigurationSource.java b/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/main/java/org/xwiki/user/internal/GuestConfigurationSource.java index 782d86fa7725..47c1db185390 100644 --- a/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/main/java/org/xwiki/user/internal/GuestConfigurationSource.java +++ b/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/main/java/org/xwiki/user/internal/GuestConfigurationSource.java @@ -25,8 +25,8 @@ import org.apache.commons.configuration2.BaseConfiguration; import org.xwiki.component.annotation.Component; -import org.xwiki.component.phase.Initializable; -import org.xwiki.configuration.internal.CommonsConfigurationSource; +import org.xwiki.component.phase.InitializationException; +import org.xwiki.configuration.internal.AbstractCommonsConfigurationSource; import org.xwiki.user.UserConfiguration; import static org.xwiki.user.internal.UserPropertyConstants.ACTIVE; @@ -43,14 +43,16 @@ @Component @Named("guestuser") @Singleton -public class GuestConfigurationSource extends CommonsConfigurationSource implements Initializable +public class GuestConfigurationSource extends AbstractCommonsConfigurationSource { @Inject private UserConfiguration userConfiguration; @Override - public void initialize() + public void initialize() throws InitializationException { + super.initialize(); + // Default preferences BaseConfiguration configuration = new BaseConfiguration(); configuration.addProperty(DISPLAY_HIDDEN_DOCUMENTS, "0"); diff --git a/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/main/java/org/xwiki/user/internal/SuperAdminConfigurationSource.java b/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/main/java/org/xwiki/user/internal/SuperAdminConfigurationSource.java index ad4c7cc24aba..f17c192491c2 100644 --- a/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/main/java/org/xwiki/user/internal/SuperAdminConfigurationSource.java +++ b/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/main/java/org/xwiki/user/internal/SuperAdminConfigurationSource.java @@ -25,8 +25,8 @@ import org.apache.commons.configuration2.BaseConfiguration; import org.xwiki.component.annotation.Component; -import org.xwiki.component.phase.Initializable; -import org.xwiki.configuration.internal.CommonsConfigurationSource; +import org.xwiki.component.phase.InitializationException; +import org.xwiki.configuration.internal.AbstractCommonsConfigurationSource; import org.xwiki.user.UserConfiguration; import static org.xwiki.user.internal.UserPropertyConstants.ACTIVE; @@ -44,14 +44,16 @@ @Component @Named("superadminuser") @Singleton -public class SuperAdminConfigurationSource extends CommonsConfigurationSource implements Initializable +public class SuperAdminConfigurationSource extends AbstractCommonsConfigurationSource { @Inject private UserConfiguration userConfiguration; @Override - public void initialize() + public void initialize() throws InitializationException { + super.initialize(); + // Default preferences BaseConfiguration configuration = new BaseConfiguration(); configuration.addProperty(DISPLAY_HIDDEN_DOCUMENTS, "1"); diff --git a/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/main/java/org/xwiki/user/internal/document/UserPreferencesConfigurationSource.java b/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/main/java/org/xwiki/user/internal/document/UserPreferencesConfigurationSource.java index 1b0c9dc8e206..9240f022cae0 100644 --- a/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/main/java/org/xwiki/user/internal/document/UserPreferencesConfigurationSource.java +++ b/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/main/java/org/xwiki/user/internal/document/UserPreferencesConfigurationSource.java @@ -30,7 +30,7 @@ import org.xwiki.component.annotation.Component; import org.xwiki.configuration.ConfigurationSaveException; import org.xwiki.configuration.ConfigurationSource; -import org.xwiki.configuration.internal.AbstractConfigurationSource; +import org.xwiki.configuration.internal.AbstractSystemOverwriteConfigurationSource; import org.xwiki.model.reference.DocumentReference; import org.xwiki.user.GuestUserReference; import org.xwiki.user.SuperAdminUserReference; @@ -48,7 +48,7 @@ @Component @Named("user") @Singleton -public class UserPreferencesConfigurationSource extends AbstractConfigurationSource +public class UserPreferencesConfigurationSource extends AbstractSystemOverwriteConfigurationSource { @Inject @Named("normaluser") @@ -70,43 +70,55 @@ public class UserPreferencesConfigurationSource extends AbstractConfigurationSou private UserReferenceResolver userReferenceResolver; @Override - public T getProperty(String key, T defaultValue) + public T getPropertyInternal(String key, T defaultValue) { return getConfigurationSource().getProperty(key, defaultValue); } @Override - public T getProperty(String key, Class valueClass) + public T getPropertyInternal(String key, Class valueClass) { return getConfigurationSource().getProperty(key, valueClass); } @Override - public T getProperty(String key) + public T getPropertyInternal(String key) { return getConfigurationSource().getProperty(key); } @Override - public List getKeys() + public List getKeysInternal() { return getConfigurationSource().getKeys(); } @Override - public boolean containsKey(String key) + public List getKeysInternal(String prefix) + { + return getConfigurationSource().getKeys(prefix); + } + + @Override + public boolean containsKeyInternal(String key) { return getConfigurationSource().containsKey(key); } @Override - public boolean isEmpty() + public boolean isEmptyInternal() { return getConfigurationSource().isEmpty(); } @Override - public T getProperty(String key, Class valueClass, T defaultValue) + public boolean isEmptyInternal(String prefix) + { + return getConfigurationSource().isEmpty(prefix); + } + + @Override + public T getPropertyInternal(String key, Class valueClass, T defaultValue) { return getConfigurationSource().getProperty(key, valueClass, defaultValue); } diff --git a/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/test/java/org/xwiki/user/internal/GuestConfigurationSourceTest.java b/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/test/java/org/xwiki/user/internal/GuestConfigurationSourceTest.java index b347ce366064..0cb77cb30cf9 100644 --- a/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/test/java/org/xwiki/user/internal/GuestConfigurationSourceTest.java +++ b/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/test/java/org/xwiki/user/internal/GuestConfigurationSourceTest.java @@ -21,7 +21,10 @@ import java.util.Properties; +import jakarta.inject.Named; + import org.junit.jupiter.api.Test; +import org.xwiki.configuration.ConfigurationSource; import org.xwiki.test.annotation.BeforeComponent; import org.xwiki.test.junit5.mockito.ComponentTest; import org.xwiki.test.junit5.mockito.InjectMockComponents; @@ -37,8 +40,12 @@ * @version $Id$ */ @ComponentTest -public class GuestConfigurationSourceTest +class GuestConfigurationSourceTest { + @MockComponent + @Named("system") + private ConfigurationSource configurationSource; + @InjectMockComponents private GuestConfigurationSource source; @@ -46,7 +53,7 @@ public class GuestConfigurationSourceTest private UserConfiguration userConfiguration; @BeforeComponent - public void setup() + public void beforeComponent() { when(this.userConfiguration.getGuestPreference()).thenReturn(new Properties()); } diff --git a/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/test/java/org/xwiki/user/internal/SuperAdminConfigurationSourceTest.java b/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/test/java/org/xwiki/user/internal/SuperAdminConfigurationSourceTest.java index 153a6220803c..42c2d0de2fd9 100644 --- a/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/test/java/org/xwiki/user/internal/SuperAdminConfigurationSourceTest.java +++ b/xwiki-platform-core/xwiki-platform-user/xwiki-platform-user-default/src/test/java/org/xwiki/user/internal/SuperAdminConfigurationSourceTest.java @@ -21,7 +21,10 @@ import java.util.Properties; +import jakarta.inject.Named; + import org.junit.jupiter.api.Test; +import org.xwiki.configuration.ConfigurationSource; import org.xwiki.test.annotation.BeforeComponent; import org.xwiki.test.junit5.mockito.ComponentTest; import org.xwiki.test.junit5.mockito.InjectMockComponents; @@ -37,8 +40,12 @@ * @version $Id$ */ @ComponentTest -public class SuperAdminConfigurationSourceTest +class SuperAdminConfigurationSourceTest { + @MockComponent + @Named("system") + private ConfigurationSource configurationSource; + @InjectMockComponents private SuperAdminConfigurationSource source; @@ -46,7 +53,7 @@ public class SuperAdminConfigurationSourceTest private UserConfiguration userConfiguration; @BeforeComponent - public void setup() + public void beforeComponent() { when(this.userConfiguration.getSuperAdminPreferences()).thenReturn(new Properties()); } diff --git a/xwiki-platform-core/xwiki-platform-whatsnew/xwiki-platform-whatsnew-api/src/main/java/org/xwiki/whatsnew/internal/DefaultNewsConfiguration.java b/xwiki-platform-core/xwiki-platform-whatsnew/xwiki-platform-whatsnew-api/src/main/java/org/xwiki/whatsnew/internal/DefaultNewsConfiguration.java index 7442f409b610..3d659c7384fb 100644 --- a/xwiki-platform-core/xwiki-platform-whatsnew/xwiki-platform-whatsnew-api/src/main/java/org/xwiki/whatsnew/internal/DefaultNewsConfiguration.java +++ b/xwiki-platform-core/xwiki-platform-whatsnew/xwiki-platform-whatsnew-api/src/main/java/org/xwiki/whatsnew/internal/DefaultNewsConfiguration.java @@ -132,13 +132,8 @@ private List getConfiguredNewsSourceDescriptors(Properties { List descriptors = new ArrayList<>(); // Only keep the keys related to configuring news sources, for performance. - List keys = new ArrayList<>(); String sourceKeyNamePrefix = String.format("%s.", getFullKeyName(SOURCE_CONFIG_NAME)); - for (String key : this.configurationSource.getKeys()) { - if (key.startsWith(sourceKeyNamePrefix)) { - keys.add(key); - } - } + List keys = this.configurationSource.getKeys(sourceKeyNamePrefix); for (Map.Entry entry : sources.entrySet()) { // Find all parameter properties for the defined source Map parameters = new HashMap<>(); diff --git a/xwiki-platform-core/xwiki-platform-whatsnew/xwiki-platform-whatsnew-api/src/test/java/org/xwiki/whatsnew/internal/DefaultNewsConfigurationTest.java b/xwiki-platform-core/xwiki-platform-whatsnew/xwiki-platform-whatsnew-api/src/test/java/org/xwiki/whatsnew/internal/DefaultNewsConfigurationTest.java index 08a9ef00eaa5..b35fb751f96b 100644 --- a/xwiki-platform-core/xwiki-platform-whatsnew/xwiki-platform-whatsnew-api/src/test/java/org/xwiki/whatsnew/internal/DefaultNewsConfigurationTest.java +++ b/xwiki-platform-core/xwiki-platform-whatsnew/xwiki-platform-whatsnew-api/src/test/java/org/xwiki/whatsnew/internal/DefaultNewsConfigurationTest.java @@ -105,8 +105,8 @@ void getNewsSourceDescriptorsWithParameters() data.setProperty("sourceid2", "sourcetype2"); when(this.configurationSource.containsKey("whatsnew.sources")).thenReturn(true); when(this.configurationSource.getProperty("whatsnew.sources", Properties.class)).thenReturn(data); - when(this.configurationSource.getKeys()).thenReturn(List.of("whatever", "whatsnew.sources", - "whatsnew.source.sourceid1.a", "whatsnew.source.sourceid1.aa", "whatsnew.source.sourceid2.c")); + when(this.configurationSource.getKeys("whatsnew.source.")).thenReturn( + List.of("whatsnew.source.sourceid1.a", "whatsnew.source.sourceid1.aa", "whatsnew.source.sourceid2.c")); when(this.configurationSource.getProperty("whatsnew.source.sourceid1.a", String.class)).thenReturn("b"); when(this.configurationSource.getProperty("whatsnew.source.sourceid1.aa", String.class)).thenReturn("bb"); when(this.configurationSource.getProperty("whatsnew.source.sourceid2.c", String.class)).thenReturn("d");