Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,11 @@
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit-pioneer</groupId>
<artifactId>junit-pioneer</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@
import org.apache.commons.configuration2.convert.ListDelimiterHandler;
import org.apache.commons.configuration2.convert.ValueTransformer;
import org.apache.commons.configuration2.event.ConfigurationEvent;
import org.apache.commons.configuration2.ex.ConfigurationDeniedException;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.configuration2.ex.ConfigurationRuntimeException;
import org.apache.commons.configuration2.io.AbstractFileLocationStrategy;
import org.apache.commons.configuration2.io.AbstractFileLocationStrategy.AbstractBuilder;
import org.apache.commons.configuration2.io.FileHandler;
import org.apache.commons.configuration2.io.FileLocator;
import org.apache.commons.configuration2.io.FileLocatorAware;
Expand Down Expand Up @@ -159,22 +162,44 @@
* class, which is responsible for storing the layout of the parsed properties file (i.e. empty lines, comments, and
* such things). The {@code getLayout()} method can be used to obtain this layout object. With {@code setLayout()} a new
* layout object can be set. This should be done before a properties file was loaded.
* </p>
* <p>
* Like other {@code Configuration} implementations, this class uses a {@code Synchronizer} object to control concurrent
* access. By choosing a suitable implementation of the {@code Synchronizer} interface, an instance can be made
* thread-safe or not. Note that access to most of the properties typically set through a builder is not protected by
* the {@code Synchronizer}. The intended usage is that these properties are set once at construction time through the
* builder and after that remain constant. If you wish to change such properties during life time of an instance, you
* have to use the {@code lock()} and {@code unlock()} methods manually to ensure that other threads see your changes.
* </p>
* <p>
* As this class extends {@link AbstractConfiguration}, all basic features like variable interpolation, list handling,
* or data type conversions are available as well. This is described in the chapter
* <a href="https://commons.apache.org/proper/commons-configuration/userguide/howto_basicfeatures.html"> Basic features
* and AbstractConfiguration</a> of the user's guide. There is also a separate chapter dealing with
* <a href="commons.apache.org/proper/commons-configuration/userguide/howto_properties.html"> Properties files</a> in
* special.
* </p>
* <p>
* As of version 2.15.0, by default, when including files, the only URL schemes allowed are {@code file} and {@code jar}. To override this default,
* you can either use the system property {@code org.apache.commons.configuration2.io.FileLocationStrategy.schemes} or build a subclass of
* {@link AbstractFileLocationStrategy}.
* </p>
* <strong>Using System Properties</strong>
* <p>
* The system property {@code org.apache.commons.configuration2.io.FileLocationStrategy.schemes} String value must be a comma-separated list of schemes,
* where the default is {@code "file,jar"}, and the complete list is {@code "file,http,https,jar"}.
* </p>
* <strong>Using a Builder</strong>
* <p>
* The root builder for {@link AbstractFileLocationStrategy} is {@link AbstractBuilder} where you define allowed schemes and hosts through its setter
* methods.
* </p>
* <p>
* For example, to programatically enable the shemes "file", "http", "https", and "jar" for all strategies, see {@link AbstractFileLocationStrategy}.
* </p>
*
* @see java.util.Properties#load
* @see AbstractFileLocationStrategy
*/
public class PropertiesConfiguration extends BaseConfiguration implements FileBasedConfiguration, FileLocatorAware {

Expand Down Expand Up @@ -1336,7 +1361,17 @@ public PropertiesConfigurationLayout getLayout() {
}

/**
* Stores the current {@code FileLocator} for a following IO operation. The {@code FileLocator} is needed to resolve
* Gets the file locator.
*
* @return the file locator.
* @since 2.15.0
*/
public FileLocator getLocator() {
return locator;
}

/**
* Sets the current {@code FileLocator} for a following IO operation. The {@code FileLocator} is needed to resolve
* include files with relative file names.
*
* @param locator the current {@code FileLocator}
Expand Down Expand Up @@ -1377,7 +1412,7 @@ public boolean isIncludesAllowed() {
}

/**
* Helper method for loading an included properties file. This method is called by {@code load()} when an
* Loads an included properties file. This method is called by {@code load()} when an
* {@code include} property is encountered. It tries to resolve relative file names based on the current base path. If
* this fails, a resolution based on the location of this properties file is tried.
*
Expand All @@ -1389,21 +1424,23 @@ public boolean isIncludesAllowed() {
private void loadIncludeFile(final String fileName, final boolean optional, final Deque<URL> seenStack) throws ConfigurationException {
if (locator == null) {
throw new ConfigurationException(
"Load operation not properly initialized! Do not call read(InputStream) directly, but use a FileHandler to load a configuration.");
"Load operation not properly initialized. Do not call read(InputStream) directly, use a FileHandler to load a configuration.");
}

URL url = locateIncludeFile(locator.getBasePath(), fileName);
if (url == null) {
final URL baseURL = locator.getSourceURL();
if (baseURL != null) {
url = locateIncludeFile(baseURL.toString(), fileName);
URL url = null;
try {
url = locateIncludeFile(locator.getBasePath(), fileName);
if (url == null) {
final URL baseURL = locator.getSourceURL();
if (baseURL != null) {
url = locateIncludeFile(baseURL.toString(), fileName);
}
}
} catch (ConfigurationDeniedException e) {
getIncludeListener().accept(new ConfigurationException(e));
}

if (optional && url == null) {
return;
}

if (url == null) {
getIncludeListener().accept(new ConfigurationException(new FileNotFoundException(fileName), "Cannot resolve include file %s", fileName));
} else {
Expand Down Expand Up @@ -1432,7 +1469,7 @@ private void loadIncludeFile(final String fileName, final boolean optional, fina
}

/**
* Tries to obtain the URL of an include file using the specified (optional) base path and file name.
* Locates the URL of an include file using the specified (optional) base path and file name.
*
* @param basePath the base path
* @param fileName the file name
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.commons.configuration2.ex;

/**
* Thrown when an application only grants specific configurations for elements like URL schemes and hosts.
*
* @since 2.15.0
*/
public class ConfigurationDeniedException extends ConfigurationRuntimeException {

private static final long serialVersionUID = 1L;

/**
* Constructs a new {@code ConfigurationDeniedException} with specified detail message using {@link String#format(String,Object...)}.
*
* @param message the error message.
* @param args arguments to the error message.
* @see String#format(String,Object...)
*/
public ConfigurationDeniedException(final String message, final Object... args) {
super(message, args);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,33 +28,57 @@
* This strategy ignores the URL and the base path stored in the passed in {@link FileLocator}. It is only triggered by
* absolute names in the locator's {@code fileName} component.
* </p>
* <p>
* See {@link AbstractFileLocationStrategy} learn how to grant an deny URL schemes and hosts.
* </p>
*
* @see AbstractFileLocationStrategy
* @since 2.0
*/
public class AbsoluteNameLocationStrategy extends AbstractFileLocationStrategy {

/**
* A singleton instance of this strategy.
* Builds new instances of {@link ProvidedURLLocationStrategy}.
*
* @return a new builder.
* @since 2.15.0
*/
static final AbsoluteNameLocationStrategy INSTANCE = new AbsoluteNameLocationStrategy();
public static StrategyBuilder<AbsoluteNameLocationStrategy> builder() {
return new StrategyBuilder<>(AbsoluteNameLocationStrategy::new);
}

/**
* Constructs a new instance.
* Constructs a new instance where URL resources are bound by {@link AbstractFileLocationStrategy.AbstractBuilder}.
* <p>
* </p>
*/
public AbsoluteNameLocationStrategy() {
// empty
}

/**
* {@inheritDoc} This implementation constructs a {@code File} object from the locator's file name (if defined). If this
* Constructs a new instance where URL resources are bound by {@link AbstractFileLocationStrategy.AbstractBuilder}.
*
* @param builder How to build the instance.
* @since 2.15.0
*/
public AbsoluteNameLocationStrategy(final AbstractBuilder<?, ?> builder) {
super(builder);
}

/**
* {@inheritDoc}
* <p>
* This implementation constructs a {@code File} object from the locator's file name (if defined). If this
* results in an absolute file name pointing to an existing file, the corresponding URL is returned.
* </p>
*/
@Override
public URL locate(final FileSystem fileSystem, final FileLocator locator) {
if (StringUtils.isNotEmpty(locator.getFileName())) {
final File file = new File(locator.getFileName());
if (file.isAbsolute() && file.exists()) {
return FileLocatorUtils.convertFileToURL(file);
return check(FileLocatorUtils.convertFileToURL(file));
}
}
return null;
Expand Down
Loading
Loading