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.util.log4j;
016    
017    import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
018    import com.liferay.portal.kernel.log.LogFactory;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.util.PropsKeys;
021    import com.liferay.portal.kernel.util.PropsUtil;
022    import com.liferay.portal.kernel.util.ServerDetector;
023    import com.liferay.portal.kernel.util.StreamUtil;
024    import com.liferay.portal.kernel.util.StringPool;
025    import com.liferay.portal.kernel.util.StringUtil;
026    
027    import java.io.IOException;
028    import java.io.InputStream;
029    import java.io.Reader;
030    import java.io.StringReader;
031    
032    import java.net.URL;
033    
034    import java.util.Enumeration;
035    import java.util.HashMap;
036    import java.util.HashSet;
037    import java.util.List;
038    import java.util.Map;
039    import java.util.Set;
040    import java.util.concurrent.ConcurrentHashMap;
041    
042    import org.apache.log4j.Appender;
043    import org.apache.log4j.Level;
044    import org.apache.log4j.LogManager;
045    import org.apache.log4j.Logger;
046    import org.apache.log4j.WriterAppender;
047    import org.apache.log4j.xml.DOMConfigurator;
048    
049    import org.dom4j.Document;
050    import org.dom4j.Element;
051    import org.dom4j.io.SAXReader;
052    
053    /**
054     * @author Brian Wing Shun Chan
055     * @author Tomas Polesovsky
056     */
057    public class Log4JUtil {
058    
059            public static void configureLog4J(ClassLoader classLoader) {
060                    configureLog4J(classLoader.getResource("META-INF/portal-log4j.xml"));
061    
062                    try {
063                            Enumeration<URL> enu = classLoader.getResources(
064                                    "META-INF/portal-log4j-ext.xml");
065    
066                            while (enu.hasMoreElements()) {
067                                    configureLog4J(enu.nextElement());
068                            }
069                    }
070                    catch (IOException ioe) {
071                            java.util.logging.Logger logger =
072                                    java.util.logging.Logger.getLogger(Log4JUtil.class.getName());
073    
074                            logger.log(
075                                    java.util.logging.Level.WARNING,
076                                    "Unable to load portal-log4j-ext.xml", ioe);
077                    }
078    
079                    if (ServerDetector.isJBoss5()) {
080                            Logger rootLogger = LogManager.getRootLogger();
081    
082                            Enumeration<Appender> enu = rootLogger.getAllAppenders();
083    
084                            while (enu.hasMoreElements()) {
085                                    Appender appender = enu.nextElement();
086    
087                                    if (appender instanceof WriterAppender) {
088                                            WriterAppender writerAppender = (WriterAppender)appender;
089    
090                                            writerAppender.activateOptions();
091                                    }
092                            }
093                    }
094            }
095    
096            public static void configureLog4J(URL url) {
097                    if (url == null) {
098                            return;
099                    }
100    
101                    String urlContent = _getURLContent(url);
102    
103                    if (urlContent == null) {
104                            return;
105                    }
106    
107                    // See LPS-6029, LPS-8865, and LPS-24280
108    
109                    DOMConfigurator domConfigurator = new DOMConfigurator();
110    
111                    Reader urlReader = new StringReader(urlContent);
112    
113                    domConfigurator.doConfigure(
114                            urlReader, LogManager.getLoggerRepository());
115    
116                    Set<String> currentLoggerNames = new HashSet<>();
117    
118                    Enumeration<Logger> enu = LogManager.getCurrentLoggers();
119    
120                    while (enu.hasMoreElements()) {
121                            Logger logger = enu.nextElement();
122    
123                            currentLoggerNames.add(logger.getName());
124                    }
125    
126                    try {
127                            SAXReader saxReader = new SAXReader();
128    
129                            Reader reader = new StringReader(urlContent);
130    
131                            Document document = saxReader.read(reader, url.toExternalForm());
132    
133                            Element rootElement = document.getRootElement();
134    
135                            List<Element> categoryElements = rootElement.elements("category");
136    
137                            for (Element categoryElement : categoryElements) {
138                                    String name = categoryElement.attributeValue("name");
139    
140                                    Element priorityElement = categoryElement.element("priority");
141    
142                                    String priority = priorityElement.attributeValue("value");
143    
144                                    setLevel(name, priority, false);
145                            }
146                    }
147                    catch (Exception e) {
148                            _logger.error(e, e);
149                    }
150            }
151    
152            public static Map<String, String> getCustomLogSettings() {
153                    return new HashMap<>(_customLogSettings);
154            }
155    
156            public static String getOriginalLevel(String className) {
157                    Level level = Level.ALL;
158    
159                    Enumeration<Logger> enu = LogManager.getCurrentLoggers();
160    
161                    while (enu.hasMoreElements()) {
162                            Logger logger = enu.nextElement();
163    
164                            if (className.equals(logger.getName())) {
165                                    level = logger.getLevel();
166    
167                                    break;
168                            }
169                    }
170    
171                    return level.toString();
172            }
173    
174            public static void initLog4J(
175                    String serverId, String liferayHome, ClassLoader classLoader,
176                    LogFactory logFactory, Map<String, String> customLogSettings) {
177    
178                    ServerDetector.init(serverId);
179    
180                    _liferayHome = liferayHome;
181    
182                    configureLog4J(classLoader);
183    
184                    try {
185                            LogFactoryUtil.setLogFactory(logFactory);
186                    }
187                    catch (Exception e) {
188                            _logger.error(e, e);
189                    }
190    
191                    for (String name : customLogSettings.keySet()) {
192                            String priority = customLogSettings.get(name);
193    
194                            setLevel(name, priority, false);
195                    }
196            }
197    
198            public static void setLevel(String name, String priority, boolean custom) {
199                    Logger logger = Logger.getLogger(name);
200    
201                    logger.setLevel(Level.toLevel(priority));
202    
203                    java.util.logging.Logger jdkLogger = java.util.logging.Logger.getLogger(
204                            name);
205    
206                    jdkLogger.setLevel(_getJdkLevel(priority));
207    
208                    if (custom) {
209                            _customLogSettings.put(name, priority);
210                    }
211            }
212    
213            /**
214             * @see com.liferay.portal.util.FileImpl#getBytes(InputStream, int, boolean)
215             */
216            private static byte[] _getBytes(InputStream inputStream)
217                    throws IOException {
218    
219                    UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
220                            new UnsyncByteArrayOutputStream();
221    
222                    StreamUtil.transfer(inputStream, unsyncByteArrayOutputStream, -1, true);
223    
224                    return unsyncByteArrayOutputStream.toByteArray();
225            }
226    
227            private static java.util.logging.Level _getJdkLevel(String priority) {
228                    if (StringUtil.equalsIgnoreCase(priority, Level.DEBUG.toString())) {
229                            return java.util.logging.Level.FINE;
230                    }
231                    else if (StringUtil.equalsIgnoreCase(
232                                            priority, Level.ERROR.toString())) {
233    
234                            return java.util.logging.Level.SEVERE;
235                    }
236                    else if (StringUtil.equalsIgnoreCase(priority, Level.WARN.toString())) {
237                            return java.util.logging.Level.WARNING;
238                    }
239                    else {
240                            return java.util.logging.Level.INFO;
241                    }
242            }
243    
244            private static String _getLiferayHome() {
245                    if (_liferayHome == null) {
246                            _liferayHome = PropsUtil.get(PropsKeys.LIFERAY_HOME);
247                    }
248    
249                    return _liferayHome;
250            }
251    
252            private static String _getURLContent(URL url) {
253                    Map<String, String> variables = new HashMap<>();
254    
255                    variables.put("@liferay.home@", _getLiferayHome());
256    
257                    String spiId = System.getProperty("spi.id");
258    
259                    if (spiId == null) {
260                            spiId = StringPool.BLANK;
261                    }
262    
263                    variables.put("@spi.id@", spiId);
264    
265                    String urlContent = null;
266    
267                    InputStream inputStream = null;
268    
269                    try {
270                            inputStream = url.openStream();
271    
272                            byte[] bytes = _getBytes(inputStream);
273    
274                            urlContent = new String(bytes, StringPool.UTF8);
275                    }
276                    catch (Exception e) {
277                            _logger.error(e, e);
278    
279                            return null;
280                    }
281                    finally {
282                            StreamUtil.cleanUp(inputStream);
283                    }
284    
285                    for (Map.Entry<String, String> variable : variables.entrySet()) {
286                            urlContent = StringUtil.replace(
287                                    urlContent, variable.getKey(), variable.getValue());
288                    }
289    
290                    if (ServerDetector.getServerId() != null) {
291                            return urlContent;
292                    }
293    
294                    urlContent = _removeAppender(urlContent, "TEXT_FILE");
295    
296                    return _removeAppender(urlContent, "XML_FILE");
297            }
298    
299            private static String _removeAppender(String content, String appenderName) {
300                    int x = content.indexOf("<appender name=\"" + appenderName + "\"");
301    
302                    int y = content.indexOf("</appender>", x);
303    
304                    if (y != -1) {
305                            y = content.indexOf("<", y + 1);
306                    }
307    
308                    if ((x != -1) && (y != -1)) {
309                            content = content.substring(0, x) + content.substring(y);
310                    }
311    
312                    return StringUtil.replace(
313                            content, "<appender-ref ref=\"" + appenderName + "\" />",
314                            StringPool.BLANK);
315            }
316    
317            private static final Logger _logger = Logger.getRootLogger();
318    
319            private static final Map<String, String> _customLogSettings =
320                    new ConcurrentHashMap<>();
321            private static String _liferayHome;
322    
323    }