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
9
* http://www.apache.org/licenses/LICENSE-2.0
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.
18
package org.apache.commons.configuration;
20
import static org.junit.Assert.assertEquals;
21
import static org.junit.Assert.assertFalse;
22
import static org.junit.Assert.assertNotNull;
23
import static org.junit.Assert.assertTrue;
26
import java.io.FileReader;
27
import java.io.FileWriter;
28
import java.io.IOException;
29
import java.io.Reader;
30
import java.io.Writer;
32
import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
33
import org.apache.commons.lang.text.StrLookup;
34
import org.junit.Test;
36
public class TestDynamicCombinedConfiguration
38
private static String PATTERN = "${sys:Id}";
39
private static String PATTERN1 = "target/test-classes/testMultiConfiguration_${sys:Id}.xml";
40
private static String DEFAULT_FILE = "target/test-classes/testMultiConfiguration_default.xml";
41
private static final File MULTI_TENENT_FILE = new File(
42
"conf/testMultiTenentConfigurationBuilder4.xml");
43
private static final File MULTI_DYNAMIC_FILE = new File(
44
"conf/testMultiTenentConfigurationBuilder5.xml");
46
/** Constant for the number of test threads. */
47
private static final int THREAD_COUNT = 3;
49
/** Constant for the number of loops in the multi-thread tests. */
50
private static final int LOOP_COUNT = 100;
53
public void testConfiguration() throws Exception
55
DynamicCombinedConfiguration config = new DynamicCombinedConfiguration();
56
XPathExpressionEngine engine = new XPathExpressionEngine();
57
config.setExpressionEngine(engine);
58
config.setKeyPattern(PATTERN);
59
config.setDelimiterParsingDisabled(true);
60
MultiFileHierarchicalConfiguration multi = new MultiFileHierarchicalConfiguration(PATTERN1);
61
multi.setExpressionEngine(engine);
62
config.addConfiguration(multi, "Multi");
63
XMLConfiguration xml = new XMLConfiguration();
64
xml.setExpressionEngine(engine);
65
xml.setDelimiterParsingDisabled(true);
66
xml.setFile(new File(DEFAULT_FILE));
68
config.addConfiguration(xml, "Default");
70
verify("1001", config, 15);
71
verify("1002", config, 25);
72
verify("1003", config, 35);
73
verify("1004", config, 50);
74
assertEquals("a,b,c", config.getString("split/list3/@values"));
75
assertEquals(0, config.getMaxIndex("split/list3/@values"));
76
assertEquals("a\\,b\\,c", config.getString("split/list4/@values"));
77
assertEquals("a,b,c", config.getString("split/list1"));
78
assertEquals(0, config.getMaxIndex("split/list1"));
79
assertEquals("a\\,b\\,c", config.getString("split/list2"));
83
public void testConcurrentGetAndReload() throws Exception
85
System.getProperties().remove("Id");
86
DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
87
factory.setFile(MULTI_TENENT_FILE);
88
CombinedConfiguration config = factory.getConfiguration(true);
90
assertEquals(config.getString("rowsPerPage"), "50");
91
Thread testThreads[] = new Thread[THREAD_COUNT];
92
int failures[] = new int[THREAD_COUNT];
94
for (int i = 0; i < testThreads.length; ++i)
96
testThreads[i] = new ReloadThread(config, failures, i, LOOP_COUNT, false, null, "50");
97
testThreads[i].start();
100
int totalFailures = 0;
101
for (int i = 0; i < testThreads.length; ++i)
103
testThreads[i].join();
104
totalFailures += failures[i];
106
assertTrue(totalFailures + " failures Occurred", totalFailures == 0);
110
public void testConcurrentGetAndReload2() throws Exception
112
System.getProperties().remove("Id");
113
DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
114
factory.setFile(MULTI_TENENT_FILE);
115
CombinedConfiguration config = factory.getConfiguration(true);
117
assertEquals(config.getString("rowsPerPage"), "50");
119
Thread testThreads[] = new Thread[THREAD_COUNT];
120
int failures[] = new int[THREAD_COUNT];
121
System.setProperty("Id", "2002");
122
assertEquals(config.getString("rowsPerPage"), "25");
123
for (int i = 0; i < testThreads.length; ++i)
125
testThreads[i] = new ReloadThread(config, failures, i, LOOP_COUNT, false, null, "25");
126
testThreads[i].start();
129
int totalFailures = 0;
130
for (int i = 0; i < testThreads.length; ++i)
132
testThreads[i].join();
133
totalFailures += failures[i];
135
System.getProperties().remove("Id");
136
assertTrue(totalFailures + " failures Occurred", totalFailures == 0);
140
public void testConcurrentGetAndReloadMultipleClients() throws Exception
142
System.getProperties().remove("Id");
143
DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
144
factory.setFile(MULTI_TENENT_FILE);
145
CombinedConfiguration config = factory.getConfiguration(true);
147
assertEquals(config.getString("rowsPerPage"), "50");
149
Thread testThreads[] = new Thread[THREAD_COUNT];
150
int failures[] = new int[THREAD_COUNT];
151
String[] ids = new String[] {null, "2002", "3001", "3002", "3003"};
152
String[] expected = new String[] {"50", "25", "15", "25", "50"};
153
for (int i = 0; i < testThreads.length; ++i)
155
testThreads[i] = new ReloadThread(config, failures, i, LOOP_COUNT, true, ids[i], expected[i]);
156
testThreads[i].start();
159
int totalFailures = 0;
160
for (int i = 0; i < testThreads.length; ++i)
162
testThreads[i].join();
163
totalFailures += failures[i];
165
System.getProperties().remove("Id");
166
if (totalFailures != 0)
168
System.out.println("Failures:");
169
for (int i = 0; i < testThreads.length; ++i)
171
System.out.println("Thread " + i + " " + failures[i]);
174
assertTrue(totalFailures + " failures Occurred", totalFailures == 0);
178
public void testConcurrentGetAndReloadFile() throws Exception
180
final int threadCount = 25;
181
System.getProperties().remove("Id");
182
// create a new configuration
183
File input = new File("target/test-classes/testMultiDynamic_default.xml");
184
File output = new File("target/test-classes/testwrite/testMultiDynamic_default.xml");
186
output.getParentFile().mkdir();
187
copyFile(input, output);
189
DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder();
190
factory.setFile(MULTI_DYNAMIC_FILE);
191
CombinedConfiguration config = factory.getConfiguration(true);
193
assertEquals(config.getString("Product/FIIndex/FI[@id='123456781']"), "ID0001");
195
ReaderThread testThreads[] = new ReaderThread[threadCount];
196
for (int i = 0; i < testThreads.length; ++i)
198
testThreads[i] = new ReaderThread(config);
199
testThreads[i].start();
204
input = new File("target/test-classes/testMultiDynamic_default2.xml");
205
copyFile(input, output);
208
String id = config.getString("Product/FIIndex/FI[@id='123456782']");
209
assertNotNull("File did not reload, id is null", id);
210
String rows = config.getString("rowsPerPage");
211
assertTrue("Incorrect value for rowsPerPage", "25".equals(rows));
213
for (int i = 0; i < testThreads.length; ++i)
215
testThreads[i].shutdown();
216
testThreads[i].join();
218
for (int i = 0; i < testThreads.length; ++i)
220
assertFalse(testThreads[i].failed());
222
assertEquals("ID0002", config.getString("Product/FIIndex/FI[@id='123456782']"));
227
private class ReloadThread extends Thread
229
CombinedConfiguration combined;
237
ReloadThread(CombinedConfiguration config, int[] failures, int index, int count,
238
boolean useId, String id, String expected)
241
this.failures = failures;
244
this.expected = expected;
255
ThreadLookup.setId(id);
257
for (int i = 0; i < count; i++)
261
String value = combined.getString("rowsPerPage", null);
262
if (value == null || !value.equals(expected))
275
private class ReaderThread extends Thread
277
private boolean running = true;
278
private boolean failed = false;
279
CombinedConfiguration combined;
281
public ReaderThread(CombinedConfiguration c)
291
String bcId = combined.getString("Product/FIIndex/FI[@id='123456781']");
292
if ("ID0001".equalsIgnoreCase(bcId))
296
System.out.println("Thread failed, but recovered");
307
public boolean failed()
312
public void shutdown()
319
private void verify(String key, DynamicCombinedConfiguration config, int rows)
321
System.setProperty("Id", key);
322
assertTrue(config.getInt("rowsPerPage") == rows);
325
private void copyFile(File input, File output) throws IOException
327
Reader reader = new FileReader(input);
328
Writer writer = new FileWriter(output);
329
char[] buffer = new char[4096];
331
while (-1 != (n = reader.read(buffer)))
333
writer.write(buffer, 0, n);
339
public static class ThreadLookup extends StrLookup
341
private static ThreadLocal<String> id = new ThreadLocal<String>();
345
public ThreadLookup()
350
public static void setId(String value)
356
public String lookup(String key)
358
if (key == null || !key.equals("Id"))
362
String value = System.getProperty("Id");