001    /**
002     * Copyright (c) 2000-2011 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.Level;
043    import org.apache.log4j.LogManager;
044    import org.apache.log4j.Logger;
045    import org.apache.log4j.xml.DOMConfigurator;
046    
047    import org.dom4j.Document;
048    import org.dom4j.Element;
049    import org.dom4j.io.SAXReader;
050    
051    /**
052     * @author Brian Wing Shun Chan
053     */
054    public class Log4JUtil {
055    
056            public static void configureLog4J(ClassLoader classLoader) {
057                    configureLog4J(classLoader.getResource("META-INF/portal-log4j.xml"));
058                    configureLog4J(
059                            classLoader.getResource("META-INF/portal-log4j-ext.xml"));
060            }
061    
062            public static void configureLog4J(URL url) {
063                    if (url == null) {
064                            return;
065                    }
066    
067                    String urlContent = _getURLContent(url);
068    
069                    if (urlContent == null) {
070                            return;
071                    }
072    
073                    // See LPS-6029 and LPS-8865
074    
075                    if (!ServerDetector.isJBoss()) {
076                            DOMConfigurator domConfigurator = new DOMConfigurator();
077    
078                            Reader urlReader = new StringReader(urlContent);
079    
080                            domConfigurator.doConfigure(
081                                    urlReader, LogManager.getLoggerRepository());
082                    }
083    
084                    Set<String> currentLoggerNames = new HashSet<String>();
085    
086                    Enumeration<Logger> enu = LogManager.getCurrentLoggers();
087    
088                    while (enu.hasMoreElements()) {
089                            Logger logger = enu.nextElement();
090    
091                            currentLoggerNames.add(logger.getName());
092                    }
093    
094                    try {
095                            SAXReader saxReader = new SAXReader();
096    
097                            Reader reader = new StringReader(urlContent);
098    
099                            Document document = saxReader.read(reader, url.toExternalForm());
100    
101                            Element rootElement = document.getRootElement();
102    
103                            List<Element> categoryElements = rootElement.elements("category");
104    
105                            for (Element categoryElement : categoryElements) {
106                                    String name = categoryElement.attributeValue("name");
107    
108                                    Element priorityElement = categoryElement.element("priority");
109    
110                                    String priority = priorityElement.attributeValue("value");
111    
112                                    setLevel(name, priority, false);
113                            }
114                    }
115                    catch (Exception e) {
116                            e.printStackTrace();
117                    }
118            }
119    
120            public static Map<String, String> getCustomLogSettings() {
121                    return new HashMap<String, String>(_customLogSettings);
122            }
123    
124            public static void initLog4J(
125                    String serverId, String liferayHome, ClassLoader classLoader,
126                    LogFactory logFactory, Map<String, String> customLogSettings) {
127    
128                    ServerDetector.init(serverId);
129    
130                    _liferayHome = liferayHome;
131    
132                    configureLog4J(classLoader);
133    
134                    try {
135                            LogFactoryUtil.setLogFactory(logFactory);
136                    }
137                    catch (Exception e) {
138                            e.printStackTrace();
139                    }
140    
141                    for (String name : customLogSettings.keySet()) {
142                            String priority = customLogSettings.get(name);
143    
144                            setLevel(name, priority, false);
145                    }
146            }
147    
148            public static void setLevel(String name, String priority, boolean custom) {
149                    Logger logger = Logger.getLogger(name);
150    
151                    logger.setLevel(Level.toLevel(priority));
152    
153                    java.util.logging.Logger jdkLogger = java.util.logging.Logger.getLogger(
154                            name);
155    
156                    jdkLogger.setLevel(_getJdkLevel(priority));
157    
158                    if (custom) {
159                            _customLogSettings.put(name, priority);
160                    }
161            }
162    
163            /**
164             * @see {@link com.liferay.portal.util.FileImpl#getBytes(InputStream, int,
165             *      boolean)}
166             */
167            private static byte[] _getBytes(InputStream inputStream)
168                    throws IOException {
169    
170                    UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
171                            new UnsyncByteArrayOutputStream();
172    
173                    StreamUtil.transfer(inputStream, unsyncByteArrayOutputStream, -1, true);
174    
175                    return unsyncByteArrayOutputStream.toByteArray();
176            }
177    
178            private static java.util.logging.Level _getJdkLevel(String priority) {
179                    if (priority.equalsIgnoreCase(Level.DEBUG.toString())) {
180                            return java.util.logging.Level.FINE;
181                    }
182                    else if (priority.equalsIgnoreCase(Level.ERROR.toString())) {
183                            return java.util.logging.Level.SEVERE;
184                    }
185                    else if (priority.equalsIgnoreCase(Level.WARN.toString())) {
186                            return java.util.logging.Level.WARNING;
187                    }
188                    else {
189                            return java.util.logging.Level.INFO;
190                    }
191            }
192    
193            private static String _getLiferayHome() {
194                    if (_liferayHome == null) {
195                            _liferayHome = PropsUtil.get(PropsKeys.LIFERAY_HOME);
196                    }
197    
198                    return _liferayHome;
199            }
200            private static String _getURLContent(URL url) {
201                    Map<String, String> variables = new HashMap<String, String>();
202    
203                    variables.put("liferay.home", _getLiferayHome());
204    
205                    String urlContent = null;
206    
207                    InputStream inputStream = null;
208    
209                    try {
210                            inputStream = url.openStream();
211    
212                            byte[] bytes = _getBytes(inputStream);
213    
214                            urlContent = new String(bytes, StringPool.UTF8);
215                    }
216                    catch (Exception e) {
217                            e.printStackTrace();
218    
219                            return null;
220                    }
221                    finally {
222                            StreamUtil.cleanUp(inputStream);
223                    }
224    
225                    for (Map.Entry<String, String> variable : variables.entrySet()) {
226                            urlContent = urlContent.replaceAll(
227                                    "@" + variable.getKey() + "@", variable.getValue());
228                    }
229    
230                    if (ServerDetector.getServerId() != null) {
231                            return urlContent;
232                    }
233    
234                    int x = urlContent.indexOf("<appender name=\"FILE\"");
235    
236                    int y = urlContent.indexOf("</appender>", x);
237    
238                    if (y != -1) {
239                            y = urlContent.indexOf("<", y + 1);
240                    }
241    
242                    if ((x != -1) && (y != -1)) {
243                            urlContent = urlContent.substring(0, x) + urlContent.substring(y);
244                    }
245    
246                    urlContent = StringUtil.replace(
247                            urlContent, "<appender-ref ref=\"FILE\" />", StringPool.BLANK);
248    
249                    return urlContent;
250            }
251    
252            private static Map<String, String> _customLogSettings =
253                    new ConcurrentHashMap<String, String>();
254            private static String _liferayHome;
255    
256    }