View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.configuration2.builder.combined;
18  
19  import java.util.Collection;
20  import java.util.Collections;
21  import java.util.Map;
22  import java.util.Set;
23  import java.util.stream.Collectors;
24  
25  import org.apache.commons.configuration2.FileBasedConfiguration;
26  import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
27  import org.apache.commons.configuration2.builder.ReloadingFileBasedConfigurationBuilder;
28  import org.apache.commons.configuration2.ex.ConfigurationException;
29  import org.apache.commons.configuration2.reloading.CombinedReloadingController;
30  import org.apache.commons.configuration2.reloading.ReloadingController;
31  import org.apache.commons.configuration2.reloading.ReloadingControllerSupport;
32  
33  /**
34   * <p>
35   * A specialized {@code MultiFileConfigurationBuilder} implementation which adds support for reloading.
36   * </p>
37   * <p>
38   * This class - as its super class - allows operating on multiple configuration files whose file names are determined
39   * using a file name pattern and a {@code ConfigurationInterpolator} object. It provides the following additional
40   * features:
41   * </p>
42   * <ul>
43   * <li>Configuration builder for managed configurations have reloading support. So reloading is possible for all
44   * configuration sources loaded by this builder instance.</li>
45   * <li>A {@link ReloadingController} is provided which can be used to trigger reload checks on all managed
46   * configurations.</li>
47   * </ul>
48   * <p>
49   * Although this builder manages an arbitrary number of child configurations, to clients only a single configuration is
50   * visible - the one selected by the evaluation of the file name pattern. Builder reset notifications triggered by the
51   * reloading mechanism do not really take this fact into account; they are not limited to the currently selected child
52   * configuration, but occur for each of the managed configuration.
53   * </p>
54   *
55   * @param <T> the concrete type of {@code Configuration} objects created by this builder
56   * @since 2.0
57   */
58  public class ReloadingMultiFileConfigurationBuilder<T extends FileBasedConfiguration> extends MultiFileConfigurationBuilder<T>
59      implements ReloadingControllerSupport {
60      /** The reloading controller used by this builder. */
61      private final ReloadingController reloadingController = createReloadingController();
62  
63      /**
64       * Creates a new instance of {@code ReloadingMultiFileConfigurationBuilder} without setting initialization parameters.
65       *
66       * @param resCls the result configuration class
67       * @throws IllegalArgumentException if the result class is <strong>null</strong>
68       */
69      public ReloadingMultiFileConfigurationBuilder(final Class<T> resCls) {
70          super(resCls);
71      }
72  
73      /**
74       * Creates a new instance of {@code ReloadingMultiFileConfigurationBuilder} and sets initialization parameters.
75       *
76       * @param resCls the result configuration class
77       * @param params a map with initialization parameters
78       * @throws IllegalArgumentException if the result class is <strong>null</strong>
79       */
80      public ReloadingMultiFileConfigurationBuilder(final Class<T> resCls, final Map<String, Object> params) {
81          super(resCls, params);
82      }
83  
84      /**
85       * Creates a new instance of {@code ReloadingMultiFileConfigurationBuilder} and sets initialization parameters and a
86       * flag whether initialization failures should be ignored.
87       *
88       * @param resCls the result configuration class
89       * @param params a map with initialization parameters
90       * @param allowFailOnInit a flag whether initialization errors should be ignored
91       * @throws IllegalArgumentException if the result class is <strong>null</strong>
92       */
93      public ReloadingMultiFileConfigurationBuilder(final Class<T> resCls, final Map<String, Object> params, final boolean allowFailOnInit) {
94          super(resCls, params, allowFailOnInit);
95      }
96  
97      /**
98       * {@inheritDoc} This implementation returns a file-based configuration builder with reloading support.
99       */
100     @Override
101     protected FileBasedConfigurationBuilder<T> createManagedBuilder(final String fileName, final Map<String, Object> params) throws ConfigurationException {
102         return new ReloadingFileBasedConfigurationBuilder<>(getResultClass(), params, isAllowFailOnInit());
103     }
104 
105     /**
106      * Creates the reloading controller used by this builder. This method creates a specialized
107      * {@link CombinedReloadingController} which operates on the reloading controllers of the managed builders created so
108      * far.
109      *
110      * @return the newly created {@code ReloadingController}
111      */
112     private ReloadingController createReloadingController() {
113         final Set<ReloadingController> empty = Collections.emptySet();
114         return new CombinedReloadingController(empty) {
115             @Override
116             public Collection<ReloadingController> getSubControllers() {
117                 return getManagedBuilders().values().stream().map(b -> ((ReloadingControllerSupport) b).getReloadingController()).collect(Collectors.toList());
118             }
119         };
120     }
121 
122     /**
123      * {@inheritDoc} This implementation returns a special {@code ReloadingController} that delegates to the reloading
124      * controllers of the managed builders created so far.
125      */
126     @Override
127     public ReloadingController getReloadingController() {
128         return reloadingController;
129     }
130 }