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