All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.commons.configuration2.builder.ReloadingFileBasedConfigurationBuilder Maven / Gradle / Ivy

Go to download

Tools to assist in the reading of configuration/preferences files in various formats

There is a newer version: 2.10.1
Show newest version
/*
 * 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;

import java.util.Map;

import org.apache.commons.configuration2.FileBasedConfiguration;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.configuration2.io.FileHandler;
import org.apache.commons.configuration2.reloading.ReloadingController;
import org.apache.commons.configuration2.reloading.ReloadingControllerSupport;
import org.apache.commons.configuration2.reloading.ReloadingDetector;

/**
 * 

* A specialized {@code ConfigurationBuilder} implementation which can handle * configurations read from a {@link FileHandler} and supports reloading. *

*

* This builder class exposes a {@link ReloadingController} object controlling * reload operations on the file-based configuration produced as result object. * For the {@code FileHandler} defining the location of the configuration a * configurable {@link ReloadingDetector} is created and associated with the * controller. So changes on the source file can be detected. When ever such a * change occurs, the result object of this builder is reset. This means that * the next time {@code getConfiguration()} is called a new * {@code Configuration} object is created which is loaded from the modified * file. *

*

* Client code interested in notifications can register a listener at this * builder to receive reset events. When such an event is received the new * result object can be requested. This way client applications can be sure to * work with an up-to-date configuration. It is also possible to register a * listener directly at the {@code ReloadingController}. *

*

* This builder does not actively trigger the {@code ReloadingController} to * perform a reload check. This has to be done by an external component, e.g. a * timer. *

* * @since 2.0 * @param the concrete type of {@code Configuration} objects created by this * builder */ public class ReloadingFileBasedConfigurationBuilder extends FileBasedConfigurationBuilder implements ReloadingControllerSupport { /** The default factory for creating reloading detector objects. */ private static final ReloadingDetectorFactory DEFAULT_DETECTOR_FACTORY = new DefaultReloadingDetectorFactory(); /** The reloading controller associated with this object. */ private final ReloadingController reloadingController; /** * The reloading detector which does the actual reload check for the current * result object. A new instance is created whenever a new result object * (and thus a new current file handler) becomes available. The field must * be volatile because it is accessed by the reloading controller probably * from within another thread. */ private volatile ReloadingDetector resultReloadingDetector; /** * Creates a new instance of {@code ReloadingFileBasedConfigurationBuilder} * which produces result objects of the specified class and sets * initialization parameters. * * @param resCls the result class (must not be null * @param params a map with initialization parameters * @throws IllegalArgumentException if the result class is null */ public ReloadingFileBasedConfigurationBuilder(final Class resCls, final Map params) { super(resCls, params); reloadingController = createReloadingController(); } /** * Creates a new instance of {@code ReloadingFileBasedConfigurationBuilder} * which produces result objects of the specified class and sets * initialization parameters and the allowFailOnInit flag. * * @param resCls the result class (must not be null * @param params a map with initialization parameters * @param allowFailOnInit the allowFailOnInit flag * @throws IllegalArgumentException if the result class is null */ public ReloadingFileBasedConfigurationBuilder(final Class resCls, final Map params, final boolean allowFailOnInit) { super(resCls, params, allowFailOnInit); reloadingController = createReloadingController(); } /** * Creates a new instance of {@code ReloadingFileBasedConfigurationBuilder} * which produces result objects of the specified class. * * @param resCls the result class (must not be null * @throws IllegalArgumentException if the result class is null */ public ReloadingFileBasedConfigurationBuilder(final Class resCls) { super(resCls); reloadingController = createReloadingController(); } /** * Returns the {@code ReloadingController} associated with this builder. * This controller is directly created. However, it becomes active (i.e. * associated with a meaningful reloading detector) not before a result * object was created. * * @return the {@code ReloadingController} */ @Override public ReloadingController getReloadingController() { return reloadingController; } /** * {@inheritDoc} This method is overridden here to change the result type. */ @Override public ReloadingFileBasedConfigurationBuilder configure( final BuilderParameters... params) { super.configure(params); return this; } /** * Creates a {@code ReloadingDetector} which monitors the passed in * {@code FileHandler}. This method is called each time a new result object * is created with the current {@code FileHandler}. This implementation * checks whether a {@code ReloadingDetectorFactory} is specified in the * current parameters. If this is the case, it is invoked. Otherwise, a * default factory is used to create a {@code FileHandlerReloadingDetector} * object. Note: This method is called from a synchronized block. * * @param handler the current {@code FileHandler} * @param fbparams the object with parameters related to file-based builders * @return a {@code ReloadingDetector} for this {@code FileHandler} * @throws ConfigurationException if an error occurs */ protected ReloadingDetector createReloadingDetector(final FileHandler handler, final FileBasedBuilderParametersImpl fbparams) throws ConfigurationException { return fetchDetectorFactory(fbparams).createReloadingDetector(handler, fbparams); } /** * {@inheritDoc} This implementation also takes care that a new * {@code ReloadingDetector} for the new current {@code FileHandler} is * created. Also, the reloading controller's reloading state has to be * reset; after the creation of a new result object changes in the * underlying configuration source have to be monitored again. */ @Override protected void initFileHandler(final FileHandler handler) throws ConfigurationException { super.initFileHandler(handler); resultReloadingDetector = createReloadingDetector(handler, FileBasedBuilderParametersImpl.fromParameters( getParameters(), true)); } /** * Creates the {@code ReloadingController} associated with this object. The * controller is assigned a specialized reloading detector which delegates * to the detector for the current result object. ( * {@code FileHandlerReloadingDetector} does not support changing the file * handler, and {@code ReloadingController} does not support changing the * reloading detector; therefore, this level of indirection is needed to * change the monitored file dynamically.) * * @return the new {@code ReloadingController} */ private ReloadingController createReloadingController() { final ReloadingDetector ctrlDetector = createReloadingDetectorForController(); final ReloadingController ctrl = new ReloadingController(ctrlDetector); connectToReloadingController(ctrl); return ctrl; } /** * Creates a {@code ReloadingDetector} wrapper to be passed to the * associated {@code ReloadingController}. This detector wrapper simply * delegates to the current {@code ReloadingDetector} if it is available. * * @return the wrapper {@code ReloadingDetector} */ private ReloadingDetector createReloadingDetectorForController() { return new ReloadingDetector() { @Override public void reloadingPerformed() { final ReloadingDetector detector = resultReloadingDetector; if (detector != null) { detector.reloadingPerformed(); } } @Override public boolean isReloadingRequired() { final ReloadingDetector detector = resultReloadingDetector; return (detector != null) && detector.isReloadingRequired(); } }; } /** * Returns a {@code ReloadingDetectorFactory} either from the passed in * parameters or a default factory. * * @param params the current parameters object * @return the {@code ReloadingDetectorFactory} to be used */ private static ReloadingDetectorFactory fetchDetectorFactory( final FileBasedBuilderParametersImpl params) { final ReloadingDetectorFactory factory = params.getReloadingDetectorFactory(); return (factory != null) ? factory : DEFAULT_DETECTOR_FACTORY; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy