Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ConfigurationManagementImpl |
|
| 0.0;0 | ||||
ConfigurationManagementImpl$1 |
|
| 0.0;0 | ||||
ConfigurationManagementImpl$ConfigurationManagerImpl |
|
| 0.0;0 |
1 | package org.naftulin.configmgr; | |
2 | ||
3 | import java.util.Collections; | |
4 | import java.util.HashMap; | |
5 | import java.util.Iterator; | |
6 | import java.util.LinkedList; | |
7 | import java.util.List; | |
8 | import java.util.Map; | |
9 | import java.util.Set; | |
10 | import java.util.Map.Entry; | |
11 | ||
12 | import org.apache.log4j.Logger; | |
13 | import org.naftulin.configmgr.parsers.ConfigurationRecordsToEntriesConverter; | |
14 | ||
15 | /** | |
16 | * Configuration Management provides a convinient way to manage configuration for your programs. | |
17 | * Alows to load and reload configurations, add configuration, list all the configurations and | |
18 | * returns configuration manager interface. Configuration manager interface returns configuration | |
19 | * based on the key. | |
20 | * | |
21 | * @author Henry Naftulin | |
22 | * @since 1.0 | |
23 | */ | |
24 | 5 | public class ConfigurationManagementImpl implements ConfigurationManagement { |
25 | 220 | private final class ConfigurationManagerImpl implements ConfigurationManager { |
26 | /** | |
27 | * Returns the configuration based on the key. | |
28 | * If the configuration is not found or is in error state throws an exception. | |
29 | * @param key configuration mapped under. | |
30 | * @return the configuration based on the key. | |
31 | * @throws ConfigurationManagerException if configuration is not found or in error state. | |
32 | */ | |
33 | public Object getConfiguration(final String key) throws ConfigurationManagerException { | |
34 | ConfigurationManagementEntry entry; | |
35 | 85 | synchronized (lock) { |
36 | 75 | if (configuration.containsKey(key)) { |
37 | 65 | entry = configuration.get(key); |
38 | 65 | if (! entry.isError()) { |
39 | 65 | return entry.getContent(); |
40 | } | |
41 | 0 | throw new ConfigurationManagerException("Entry was found, but it is in error state. " + entry.getContent()); |
42 | } | |
43 | } | |
44 | 10 | log.warn("no entry for " + key + " is found in the configuration manager"); |
45 | 10 | throw new EntryNotFoundException("no entry for " + key + " is found."); |
46 | } | |
47 | ||
48 | /** | |
49 | * Returns the configuration based on the key if found and not in error state. Otherwise | |
50 | * returns null. | |
51 | * @param key configuration mapped under. | |
52 | * @return conifguration if found and it does not countain errors, null otherwise | |
53 | */ | |
54 | public Object getConfigurationSilent(final String key) { | |
55 | 115 | boolean entryFound = false; |
56 | 115 | ConfigurationManagementEntry entry = null; |
57 | 115 | Object retObject = null; |
58 | // minimal syncronized block | |
59 | 230 | synchronized (lock) { |
60 | 115 | entryFound = configuration.containsKey(key); |
61 | 115 | if (entryFound) { |
62 | 110 | entry = configuration.get(key); |
63 | 110 | if (!entry.isError()) { |
64 | 110 | retObject = entry.getContent(); |
65 | } | |
66 | } | |
67 | } | |
68 | ||
69 | 115 | if (!entryFound) { |
70 | 5 | log.warn("no entry for " + key + " is found in the configuration manager"); |
71 | } | |
72 | 115 | return retObject; |
73 | } | |
74 | ||
75 | ||
76 | } | |
77 | ||
78 | 20 | private static final Logger log = Logger.getLogger(ConfigurationManagementImpl.class); |
79 | ||
80 | /** | |
81 | * Anonymous private class that represents configuration manager interface. | |
82 | */ | |
83 | private final ConfigurationManager manager; | |
84 | 190 | private final Object lock; |
85 | private String masterRecordFileName; | |
86 | 475 | private Map<String, ConfigurationManagementEntry> configuration = new HashMap<String, ConfigurationManagementEntry>(); |
87 | private boolean intialized; | |
88 | ||
89 | ||
90 | /** | |
91 | * Creates a configuration manager without any configurations. Needed only for the unit testing. | |
92 | */ | |
93 | 110 | ConfigurationManagementImpl() { |
94 | 110 | lock = new Object(); |
95 | 110 | manager = new ConfigurationManagerImpl(); |
96 | 110 | } |
97 | ||
98 | /** | |
99 | * Creates a configuration management engine given a master configuration file. | |
100 | * @param masterRecordFileName a file that describes configuration for configuration manager | |
101 | * @throws ConfigurationManagerException if master configuration file cannot be read or contains an error. | |
102 | */ | |
103 | ConfigurationManagementImpl(String masterRecordFileName) throws ConfigurationManagerException { | |
104 | 80 | this(); |
105 | 80 | this.masterRecordFileName = masterRecordFileName; |
106 | //no reload necessary here, it is done on the factory level. More flexibe that way, which is | |
107 | //if we were to create configuration manager we can control when to load the configurations...reload(); | |
108 | 80 | } |
109 | ||
110 | /** | |
111 | * Reloades configurations stored in the configuration management engine. The | |
112 | * configurations are read again, parsed and stored. | |
113 | * @throws ConfigurationManagerException if a problem occurs while reading or parsing the configurations. | |
114 | */ | |
115 | public void reload() throws ConfigurationManagerException { | |
116 | 85 | final Map<String, ConfigurationManagementEntry> newConfig = readConfiguration(); |
117 | 170 | synchronized (lock) { |
118 | 85 | this.configuration = newConfig; |
119 | 85 | this.intialized = true; |
120 | } | |
121 | ||
122 | 85 | } |
123 | ||
124 | /** | |
125 | * Returns {@link ConfigurationManagementEntry configuration management entry} based on the key passed. | |
126 | * @param key key the entry is stored under | |
127 | * @return configuration management entry based on the key passed | |
128 | * @throws ConfigurationManagerException if the entry is not found. | |
129 | */ | |
130 | public ConfigurationManagementEntry getConfigurationManagmentEntry(final String key) throws ConfigurationManagerException { | |
131 | 0 | boolean entryFound = false; |
132 | 0 | ConfigurationManagementEntry entry = null; |
133 | 0 | synchronized (lock) { |
134 | 0 | entryFound = configuration.containsKey(key); |
135 | 0 | entry = configuration.get(key); |
136 | } | |
137 | 0 | if (!entryFound) { |
138 | 0 | throw new EntryNotFoundException("Entry identified by key "+ key + " was not found"); |
139 | } | |
140 | 0 | return entry; |
141 | } | |
142 | ||
143 | /** | |
144 | * Returns a list of {@link ConfigurationManagementEntry configuration management entries} managed by this configuration managment engine. | |
145 | * @return a list of {@link ConfigurationManagementEntry configuration management entries} managed by this configuration managment engine. | |
146 | */ | |
147 | public List<ConfigurationManagementEntry> getConfigurationManagmentEntries() { | |
148 | 15 | final List<ConfigurationManagementEntry> entries = new LinkedList<ConfigurationManagementEntry>(); |
149 | 15 | Set<Entry<String, ConfigurationManagementEntry>> set = null; |
150 | 30 | synchronized (lock) { |
151 | 15 | set = Collections.unmodifiableSet(this.configuration.entrySet()); |
152 | } | |
153 | 15 | if (set != null) { |
154 | 15 | Iterator<Entry<String, ConfigurationManagementEntry>> it = set.iterator(); |
155 | 45 | while(it.hasNext()) { |
156 | 15 | Entry<String, ConfigurationManagementEntry> mapEntry = it.next(); |
157 | 15 | entries.add((ConfigurationManagementEntry) mapEntry.getValue()); |
158 | } | |
159 | } | |
160 | 15 | return Collections.unmodifiableList(entries); |
161 | } | |
162 | ||
163 | /** | |
164 | * Returns true if configuration Management has loaded configurations. Returns false | |
165 | * before that point. After instantiation, we can confgure where configuration master | |
166 | * record is read from. Once the master record is configured, we will be able to reload | |
167 | * configuration manager. Reloading configuration manager will load all configurations, | |
168 | * and the flag will switch to initialized. | |
169 | * @return true if configuration Management has loaded configurations. | |
170 | */ | |
171 | public boolean isInitialized() { | |
172 | 10 | synchronized (lock) { |
173 | 10 | return intialized; |
174 | } | |
175 | } | |
176 | ||
177 | /** | |
178 | * Returns a map with {@link ConfigurationManagementEntry configuration management entries} keyed by confguration entry key. | |
179 | * Reads and parses all configuration entries described in master confiuration file. | |
180 | * @return a map with {@link ConfigurationManagementEntry configuration management entries} keyed by confguration entry key. | |
181 | * @throws ConfigurationManagerException if a configuration cannot be read or parsed. | |
182 | */ | |
183 | private Map<String, ConfigurationManagementEntry> readConfiguration() throws ConfigurationManagerException { | |
184 | 85 | final Map<String, ConfigurationManagementEntry> newConfiguration = new HashMap<String, ConfigurationManagementEntry>(); |
185 | 85 | if (masterRecordFileName != null) { |
186 | 80 | final ConfigurationRecordsToEntriesConverter converter = new ConfigurationRecordsToEntriesConverter(); |
187 | 80 | final ConfigurationManagementEntry[] entries = converter.createConfigurationEntriesFromConfigurationFile(masterRecordFileName); |
188 | 400 | for(int i=0; i < entries.length; ++i) { |
189 | 320 | addConfigurationManagmentEntry(newConfiguration, entries[i]); |
190 | } | |
191 | } | |
192 | 85 | return newConfiguration; |
193 | } | |
194 | ||
195 | /** | |
196 | * Returns configuration manager created by the configuration management engine. | |
197 | * @return configuration manager. | |
198 | */ | |
199 | public ConfigurationManager getConfigurationManager() { | |
200 | 90 | synchronized(lock) { |
201 | 90 | return this.manager; |
202 | } | |
203 | } | |
204 | ||
205 | /** | |
206 | * Adds a configuration entry to the configuration manager. Needed to add ad-hoc | |
207 | * configurations to the configuration manager. when adding a new configuration with the same key | |
208 | * old configuration should be replaced. Is overwritten flag for the new | |
209 | * configuration should be set. Delegates to private method that takes | |
210 | * a map to which the configuration is added. | |
211 | * @param entry configuration entry | |
212 | * @exception if the entry is in error | |
213 | */ | |
214 | public void addConfigurationManagmentEntry(final ConfigurationManagementEntry entry) throws EntryInErrorException { | |
215 | 60 | addConfigurationManagmentEntry(this.configuration, entry); |
216 | 55 | } |
217 | ||
218 | /** | |
219 | * Adds a configuration entry to the configuration manager. Needed to add ad-hoc | |
220 | * configurations to the configuration manager. when adding a new configuration with the same key | |
221 | * old configuration should be replaced. Is overwritten flag for the new | |
222 | * configuration should be set. | |
223 | * @param toConfiguration a configuration to which an entry is added | |
224 | * @param entry configuration entry | |
225 | * @exception if the entry is in error | |
226 | */ | |
227 | private void addConfigurationManagmentEntry(final Map<String, ConfigurationManagementEntry> toConfiguration, | |
228 | final ConfigurationManagementEntry entry) throws EntryInErrorException { | |
229 | 380 | if (entry.getKey() == null) { |
230 | 5 | throw new EntryInErrorException("Entry key should not be null. Entry is " + entry); |
231 | } | |
232 | 750 | synchronized(lock) { |
233 | 375 | final Object obj = toConfiguration.put(entry.getKey(), entry); |
234 | 375 | entry.setOverwritten(obj != null); |
235 | } | |
236 | 375 | } |
237 | } |