    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;
    026
    027/**
    028 * <p>
    029 * An implementation of {@code BuilderParameters} which contains parameters
    030 * related to {@code Configuration} implementations that are loaded from files.
    031 * </p>
    032 * <p>
    033 * The parameters defined here are interpreted by builder implementations that
    034 * can deal with file-based configurations. Note that these parameters are
    035 * typically no initialization properties of configuration objects (i.e. they
    036 * are not passed to set methods after the creation of the result
    037 * configuration). Rather, the parameters object is stored as a whole in the
    038 * builder's map with initialization parameters and can be accessed from there.
    039 * </p>
    040 * <p>
    041 * This class is not thread-safe. It is intended that an instance is constructed
    042 * and initialized by a single thread during configuration of a
    043 * {@code ConfigurationBuilder}.
    044 * </p>
    045 *
    046 * @version $Id: FileBasedBuilderParametersImpl.java 1842194 2018-09-27 22:24:23Z ggregory $
    047 * @since 2.0
    048 */
    049public class FileBasedBuilderParametersImpl extends BasicBuilderParameters
    050        implements FileBasedBuilderProperties<FileBasedBuilderParametersImpl>
    051{
    052    /** Constant for the key in the parameters map used by this class. */
    053    private static final String PARAM_KEY = RESERVED_PARAMETER_PREFIX
    054            + "fileBased";
    055
    056    /** Property name for the reloading refresh delay. */
    057    private static final String PROP_REFRESH_DELAY = "reloadingRefreshDelay";
    058
    059    /** Property name of the reloading detector factory. */
    060    private static final String PROP_DETECTOR_FACTORY =
    061            "reloadingDetectorFactory";
    062
    063    /**
    064     * Stores the associated file handler for the location of the configuration.
    065     */
    066    private FileHandler fileHandler;
    067
    068    /** The factory for reloading detectors. */
    069    private ReloadingDetectorFactory reloadingDetectorFactory;
    070
    071    /** The refresh delay for reloading support. */
    072    private Long reloadingRefreshDelay;
    073
    074    /**
    075     * Creates a new instance of {@code FileBasedBuilderParametersImpl} with an
    076     * uninitialized {@code FileHandler} object.
    077     */
    078    public FileBasedBuilderParametersImpl()
    079    {
    080        this(null);
    081    }
    082
    083    /**
    084     * Creates a new instance of {@code FileBasedBuilderParametersImpl} and
    085     * associates it with the given {@code FileHandler} object. If the handler
    086     * is <b>null</b>, a new handler instance is created.
    087     *
    088     * @param handler the associated {@code FileHandler} (can be <b>null</b>)
    089     */
    090    public FileBasedBuilderParametersImpl(final FileHandler handler)
    091    {
    092        fileHandler = (handler != null) ? handler : new FileHandler();
    093    }
    094
    095    /**
    096     * Looks up an instance of this class in the specified parameters map. This
    097     * is equivalent to {@code fromParameters(params, false};}
    098     *
    099     * @param params the map with parameters (must not be <b>null</b>
    100     * @return the instance obtained from the map or <b>null</b>
    101     * @throws IllegalArgumentException if the map is <b>null</b>
    102     */
    103    public static FileBasedBuilderParametersImpl fromParameters(
    104            final Map<String, ?> params)
    105    {
    106        return fromParameters(params, false);
    107    }
    108
    109    /**
    110     * Looks up an instance of this class in the specified parameters map and
    111     * optionally creates a new one if none is found. This method can be used to
    112     * obtain an instance of this class which has been stored in a parameters
    113     * map. It is compatible with the {@code getParameters()} method.
    114     *
    115     * @param params the map with parameters (must not be <b>null</b>
    116     * @param createIfMissing determines the behavior if no instance is found in
    117     *        the map; if <b>true</b>, a new instance with default settings is
    118     *        created; if <b>false</b>, <b>null</b> is returned
    119     * @return the instance obtained from the map or <b>null</b>
    120     * @throws IllegalArgumentException if the map is <b>null</b>
    121     */
    122    public static FileBasedBuilderParametersImpl fromParameters(
    123            final Map<String, ?> params, final boolean createIfMissing)
    124    {
    125        if (params == null)
    126        {
    127            throw new IllegalArgumentException(
    128                    "Parameters map must not be null!");
    129        }
    130
    131        FileBasedBuilderParametersImpl instance =
    132                (FileBasedBuilderParametersImpl) params.get(PARAM_KEY);
    133        if (instance == null && createIfMissing)
    134        {
    135            instance = new FileBasedBuilderParametersImpl();
    136        }
    137        return instance;
    138    }
    139
    140    /**
    141     * Creates a new {@code FileBasedBuilderParametersImpl} object from the
    142     * content of the given map. While {@code fromParameters()} expects that an
    143     * object already exists and is stored in the given map, this method creates
    144     * a new instance based on the content of the map. The map can contain
    145     * properties of a {@code FileHandler} and some additional settings which
    146     * are stored directly in the newly created object. If the map is
    147     * <b>null</b>, an uninitialized instance is returned.
    148     *
    149     * @param map the map with properties (must not be <b>null</b>)
    150     * @return the newly created instance
    151     * @throws ClassCastException if the map contains invalid data
    152     */
    153    public static FileBasedBuilderParametersImpl fromMap(final Map<String, ?> map)
    154    {
    155        final FileBasedBuilderParametersImpl params =
    156                new FileBasedBuilderParametersImpl(FileHandler.fromMap(map));
    157        if (map != null)
    158        {
    159            params.setReloadingRefreshDelay((Long) map.get(PROP_REFRESH_DELAY));
    160            params.setReloadingDetectorFactory((ReloadingDetectorFactory) map
    161                    .get(PROP_DETECTOR_FACTORY));
    162        }
    163        return params;
    164    }
    165
    166    /**
    167     * {@inheritDoc} This implementation takes some properties defined in this
    168     * class into account.
    169     */
    170    @Override
    171    public void inheritFrom(final Map<String, ?> source)
    172    {
    173        super.inheritFrom(source);
    174
    175        final FileBasedBuilderParametersImpl srcParams = fromParameters(source);
    176        if (srcParams != null)
    177        {
    178            setFileSystem(srcParams.getFileHandler().getFileSystem());
    179            setLocationStrategy(
    180                    srcParams.getFileHandler().getLocationStrategy());
    181            if (srcParams.getFileHandler().getEncoding() != null)
    182            {
    183                setEncoding(srcParams.getFileHandler().getEncoding());
    184            }
    185            if (srcParams.getReloadingDetectorFactory() != null)
    186            {
    187                setReloadingDetectorFactory(
    188                        srcParams.getReloadingDetectorFactory());
    189            }
    190            if (srcParams.getReloadingRefreshDelay() != null)
    191            {
    192                setReloadingRefreshDelay(srcParams.getReloadingRefreshDelay());
    193            }
    194        }
    195    }
    196
    197    /**
    198     * Returns the {@code FileHandler} managed by this object. This object is
    199     * updated every time the file location is changed.
    200     *
    201     * @return the managed {@code FileHandler}
    202     */
    203    public FileHandler getFileHandler()
    204    {
    205        return fileHandler;
    206    }
    207
    208    /**
    209     * Returns the refresh delay for reload operations. Result may be
    210     * <b>null</b> if this value has not been set.
    211     *
    212     * @return the reloading refresh delay
    213     */
    214    public Long getReloadingRefreshDelay()
    215    {
    216        return reloadingRefreshDelay;
    217    }
    218
    219    @Override
    220    public FileBasedBuilderParametersImpl setReloadingRefreshDelay(
    221            final Long reloadingRefreshDelay)
    222    {
    223        this.reloadingRefreshDelay = reloadingRefreshDelay;
    224        return this;
    225    }
    226
    227    /**
    228     * Returns the {@code ReloadingDetectorFactory}. Result may be <b>null</b>
    229     * which means that the default factory is to be used.
    230     *
    231     * @return the {@code ReloadingDetectorFactory}
    232     */
    233    public ReloadingDetectorFactory getReloadingDetectorFactory()
    234    {
    235        return reloadingDetectorFactory;
    236    }
    237
    238    @Override
    239    public FileBasedBuilderParametersImpl setReloadingDetectorFactory(
    240            final ReloadingDetectorFactory reloadingDetectorFactory)
    241    {
    242        this.reloadingDetectorFactory = reloadingDetectorFactory;
    243        return this;
    244    }
    245
    246    @Override
    247    public FileBasedBuilderParametersImpl setFile(final File file)
    248    {
    249        getFileHandler().setFile(file);
    250        return this;
    251    }
    252
    253    @Override
    254    public FileBasedBuilderParametersImpl setURL(final URL url)
    255    {
    256        getFileHandler().setURL(url);
    257        return this;
    258    }
    259
    260    @Override
    261    public FileBasedBuilderParametersImpl setPath(final String path)
    262    {
    263        getFileHandler().setPath(path);
    264        return this;
    265    }
    266
    267    @Override
    268    public FileBasedBuilderParametersImpl setFileName(final String name)
    269    {
    270        getFileHandler().setFileName(name);
    271        return this;
    272    }
    273
    274    @Override
    275    public FileBasedBuilderParametersImpl setBasePath(final String path)
    276    {
    277        getFileHandler().setBasePath(path);
    278        return this;
    279    }
    280
    281    @Override
    282    public FileBasedBuilderParametersImpl setFileSystem(final FileSystem fs)
    283    {
    284        getFileHandler().setFileSystem(fs);
    285        return this;
    286    }
    287
    288    @Override
    289    public FileBasedBuilderParametersImpl setLocationStrategy(
    290            final FileLocationStrategy strategy)
    291    {
    292        getFileHandler().setLocationStrategy(strategy);
    293        return this;
    294    }
    295
    296    @Override
    297    public FileBasedBuilderParametersImpl setEncoding(final String enc)
    298    {
    299        getFileHandler().setEncoding(enc);
    300        return this;
    301    }
    302
    303    /**
    304     * {@inheritDoc} This implementation returns a map which contains this
    305     * object itself under a specific key. The static {@code fromParameters()}
    306     * method can be used to extract an instance from a parameters map. Of
    307     * course, the properties inherited from the base class are also added to
    308     * the result map.
    309     */
    310    @Override
    311    public Map<String, Object> getParameters()
    312    {
    313        final Map<String, Object> params = super.getParameters();
    314        params.put(PARAM_KEY, this);
    315        return params;
    316    }
    317
    318    /**
    319     * {@inheritDoc} This implementation also creates a copy of the
    320     * {@code FileHandler}.
    321     */
    322    @Override
    323    public FileBasedBuilderParametersImpl clone()
    324    {
    325        final FileBasedBuilderParametersImpl copy =
    326                (FileBasedBuilderParametersImpl) super.clone();
    327        copy.fileHandler =
    328                new FileHandler(fileHandler.getContent(), fileHandler);
    329        return copy;
    330    }
    331}