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