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                    if (cacheConfiguration == null) {
212                            return null;
213                    }
214    
215                    String portalCacheName = cacheConfiguration.getName();
216    
217                    if (portalCacheName == null) {
218                            portalCacheName =
219                                    PortalCacheConfiguration.DEFAULT_PORTAL_CACHE_NAME;
220                    }
221    
222                    Map<CallbackConfiguration, CacheListenerScope>
223                            cacheListenerConfigurations =
224                                    new HashMap<CallbackConfiguration, CacheListenerScope>();
225    
226                    List<CacheEventListenerFactoryConfiguration>
227                            cacheEventListenerConfigurations =
228                                    cacheConfiguration.getCacheEventListenerConfigurations();
229    
230                    for (CacheEventListenerFactoryConfiguration
231                                    cacheEventListenerFactoryConfiguration :
232                                            cacheEventListenerConfigurations) {
233    
234                            String fullyQualifiedClassPath =
235                                    cacheEventListenerFactoryConfiguration.
236                                            getFullyQualifiedClassPath();
237    
238                            Properties properties = _parseProperties(
239                                    cacheEventListenerFactoryConfiguration.getProperties(),
240                                    cacheEventListenerFactoryConfiguration. getPropertySeparator());
241    
242                            CacheListenerScope cacheListenerScope = _getCacheListenerScope(
243                                    cacheEventListenerFactoryConfiguration.getListenFor());
244    
245                            if (fullyQualifiedClassPath.contains(
246                                            "LiferayCacheEventListenerFactory") ||
247                                    fullyQualifiedClassPath.contains(
248                                            "net.sf.ehcache.distribution")) {
249    
250                                    if (clusterAware && PropsValues.CLUSTER_LINK_ENABLED) {
251                                            if (PropsValues.EHCACHE_CLUSTER_LINK_REPLICATION_ENABLED) {
252                                                    cacheListenerConfigurations.put(
253                                                            new CallbackConfiguration(
254                                                                    ClusterLinkCallbackFactory.INSTANCE,
255                                                                    properties),
256                                                            cacheListenerScope);
257                                            }
258                                            else {
259                                                    properties.put(
260                                                            EhcacheConstants.
261                                                                    CACHE_EVENT_LISTENER_FACTORY_CLASS_NAME,
262                                                            cacheEventListenerFactoryConfiguration.
263                                                                    getFullyQualifiedClassPath());
264    
265                                                    cacheListenerConfigurations.put(
266                                                            new CallbackConfiguration(
267                                                                    EhcacheCallbackFactory.INSTANCE, properties),
268                                                            cacheListenerScope);
269                                            }
270                                    }
271                            }
272                            else if (!usingDefault) {
273                                    properties.put(
274                                            EhcacheConstants.CACHE_EVENT_LISTENER_FACTORY_CLASS_NAME,
275                                            cacheEventListenerFactoryConfiguration.
276                                                    getFullyQualifiedClassPath());
277    
278                                    cacheListenerConfigurations.put(
279                                            new CallbackConfiguration(
280                                                    EhcacheCallbackFactory.INSTANCE, properties),
281                                            cacheListenerScope);
282                            }
283                    }
284    
285                    cacheEventListenerConfigurations.clear();
286    
287                    CallbackConfiguration bootstrapLoaderConfiguration = null;
288    
289                    BootstrapCacheLoaderFactoryConfiguration
290                            bootstrapCacheLoaderFactoryConfiguration =
291                                    cacheConfiguration.
292                                            getBootstrapCacheLoaderFactoryConfiguration();
293    
294                    if (bootstrapCacheLoaderFactoryConfiguration != null) {
295                            Properties properties = _parseProperties(
296                                    bootstrapCacheLoaderFactoryConfiguration.getProperties(),
297                                    bootstrapCacheLoaderFactoryConfiguration.
298                                            getPropertySeparator());
299    
300                            if (clusterAware && PropsValues.CLUSTER_LINK_ENABLED) {
301                                    if (PropsValues.EHCACHE_CLUSTER_LINK_REPLICATION_ENABLED) {
302                                            bootstrapLoaderConfiguration = new CallbackConfiguration(
303                                                    ClusterLinkCallbackFactory.INSTANCE, properties);
304                                    }
305                                    else {
306                                            properties.put(
307                                                    EhcacheConstants.
308                                                            BOOTSTRAP_CACHE_LOADER_FACTORY_CLASS_NAME,
309                                                    bootstrapCacheLoaderFactoryConfiguration.
310                                                            getFullyQualifiedClassPath());
311    
312                                            bootstrapLoaderConfiguration = new CallbackConfiguration(
313                                                    EhcacheCallbackFactory.INSTANCE, properties);
314                                    }
315                            }
316    
317                            cacheConfiguration.addBootstrapCacheLoaderFactory(null);
318                    }
319    
320                    return new PortalCacheConfiguration(
321                            portalCacheName, cacheListenerConfigurations,
322                            bootstrapLoaderConfiguration);
323            }
324    
325            private static Properties _parseProperties(
326                    String propertiesString, String propertySeparator) {
327    
328                    Properties properties = new Properties();
329    
330                    if (propertiesString == null) {
331                            return properties;
332                    }
333    
334                    if (propertySeparator == null) {
335                            propertySeparator = StringPool.COMMA;
336                    }
337    
338                    String propertyLines = propertiesString.trim();
339    
340                    propertyLines = StringUtil.replace(
341                            propertyLines, propertySeparator, StringPool.NEW_LINE);
342    
343                    try {
344                            properties.load(new UnsyncStringReader(propertyLines));
345                    }
346                    catch (IOException ioe) {
347                            throw new RuntimeException(ioe);
348                    }
349    
350                    return properties;
351            }
352    
353    }