001    /**
002     * Copyright (c) 2000-present 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.cache.ehcache;
016    
017    import com.liferay.portal.cache.cluster.ClusterLinkCallbackFactory;
018    import com.liferay.portal.kernel.cache.CacheListenerScope;
019    import com.liferay.portal.kernel.cache.configuration.CallbackConfiguration;
020    import com.liferay.portal.kernel.cache.configuration.PortalCacheConfiguration;
021    import com.liferay.portal.kernel.cache.configuration.PortalCacheManagerConfiguration;
022    import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
023    import com.liferay.portal.kernel.util.ObjectValuePair;
024    import com.liferay.portal.kernel.util.StringPool;
025    import com.liferay.portal.kernel.util.StringUtil;
026    import com.liferay.portal.util.PropsValues;
027    
028    import java.io.IOException;
029    
030    import java.net.URL;
031    
032    import java.util.Collections;
033    import java.util.HashMap;
034    import java.util.HashSet;
035    import java.util.List;
036    import java.util.Map;
037    import java.util.Properties;
038    import java.util.Set;
039    
040    import net.sf.ehcache.config.CacheConfiguration;
041    import net.sf.ehcache.config.CacheConfiguration.BootstrapCacheLoaderFactoryConfiguration;
042    import net.sf.ehcache.config.CacheConfiguration.CacheEventListenerFactoryConfiguration;
043    import net.sf.ehcache.config.Configuration;
044    import net.sf.ehcache.config.ConfigurationFactory;
045    import net.sf.ehcache.config.FactoryConfiguration;
046    import net.sf.ehcache.event.NotificationScope;
047    
048    /**
049     * @author Tina Tian
050     */
051    public class EhcacheConfigurationHelperUtil {
052    
053            public static ObjectValuePair<
054                            Configuration, PortalCacheManagerConfiguration>
055                    getConfiguration(String configurationPath) {
056    
057                    return getConfiguration(configurationPath, false, false);
058            }
059    
060            public static ObjectValuePair<
061                            Configuration, PortalCacheManagerConfiguration>
062                    getConfiguration(String configurationPath, boolean clusterAware) {
063    
064                    return getConfiguration(configurationPath, clusterAware, false);
065            }
066    
067            public static ObjectValuePair<
068                            Configuration, PortalCacheManagerConfiguration>
069                    getConfiguration(
070                            String configurationPath, boolean clusterAware,
071                            boolean usingDefault) {
072    
073                    if (configurationPath == null) {
074                            throw new NullPointerException("Configuration path is null");
075                    }
076    
077                    return getConfiguration(
078                            EhcacheConfigurationHelperUtil.class.getResource(configurationPath),
079                            clusterAware, usingDefault);
080            }
081    
082            public static ObjectValuePair<
083                            Configuration, PortalCacheManagerConfiguration>
084                    getConfiguration(URL configurationURL) {
085    
086                    return getConfiguration(configurationURL, false, false);
087            }
088    
089            public static ObjectValuePair<
090                            Configuration, PortalCacheManagerConfiguration>
091                    getConfiguration(URL configurationURL, boolean clusterAware) {
092    
093                    return getConfiguration(configurationURL, clusterAware, false);
094            }
095    
096            public static ObjectValuePair<
097                            Configuration, PortalCacheManagerConfiguration>
098                    getConfiguration(
099                            URL configurationURL, boolean clusterAware, boolean usingDefault) {
100    
101                    if (configurationURL == null) {
102                            throw new NullPointerException("Configuration path is null");
103                    }
104    
105                    Configuration ehcacheConfiguration =
106                            ConfigurationFactory.parseConfiguration(configurationURL);
107    
108                    List<?> peerProviderConfiguration =
109                            ehcacheConfiguration.
110                                    getCacheManagerPeerProviderFactoryConfiguration();
111    
112                    if (!peerProviderConfiguration.isEmpty() &&
113                            (!clusterAware || !PropsValues.CLUSTER_LINK_ENABLED ||
114                             PropsValues.EHCACHE_CLUSTER_LINK_REPLICATION_ENABLED)) {
115    
116                            peerProviderConfiguration.clear();
117                    }
118    
119                    peerProviderConfiguration =
120                            ehcacheConfiguration.
121                                    getCacheManagerPeerListenerFactoryConfigurations();
122    
123                    if (!peerProviderConfiguration.isEmpty() &&
124                            (!clusterAware || !PropsValues.CLUSTER_LINK_ENABLED ||
125                             PropsValues.EHCACHE_CLUSTER_LINK_REPLICATION_ENABLED)) {
126    
127                            peerProviderConfiguration.clear();
128                    }
129    
130                    Set<CallbackConfiguration> cacheManagerListenerConfigurations =
131                            _getCacheManagerListenerConfigurations(ehcacheConfiguration);
132    
133                    PortalCacheConfiguration defaultPortalCacheConfiguration =
134                            _parseCacheConfiguration(
135                                    ehcacheConfiguration.getDefaultCacheConfiguration(),
136                                    clusterAware, usingDefault);
137    
138                    Set<PortalCacheConfiguration> portalCacheConfigurations =
139                            new HashSet<PortalCacheConfiguration>();
140    
141                    Map<String, CacheConfiguration> cacheConfigurations =
142                            ehcacheConfiguration.getCacheConfigurations();
143    
144                    for (Map.Entry<String, CacheConfiguration> entry :
145                                    cacheConfigurations.entrySet()) {
146    
147                            portalCacheConfigurations.add(
148                                    _parseCacheConfiguration(
149                                            entry.getValue(), clusterAware, usingDefault));
150                    }
151    
152                    PortalCacheManagerConfiguration portalCacheManagerConfiguration =
153                            new PortalCacheManagerConfiguration(
154                                    cacheManagerListenerConfigurations,
155                                    defaultPortalCacheConfiguration, portalCacheConfigurations);
156    
157                    return new ObjectValuePair<
158                                    Configuration, PortalCacheManagerConfiguration>(
159                            ehcacheConfiguration, portalCacheManagerConfiguration);
160            }
161    
162            private static CacheListenerScope _getCacheListenerScope(
163                    NotificationScope notificationScope) {
164    
165                    if (notificationScope == NotificationScope.ALL) {
166                            return CacheListenerScope.ALL;
167                    }
168                    else if (notificationScope == NotificationScope.LOCAL) {
169                            return CacheListenerScope.LOCAL;
170                    }
171                    else if (notificationScope == NotificationScope.REMOTE) {
172                            return CacheListenerScope.REMOTE;
173                    }
174    
175                    throw new IllegalArgumentException(
176                            "Unable to parse notification scope " + notificationScope);
177            }
178    
179            private static Set<CallbackConfiguration>
180                    _getCacheManagerListenerConfigurations(
181                            Configuration ehcacheConfiguration) {
182    
183                    FactoryConfiguration<?> factoryConfiguration =
184                            ehcacheConfiguration.
185                                    getCacheManagerEventListenerFactoryConfiguration();
186    
187                    if (factoryConfiguration == null) {
188                            return Collections.emptySet();
189                    }
190    
191                    Properties properties = _parseProperties(
192                            factoryConfiguration.getProperties(),
193                            factoryConfiguration.getPropertySeparator());
194    
195                    properties.put(
196                            EhcacheConstants.CACHE_MANAGER_LISTENER_FACTORY_CLASS_NAME,
197                            factoryConfiguration.getFullyQualifiedClassPath());
198                    properties.put(
199                            EhcacheConstants.PORTAL_CACHE_MANAGER_NAME,
200                            ehcacheConfiguration.getName());
201    
202                    return Collections.singleton(
203                            new CallbackConfiguration(
204                                    EhcacheCallbackFactory.INSTANCE, properties));
205            }
206    
207            private static PortalCacheConfiguration _parseCacheConfiguration(
208                    CacheConfiguration cacheConfiguration, boolean clusterAware,
209                    boolean usingDefault) {
210    
211                    String portalCacheName = cacheConfiguration.getName();
212    
213                    if (portalCacheName == null) {
214                            portalCacheName =
215                                    PortalCacheConfiguration.DEFAULT_PORTAL_CACHE_NAME;
216                    }
217    
218                    Map<CallbackConfiguration, CacheListenerScope>
219                            cacheListenerConfigurations =
220                                    new HashMap<CallbackConfiguration, CacheListenerScope>();
221    
222                    List<CacheEventListenerFactoryConfiguration>
223                            cacheEventListenerConfigurations =
224                                    cacheConfiguration.getCacheEventListenerConfigurations();
225    
226                    for (CacheEventListenerFactoryConfiguration
227                                    cacheEventListenerFactoryConfiguration :
228                                            cacheEventListenerConfigurations) {
229    
230                            String fullyQualifiedClassPath =
231                                    cacheEventListenerFactoryConfiguration.
232                                            getFullyQualifiedClassPath();
233    
234                            Properties properties = _parseProperties(
235                                    cacheEventListenerFactoryConfiguration.getProperties(),
236                                    cacheEventListenerFactoryConfiguration. getPropertySeparator());
237    
238                            CacheListenerScope cacheListenerScope = _getCacheListenerScope(
239                                    cacheEventListenerFactoryConfiguration.getListenFor());
240    
241                            if (fullyQualifiedClassPath.contains(
242                                            "LiferayCacheEventListenerFactory") ||
243                                    fullyQualifiedClassPath.contains(
244                                            "net.sf.ehcache.distribution")) {
245    
246                                    if (clusterAware && PropsValues.CLUSTER_LINK_ENABLED) {
247                                            if (PropsValues.EHCACHE_CLUSTER_LINK_REPLICATION_ENABLED) {
248                                                    cacheListenerConfigurations.put(
249                                                            new CallbackConfiguration(
250                                                                    ClusterLinkCallbackFactory.INSTANCE,
251                                                                    properties),
252                                                            cacheListenerScope);
253                                            }
254                                            else {
255                                                    properties.put(
256                                                            EhcacheConstants.
257                                                                    CACHE_EVENT_LISTENER_FACTORY_CLASS_NAME,
258                                                            cacheEventListenerFactoryConfiguration.
259                                                                    getFullyQualifiedClassPath());
260    
261                                                    cacheListenerConfigurations.put(
262                                                            new CallbackConfiguration(
263                                                                    EhcacheCallbackFactory.INSTANCE, properties),
264                                                            cacheListenerScope);
265                                            }
266                                    }
267                            }
268                            else if (!usingDefault) {
269                                    properties.put(
270                                            EhcacheConstants.CACHE_EVENT_LISTENER_FACTORY_CLASS_NAME,
271                                            cacheEventListenerFactoryConfiguration.
272                                                    getFullyQualifiedClassPath());
273    
274                                    cacheListenerConfigurations.put(
275                                            new CallbackConfiguration(
276                                                    EhcacheCallbackFactory.INSTANCE, properties),
277                                            cacheListenerScope);
278                            }
279                    }
280    
281                    cacheEventListenerConfigurations.clear();
282    
283                    CallbackConfiguration bootstrapLoaderConfiguration = null;
284    
285                    BootstrapCacheLoaderFactoryConfiguration
286                            bootstrapCacheLoaderFactoryConfiguration =
287                                    cacheConfiguration.
288                                            getBootstrapCacheLoaderFactoryConfiguration();
289    
290                    if (bootstrapCacheLoaderFactoryConfiguration != null) {
291                            Properties properties = _parseProperties(
292                                    bootstrapCacheLoaderFactoryConfiguration.getProperties(),
293                                    bootstrapCacheLoaderFactoryConfiguration.
294                                            getPropertySeparator());
295    
296                            if (clusterAware && PropsValues.CLUSTER_LINK_ENABLED) {
297                                    if (PropsValues.EHCACHE_CLUSTER_LINK_REPLICATION_ENABLED) {
298                                            bootstrapLoaderConfiguration = new CallbackConfiguration(
299                                                    ClusterLinkCallbackFactory.INSTANCE, properties);
300                                    }
301                                    else {
302                                            properties.put(
303                                                    EhcacheConstants.
304                                                            BOOTSTRAP_CACHE_LOADER_FACTORY_CLASS_NAME,
305                                                    bootstrapCacheLoaderFactoryConfiguration.
306                                                            getFullyQualifiedClassPath());
307    
308                                            bootstrapLoaderConfiguration = new CallbackConfiguration(
309                                                    EhcacheCallbackFactory.INSTANCE, properties);
310                                    }
311                            }
312    
313                            cacheConfiguration.addBootstrapCacheLoaderFactory(null);
314                    }
315    
316                    return new PortalCacheConfiguration(
317                            portalCacheName, cacheListenerConfigurations,
318                            bootstrapLoaderConfiguration);
319            }
320    
321            private static Properties _parseProperties(
322                    String propertiesString, String propertySeparator) {
323    
324                    Properties properties = new Properties();
325    
326                    if (propertiesString == null) {
327                            return properties;
328                    }
329    
330                    if (propertySeparator == null) {
331                            propertySeparator = StringPool.COMMA;
332                    }
333    
334                    String propertyLines = propertiesString.trim();
335    
336                    propertyLines = StringUtil.replace(
337                            propertyLines, propertySeparator, StringPool.NEW_LINE);
338    
339                    try {
340                            properties.load(new UnsyncStringReader(propertyLines));
341                    }
342                    catch (IOException ioe) {
343                            throw new RuntimeException(ioe);
344                    }
345    
346                    return properties;
347            }
348    
349    }