    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *     http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.configuration2.builder;
    018
    019import java.io.File;
    020import java.net.URL;
    021import java.util.Map;
    022
    023import org.apache.commons.configuration2.io.FileHandler;
    024import org.apache.commons.configuration2.io.FileLocationStrategy;
    025import org.apache.commons.configuration2.io.FileSystem;
    026import org.apache.commons.configuration2.io.URLConnectionOptions;
    027
    028/**
    029 * <p>
    030 * An implementation of {@code BuilderParameters} which contains parameters related to {@code Configuration}
    031 * implementations that are loaded from files.
    032 * </p>
    033 * <p>
    034 * The parameters defined here are interpreted by builder implementations that can deal with file-based configurations.
    035 * Note that these parameters are typically no initialization properties of configuration objects (i.e. they are not
    036 * passed to set methods after the creation of the result configuration). Rather, the parameters object is stored as a
    037 * whole in the builder's map with initialization parameters and can be accessed from there.
    038 * </p>
    039 * <p>
    040 * This class is not thread-safe. It is intended that an instance is constructed and initialized by a single thread
    041 * during configuration of a {@code ConfigurationBuilder}.
    042 * </p>
    043 *
    044 * @since 2.0
    045 */
    046public class FileBasedBuilderParametersImpl extends BasicBuilderParameters implements FileBasedBuilderProperties<FileBasedBuilderParametersImpl> {
    047    /** Constant for the key in the parameters map used by this class. */
    048    private static final String PARAM_KEY = RESERVED_PARAMETER_PREFIX + "fileBased";
    049
    050    /** Property name for the reloading refresh delay. */
    051    private static final String PROP_REFRESH_DELAY = "reloadingRefreshDelay";
    052
    053    /** Property name of the reloading detector factory. */
    054    private static final String PROP_DETECTOR_FACTORY = "reloadingDetectorFactory";
    055
    056    /**
    057     * Stores the associated file handler for the location of the configuration.
    058     */
    059    private FileHandler fileHandler;
    060
    061    /** The factory for reloading detectors. */
    062    private ReloadingDetectorFactory reloadingDetectorFactory;
    063
    064    /** The refresh delay for reloading support. */
    065    private Long reloadingRefreshDelay;
    066
    067    /**
    068     * Creates a new instance of {@code FileBasedBuilderParametersImpl} with an uninitialized {@code FileHandler} object.
    069     */
    070    public FileBasedBuilderParametersImpl() {
    071        this(null);
    072    }
    073
    074    /**
    075     * Creates a new instance of {@code FileBasedBuilderParametersImpl} and associates it with the given {@code FileHandler}
    076     * object. If the handler is <b>null</b>, a new handler instance is created.
    077     *
    078     * @param handler the associated {@code FileHandler} (can be <b>null</b>)
    079     */
    080    public FileBasedBuilderParametersImpl(final FileHandler handler) {
    081        fileHandler = handler != null ? handler : new FileHandler();
    082    }
    083
    084    /**
    085     * Creates a new {@code FileBasedBuilderParametersImpl} object from the content of the given map. While
    086     * {@code fromParameters()} expects that an object already exists and is stored in the given map, this method creates a
    087     * new instance based on the content of the map. The map can contain properties of a {@code FileHandler} and some
    088     * additional settings which are stored directly in the newly created object. If the map is <b>null</b>, an
    089     * uninitialized instance is returned.
    090     *
    091     * @param map the map with properties (must not be <b>null</b>)
    092     * @return the newly created instance
    093     * @throws ClassCastException if the map contains invalid data
    094     */
    095    public static FileBasedBuilderParametersImpl fromMap(final Map<String, ?> map) {
    096        final FileBasedBuilderParametersImpl params = new FileBasedBuilderParametersImpl(FileHandler.fromMap(map));
    097        if (map != null) {
    098            params.setReloadingRefreshDelay((Long) map.get(PROP_REFRESH_DELAY));
    099            params.setReloadingDetectorFactory((ReloadingDetectorFactory) map.get(PROP_DETECTOR_FACTORY));
    100        }
    101        return params;
    102    }
    103
    104    /**
    105     * Looks up an instance of this class in the specified parameters map. This is equivalent to
    106     * {@code fromParameters(params, false};}
    107     *
    108     * @param params the map with parameters (must not be <b>null</b>
    109     * @return the instance obtained from the map or <b>null</b>
    110     * @throws IllegalArgumentException if the map is <b>null</b>
    111     */
    112    public static FileBasedBuilderParametersImpl fromParameters(final Map<String, ?> params) {
    113        return fromParameters(params, false);
    114    }
    115
    116    /**
    117     * Looks up an instance of this class in the specified parameters map and optionally creates a new one if none is found.
    118     * This method can be used to obtain an instance of this class which has been stored in a parameters map. It is
    119     * compatible with the {@code getParameters()} method.
    120     *
    121     * @param params the map with parameters (must not be <b>null</b>
    122     * @param createIfMissing determines the behavior if no instance is found in the map; if <b>true</b>, a new instance
    123     *        with default settings is created; if <b>false</b>, <b>null</b> is returned
    124     * @return the instance obtained from the map or <b>null</b>
    125     * @throws IllegalArgumentException if the map is <b>null</b>
    126     */
    127    public static FileBasedBuilderParametersImpl fromParameters(final Map<String, ?> params, final boolean createIfMissing) {
    128        if (params == null) {
    129            throw new IllegalArgumentException("Parameters map must not be null!");
    130        }
    131
    132        FileBasedBuilderParametersImpl instance = (FileBasedBuilderParametersImpl) params.get(PARAM_KEY);
    133        if (instance == null && createIfMissing) {
    134            instance = new FileBasedBuilderParametersImpl();
    135        }
    136        return instance;
    137    }
    138
    139    /**
    140     * {@inheritDoc} This implementation also creates a copy of the {@code FileHandler}.
    141     */
    142    @Override
    143    public FileBasedBuilderParametersImpl clone() {
    144        final FileBasedBuilderParametersImpl copy = (FileBasedBuilderParametersImpl) super.clone();
    145        copy.fileHandler = new FileHandler(fileHandler.getContent(), fileHandler);
    146        return copy;
    147    }
    148
    149    /**
    150     * Gets the {@code FileHandler} managed by this object. This object is updated every time the file location is
    151     * changed.
    152     *
    153     * @return the managed {@code FileHandler}
    154     */
    155    public FileHandler getFileHandler() {
    156        return fileHandler;
    157    }
    158
    159    /**
    160     * {@inheritDoc} This implementation returns a map which contains this object itself under a specific key. The static
    161     * {@code fromParameters()} method can be used to extract an instance from a parameters map. Of course, the properties
    162     * inherited from the base class are also added to the result map.
    163     */
    164    @Override
    165    public Map<String, Object> getParameters() {
    166        final Map<String, Object> params = super.getParameters();
    167        params.put(PARAM_KEY, this);
    168        return params;
    169    }
    170
    171    /**
    172     * Gets the {@code ReloadingDetectorFactory}. Result may be <b>null</b> which means that the default factory is to be
    173     * used.
    174     *
    175     * @return the {@code ReloadingDetectorFactory}
    176     */
    177    public ReloadingDetectorFactory getReloadingDetectorFactory() {
    178        return reloadingDetectorFactory;
    179    }
    180
    181    /**
    182     * Gets the refresh delay for reload operations. Result may be <b>null</b> if this value has not been set.
    183     *
    184     * @return the reloading refresh delay
    185     */
    186    public Long getReloadingRefreshDelay() {
    187        return reloadingRefreshDelay;
    188    }
    189
    190    /**
    191     * {@inheritDoc} This implementation takes some properties defined in this class into account.
    192     */
    193    @Override
    194    public void inheritFrom(final Map<String, ?> source) {
    195        super.inheritFrom(source);
    196
    197        final FileBasedBuilderParametersImpl srcParams = fromParameters(source);
    198        if (srcParams != null) {
    199            setFileSystem(srcParams.getFileHandler().getFileSystem());
    200            setLocationStrategy(srcParams.getFileHandler().getLocationStrategy());
    201            if (srcParams.getFileHandler().getEncoding() != null) {
    202                setEncoding(srcParams.getFileHandler().getEncoding());
    203            }
    204            if (srcParams.getReloadingDetectorFactory() != null) {
    205                setReloadingDetectorFactory(srcParams.getReloadingDetectorFactory());
    206            }
    207            if (srcParams.getReloadingRefreshDelay() != null) {
    208                setReloadingRefreshDelay(srcParams.getReloadingRefreshDelay());
    209            }
    210        }
    211    }
    212
    213    @Override
    214    public FileBasedBuilderParametersImpl setBasePath(final String path) {
    215        getFileHandler().setBasePath(path);
    216        return this;
    217    }
    218
    219    @Override
    220    public FileBasedBuilderParametersImpl setEncoding(final String enc) {
    221        getFileHandler().setEncoding(enc);
    222        return this;
    223    }
    224
    225    @Override
    226    public FileBasedBuilderParametersImpl setFile(final File file) {
    227        getFileHandler().setFile(file);
    228        return this;
    229    }
    230
    231    @Override
    232    public FileBasedBuilderParametersImpl setFileName(final String name) {
    233        getFileHandler().setFileName(name);
    234        return this;
    235    }
    236
    237    @Override
    238    public FileBasedBuilderParametersImpl setFileSystem(final FileSystem fs) {
    239        getFileHandler().setFileSystem(fs);
    240        return this;
    241    }
    242
    243    @Override
    244    public FileBasedBuilderParametersImpl setLocationStrategy(final FileLocationStrategy strategy) {
    245        getFileHandler().setLocationStrategy(strategy);
    246        return this;
    247    }
    248
    249    @Override
    250    public FileBasedBuilderParametersImpl setPath(final String path) {
    251        getFileHandler().setPath(path);
    252        return this;
    253    }
    254
    255    @Override
    256    public FileBasedBuilderParametersImpl setReloadingDetectorFactory(final ReloadingDetectorFactory reloadingDetectorFactory) {
    257        this.reloadingDetectorFactory = reloadingDetectorFactory;
    258        return this;
    259    }
    260
    261    @Override
    262    public FileBasedBuilderParametersImpl setReloadingRefreshDelay(final Long reloadingRefreshDelay) {
    263        this.reloadingRefreshDelay = reloadingRefreshDelay;
    264        return this;
    265    }
    266
    267    @Override
    268    public FileBasedBuilderParametersImpl setURL(final URL url) {
    269        getFileHandler().setURL(url);
    270        return this;
    271    }
    272
    273    @Override
    274    public FileBasedBuilderParametersImpl setURL(final URL url, final URLConnectionOptions urlConnectionOptions) {
    275        getFileHandler().setURL(url, urlConnectionOptions);
    276        return this;
    277    }
    278}