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    *     http://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   * @since 2.0
56   * @param <T> the concrete type of {@code Configuration} objects created by this builder
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} and sets initialization parameters and a
65       * flag whether initialization failures should be ignored.
66       *
67       * @param resCls the result configuration class
68       * @param params a map with initialization parameters
69       * @param allowFailOnInit a flag whether initialization errors should be ignored
70       * @throws IllegalArgumentException if the result class is <b>null</b>
71       */
72      public ReloadingMultiFileConfigurationBuilder(final Class<T> resCls, final Map<String, Object> params, final boolean allowFailOnInit) {
73          super(resCls, params, allowFailOnInit);
74      }
75  
76      /**
77       * Creates a new instance of {@code ReloadingMultiFileConfigurationBuilder} and sets initialization parameters.
78       *
79       * @param resCls the result configuration class
80       * @param params a map with initialization parameters
81       * @throws IllegalArgumentException if the result class is <b>null</b>
82       */
83      public ReloadingMultiFileConfigurationBuilder(final Class<T> resCls, final Map<String, Object> params) {
84          super(resCls, params);
85      }
86  
87      /**
88       * Creates a new instance of {@code ReloadingMultiFileConfigurationBuilder} without setting initialization parameters.
89       *
90       * @param resCls the result configuration class
91       * @throws IllegalArgumentException if the result class is <b>null</b>
92       */
93      public ReloadingMultiFileConfigurationBuilder(final Class<T> resCls) {
94          super(resCls);
95      }
96  
97      /**
98       * {@inheritDoc} This implementation returns a special {@code ReloadingController} that delegates to the reloading
99       * controllers of the managed builders created so far.
100      */
101     @Override
102     public ReloadingController getReloadingController() {
103         return reloadingController;
104     }
105 
106     /**
107      * {@inheritDoc} This implementation returns a file-based configuration builder with reloading support.
108      */
109     @Override
110     protected FileBasedConfigurationBuilder<T> createManagedBuilder(final String fileName, final Map<String, Object> params) throws ConfigurationException {
111         return new ReloadingFileBasedConfigurationBuilder<>(getResultClass(), params, isAllowFailOnInit());
112     }
113 
114     /**
115      * Creates the reloading controller used by this builder. This method creates a specialized
116      * {@link CombinedReloadingController} which operates on the reloading controllers of the managed builders created so
117      * far.
118      *
119      * @return the newly created {@code ReloadingController}
120      */
121     private ReloadingController createReloadingController() {
122         final Set<ReloadingController> empty = Collections.emptySet();
123         return new CombinedReloadingController(empty) {
124             @Override
125             public Collection<ReloadingController> getSubControllers() {
126                 return getManagedBuilders().values().stream().map(b -> ((ReloadingControllerSupport) b).getReloadingController()).collect(Collectors.toList());
127             }
128         };
129     }
130 }