001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
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.security.lang.PortalSecurityManagerThreadLocal;
028    
029    import java.net.URL;
030    
031    import java.util.ArrayList;
032    import java.util.List;
033    
034    import org.apache.commons.configuration.AbstractFileConfiguration;
035    import org.apache.commons.configuration.CompositeConfiguration;
036    import org.apache.commons.configuration.Configuration;
037    import org.apache.commons.configuration.FileConfiguration;
038    import org.apache.commons.configuration.PropertiesConfiguration;
039    import org.apache.commons.configuration.SubsetConfiguration;
040    import org.apache.commons.configuration.SystemConfiguration;
041    import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
042    
043    /**
044     * @author Raymond Augé
045     */
046    public class ClassLoaderAggregateProperties extends AggregatedProperties {
047    
048            public ClassLoaderAggregateProperties(
049                    ClassLoader classLoader, String companyId, String componentName) {
050    
051                    super(companyId, componentName);
052    
053                    _classLoader = classLoader;
054                    _companyId = companyId;
055                    _componentName = componentName;
056    
057                    _prefixedSystemConfiguration = new SubsetConfiguration(
058                            _systemConfiguration, _getPrefix(), null);
059            }
060    
061            @Override
062            public void addBaseFileName(String fileName) {
063                    URL url = _classLoader.getResource(fileName);
064    
065                    Configuration configuration = _addPropertiesSource(
066                            fileName, url, _baseCompositeConfiguration);
067    
068                    if ((configuration != null) && !configuration.isEmpty()) {
069                            _baseConfigurationLoaded = true;
070                    }
071            }
072    
073            @Override
074            public void addGlobalFileName(String fileName) {
075                    URL url = _classLoader.getResource(fileName);
076    
077                    _addPropertiesSource(fileName, url, _globalCompositeConfiguration);
078            }
079    
080            public CompositeConfiguration getBaseConfiguration() {
081                    return _baseCompositeConfiguration;
082            }
083    
084            @Override
085            public String getComponentName() {
086                    return _componentName;
087            }
088    
089            @Override
090            public Object getProperty(String key) {
091                    Object value = null;
092    
093                    if (value == null) {
094                            value = System.getProperty(_getPrefix().concat(key));
095                    }
096    
097                    if (value == null) {
098                            value = _globalCompositeConfiguration.getProperty(
099                                    _getPrefix().concat(key));
100                    }
101    
102                    if (value == null) {
103                            value = _globalCompositeConfiguration.getProperty(key);
104                    }
105    
106                    if (value == null) {
107                            value = _baseCompositeConfiguration.getProperty(key);
108                    }
109    
110                    if (value == null) {
111                            value = super.getProperty(key);
112                    }
113    
114                    if (value == null) {
115                            value = System.getProperty(key);
116                    }
117    
118                    if ((value == null) && key.equals(Conventions.COMPANY_ID_PROPERTY)) {
119                            value = _companyId;
120                    }
121    
122                    if ((value == null) &&
123                            key.equals(Conventions.COMPONENT_NAME_PROPERTY)) {
124    
125                            value = _componentName;
126                    }
127    
128                    return value;
129            }
130    
131            @Override
132            public boolean hasBaseConfiguration() {
133                    return _baseConfigurationLoaded;
134            }
135    
136            @Override
137            public List<String> loadedSources() {
138                    return _loadedSources;
139            }
140    
141            private Configuration _addDatasourceProperties(String datasourcePath) {
142                    DatasourceURL datasourceURL = new DatasourceURL(
143                            datasourcePath, _companyId, _componentName,
144                            DatasourceURL.PROPERTIES_TABLE);
145    
146                    return datasourceURL.getConfiguration();
147            }
148    
149            private Configuration _addFileProperties(
150                            String fileName,
151                            CompositeConfiguration loadedCompositeConfiguration)
152                    throws ConfigurationException {
153    
154                    try {
155                            FileConfiguration newFileConfiguration =
156                                    new PropertiesConfiguration(fileName);
157    
158                            URL url = newFileConfiguration.getURL();
159    
160                            if (_log.isDebugEnabled()) {
161                                    _log.debug("Adding file " + url);
162                            }
163    
164                            Long delay = _getReloadDelay(
165                                    loadedCompositeConfiguration, newFileConfiguration);
166    
167                            if (delay != null) {
168                                    FileChangedReloadingStrategy fileChangedReloadingStrategy =
169                                            new FileConfigurationChangedReloadingStrategy();
170    
171                                    if (_log.isDebugEnabled()) {
172                                            _log.debug(
173                                                    "File " + url + " will be reloaded every " +
174                                                            delay + " seconds");
175                                    }
176    
177                                    long milliseconds = delay.longValue() * 1000;
178    
179                                    fileChangedReloadingStrategy.setRefreshDelay(milliseconds);
180    
181                                    newFileConfiguration.setReloadingStrategy(
182                                            fileChangedReloadingStrategy);
183                            }
184    
185                            _addIncludedPropertiesSources(
186                                    newFileConfiguration, loadedCompositeConfiguration);
187    
188                            return newFileConfiguration;
189                    }
190                    catch (org.apache.commons.configuration.ConfigurationException ce) {
191                            if (_log.isDebugEnabled()) {
192                                    _log.debug("Configuration source " + fileName + " ignored");
193                            }
194    
195                            return null;
196                    }
197            }
198    
199            private void _addIncludedPropertiesSources(
200                    Configuration newConfiguration,
201                    CompositeConfiguration loadedCompositeConfiguration) {
202    
203                    CompositeConfiguration tempCompositeConfiguration =
204                            new CompositeConfiguration();
205    
206                    tempCompositeConfiguration.addConfiguration(
207                            _prefixedSystemConfiguration);
208                    tempCompositeConfiguration.addConfiguration(newConfiguration);
209                    tempCompositeConfiguration.addConfiguration(_systemConfiguration);
210                    tempCompositeConfiguration.addProperty(
211                            Conventions.COMPANY_ID_PROPERTY, _companyId);
212                    tempCompositeConfiguration.addProperty(
213                            Conventions.COMPONENT_NAME_PROPERTY, _componentName);
214    
215                    String[] fileNames = tempCompositeConfiguration.getStringArray(
216                            Conventions.INCLUDE_PROPERTY);
217    
218                    ArrayUtil.reverse(fileNames);
219    
220                    for (String fileName : fileNames) {
221                            URL url = null;
222    
223                            try {
224                                    url = _classLoader.getResource(fileName);
225                            }
226                            catch (RuntimeException re) {
227                                    if (fileName.startsWith("file:/")) {
228                                            throw re;
229                                    }
230    
231                                    fileName = "file:/".concat(fileName);
232    
233                                    url = _classLoader.getResource(fileName);
234                            }
235    
236                            _addPropertiesSource(fileName, url, loadedCompositeConfiguration);
237                    }
238            }
239    
240            private Configuration _addJNDIProperties(String sourcePath) {
241                    JndiURL jndiURL = new JndiURL(sourcePath, _companyId, _componentName);
242    
243                    return jndiURL.getConfiguration();
244            }
245    
246            private Configuration _addPropertiesSource(
247                    String sourceName, URL url,
248                    CompositeConfiguration loadedCompositeConfiguration) {
249    
250                    boolean checkGetClassLoader =
251                            PortalSecurityManagerThreadLocal.isCheckGetClassLoader();
252    
253                    try {
254                            PortalSecurityManagerThreadLocal.setCheckGetClassLoader(false);
255    
256                            Configuration newConfiguration = null;
257    
258                            if (DatasourceURL.isDatasource(sourceName)) {
259                                    newConfiguration = _addDatasourceProperties(sourceName);
260                            }
261                            else if (JndiURL.isJndi(sourceName)) {
262                                    newConfiguration = _addJNDIProperties(sourceName);
263                            }
264                            else if (url != null) {
265                                    newConfiguration = _addURLProperties(
266                                            url, loadedCompositeConfiguration);
267                            }
268                            else {
269                                    newConfiguration = _addFileProperties(
270                                            sourceName, loadedCompositeConfiguration);
271                            }
272    
273                            if (newConfiguration == null) {
274                                    return newConfiguration;
275                            }
276    
277                            loadedCompositeConfiguration.addConfiguration(newConfiguration);
278    
279                            super.addConfiguration(newConfiguration);
280    
281                            if (newConfiguration instanceof AbstractFileConfiguration) {
282                                    AbstractFileConfiguration abstractFileConfiguration =
283                                            (AbstractFileConfiguration)newConfiguration;
284    
285                                    URL abstractFileConfigurationURL =
286                                            abstractFileConfiguration.getURL();
287    
288                                    _loadedSources.add(abstractFileConfigurationURL.toString());
289                            }
290                            else {
291                                    _loadedSources.add(sourceName);
292                            }
293    
294                            return newConfiguration;
295                    }
296                    catch (Exception e) {
297                            if (_log.isDebugEnabled()) {
298                                    _log.debug(
299                                            "Configuration source " + sourceName + " ignored: " +
300                                                    e.getMessage());
301                            }
302    
303                            return null;
304                    }
305                    finally {
306                            PortalSecurityManagerThreadLocal.setCheckGetClassLoader(
307                                    checkGetClassLoader);
308                    }
309            }
310    
311            private Configuration _addURLProperties(
312                            URL url, CompositeConfiguration loadedCompositeConfiguration)
313                    throws ConfigurationException {
314    
315                    try {
316                            FileConfiguration newFileConfiguration =
317                                    new PropertiesConfiguration(url);
318    
319                            if (_log.isDebugEnabled()) {
320                                    _log.debug("Adding resource " + url);
321                            }
322    
323                            Long delay = _getReloadDelay(
324                                    loadedCompositeConfiguration, newFileConfiguration);
325    
326                            if (delay != null) {
327                                    FileChangedReloadingStrategy fileChangedReloadingStrategy =
328                                            new FileConfigurationChangedReloadingStrategy();
329    
330                                    if (_log.isDebugEnabled()) {
331                                            _log.debug(
332                                                    "Resource " + url + " will be reloaded every " +
333                                                            delay + " seconds");
334                                    }
335    
336                                    long milliseconds = delay.longValue() * 1000;
337    
338                                    fileChangedReloadingStrategy.setRefreshDelay(milliseconds);
339    
340                                    newFileConfiguration.setReloadingStrategy(
341                                            fileChangedReloadingStrategy);
342                            }
343    
344                            _addIncludedPropertiesSources(
345                                    newFileConfiguration, loadedCompositeConfiguration);
346    
347                            return newFileConfiguration;
348                    }
349                    catch (org.apache.commons.configuration.ConfigurationException ce) {
350                            if (_log.isDebugEnabled()) {
351                                    _log.debug("Configuration source " + url + " ignored");
352                            }
353    
354                            return null;
355                    }
356            }
357    
358            private String _getPrefix() {
359                    return _componentName.concat(Conventions.PREFIX_SEPARATOR);
360            }
361    
362            private Long _getReloadDelay(
363                    CompositeConfiguration loadedCompositeConfiguration,
364                    FileConfiguration newFileConfiguration) {
365    
366                    Long delay = newFileConfiguration.getLong(
367                            Conventions.RELOAD_DELAY_PROPERTY, null);
368    
369                    if (delay == null) {
370                            delay = loadedCompositeConfiguration.getLong(
371                                    Conventions.RELOAD_DELAY_PROPERTY, null);
372                    }
373    
374                    return delay;
375            }
376    
377            private static Log _log = LogFactoryUtil.getLog(AggregatedProperties.class);
378    
379            private CompositeConfiguration _baseCompositeConfiguration =
380                    new CompositeConfiguration();
381            private boolean _baseConfigurationLoaded;
382            private ClassLoader _classLoader;
383            private String _companyId;
384            private String _componentName;
385            private CompositeConfiguration _globalCompositeConfiguration =
386                    new CompositeConfiguration();
387            private List<String> _loadedSources = new ArrayList<String>();
388            private Configuration _prefixedSystemConfiguration;
389            private SystemConfiguration _systemConfiguration =
390                    new SystemConfiguration();
391    
392    }