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.fluent;
018
019import java.io.File;
020import java.net.URL;
021
022import org.apache.commons.configuration2.CombinedConfiguration;
023import org.apache.commons.configuration2.FileBasedConfiguration;
024import org.apache.commons.configuration2.INIConfiguration;
025import org.apache.commons.configuration2.PropertiesConfiguration;
026import org.apache.commons.configuration2.XMLConfiguration;
027import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
028import org.apache.commons.configuration2.builder.combined.CombinedConfigurationBuilder;
029import org.apache.commons.configuration2.ex.ConfigurationException;
030
031/**
032 * <p>
033 * A convenience class which simplifies the creation of standard configurations
034 * and their builders.
035 * </p>
036 * <p>
037 * Complex initializations of configuration builders can be done in a pretty
038 * straight-forward way by making use of the provided fluent API. However, if
039 * only default settings are used (and maybe a configuration file to be loaded
040 * has to be specified), this approach tends to become a bit verbose. This class
041 * was introduced to simplify the creation of configuration objects in such
042 * cases. It offers a bunch of methods which allow the creation of some standard
043 * configuration classes with default settings passing in only a minimum
044 * required parameters.
045 * </p>
046 * <p>
047 * An an example consider the creation of a {@code PropertiesConfiguration}
048 * object from a file. Using a builder, code like the following one would have
049 * to be written:
050 * </p>
051 * <pre>
052 * Parameters params = new Parameters();
053 * FileBasedConfigurationBuilder&lt;PropertiesConfiguration&gt; builder =
054 *         new FileBasedConfigurationBuilder&lt;PropertiesConfiguration&gt;(
055 *                 PropertiesConfiguration.class).configure(params.fileBased()
056 *                 .setFile(new File(&quot;config.properties&quot;)));
057 * PropertiesConfiguration config = builder.getConfiguration();
058 * </pre>
059 * <p>
060 * With a convenience method of {@code Configurations} the same can be achieved
061 * with the following:
062 * </p>
063 * <pre>
064 * Configurations configurations = new Configurations();
065 * PropertiesConfiguration config = configurations.properties(new File(
066 *         &quot;config.properties&quot;));
067 * </pre>
068 * <p>
069 * There are similar methods for constructing builder objects from which
070 * configurations can then be obtained.
071 * </p>
072 * <p>
073 * This class is thread-safe. A single instance can be created by an application
074 * and used in a central way to create configuration objects. When an instance
075 * is created a {@link Parameters} instance can be passed in. Otherwise, a
076 * default instance is created. In any case, the {@code Parameters} instance
077 * associated with a {@code Configurations} object can be used to define default
078 * settings for the configurations to be created.
079 * </p>
080 *
081 * @version $Id: Configurations.java 1790899 2017-04-10 21:56:46Z ggregory $
082 * @since 2.0
083 * @see org.apache.commons.configuration2.builder.DefaultParametersManager
084 */
085public class Configurations
086{
087    /** The parameters object associated with this instance. */
088    private final Parameters parameters;
089
090    /**
091     * Creates a new {@code Configurations} instance with default settings.
092     */
093    public Configurations()
094    {
095        this(null);
096    }
097
098    /**
099     * Creates a new instance of {@code Configurations} and initializes it with
100     * the specified {@code Parameters} object.
101     *
102     * @param params the {@code Parameters} (may be <b>null</b>, then a default
103     *        instance is created)
104     */
105    public Configurations(Parameters params)
106    {
107        parameters = (params != null) ? params : new Parameters();
108    }
109
110    /**
111     * Returns the {@code Parameters} instance associated with this object.
112     *
113     * @return the associated {@code Parameters} object
114     */
115    public Parameters getParameters()
116    {
117        return parameters;
118    }
119
120    /**
121     * Creates a {@code FileBasedConfigurationBuilder} for the specified
122     * configuration class and initializes it with the file to be loaded.
123     *
124     * @param configClass the configuration class
125     * @param file the file to be loaded
126     * @param <T> the type of the configuration to be constructed
127     * @return the new {@code FileBasedConfigurationBuilder}
128     */
129    public <T extends FileBasedConfiguration> FileBasedConfigurationBuilder<T> fileBasedBuilder(
130            Class<T> configClass, File file)
131    {
132        return createFileBasedBuilder(configClass, fileParams(file));
133    }
134
135    /**
136     * Creates a {@code FileBasedConfigurationBuilder} for the specified
137     * configuration class and initializes it with the URL to the file to be
138     * loaded.
139     *
140     * @param configClass the configuration class
141     * @param url the URL to be loaded
142     * @param <T> the type of the configuration to be constructed
143     * @return the new {@code FileBasedConfigurationBuilder}
144     */
145    public <T extends FileBasedConfiguration> FileBasedConfigurationBuilder<T> fileBasedBuilder(
146            Class<T> configClass, URL url)
147    {
148        return createFileBasedBuilder(configClass, fileParams(url));
149    }
150
151    /**
152     * Creates a {@code FileBasedConfigurationBuilder} for the specified
153     * configuration class and initializes it with the path to the file to be
154     * loaded.
155     *
156     * @param configClass the configuration class
157     * @param path the path to the file to be loaded
158     * @param <T> the type of the configuration to be constructed
159     * @return the new {@code FileBasedConfigurationBuilder}
160     */
161    public <T extends FileBasedConfiguration> FileBasedConfigurationBuilder<T> fileBasedBuilder(
162            Class<T> configClass, String path)
163    {
164        return createFileBasedBuilder(configClass, fileParams(path));
165    }
166
167    /**
168     * Creates an instance of the specified file-based configuration class from
169     * the content of the given file. This is a convenience method which can be
170     * used if no builder is needed for managing the configuration object.
171     * (Although, behind the scenes a builder is created).
172     *
173     * @param configClass the configuration class
174     * @param file the file to be loaded
175     * @param <T> the type of the configuration to be constructed
176     * @return a {@code FileBasedConfiguration} object initialized from this
177     *         file
178     * @throws ConfigurationException if an error occurred when loading the
179     *         configuration
180     */
181    public <T extends FileBasedConfiguration> T fileBased(Class<T> configClass,
182            File file) throws ConfigurationException
183    {
184        return fileBasedBuilder(configClass, file).getConfiguration();
185    }
186
187    /**
188     * Creates an instance of the specified file-based configuration class from
189     * the content of the given URL. This is a convenience method which can be
190     * used if no builder is needed for managing the configuration object.
191     * (Although, behind the scenes a builder is created).
192     *
193     * @param configClass the configuration class
194     * @param url the URL to be loaded
195     * @param <T> the type of the configuration to be constructed
196     * @return a {@code FileBasedConfiguration} object initialized from this
197     *         file
198     * @throws ConfigurationException if an error occurred when loading the
199     *         configuration
200     */
201    public <T extends FileBasedConfiguration> T fileBased(Class<T> configClass,
202            URL url) throws ConfigurationException
203    {
204        return fileBasedBuilder(configClass, url).getConfiguration();
205    }
206
207    /**
208     * Creates an instance of the specified file-based configuration class from
209     * the content of the file identified by the given path. This is a
210     * convenience method which can be used if no builder is needed for managing
211     * the configuration object. (Although, behind the scenes a builder is
212     * created).
213     *
214     * @param configClass the configuration class
215     * @param path the path to the file to be loaded
216     * @param <T> the type of the configuration to be constructed
217     * @return a {@code FileBasedConfiguration} object initialized from this
218     *         file
219     * @throws ConfigurationException if an error occurred when loading the
220     *         configuration
221     */
222    public <T extends FileBasedConfiguration> T fileBased(Class<T> configClass,
223            String path) throws ConfigurationException
224    {
225        return fileBasedBuilder(configClass, path).getConfiguration();
226    }
227
228    /**
229     * Creates a builder for a {@code PropertiesConfiguration} and initializes
230     * it with the given file to be loaded.
231     *
232     * @param file the file to be loaded
233     * @return the newly created {@code FileBasedConfigurationBuilder}
234     */
235    public FileBasedConfigurationBuilder<PropertiesConfiguration> propertiesBuilder(
236            File file)
237    {
238        return fileBasedBuilder(PropertiesConfiguration.class, file);
239    }
240
241    /**
242     * Creates a builder for a {@code PropertiesConfiguration} and initializes
243     * it with the given URL to be loaded.
244     *
245     * @param url the URL to be loaded
246     * @return the newly created {@code FileBasedConfigurationBuilder}
247     */
248    public FileBasedConfigurationBuilder<PropertiesConfiguration> propertiesBuilder(
249            URL url)
250    {
251        return fileBasedBuilder(PropertiesConfiguration.class, url);
252    }
253
254    /**
255     * Creates a builder for a {@code PropertiesConfiguration} and initializes
256     * it with the given path to the file to be loaded.
257     *
258     * @param path the path to the file to be loaded
259     * @return the newly created {@code FileBasedConfigurationBuilder}
260     */
261    public FileBasedConfigurationBuilder<PropertiesConfiguration> propertiesBuilder(
262            String path)
263    {
264        return fileBasedBuilder(PropertiesConfiguration.class, path);
265    }
266
267    /**
268     * Creates a {@code PropertiesConfiguration} instance from the content of
269     * the given file. This is a convenience method which can be used if no
270     * builder is needed for managing the configuration object. (Although,
271     * behind the scenes a builder is created).
272     *
273     * @param file the file to be loaded
274     * @return a {@code PropertiesConfiguration} object initialized from this
275     *         file
276     * @throws ConfigurationException if an error occurred when loading the
277     *         configuration
278     */
279    public PropertiesConfiguration properties(File file)
280            throws ConfigurationException
281    {
282        return propertiesBuilder(file).getConfiguration();
283    }
284
285    /**
286     * Creates a {@code PropertiesConfiguration} instance from the content of
287     * the given URL. This is a convenience method which can be used if no
288     * builder is needed for managing the configuration object. (Although,
289     * behind the scenes a builder is created).
290     *
291     * @param url the URL to be loaded
292     * @return a {@code PropertiesConfiguration} object initialized from this
293     *         URL
294     * @throws ConfigurationException if an error occurred when loading the
295     *         configuration
296     */
297    public PropertiesConfiguration properties(URL url)
298            throws ConfigurationException
299    {
300        return propertiesBuilder(url).getConfiguration();
301    }
302
303    /**
304     * Creates a {@code PropertiesConfiguration} instance from the content of
305     * the file identified by the given path. This is a convenience method which
306     * can be used if no builder is needed for managing the configuration
307     * object. (Although, behind the scenes a builder is created).
308     *
309     * @param path the path to the file to be loaded
310     * @return a {@code PropertiesConfiguration} object initialized from this
311     *         path
312     * @throws ConfigurationException if an error occurred when loading the
313     *         configuration
314     */
315    public PropertiesConfiguration properties(String path)
316            throws ConfigurationException
317    {
318        return propertiesBuilder(path).getConfiguration();
319    }
320
321    /**
322     * Creates a builder for a {@code XMLConfiguration} and initializes it with
323     * the given file to be loaded.
324     *
325     * @param file the file to be loaded
326     * @return the newly created {@code FileBasedConfigurationBuilder}
327     */
328    public FileBasedConfigurationBuilder<XMLConfiguration> xmlBuilder(File file)
329    {
330        return fileBasedBuilder(XMLConfiguration.class, file);
331    }
332
333    /**
334     * Creates a builder for a {@code XMLConfiguration} and initializes it with
335     * the given URL to be loaded.
336     *
337     * @param url the URL to be loaded
338     * @return the newly created {@code FileBasedConfigurationBuilder}
339     */
340    public FileBasedConfigurationBuilder<XMLConfiguration> xmlBuilder(URL url)
341    {
342        return fileBasedBuilder(XMLConfiguration.class, url);
343    }
344
345    /**
346     * Creates a builder for a {@code XMLConfiguration} and initializes it with
347     * the given path to the file to be loaded.
348     *
349     * @param path the path to the file to be loaded
350     * @return the newly created {@code FileBasedConfigurationBuilder}
351     */
352    public FileBasedConfigurationBuilder<XMLConfiguration> xmlBuilder(
353            String path)
354    {
355        return fileBasedBuilder(XMLConfiguration.class, path);
356    }
357
358    /**
359     * Creates a {@code XMLConfiguration} instance from the content of the given
360     * file. This is a convenience method which can be used if no builder is
361     * needed for managing the configuration object. (Although, behind the
362     * scenes a builder is created).
363     *
364     * @param file the file to be loaded
365     * @return a {@code XMLConfiguration} object initialized from this file
366     * @throws ConfigurationException if an error occurred when loading the
367     *         configuration
368     */
369    public XMLConfiguration xml(File file) throws ConfigurationException
370    {
371        return xmlBuilder(file).getConfiguration();
372    }
373
374    /**
375     * Creates a {@code XMLConfiguration} instance from the content of the given
376     * URL. This is a convenience method which can be used if no builder is
377     * needed for managing the configuration object. (Although, behind the
378     * scenes a builder is created).
379     *
380     * @param url the URL to be loaded
381     * @return a {@code XMLConfiguration} object initialized from this file
382     * @throws ConfigurationException if an error occurred when loading the
383     *         configuration
384     */
385    public XMLConfiguration xml(URL url) throws ConfigurationException
386    {
387        return xmlBuilder(url).getConfiguration();
388    }
389
390    /**
391     * Creates a {@code XMLConfiguration} instance from the content of the file
392     * identified by the given path. This is a convenience method which can be
393     * used if no builder is needed for managing the configuration object.
394     * (Although, behind the scenes a builder is created).
395     *
396     * @param path the path to the file to be loaded
397     * @return a {@code XMLConfiguration} object initialized from this file
398     * @throws ConfigurationException if an error occurred when loading the
399     *         configuration
400     */
401    public XMLConfiguration xml(String path) throws ConfigurationException
402    {
403        return xmlBuilder(path).getConfiguration();
404    }
405
406    /**
407     * Creates a builder for a {@code INIConfiguration} and initializes it with
408     * the given file to be loaded.
409     *
410     * @param file the file to be loaded
411     * @return the newly created {@code FileBasedConfigurationBuilder}
412     */
413    public FileBasedConfigurationBuilder<INIConfiguration> iniBuilder(File file)
414    {
415        return fileBasedBuilder(INIConfiguration.class, file);
416    }
417
418    /**
419     * Creates a builder for a {@code INIConfiguration} and initializes it with
420     * the given URL to be loaded.
421     *
422     * @param url the URL to be loaded
423     * @return the newly created {@code FileBasedConfigurationBuilder}
424     */
425    public FileBasedConfigurationBuilder<INIConfiguration> iniBuilder(URL url)
426    {
427        return fileBasedBuilder(INIConfiguration.class, url);
428    }
429
430    /**
431     * Creates a builder for a {@code INIConfiguration} and initializes it with
432     * the file file identified by the given path.
433     *
434     * @param path the path to the file to be loaded
435     * @return the newly created {@code FileBasedConfigurationBuilder}
436     */
437    public FileBasedConfigurationBuilder<INIConfiguration> iniBuilder(
438            String path)
439    {
440        return fileBasedBuilder(INIConfiguration.class, path);
441    }
442
443    /**
444     * Creates a {@code INIConfiguration} instance from the content of the given
445     * file. This is a convenience method which can be used if no builder is
446     * needed for managing the configuration object. (Although, behind the
447     * scenes a builder is created).
448     *
449     * @param file the file to be loaded
450     * @return a {@code INIConfiguration} object initialized from this file
451     * @throws ConfigurationException if an error occurred when loading the
452     *         configuration
453     */
454    public INIConfiguration ini(File file) throws ConfigurationException
455    {
456        return iniBuilder(file).getConfiguration();
457    }
458
459    /**
460     * Creates a {@code INIConfiguration} instance from the content of the given
461     * URL. This is a convenience method which can be used if no builder is
462     * needed for managing the configuration object. (Although, behind the
463     * scenes a builder is created).
464     *
465     * @param url the URL to be loaded
466     * @return a {@code INIConfiguration} object initialized from this file
467     * @throws ConfigurationException if an error occurred when loading the
468     *         configuration
469     */
470    public INIConfiguration ini(URL url) throws ConfigurationException
471    {
472        return iniBuilder(url).getConfiguration();
473    }
474
475    /**
476     * Creates a {@code INIConfiguration} instance from the content of the file
477     * identified by the given path. This is a convenience method which can be
478     * used if no builder is needed for managing the configuration object.
479     * (Although, behind the scenes a builder is created).
480     *
481     * @param path the path to the file to be loaded
482     * @return a {@code INIConfiguration} object initialized from this file
483     * @throws ConfigurationException if an error occurred when loading the
484     *         configuration
485     */
486    public INIConfiguration ini(String path) throws ConfigurationException
487    {
488        return iniBuilder(path).getConfiguration();
489    }
490
491    /**
492     * Creates a builder for a {@code CombinedConfiguration} and initializes it
493     * with the given file to be loaded.
494     *
495     * @param file the file to be loaded
496     * @return the newly created {@code CombinedConfigurationBuilder}
497     */
498    public CombinedConfigurationBuilder combinedBuilder(File file)
499    {
500        return new CombinedConfigurationBuilder().configure(fileParams(file));
501    }
502
503    /**
504     * Creates a builder for a {@code CombinedConfiguration} and initializes it
505     * with the given URL to be loaded.
506     *
507     * @param url the URL to be loaded
508     * @return the newly created {@code CombinedConfigurationBuilder}
509     */
510    public CombinedConfigurationBuilder combinedBuilder(URL url)
511    {
512        return new CombinedConfigurationBuilder().configure(fileParams(url));
513    }
514
515    /**
516     * Creates a builder for a {@code CombinedConfiguration} and initializes it
517     * with the given path to the file to be loaded.
518     *
519     * @param path the path to the file to be loaded
520     * @return the newly created {@code CombinedConfigurationBuilder}
521     */
522    public CombinedConfigurationBuilder combinedBuilder(String path)
523    {
524        return new CombinedConfigurationBuilder().configure(fileParams(path));
525    }
526
527    /**
528     * Creates a {@code CombinedConfiguration} instance from the content of the
529     * given file. This is a convenience method which can be used if no builder
530     * is needed for managing the configuration object. (Although, behind the
531     * scenes a builder is created).
532     *
533     * @param file the file to be loaded
534     * @return a {@code CombinedConfiguration} object initialized from this file
535     * @throws ConfigurationException if an error occurred when loading the
536     *         configuration
537     */
538    public CombinedConfiguration combined(File file)
539            throws ConfigurationException
540    {
541        return combinedBuilder(file).getConfiguration();
542    }
543
544    /**
545     * Creates a {@code CombinedConfiguration} instance from the content of the
546     * given URL. This is a convenience method which can be used if no builder
547     * is needed for managing the configuration object. (Although, behind the
548     * scenes a builder is created).
549     *
550     * @param url the URL to be loaded
551     * @return a {@code CombinedConfiguration} object initialized from this URL
552     * @throws ConfigurationException if an error occurred when loading the
553     *         configuration
554     */
555    public CombinedConfiguration combined(URL url)
556            throws ConfigurationException
557    {
558        return combinedBuilder(url).getConfiguration();
559    }
560
561    /**
562     * Creates a {@code CombinedConfiguration} instance from the content of the
563     * file identified by the given path. This is a convenience method which can
564     * be used if no builder is needed for managing the configuration object.
565     * (Although, behind the scenes a builder is created).
566     *
567     * @param path the path to the file to be loaded
568     * @return a {@code CombinedConfiguration} object initialized from this URL
569     * @throws ConfigurationException if an error occurred when loading the
570     *         configuration
571     */
572    public CombinedConfiguration combined(String path)
573            throws ConfigurationException
574    {
575        return combinedBuilder(path).getConfiguration();
576    }
577
578    /**
579     * Creates a configured builder for a file-based configuration of the
580     * specified type.
581     *
582     * @param configClass the configuration class
583     * @param params the parameters object for configuring the builder
584     * @param <T> the type of the configuration to be constructed
585     * @return the newly created builder
586     */
587    private <T extends FileBasedConfiguration> FileBasedConfigurationBuilder<T> createFileBasedBuilder(
588            Class<T> configClass, FileBasedBuilderParameters params)
589    {
590        return new FileBasedConfigurationBuilder<>(configClass)
591                .configure(params);
592    }
593
594    /**
595     * Convenience method for creating a parameters object for a file-based
596     * configuration.
597     *
598     * @return the newly created parameters object
599     */
600    private FileBasedBuilderParameters fileParams()
601    {
602        return getParameters().fileBased();
603    }
604
605    /**
606     * Convenience method for creating a file-based parameters object
607     * initialized with the given file.
608     *
609     * @param file the file to be loaded
610     * @return the initialized parameters object
611     */
612    private FileBasedBuilderParameters fileParams(File file)
613    {
614        return fileParams().setFile(file);
615    }
616
617    /**
618     * Convenience method for creating a file-based parameters object
619     * initialized with the given file.
620     *
621     * @param url the URL to be loaded
622     * @return the initialized parameters object
623     */
624    private FileBasedBuilderParameters fileParams(URL url)
625    {
626        return fileParams().setURL(url);
627    }
628
629    /**
630     * Convenience method for creating a file-based parameters object
631     * initialized with the given file path.
632     *
633     * @param path the path to the file to be loaded
634     * @return the initialized parameters object
635     */
636    private FileBasedBuilderParameters fileParams(String path)
637    {
638        return fileParams().setFileName(path);
639    }
640}