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

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

Go to download

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

The 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.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.apache.commons.configuration2.ConfigurationUtils;
import org.apache.commons.configuration2.ImmutableConfiguration;
import org.apache.commons.configuration2.event.EventSource;
import org.apache.commons.configuration2.ex.ConfigurationException;

/**
 * 

* A class that allows the creation of configuration objects wrapping a {@link ConfigurationBuilder}. *

*

* Using this class special {@code ImmutableConfiguration} proxies can be created that delegate all method invocations * to another {@code ImmutableConfiguration} obtained from a {@code ConfigurationBuilder}. For instance, if there is a * configuration {@code c} wrapping the builder {@code builder}, the call {@code c.getString(myKey)} is transformed to * {@code builder.getConfiguration().getString(myKey)}. *

*

* There are multiple use cases for such a constellation. One example is that client code can continue working with * {@code ImmutableConfiguration} objects while under the hood builders are used. Another example is that dynamic * configurations can be realized in a transparent way: a client holds a single configuration (proxy) object, but the * underlying builder may return a different data object on each call. *

* * @since 2.0 */ public class BuilderConfigurationWrapperFactory { /** * A specialized {@code InvocationHandler} implementation for wrapper configurations. Here the logic of accessing a * wrapped builder is implemented. */ private static final class BuilderConfigurationWrapperInvocationHandler implements InvocationHandler { /** The wrapped builder. */ private final ConfigurationBuilder builder; /** The level of {@code EventSource} support. */ private final EventSourceSupport eventSourceSupport; /** * Creates a new instance of {@code BuilderConfigurationWrapperInvocationHandler}. * * @param wrappedBuilder the wrapped builder * @param evSrcSupport the level of {@code EventSource} support */ public BuilderConfigurationWrapperInvocationHandler(final ConfigurationBuilder wrappedBuilder, final EventSourceSupport evSrcSupport) { builder = wrappedBuilder; eventSourceSupport = evSrcSupport; } /** * Handles a method invocation on the associated builder's configuration object. * * @param method the method to be invoked * @param args method arguments * @return the return value of the method * @throws Exception if an error occurs */ private Object handleConfigurationInvocation(final Method method, final Object[] args) throws ReflectiveOperationException, ConfigurationException { return method.invoke(builder.getConfiguration(), args); } /** * Handles a method invocation on the {@code EventSource} interface. This method evaluates the current * {@code EventSourceSupport} object in order to find the appropriate target for the invocation. * * @param method the method to be invoked * @param args method arguments * @return the return value of the method * @throws ReflectiveOperationException if an error occurs */ private Object handleEventSourceInvocation(final Method method, final Object... args) throws ReflectiveOperationException { return method.invoke(EventSourceSupport.DUMMY == eventSourceSupport ? ConfigurationUtils.asEventSource(this, true) : builder, args); } /** * Handles method invocations. This implementation handles methods of two different interfaces: *
    *
  • Methods from the {@code EventSource} interface are handled according to the current support level.
  • *
  • Other method calls are delegated to the builder's configuration object.
  • *
* * @param proxy the proxy object * @param method the method to be invoked * @param args method arguments * @return the return value of the method * @throws ReflectiveOperationException if an error occurs * @throws ConfigurationException if an error occurs */ @Override public Object invoke(final Object proxy, final Method method, final Object[] args) throws ReflectiveOperationException, ConfigurationException { return EventSource.class.equals(method.getDeclaringClass()) ? handleEventSourceInvocation(method, args) : handleConfigurationInvocation(method, args); } } /** *

* An enumeration class with different options for supporting the {@code EventSource} interface in generated * {@code ImmutableConfiguration} proxies. *

*

* Using literals of this class it is possible to specify that a {@code ImmutableConfiguration} object returned by * {@code BuilderConfigurationWrapperFactory} also implements the {@code EventSource} interface and how this * implementation should work. See the documentation of the single constants for more details. *

*/ public enum EventSourceSupport { /** * No support of the {@code EventSource} interface. If this option is set, {@code ImmutableConfiguration} objects * generated by {@code BuilderConfigurationWrapperFactory} do not implement the {@code EventSource} interface. */ NONE, /** * Dummy support of the {@code EventSource} interface. This option causes {@code ImmutableConfiguration} objects * generated by {@code BuilderConfigurationWrapperFactory} to implement the {@code EventSource} interface, however, this * implementation consists only of empty dummy methods without real functionality. */ DUMMY, /** * {@code EventSource} support is implemented by delegating to the associated {@code ConfigurationBuilder} object. If * this option is used, generated {@code ImmutableConfiguration} objects provide a fully functional implementation of * {@code EventSource} by delegating to the builder. Because the {@code ConfigurationBuilder} interface extends * {@code EventSource} this delegation is always possible. */ BUILDER } /** * Creates a {@code ImmutableConfiguration} object which wraps the specified {@code ConfigurationBuilder}. Each access * of the configuration is delegated to a corresponding call on the {@code ImmutableConfiguration} object managed by the * builder. This is a convenience method which allows creating wrapper configurations without having to instantiate this * class. * * @param the type of the configuration objects returned by this method * @param ifcClass the class of the configuration objects returned by this method; this must be an interface class and * must not be null * @param builder the wrapped {@code ConfigurationBuilder} (must not be null) * @param evSrcSupport the level of {@code EventSource} support * @return the wrapper configuration * @throws IllegalArgumentException if a required parameter is missing * @throws org.apache.commons.configuration2.ex.ConfigurationRuntimeException if an error occurs when creating the * result {@code ImmutableConfiguration} */ public static T createBuilderConfigurationWrapper(final Class ifcClass, final ConfigurationBuilder builder, final EventSourceSupport evSrcSupport) { if (ifcClass == null) { throw new IllegalArgumentException("Interface class must not be null!"); } if (builder == null) { throw new IllegalArgumentException("Builder must not be null!"); } return ifcClass.cast(Proxy.newProxyInstance(BuilderConfigurationWrapperFactory.class.getClassLoader(), getSupportedInterfaces(ifcClass, evSrcSupport), new BuilderConfigurationWrapperInvocationHandler(builder, evSrcSupport))); } /** * Gets an array with the classes the generated proxy has to support. * * @param ifcClass the class of the configuration objects returned by this method; this must be an interface class and * must not be null * @param evSrcSupport the level of {@code EventSource} support * @return an array with the interface classes to implement */ private static Class[] getSupportedInterfaces(final Class ifcClass, final EventSourceSupport evSrcSupport) { return EventSourceSupport.NONE == evSrcSupport ? new Class[] {ifcClass} : new Class[] {EventSource.class, ifcClass}; } /** The current {@code EventSourceSupport} value. */ private final EventSourceSupport eventSourceSupport; /** * Creates a new instance of {@code BuilderConfigurationWrapperFactory} setting the default {@code EventSourceSupport} * NONE. */ public BuilderConfigurationWrapperFactory() { this(EventSourceSupport.NONE); } /** * Creates a new instance of {@code BuilderConfigurationWrapperFactory} and sets the property for supporting the * {@code EventSource} interface. * * @param evSrcSupport the level of {@code EventSource} support */ public BuilderConfigurationWrapperFactory(final EventSourceSupport evSrcSupport) { eventSourceSupport = evSrcSupport; } /** * Creates a wrapper {@code ImmutableConfiguration} on top of the specified {@code ConfigurationBuilder}. This * implementation delegates to * {@link #createBuilderConfigurationWrapper(Class, ConfigurationBuilder, EventSourceSupport)} . * * @param the type of the configuration objects returned by this method * @param ifcClass the class of the configuration objects returned by this method; this must be an interface class and * must not be null * @param builder the wrapped {@code ConfigurationBuilder} (must not be null) * @return the wrapper configuration * @throws IllegalArgumentException if a required parameter is missing * @throws org.apache.commons.configuration2.ex.ConfigurationRuntimeException if an error occurs when creating the * result {@code ImmutableConfiguration} */ public T createBuilderConfigurationWrapper(final Class ifcClass, final ConfigurationBuilder builder) { return createBuilderConfigurationWrapper(ifcClass, builder, getEventSourceSupport()); } /** * Gets the level of {@code EventSource} support used when generating {@code ImmutableConfiguration} objects. * * @return the level of {@code EventSource} support */ public EventSourceSupport getEventSourceSupport() { return eventSourceSupport; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy