View Javadoc
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    *     https://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  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertThrows;
21  import static org.junit.jupiter.api.Assertions.assertTrue;
22  
23  import java.util.ArrayList;
24  import java.util.Arrays;
25  import java.util.Collection;
26  import java.util.Collections;
27  
28  import org.apache.commons.configuration2.BaseHierarchicalConfiguration;
29  import org.apache.commons.configuration2.Configuration;
30  import org.apache.commons.configuration2.ConfigurationAssert;
31  import org.apache.commons.configuration2.HierarchicalConfiguration;
32  import org.apache.commons.configuration2.PropertiesConfiguration;
33  import org.apache.commons.configuration2.builder.BasicBuilderParameters;
34  import org.apache.commons.configuration2.builder.BasicConfigurationBuilder;
35  import org.apache.commons.configuration2.builder.BuilderParameters;
36  import org.apache.commons.configuration2.builder.ConfigurationBuilder;
37  import org.apache.commons.configuration2.builder.FileBasedBuilderParametersImpl;
38  import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
39  import org.apache.commons.configuration2.builder.ReloadingFileBasedConfigurationBuilder;
40  import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
41  import org.apache.commons.configuration2.convert.DisabledListDelimiterHandler;
42  import org.apache.commons.configuration2.ex.ConfigurationException;
43  import org.junit.jupiter.api.Test;
44  
45  /**
46   * Test class for {@code BaseConfigurationBuilderProvider}.
47   */
48  public class TestBaseConfigurationBuilderProvider {
49  
50      /**
51       * Helper method for testing whether the builder's allowFailOnInit flag is set correctly.
52       *
53       * @param expFlag the expected flag value
54       * @param props the properties to set in the configuration for the declaration
55       * @throws ConfigurationException if an error occurs
56       */
57      private void checkAllowFailOnInit(final boolean expFlag, final String... props) throws ConfigurationException {
58          final HierarchicalConfiguration<?> declConfig = setUpConfig(false);
59          for (final String key : props) {
60              declConfig.addProperty(key, Boolean.TRUE);
61          }
62          final ConfigurationDeclaration decl = createDeclaration(declConfig);
63          final BasicConfigurationBuilder<? extends Configuration> builder = (BasicConfigurationBuilder<? extends Configuration>) createProvider()
64              .getConfigurationBuilder(decl);
65          assertEquals(expFlag, builder.isAllowFailOnInit());
66      }
67  
68      /**
69       * Helper method for setting up a builder and checking properties of the created configuration object.
70       *
71       * @param reload a flag whether reloading is supported
72       * @return the builder created by the provider
73       * @throws ConfigurationException if an error occurs
74       */
75      private ConfigurationBuilder<? extends Configuration> checkBuilder(final boolean reload) throws ConfigurationException {
76          final HierarchicalConfiguration<?> declConfig = setUpConfig(reload);
77          final ConfigurationDeclaration decl = createDeclaration(declConfig);
78          final ConfigurationBuilder<? extends Configuration> builder = createProvider().getConfigurationBuilder(decl);
79          final Configuration config = builder.getConfiguration();
80          assertEquals(PropertiesConfiguration.class, config.getClass());
81          final PropertiesConfiguration pconfig = (PropertiesConfiguration) config;
82          assertTrue(pconfig.isThrowExceptionOnMissing());
83          final DefaultListDelimiterHandler listHandler = (DefaultListDelimiterHandler) pconfig.getListDelimiterHandler();
84          assertEquals(';', listHandler.getDelimiter());
85          assertTrue(pconfig.getBoolean("configuration.loaded"));
86          return builder;
87      }
88  
89      /**
90       * Creates a configuration declaration based on the given configuration.
91       *
92       * @param declConfig the configuration for the declaration
93       * @return the declaration
94       */
95      private ConfigurationDeclaration createDeclaration(final HierarchicalConfiguration<?> declConfig) {
96          final CombinedConfigurationBuilder parentBuilder = new CombinedConfigurationBuilder() {
97              @Override
98              protected void initChildBuilderParameters(final BuilderParameters params) {
99                  // set a property value; this should be overridden by
100                 // child builders
101                 if (params instanceof BasicBuilderParameters) {
102                     ((BasicBuilderParameters) params).setListDelimiterHandler(DisabledListDelimiterHandler.INSTANCE);
103                 }
104             }
105         };
106         return new ConfigurationDeclaration(parentBuilder, declConfig) {
107             @Override
108             protected Object interpolate(final Object value) {
109                 return value;
110             }
111         };
112     }
113 
114     /**
115      * Creates a default test instance.
116      *
117      * @return the test instance
118      */
119     private BaseConfigurationBuilderProvider createProvider() {
120         return new BaseConfigurationBuilderProvider(FileBasedConfigurationBuilder.class.getName(), ReloadingFileBasedConfigurationBuilder.class.getName(),
121             PropertiesConfiguration.class.getName(), Arrays.asList(FileBasedBuilderParametersImpl.class.getName()));
122     }
123 
124     /**
125      * Creates a configuration object describing a configuration source.
126      *
127      * @param reload a flag whether reload operations are supported
128      * @return the configuration object
129      */
130     private HierarchicalConfiguration<?> setUpConfig(final boolean reload) {
131         final HierarchicalConfiguration<?> config = new BaseHierarchicalConfiguration();
132         config.addProperty(CombinedConfigurationBuilder.ATTR_RELOAD, Boolean.valueOf(reload));
133         config.addProperty("[@throwExceptionOnMissing]", Boolean.TRUE);
134         config.addProperty("[@path]", ConfigurationAssert.getTestFile("test.properties").getAbsolutePath());
135         config.addProperty("listDelimiterHandler[@config-class]", DefaultListDelimiterHandler.class.getName());
136         config.addProperty("listDelimiterHandler.config-constrarg[@config-value]", ";");
137         return config;
138     }
139 
140     /**
141      * Tests whether the allowFailOnInit flag can be enabled on the builder.
142      */
143     @Test
144     void testGetBuilderAllowFailOnInit() throws ConfigurationException {
145         checkAllowFailOnInit(true, CombinedConfigurationBuilder.ATTR_OPTIONAL_RES, CombinedConfigurationBuilder.ATTR_FORCECREATE);
146     }
147 
148     /**
149      * Tests that the allowFailOnInit flag is not set for builders which are not optional.
150      */
151     void testGetBuilderAllowFailOnInitNotOptional() throws ConfigurationException {
152         checkAllowFailOnInit(false, CombinedConfigurationBuilder.ATTR_FORCECREATE);
153     }
154 
155     /**
156      * Tests that the allowFailOnInit flag is not set per default on the builder.
157      */
158     @Test
159     void testGetBuilderNoFailOnInit() throws ConfigurationException {
160         checkAllowFailOnInit(false);
161     }
162 
163     /**
164      * Tests whether a builder without reloading support can be created.
165      */
166     @Test
167     void testGetBuilderNotReloading() throws ConfigurationException {
168         final ConfigurationBuilder<? extends Configuration> builder = checkBuilder(false);
169         assertEquals(FileBasedConfigurationBuilder.class, builder.getClass());
170     }
171 
172     /**
173      * Tests whether a builder with reloading support can be created.
174      */
175     @Test
176     void testGetBuilderReloading() throws ConfigurationException {
177         final ConfigurationBuilder<? extends Configuration> builder = checkBuilder(true);
178         assertEquals(ReloadingFileBasedConfigurationBuilder.class, builder.getClass());
179     }
180 
181     /**
182      * Tests that the collection with parameter classes cannot be modified.
183      */
184     @Test
185     void testGetParameterClassesModify() {
186         final BaseConfigurationBuilderProvider provider = new BaseConfigurationBuilderProvider(BasicConfigurationBuilder.class.getName(), null,
187             PropertiesConfiguration.class.getName(), Arrays.asList(BasicBuilderParameters.class.getName()));
188         final Collection<String> parameterClasses = provider.getParameterClasses();
189         assertThrows(UnsupportedOperationException.class, parameterClasses::clear);
190     }
191 
192     /**
193      * Tries to create a reloading builder if this is not supported by the provider.
194      */
195     @Test
196     void testGetReloadingBuilderNotSupported() {
197         final BaseConfigurationBuilderProvider provider = new BaseConfigurationBuilderProvider(FileBasedConfigurationBuilder.class.getName(), null,
198             PropertiesConfiguration.class.getName(), Arrays.asList(FileBasedBuilderParametersImpl.class.getName()));
199         final HierarchicalConfiguration<?> declConfig = setUpConfig(true);
200         final ConfigurationDeclaration decl = createDeclaration(declConfig);
201         assertThrows(ConfigurationException.class, () -> provider.getConfigurationBuilder(decl));
202     }
203 
204     /**
205      * Tries to create an instance without a builder class.
206      */
207     @Test
208     void testInitNoBuilderClass() {
209         final String configClass = PropertiesConfiguration.class.getName();
210         assertThrows(IllegalArgumentException.class, () -> new BaseConfigurationBuilderProvider(null, null, configClass, null));
211     }
212 
213     /**
214      * Tries to create an instance without a configuration class.
215      */
216     @Test
217     void testInitNoConfigurationClass() {
218         final String builderClass = BasicConfigurationBuilder.class.getName();
219         assertThrows(IllegalArgumentException.class, () -> new BaseConfigurationBuilderProvider(builderClass, null, null, null));
220     }
221 
222     /**
223      * Tests whether a null collection of parameter classes is handled correctly.
224      */
225     @Test
226     void testInitNoParameterClasses() {
227         final BaseConfigurationBuilderProvider provider = new BaseConfigurationBuilderProvider(BasicConfigurationBuilder.class.getName(), null,
228             PropertiesConfiguration.class.getName(), null);
229         assertEquals(Collections.emptyList(), new ArrayList<>(provider.getParameterClasses()));
230     }
231 }