FileExtensionConfigurationBuilderProvider.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.configuration2.builder.combined;

  18. import java.util.Collection;

  19. import org.apache.commons.configuration2.builder.BuilderParameters;
  20. import org.apache.commons.configuration2.builder.FileBasedBuilderParametersImpl;
  21. import org.apache.commons.configuration2.ex.ConfigurationException;

  22. /**
  23.  * <p>
  24.  * A specialized implementation of {@link ConfigurationBuilderProvider} which determines the name of the result
  25.  * configuration class based on the extension of the file to load.
  26.  * </p>
  27.  * <p>
  28.  * This class works analogously to its base class {@link BaseConfigurationBuilderProvider}; especially, the resulting
  29.  * builder is created based on reflection. It extends the super class's functionality by a specific mechanism for
  30.  * determining the resulting configuration class: At construction time two configuration class names and a file
  31.  * extension are passed in. If a file name is provided in the builder's initialization parameters and this file name has
  32.  * the specified extension, then the first configuration class name is used; otherwise the default configuration class
  33.  * name is selected.
  34.  * </p>
  35.  * <p>
  36.  * There are some tags for {@code CombinedConfigurationProvider} which can produce different results depending on the
  37.  * configuration files they have to load. This class can be used to implement this feature in a generic way.
  38.  * </p>
  39.  *
  40.  * @since 2.0
  41.  */
  42. public class FileExtensionConfigurationBuilderProvider extends BaseConfigurationBuilderProvider {
  43.     /** Constant for the file extension separator. */
  44.     private static final char EXT_SEPARATOR = '.';

  45.     /**
  46.      * Extracts the extension from the given file name. The name can be <strong>null</strong>.
  47.      *
  48.      * @param fileName the file name
  49.      * @return the extension (<strong>null</strong> if there is none)
  50.      */
  51.     private static String extractExtension(final String fileName) {
  52.         if (fileName == null) {
  53.             return null;
  54.         }

  55.         final int pos = fileName.lastIndexOf(EXT_SEPARATOR);
  56.         return pos < 0 ? null : fileName.substring(pos + 1);
  57.     }

  58.     /**
  59.      * Tries to obtain the current file name from the given list of parameter objects.
  60.      *
  61.      * @param params the parameter objects
  62.      * @return the file name or <strong>null</strong> if unspecified
  63.      */
  64.     private static String fetchCurrentFileName(final Collection<BuilderParameters> params) {
  65.         for (final BuilderParameters p : params) {
  66.             if (p instanceof FileBasedBuilderParametersImpl) {
  67.                 final FileBasedBuilderParametersImpl fp = (FileBasedBuilderParametersImpl) p;
  68.                 return fp.getFileHandler().getFileName();
  69.             }
  70.         }
  71.         return null;
  72.     }

  73.     /** The matching configuration class. */
  74.     private final String matchingConfigurationClass;

  75.     /** The file extension. */
  76.     private final String extension;

  77.     /**
  78.      * Creates a new instance of {@code FileExtensionConfigurationBuilderProvider}.
  79.      *
  80.      * @param bldrCls the name of the builder class
  81.      * @param reloadBldrCls the name of a builder class to be used if reloading support is required (<strong>null</strong> if
  82.      *        reloading is not supported)
  83.      * @param matchingConfigCls the name of the configuration class to be used if the provided file extension matches (must
  84.      *        not be <strong>null</strong>)
  85.      * @param defConfigClass the name of the configuration class to be used if the provided file extension does not match
  86.      *        (must not be <strong>null</strong>)
  87.      * @param ext the file extension to select the configuration class (must not be <strong>null</strong>)
  88.      * @param paramCls a collection with the names of parameters classes; an instance of a parameters object with basic
  89.      *        properties is created automatically and does not need to be contained in this list; the collection can be
  90.      *        <strong>null</strong> if no additional parameter objects are needed
  91.      * @throws IllegalArgumentException if a required parameter is missing
  92.      */
  93.     public FileExtensionConfigurationBuilderProvider(final String bldrCls, final String reloadBldrCls, final String matchingConfigCls,
  94.         final String defConfigClass, final String ext, final Collection<String> paramCls) {
  95.         super(bldrCls, reloadBldrCls, defConfigClass, paramCls);
  96.         if (matchingConfigCls == null) {
  97.             throw new IllegalArgumentException("Matching configuration class must not be null!");
  98.         }
  99.         if (ext == null) {
  100.             throw new IllegalArgumentException("File extension must not be null!");
  101.         }

  102.         matchingConfigurationClass = matchingConfigCls;
  103.         extension = ext;
  104.     }

  105.     /**
  106.      * {@inheritDoc} This implementation tries to find a {@link FileBasedBuilderParametersImpl} object in the parameter
  107.      * objects. If one is found, the extension of the file name is obtained and compared against the stored file extension.
  108.      * In case of a match, the matching configuration class is selected, otherwise the default one.
  109.      */
  110.     @Override
  111.     protected String determineConfigurationClass(final ConfigurationDeclaration decl, final Collection<BuilderParameters> params)
  112.         throws ConfigurationException {
  113.         final String currentExt = extractExtension(fetchCurrentFileName(params));
  114.         return getExtension().equalsIgnoreCase(currentExt) ? getMatchingConfigurationClass() : getConfigurationClass();
  115.     }

  116.     /**
  117.      * Gets the file extension of this provider.
  118.      *
  119.      * @return the file extension to match
  120.      */
  121.     public String getExtension() {
  122.         return extension;
  123.     }

  124.     /**
  125.      * Gets the name of the matching configuration class. This class is used if the file extension matches the extension
  126.      * of this provider.
  127.      *
  128.      * @return the matching configuration class
  129.      */
  130.     public String getMatchingConfigurationClass() {
  131.         return matchingConfigurationClass;
  132.     }
  133. }