MultiFileConfigurationBuilderProvider.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.Arrays;
- import org.apache.commons.configuration2.Configuration;
- import org.apache.commons.configuration2.ConfigurationUtils;
- import org.apache.commons.configuration2.HierarchicalConfiguration;
- import org.apache.commons.configuration2.builder.BuilderConfigurationWrapperFactory;
- import org.apache.commons.configuration2.builder.BuilderConfigurationWrapperFactory.EventSourceSupport;
- import org.apache.commons.configuration2.builder.ConfigurationBuilder;
- import org.apache.commons.configuration2.event.Event;
- import org.apache.commons.configuration2.event.EventListener;
- import org.apache.commons.configuration2.event.EventType;
- import org.apache.commons.configuration2.ex.ConfigurationException;
- import org.apache.commons.configuration2.reloading.ReloadingController;
- import org.apache.commons.configuration2.reloading.ReloadingControllerSupport;
- /**
- * <p>
- * A specialized {@code ConfigurationBuilderProvider} implementation for integrating
- * {@link MultiFileConfigurationBuilder} with {@code CombinedConfigurationBuilder}.
- * </p>
- * <p>
- * When using a configuration source managed by {@code MultiFileConfigurationBuilder} it is not sufficient to store the
- * configuration once obtained from the builder in the resulting combined configuration. Rather, it has to be ensured
- * that each access to this configuration queries the builder anew so that it can evaluate its file pattern and return a
- * different configuration if necessary. Therefore, this class returns a specialized wrapper over a
- * {@code MultiFileConfigurationBuilder} which returns a configuration wrapping the builder; so accessing the
- * configuration's properties actually calls back to the builder. This constellation is compatible with the way
- * {@code DynamicCombinedConfiguration} manages its data.
- * </p>
- *
- * @since 2.0
- */
- public class MultiFileConfigurationBuilderProvider extends BaseConfigurationBuilderProvider {
- /**
- * A wrapper builder implementation which also provides a {@code ReloadingController}. This class assumes that the
- * wrapped builder implements {@code ReloadingControllerSupport}. So the reloading controller can be obtained from this
- * object.
- */
- private static final class ReloadableWrapperBuilder extends WrapperBuilder implements ReloadingControllerSupport {
- /** The object for obtaining the reloading controller. */
- private final ReloadingControllerSupport ctrlSupport;
- /**
- * Creates a new instance of {@code ReloadableWrapperBuilder}.
- *
- * @param conf the managed configuration
- * @param bldr the underlying builder (must implement {@code ReloadingControllerSupport})
- */
- public ReloadableWrapperBuilder(final Configuration conf, final ConfigurationBuilder<? extends Configuration> bldr) {
- super(conf, bldr);
- ctrlSupport = (ReloadingControllerSupport) bldr;
- }
- @Override
- public ReloadingController getReloadingController() {
- return ctrlSupport.getReloadingController();
- }
- }
- /**
- * A simple wrapper implementation of the {@code ConfigurationBuilder} interface which returns a fix configuration and
- * delegates to another builder for event listener management.
- */
- private static class WrapperBuilder implements ConfigurationBuilder<Configuration> {
- /** The configuration managed by this builder. */
- private final Configuration configuration;
- /** The builder to which this instance delegates. */
- private final ConfigurationBuilder<? extends Configuration> builder;
- /**
- * Creates a new instance of {@code WrapperBuilder}.
- *
- * @param conf the managed configuration
- * @param bldr the underlying builder
- */
- public WrapperBuilder(final Configuration conf, final ConfigurationBuilder<? extends Configuration> bldr) {
- configuration = conf;
- builder = bldr;
- }
- @Override
- public <T extends Event> void addEventListener(final EventType<T> eventType, final EventListener<? super T> listener) {
- builder.addEventListener(eventType, listener);
- }
- @Override
- public Configuration getConfiguration() throws ConfigurationException {
- return configuration;
- }
- @Override
- public <T extends Event> boolean removeEventListener(final EventType<T> eventType, final EventListener<? super T> listener) {
- return builder.removeEventListener(eventType, listener);
- }
- }
- /** Constant for the name of the builder class. */
- private static final String BUILDER_CLASS = "org.apache.commons.configuration2.builder.combined.MultiFileConfigurationBuilder";
- /** Constant for the name of the reloading builder class. */
- private static final String RELOADING_BUILDER_CLASS = "org.apache.commons.configuration2.builder.combined.ReloadingMultiFileConfigurationBuilder";
- /** Constant for the name of the parameters class. */
- private static final String PARAM_CLASS = "org.apache.commons.configuration2.builder.combined.MultiFileBuilderParametersImpl";
- /**
- * Creates the {@code ConfigurationBuilder} to be returned by this provider. This is a very simple implementation which
- * always returns the same wrapper configuration instance. The handling of builder listeners is delegated to the wrapped
- * {@code MultiFileConfigurationBuilder}. If reloading is support, the builder returned by this method also implements
- * the {@link ReloadingControllerSupport} interface.
- *
- * @param multiBuilder the {@code MultiFileConfigurationBuilder}
- * @param wrapConfig the configuration to be returned
- * @return the wrapper builder
- */
- private static ConfigurationBuilder<? extends Configuration> createWrapperBuilder(final ConfigurationBuilder<? extends Configuration> multiBuilder,
- final Configuration wrapConfig) {
- if (multiBuilder instanceof ReloadingControllerSupport) {
- return new ReloadableWrapperBuilder(wrapConfig, multiBuilder);
- }
- return new WrapperBuilder(wrapConfig, multiBuilder);
- }
- /**
- * Creates a new instance of {@code MultiFileConfigurationBuilderProvider} and sets the name of the configuration class
- * to be returned by {@code MultiFileConfigurationBuilder}.
- *
- * @param configCls the name of the managed configuration class
- * @param paramCls the name of the class of the parameters object to configure the managed configuration
- */
- public MultiFileConfigurationBuilderProvider(final String configCls, final String paramCls) {
- super(BUILDER_CLASS, RELOADING_BUILDER_CLASS, configCls, Arrays.asList(paramCls, PARAM_CLASS));
- }
- /**
- * Creates a configuration which wraps the specified builder.
- *
- * @param builder the builder
- * @return the wrapping configuration
- */
- // It is safe to disable any type checks because we manually determine
- // the interface class to be passed to BuilderConfigurationWrapperFactory
- @SuppressWarnings({"unchecked", "rawtypes"})
- private Configuration createWrapperConfiguration(final ConfigurationBuilder builder) {
- final Class<?> configClass = ConfigurationUtils.loadClassNoEx(getConfigurationClass());
- final Class ifcClass = HierarchicalConfiguration.class.isAssignableFrom(configClass) ? HierarchicalConfiguration.class : Configuration.class;
- return (Configuration) BuilderConfigurationWrapperFactory.createBuilderConfigurationWrapper(ifcClass, builder, EventSourceSupport.BUILDER);
- }
- /**
- * {@inheritDoc} This implementation lets the super class create a fully configured builder. Then it returns a special
- * wrapper around it.
- */
- @Override
- public ConfigurationBuilder<? extends Configuration> getConfigurationBuilder(final ConfigurationDeclaration decl) throws ConfigurationException {
- final ConfigurationBuilder<? extends Configuration> multiBuilder = super.getConfigurationBuilder(decl);
- final Configuration wrapConfig = createWrapperConfiguration(multiBuilder);
- return createWrapperBuilder(multiBuilder, wrapConfig);
- }
- }