001    /**
002     * Copyright (c) 2000-2013 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.kernel.log;
016    
017    import com.liferay.portal.kernel.security.pacl.permission.PortalRuntimePermission;
018    
019    import java.util.Map;
020    import java.util.concurrent.ConcurrentHashMap;
021    import java.util.concurrent.ConcurrentMap;
022    
023    /**
024     * @author Brian Wing Shun Chan
025     * @author Shuyang Zhou
026     */
027    public class LogFactoryUtil {
028    
029            public static Log getLog(Class<?> c) {
030                    return getLog(c.getName());
031            }
032    
033            public static Log getLog(String name) {
034    
035                    // The following concurrent collection retrieve has the side effect of a
036                    // memory fence read. This will invalidate all dirty cache data if there
037                    // are any. If the LogWrapper swap happens before this, the new Log will
038                    // be visible to the current Thread.
039    
040                    LogWrapper logWrapper = _logWrappers.get(name);
041    
042                    if (logWrapper == null) {
043                            logWrapper = new LogWrapper(_logFactory.getLog(name));
044    
045                            LogWrapper previousLogWrapper = _logWrappers.putIfAbsent(
046                                    name, logWrapper);
047    
048                            if (previousLogWrapper != null) {
049                                    logWrapper = previousLogWrapper;
050                            }
051                    }
052    
053                    return logWrapper;
054            }
055    
056            public static LogFactory getLogFactory() {
057                    PortalRuntimePermission.checkGetBeanProperty(LogFactoryUtil.class);
058    
059                    return _logFactory;
060            }
061    
062            public static void setLogFactory(LogFactory logFactory) {
063                    PortalRuntimePermission.checkSetBeanProperty(LogFactoryUtil.class);
064    
065                    for (Map.Entry<String, LogWrapper> entry : _logWrappers.entrySet()) {
066                            String name = entry.getKey();
067    
068                            LogWrapper logWrapper = entry.getValue();
069    
070                            logWrapper.setLog(logFactory.getLog(name));
071                    }
072    
073                    // The following volatile write will flush out all cache data. All
074                    // previously swapped LogWrappers will be visible for any reads after a
075                    // memory fence read according to the happens-before rules.
076    
077                    _logFactory = logFactory;
078            }
079    
080            private static volatile LogFactory _logFactory = new Jdk14LogFactoryImpl();
081    
082            private static final ConcurrentMap<String, LogWrapper> _logWrappers =
083                    new ConcurrentHashMap<String, LogWrapper>();
084    
085    }