001
014
015 package com.liferay.portal.configuration.easyconf;
016
017 import com.germinus.easyconf.AggregatedProperties;
018 import com.germinus.easyconf.ConfigurationException;
019 import com.germinus.easyconf.Conventions;
020 import com.germinus.easyconf.DatasourceURL;
021 import com.germinus.easyconf.FileConfigurationChangedReloadingStrategy;
022 import com.germinus.easyconf.JndiURL;
023
024 import com.liferay.portal.kernel.log.Log;
025 import com.liferay.portal.kernel.log.LogFactoryUtil;
026 import com.liferay.portal.kernel.util.ArrayUtil;
027 import com.liferay.portal.kernel.util.ReflectionUtil;
028
029 import java.lang.reflect.Field;
030
031 import java.net.URL;
032
033 import java.util.ArrayList;
034 import java.util.List;
035 import java.util.Map;
036
037 import org.apache.commons.configuration.AbstractFileConfiguration;
038 import org.apache.commons.configuration.CompositeConfiguration;
039 import org.apache.commons.configuration.Configuration;
040 import org.apache.commons.configuration.FileConfiguration;
041 import org.apache.commons.configuration.PropertiesConfiguration;
042 import org.apache.commons.configuration.PropertiesConfigurationLayout;
043 import org.apache.commons.configuration.SubsetConfiguration;
044 import org.apache.commons.configuration.SystemConfiguration;
045 import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
046
047
050 public class ClassLoaderAggregateProperties extends AggregatedProperties {
051
052 public ClassLoaderAggregateProperties(
053 ClassLoader classLoader, String companyId, String componentName) {
054
055 super(companyId, componentName);
056
057 _classLoader = classLoader;
058 _companyId = companyId;
059 _componentName = componentName;
060
061 _prefixedSystemConfiguration = new SubsetConfiguration(
062 _systemConfiguration, _getPrefix(), null);
063 }
064
065 @Override
066 public void addBaseFileName(String fileName) {
067 URL url = _classLoader.getResource(fileName);
068
069 Configuration configuration = _addPropertiesSource(
070 fileName, url, _baseCompositeConfiguration);
071
072 if (configuration != null) {
073 _baseConfigurationLoaded = true;
074
075 if (configuration.isEmpty() && _log.isDebugEnabled()) {
076 _log.debug("Empty configuration " + fileName);
077 }
078 }
079 }
080
081 @Override
082 public void addGlobalFileName(String fileName) {
083 URL url = _classLoader.getResource(fileName);
084
085 _addPropertiesSource(fileName, url, _globalCompositeConfiguration);
086 }
087
088 public CompositeConfiguration getBaseConfiguration() {
089 return _baseCompositeConfiguration;
090 }
091
092 @Override
093 public String getComponentName() {
094 return _componentName;
095 }
096
097 @Override
098 public Object getProperty(String key) {
099 Object value = null;
100
101 if (value == null) {
102 value = System.getProperty(_getPrefix().concat(key));
103 }
104
105 if (value == null) {
106 value = _globalCompositeConfiguration.getProperty(
107 _getPrefix().concat(key));
108 }
109
110 if (value == null) {
111 value = _globalCompositeConfiguration.getProperty(key);
112 }
113
114 if (value == null) {
115 value = _baseCompositeConfiguration.getProperty(key);
116 }
117
118 if (value == null) {
119 value = super.getProperty(key);
120 }
121
122 if (value == null) {
123 value = System.getProperty(key);
124 }
125
126 if ((value == null) && key.equals(Conventions.COMPANY_ID_PROPERTY)) {
127 value = _companyId;
128 }
129
130 if ((value == null) &&
131 key.equals(Conventions.COMPONENT_NAME_PROPERTY)) {
132
133 value = _componentName;
134 }
135
136 return value;
137 }
138
139 @Override
140 public boolean hasBaseConfiguration() {
141 return _baseConfigurationLoaded;
142 }
143
144 @Override
145 public List<String> loadedSources() {
146 return _loadedSources;
147 }
148
149 private Configuration _addDatasourceProperties(String datasourcePath) {
150 DatasourceURL datasourceURL = new DatasourceURL(
151 datasourcePath, _companyId, _componentName,
152 DatasourceURL.PROPERTIES_TABLE);
153
154 return datasourceURL.getConfiguration();
155 }
156
157 private Configuration _addFileProperties(
158 String fileName,
159 CompositeConfiguration loadedCompositeConfiguration)
160 throws ConfigurationException {
161
162 try {
163 FileConfiguration newFileConfiguration =
164 new PropertiesConfiguration(fileName);
165
166 URL url = newFileConfiguration.getURL();
167
168 if (_log.isDebugEnabled()) {
169 _log.debug("Adding file " + url);
170 }
171
172 Long delay = _getReloadDelay(
173 loadedCompositeConfiguration, newFileConfiguration);
174
175 if (delay != null) {
176 FileChangedReloadingStrategy fileChangedReloadingStrategy =
177 new FileConfigurationChangedReloadingStrategy();
178
179 if (_log.isDebugEnabled()) {
180 _log.debug(
181 "File " + url + " will be reloaded every " +
182 delay + " seconds");
183 }
184
185 long milliseconds = delay.longValue() * 1000;
186
187 fileChangedReloadingStrategy.setRefreshDelay(milliseconds);
188
189 newFileConfiguration.setReloadingStrategy(
190 fileChangedReloadingStrategy);
191 }
192
193 _addIncludedPropertiesSources(
194 newFileConfiguration, loadedCompositeConfiguration);
195
196 return newFileConfiguration;
197 }
198 catch (org.apache.commons.configuration.ConfigurationException ce) {
199 if (_log.isDebugEnabled()) {
200 _log.debug("Configuration source " + fileName + " ignored");
201 }
202
203 return null;
204 }
205 }
206
207 private void _addIncludedPropertiesSources(
208 Configuration newConfiguration,
209 CompositeConfiguration loadedCompositeConfiguration) {
210
211 CompositeConfiguration tempCompositeConfiguration =
212 new CompositeConfiguration();
213
214 tempCompositeConfiguration.addConfiguration(
215 _prefixedSystemConfiguration);
216 tempCompositeConfiguration.addConfiguration(newConfiguration);
217 tempCompositeConfiguration.addConfiguration(_systemConfiguration);
218 tempCompositeConfiguration.addProperty(
219 Conventions.COMPANY_ID_PROPERTY, _companyId);
220 tempCompositeConfiguration.addProperty(
221 Conventions.COMPONENT_NAME_PROPERTY, _componentName);
222
223 String[] fileNames = tempCompositeConfiguration.getStringArray(
224 Conventions.INCLUDE_PROPERTY);
225
226 ArrayUtil.reverse(fileNames);
227
228 for (String fileName : fileNames) {
229 URL url = null;
230
231 try {
232 url = _classLoader.getResource(fileName);
233 }
234 catch (RuntimeException re) {
235 if (fileName.startsWith("file:/")) {
236 throw re;
237 }
238
239 fileName = "file:/".concat(fileName);
240
241 url = _classLoader.getResource(fileName);
242 }
243
244 _addPropertiesSource(fileName, url, loadedCompositeConfiguration);
245 }
246 }
247
248 private Configuration _addJNDIProperties(String sourcePath) {
249 JndiURL jndiURL = new JndiURL(sourcePath, _companyId, _componentName);
250
251 return jndiURL.getConfiguration();
252 }
253
254 private Configuration _addPropertiesSource(
255 String sourceName, URL url,
256 CompositeConfiguration loadedCompositeConfiguration) {
257
258 try {
259 Configuration newConfiguration = null;
260
261 if (DatasourceURL.isDatasource(sourceName)) {
262 newConfiguration = _addDatasourceProperties(sourceName);
263 }
264 else if (JndiURL.isJndi(sourceName)) {
265 newConfiguration = _addJNDIProperties(sourceName);
266 }
267 else if (url != null) {
268 newConfiguration = _addURLProperties(
269 url, loadedCompositeConfiguration);
270 }
271 else {
272 newConfiguration = _addFileProperties(
273 sourceName, loadedCompositeConfiguration);
274 }
275
276 if (newConfiguration == null) {
277 return newConfiguration;
278 }
279
280 loadedCompositeConfiguration.addConfiguration(newConfiguration);
281
282 super.addConfiguration(newConfiguration);
283
284 if (newConfiguration instanceof AbstractFileConfiguration) {
285 AbstractFileConfiguration abstractFileConfiguration =
286 (AbstractFileConfiguration)newConfiguration;
287
288 URL abstractFileConfigurationURL =
289 abstractFileConfiguration.getURL();
290
291 _loadedSources.add(abstractFileConfigurationURL.toString());
292 }
293 else {
294 _loadedSources.add(sourceName);
295 }
296
297 return newConfiguration;
298 }
299 catch (Exception e) {
300 if (_log.isDebugEnabled()) {
301 _log.debug(
302 "Configuration source " + sourceName + " ignored: " +
303 e.getMessage());
304 }
305
306 return null;
307 }
308 }
309
310 private Configuration _addURLProperties(
311 URL url, CompositeConfiguration loadedCompositeConfiguration)
312 throws ConfigurationException {
313
314 try {
315 PropertiesConfiguration propertiesConfiguration =
316 new PropertiesConfiguration(url);
317
318 PropertiesConfigurationLayout propertiesConfigurationLayout =
319 propertiesConfiguration.getLayout();
320
321 try {
322 Map<String, Object> layoutData =
323 (Map<String, Object>)_layoutDataField.get(
324 propertiesConfigurationLayout);
325
326 for (Object propertyLayoutData : layoutData.values()) {
327 _commentField.set(propertyLayoutData, null);
328 }
329 }
330 catch (ReflectiveOperationException roe) {
331 if (_log.isWarnEnabled()) {
332 _log.warn(
333 "Unable to clear out comments from " +
334 propertiesConfiguration,
335 roe);
336 }
337 }
338
339 if (_log.isDebugEnabled()) {
340 _log.debug("Adding resource " + url);
341 }
342
343 Long delay = _getReloadDelay(
344 loadedCompositeConfiguration, propertiesConfiguration);
345
346 if (delay != null) {
347 FileChangedReloadingStrategy fileChangedReloadingStrategy =
348 new FileConfigurationChangedReloadingStrategy();
349
350 if (_log.isDebugEnabled()) {
351 _log.debug(
352 "Resource " + url + " will be reloaded every " +
353 delay + " seconds");
354 }
355
356 long milliseconds = delay.longValue() * 1000;
357
358 fileChangedReloadingStrategy.setRefreshDelay(milliseconds);
359
360 propertiesConfiguration.setReloadingStrategy(
361 fileChangedReloadingStrategy);
362 }
363
364 _addIncludedPropertiesSources(
365 propertiesConfiguration, loadedCompositeConfiguration);
366
367 return propertiesConfiguration;
368 }
369 catch (org.apache.commons.configuration.ConfigurationException ce) {
370 if (_log.isDebugEnabled()) {
371 _log.debug("Configuration source " + url + " ignored");
372 }
373
374 return null;
375 }
376 }
377
378 private String _getPrefix() {
379 return _componentName.concat(Conventions.PREFIX_SEPARATOR);
380 }
381
382 private Long _getReloadDelay(
383 CompositeConfiguration loadedCompositeConfiguration,
384 FileConfiguration newFileConfiguration) {
385
386 Long delay = newFileConfiguration.getLong(
387 Conventions.RELOAD_DELAY_PROPERTY, null);
388
389 if (delay == null) {
390 delay = loadedCompositeConfiguration.getLong(
391 Conventions.RELOAD_DELAY_PROPERTY, null);
392 }
393
394 return delay;
395 }
396
397 private static final Log _log = LogFactoryUtil.getLog(
398 ClassLoaderAggregateProperties.class);
399
400 private static final Field _commentField;
401 private static final Field _layoutDataField;
402
403 static {
404 try {
405 ClassLoader classLoader =
406 PropertiesConfigurationLayout.class.getClassLoader();
407
408 Class<?> propertyLayoutDataClass = classLoader.loadClass(
409 PropertiesConfigurationLayout.class.getName() +
410 "$PropertyLayoutData");
411
412 _commentField = ReflectionUtil.getDeclaredField(
413 propertyLayoutDataClass, "comment");
414
415 _layoutDataField = ReflectionUtil.getDeclaredField(
416 PropertiesConfigurationLayout.class, "layoutData");
417 }
418 catch (Exception e) {
419 throw new ExceptionInInitializerError(e);
420 }
421 }
422
423 private final CompositeConfiguration _baseCompositeConfiguration =
424 new CompositeConfiguration();
425 private boolean _baseConfigurationLoaded;
426 private final ClassLoader _classLoader;
427 private final String _companyId;
428 private final String _componentName;
429 private final CompositeConfiguration _globalCompositeConfiguration =
430 new CompositeConfiguration();
431 private final List<String> _loadedSources = new ArrayList<>();
432 private final Configuration _prefixedSystemConfiguration;
433 private final SystemConfiguration _systemConfiguration =
434 new SystemConfiguration();
435
436 }