Parameters.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.fluent;
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
- import org.apache.commons.configuration2.builder.BasicBuilderParameters;
- import org.apache.commons.configuration2.builder.BuilderParameters;
- import org.apache.commons.configuration2.builder.DatabaseBuilderParametersImpl;
- import org.apache.commons.configuration2.builder.DefaultParametersHandler;
- import org.apache.commons.configuration2.builder.DefaultParametersManager;
- import org.apache.commons.configuration2.builder.FileBasedBuilderParametersImpl;
- import org.apache.commons.configuration2.builder.HierarchicalBuilderParametersImpl;
- import org.apache.commons.configuration2.builder.INIBuilderParametersImpl;
- import org.apache.commons.configuration2.builder.JndiBuilderParametersImpl;
- import org.apache.commons.configuration2.builder.PropertiesBuilderParametersImpl;
- import org.apache.commons.configuration2.builder.XMLBuilderParametersImpl;
- import org.apache.commons.configuration2.builder.combined.CombinedBuilderParametersImpl;
- import org.apache.commons.configuration2.builder.combined.MultiFileBuilderParametersImpl;
- //@formatter:off
- /**
- * A convenience class for creating parameter objects for initializing configuration builder objects.
- * <p>
- * For setting initialization properties of new configuration objects, a number of specialized parameter classes exists.
- * These classes use inheritance to organize the properties they support in a logic way. For instance, parameters for
- * file-based configurations also support the basic properties common to all configuration implementations, parameters
- * for XML configurations also include file-based and basic properties, etc.
- * </p>
- * <p>
- * When constructing a configuration builder, an easy-to-use fluent API is desired to define specific properties for the
- * configuration to be created. However, the inheritance structure of the parameter classes makes it surprisingly
- * difficult to provide such an API. This class comes to rescue by defining a set of methods for the creation of
- * interface-based parameter objects offering a truly fluent API. The methods provided can be called directly when
- * setting up a configuration builder as shown in the following example code fragment:
- * </p>
- * <pre>
- * Parameters params = new Parameters();
- * configurationBuilder.configure(params.fileBased()
- * .setThrowExceptionOnMissing(true)
- * .setEncoding("UTF-8")
- * .setListDelimiter('#')
- * .setFileName("test.xml"));
- * </pre>
- * <p>
- * Using this class it is not only possible to create new parameters objects but also to initialize the newly created
- * objects with default values. This is via the associated {@link DefaultParametersManager} object. Such an object can
- * be passed to the constructor, or a new (uninitialized) instance is created. There are convenience methods for
- * interacting with the associated {@code DefaultParametersManager}, namely to register or remove
- * {@link DefaultParametersHandler} objects. On all newly created parameters objects the handlers registered at the
- * associated {@code DefaultParametersHandler} are automatically applied.
- * </p>
- * <p>
- * Implementation note: This class is thread-safe.
- * </p>
- *
- * @since 2.0
- */
- //@formatter:off
- public final class Parameters {
- /**
- * A specialized {@code InvocationHandler} implementation which maps the methods of a parameters interface to an
- * implementation of the corresponding property interfaces. The parameters interface is a union of multiple property
- * interfaces. The wrapped object implements all of these, but not the union interface. Therefore, a reflection-based
- * approach is required. A special handling is required for the method of the {@code BuilderParameters} interface
- * because here no fluent return value is used.
- */
- private static final class ParametersIfcInvocationHandler implements InvocationHandler {
- /**
- * Checks whether the specified method belongs to an interface which requires fluent result values.
- *
- * @param method the method to be checked
- * @return a flag whether the method's result should be handled as a fluent result value
- */
- private static boolean isFluentResult(final Method method) {
- final Class<?> declaringClass = method.getDeclaringClass();
- return declaringClass.isInterface() && !declaringClass.equals(BuilderParameters.class);
- }
- /** The target object of reflection calls. */
- private final Object target;
- /**
- * Creates a new instance of {@code ParametersIfcInvocationHandler} and sets the wrapped parameters object.
- *
- * @param targetObj the target object for reflection calls
- */
- public ParametersIfcInvocationHandler(final Object targetObj) {
- target = targetObj;
- }
- /**
- * {@inheritDoc} This implementation delegates method invocations to the target object and handles the return value
- * correctly.
- */
- @Override
- public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
- final Object result = method.invoke(target, args);
- return isFluentResult(method) ? proxy : result;
- }
- }
- /** The manager for default handlers. */
- private final DefaultParametersManager defaultParametersManager;
- /**
- * Creates a new instance of {@code Parameters}. A new, uninitialized {@link DefaultParametersManager} is created.
- */
- public Parameters() {
- this(null);
- }
- /**
- * Creates a new instance of {@code Parameters} and initializes it with the given {@code DefaultParametersManager}.
- * Because {@code DefaultParametersManager} is thread-safe, it makes sense to share a single instance between multiple
- * {@code Parameters} objects; that way the same initialization is performed on newly created parameters objects.
- *
- * @param manager the {@code DefaultParametersHandler} (may be <strong>null</strong>, then a new default instance is created)
- */
- public Parameters(final DefaultParametersManager manager) {
- defaultParametersManager = manager != null ? manager : new DefaultParametersManager();
- }
- /**
- * Creates a new instance of a parameters object for basic configuration properties.
- *
- * @return the new parameters object
- */
- public BasicBuilderParameters basic() {
- return new BasicBuilderParameters();
- }
- /**
- * Creates a new instance of a parameters object for combined configuration builder properties.
- *
- * @return the new parameters object
- */
- public CombinedBuilderParameters combined() {
- return createParametersProxy(new CombinedBuilderParametersImpl(), CombinedBuilderParameters.class);
- }
- /**
- * Creates a proxy object for a given parameters interface based on the given implementation object. The newly created
- * object is initialized with default values if there are matching {@link DefaultParametersHandler} objects.
- *
- * @param <T> the type of the parameters interface
- * @param target the implementing target object
- * @param ifcClass the interface class
- * @param superIfcs an array with additional interface classes to be implemented
- * @return the proxy object
- */
- private <T> T createParametersProxy(final Object target, final Class<T> ifcClass, final Class<?>... superIfcs) {
- final Class<?>[] ifcClasses = new Class<?>[1 + superIfcs.length];
- ifcClasses[0] = ifcClass;
- System.arraycopy(superIfcs, 0, ifcClasses, 1, superIfcs.length);
- final Object obj = Proxy.newProxyInstance(Parameters.class.getClassLoader(), ifcClasses, new ParametersIfcInvocationHandler(target));
- getDefaultParametersManager().initializeParameters((BuilderParameters) obj);
- return ifcClass.cast(obj);
- }
- /**
- * Creates a new instance of a parameters object for database configurations.
- *
- * @return the new parameters object
- */
- public DatabaseBuilderParameters database() {
- return createParametersProxy(new DatabaseBuilderParametersImpl(), DatabaseBuilderParameters.class);
- }
- /**
- * Creates a new instance of a parameters object for file-based configuration properties.
- *
- * @return the new parameters object
- */
- public FileBasedBuilderParameters fileBased() {
- return createParametersProxy(new FileBasedBuilderParametersImpl(), FileBasedBuilderParameters.class);
- }
- /**
- * Gets the {@code DefaultParametersManager} associated with this object.
- *
- * @return the {@code DefaultParametersManager}
- */
- public DefaultParametersManager getDefaultParametersManager() {
- return defaultParametersManager;
- }
- /**
- * Creates a new instance of a parameters object for hierarchical configurations.
- *
- * @return the new parameters object
- */
- public HierarchicalBuilderParameters hierarchical() {
- return createParametersProxy(new HierarchicalBuilderParametersImpl(), HierarchicalBuilderParameters.class, FileBasedBuilderParameters.class);
- }
- /**
- * Creates a new instance of a parameters object for INI configurations.
- *
- * @return the new parameters object
- */
- public INIBuilderParameters ini() {
- return createParametersProxy(new INIBuilderParametersImpl(), INIBuilderParameters.class, FileBasedBuilderParameters.class,
- HierarchicalBuilderParameters.class);
- }
- /**
- * Creates a new instance of a parameters object for JNDI configurations.
- *
- * @return the new parameters object
- */
- public JndiBuilderParameters jndi() {
- return createParametersProxy(new JndiBuilderParametersImpl(), JndiBuilderParameters.class);
- }
- /**
- * Creates a new instance of a parameters object for a builder for multiple file-based configurations.
- *
- * @return the new parameters object
- */
- public MultiFileBuilderParameters multiFile() {
- return createParametersProxy(new MultiFileBuilderParametersImpl(), MultiFileBuilderParameters.class);
- }
- /**
- * Creates a new instance of a parameters object for properties configurations.
- *
- * @return the new parameters object
- */
- public PropertiesBuilderParameters properties() {
- return createParametersProxy(new PropertiesBuilderParametersImpl(), PropertiesBuilderParameters.class, FileBasedBuilderParameters.class);
- }
- /**
- * Registers the specified {@code DefaultParametersHandler} object for the given parameters class. This is a convenience
- * method which just delegates to the associated {@code DefaultParametersManager}.
- *
- * @param <T> the type of the parameters supported by this handler
- * @param paramsClass the parameters class supported by this handler (must not be <strong>null</strong>)
- * @param handler the {@code DefaultParametersHandler} to be registered (must not be <strong>null</strong>)
- * @throws IllegalArgumentException if a required parameter is missing
- * @see DefaultParametersManager
- */
- public <T> void registerDefaultsHandler(final Class<T> paramsClass, final DefaultParametersHandler<? super T> handler) {
- getDefaultParametersManager().registerDefaultsHandler(paramsClass, handler);
- }
- /**
- * Registers the specified {@code DefaultParametersHandler} object for the given parameters class and start class in the
- * inheritance hierarchy. This is a convenience method which just delegates to the associated
- * {@code DefaultParametersManager}.
- *
- * @param <T> the type of the parameters supported by this handler
- * @param paramsClass the parameters class supported by this handler (must not be <strong>null</strong>)
- * @param handler the {@code DefaultParametersHandler} to be registered (must not be <strong>null</strong>)
- * @param startClass an optional start class in the hierarchy of parameter objects for which this handler should be
- * applied
- * @throws IllegalArgumentException if a required parameter is missing
- */
- public <T> void registerDefaultsHandler(final Class<T> paramsClass, final DefaultParametersHandler<? super T> handler, final Class<?> startClass) {
- getDefaultParametersManager().registerDefaultsHandler(paramsClass, handler, startClass);
- }
- /**
- * Creates a new instance of a parameters object for XML configurations.
- *
- * @return the new parameters object
- */
- public XMLBuilderParameters xml() {
- return createParametersProxy(new XMLBuilderParametersImpl(), XMLBuilderParameters.class, FileBasedBuilderParameters.class,
- HierarchicalBuilderParameters.class);
- }
- }