ReloadingCombinedConfigurationBuilder.java
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.apache.commons.configuration2.builder.combined;
- import java.util.Collection;
- import java.util.LinkedList;
- import java.util.Map;
- import org.apache.commons.configuration2.CombinedConfiguration;
- import org.apache.commons.configuration2.HierarchicalConfiguration;
- import org.apache.commons.configuration2.XMLConfiguration;
- import org.apache.commons.configuration2.builder.BuilderParameters;
- import org.apache.commons.configuration2.builder.ConfigurationBuilder;
- import org.apache.commons.configuration2.builder.ReloadingFileBasedConfigurationBuilder;
- import org.apache.commons.configuration2.ex.ConfigurationException;
- import org.apache.commons.configuration2.reloading.CombinedReloadingController;
- import org.apache.commons.configuration2.reloading.ReloadingController;
- import org.apache.commons.configuration2.reloading.ReloadingControllerSupport;
- /**
- * <p>
- * An extension of {@code CombinedConfigurationBuilder} which also supports reloading operations.
- * </p>
- * <p>
- * This class differs from its super class in the following aspects:
- * </p>
- * <ul>
- * <li>A {@link ReloadingController} is created which manages all child configuration builders supporting reloading
- * operations.</li>
- * <li>If no {@code ConfigurationBuilder} is provided for the definition configuration, a builder with reloading support
- * is created.</li>
- * </ul>
- * <p>
- * This class can be used exactly as its super class for creating combined configurations from multiple configuration
- * sources. In addition, the combined reloading controller managed by an instance can be used to react on changes in one
- * of these configuration sources or in the definition configuration.
- * </p>
- *
- * @since 2.0
- */
- public class ReloadingCombinedConfigurationBuilder extends CombinedConfigurationBuilder implements ReloadingControllerSupport {
- /**
- * Checks whether the passed in builder object supports reloading. If yes, its reloading controller is obtained and
- * added to the given list.
- *
- * @param subControllers the list with sub controllers
- * @param builder the builder object to be checked
- */
- public static void obtainReloadingController(final Collection<ReloadingController> subControllers, final Object builder) {
- if (builder instanceof ReloadingControllerSupport) {
- subControllers.add(((ReloadingControllerSupport) builder).getReloadingController());
- }
- }
- /** The reloading controller used by this builder. */
- private ReloadingController reloadingController;
- /**
- * Creates a new instance of {@code ReloadingCombinedConfigurationBuilder}. No parameters are set.
- */
- public ReloadingCombinedConfigurationBuilder() {
- }
- /**
- * Creates a new instance of {@code ReloadingCombinedConfigurationBuilder} and sets the specified initialization
- * parameters.
- *
- * @param params a map with initialization parameters
- */
- public ReloadingCombinedConfigurationBuilder(final Map<String, Object> params) {
- super(params);
- }
- /**
- * Creates a new instance of {@code ReloadingCombinedConfigurationBuilder} and sets the specified initialization
- * parameters and the <em>allowFailOnInit</em> flag.
- *
- * @param params a map with initialization parameters
- * @param allowFailOnInit the <em>allowFailOnInit</em> flag
- */
- public ReloadingCombinedConfigurationBuilder(final Map<String, Object> params, final boolean allowFailOnInit) {
- super(params, allowFailOnInit);
- }
- /**
- * {@inheritDoc} This method is overridden to adapt the return type.
- */
- @Override
- public ReloadingCombinedConfigurationBuilder configure(final BuilderParameters... params) {
- super.configure(params);
- return this;
- }
- /**
- * Creates the {@code ReloadingController} for this builder. This method is called after the result configuration has
- * been created and initialized. It is called from a synchronized block. This implementation creates a
- * {@link CombinedReloadingController}.
- *
- * @return the {@code ReloadingController} for this builder
- * @throws ConfigurationException if an error occurs
- */
- protected ReloadingController createReloadingController() throws ConfigurationException {
- final Collection<ReloadingController> subControllers = new LinkedList<>();
- final ConfigurationBuilder<? extends HierarchicalConfiguration<?>> defBuilder = getDefinitionBuilder();
- obtainReloadingController(subControllers, defBuilder);
- getChildBuilders().forEach(b -> obtainReloadingController(subControllers, b));
- final CombinedReloadingController ctrl = new CombinedReloadingController(subControllers);
- ctrl.resetInitialReloadingState();
- return ctrl;
- }
- /**
- * {@inheritDoc} This implementation creates a builder for XML configurations with reloading support.
- */
- @Override
- protected ConfigurationBuilder<? extends HierarchicalConfiguration<?>> createXMLDefinitionBuilder(final BuilderParameters builderParams) {
- return new ReloadingFileBasedConfigurationBuilder<>(XMLConfiguration.class).configure(builderParams);
- }
- /**
- * {@inheritDoc} This implementation makes sure that the reloading state of the managed reloading controller is reset.
- * Note that this has to be done here and not in {@link #initResultInstance(CombinedConfiguration)} because it must be
- * outside of a synchronized block; otherwise, a dead-lock situation can occur.
- */
- @Override
- public CombinedConfiguration getConfiguration() throws ConfigurationException {
- final CombinedConfiguration result = super.getConfiguration();
- reloadingController.resetReloadingState();
- return result;
- }
- /**
- * {@inheritDoc} This implementation returns a {@link CombinedReloadingController} which contains sub controllers for
- * all child configuration sources with reloading support. If the definition builder supports reloading, its controller
- * is contained, too. Note that the combined reloading controller is initialized when the result configuration is
- * created (i.e. when calling {@code getConfiguration()} for the first time). So this method does not return a
- * meaningful result before.
- */
- @Override
- public synchronized ReloadingController getReloadingController() {
- return reloadingController;
- }
- /**
- * {@inheritDoc} This implementation first calls the super method to actually initialize the result configuration. Then
- * it creates the {@link CombinedReloadingController} for all child configuration sources with reloading support.
- */
- @Override
- protected void initResultInstance(final CombinedConfiguration result) throws ConfigurationException {
- super.initResultInstance(result);
- if (reloadingController == null) {
- reloadingController = createReloadingController();
- }
- }
- }