001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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, LPS-8865, and LPS-24280
074    
075                    DOMConfigurator domConfigurator = new DOMConfigurator();
076    
077                    Reader urlReader = new StringReader(urlContent);
078    
079                    domConfigurator.doConfigure(
080                            urlReader, LogManager.getLoggerRepository());
081    
082                    Set<String> currentLoggerNames = new HashSet<String>();
083    
084                    Enumeration<Logger> enu = LogManager.getCurrentLoggers();
085    
086                    while (enu.hasMoreElements()) {
087                            Logger logger = enu.nextElement();
088    
089                            currentLoggerNames.add(logger.getName());
090                    }
091    
092                    try {
093                            SAXReader saxReader = new SAXReader();
094    
095                            Reader reader = new StringReader(urlContent);
096    
097                            Document document = saxReader.read(reader, url.toExternalForm());
098    
099                            Element rootElement = document.getRootElement();
100    
101                            List<Element> categoryElements = rootElement.elements("category");
102    
103                            for (Element categoryElement : categoryElements) {
104                                    String name = categoryElement.attributeValue("name");
105    
106                                    Element priorityElement = categoryElement.element("priority");
107    
108                                    String priority = priorityElement.attributeValue("value");
109    
110                                    setLevel(name, priority, false);
111                            }
112                    }
113                    catch (Exception e) {
114                            e.printStackTrace();
115                    }
116            }
117    
118            public static Map<String, String> getCustomLogSettings() {
119                    return new HashMap<String, String>(_customLogSettings);
120            }
121    
122            public static String getOriginalLevel(String className) {
123                    Level level = Level.ALL;
124    
125                    Enumeration<Logger> enu = LogManager.getCurrentLoggers();
126    
127                    while (enu.hasMoreElements()) {
128                            Logger logger = enu.nextElement();
129    
130                            if (className.equals(logger.getName())) {
131                                    level = logger.getLevel();
132    
133                                    break;
134                            }
135                    }
136    
137                    return level.toString();
138            }
139    
140            public static void initLog4J(
141                    String serverId, String liferayHome, ClassLoader classLoader,
142                    LogFactory logFactory, Map<String, String> customLogSettings) {
143    
144                    ServerDetector.init(serverId);
145    
146                    _liferayHome = liferayHome;
147    
148                    configureLog4J(classLoader);
149    
150                    try {
151                            LogFactoryUtil.setLogFactory(logFactory);
152                    }
153                    catch (Exception e) {
154                            e.printStackTrace();
155                    }
156    
157                    for (String name : customLogSettings.keySet()) {
158                            String priority = customLogSettings.get(name);
159    
160                            setLevel(name, priority, false);
161                    }
162            }
163    
164            public static void setLevel(String name, String priority, boolean custom) {
165                    Logger logger = Logger.getLogger(name);
166    
167                    logger.setLevel(Level.toLevel(priority));
168    
169                    java.util.logging.Logger jdkLogger = java.util.logging.Logger.getLogger(
170                            name);
171    
172                    jdkLogger.setLevel(_getJdkLevel(priority));
173    
174                    if (custom) {
175                            _customLogSettings.put(name, priority);
176                    }
177            }
178    
179            /**
180             * @see {@link com.liferay.portal.util.FileImpl#getBytes(InputStream, int,
181             *      boolean)}
182             */
183            private static byte[] _getBytes(InputStream inputStream)
184                    throws IOException {
185    
186                    UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
187                            new UnsyncByteArrayOutputStream();
188    
189                    StreamUtil.transfer(inputStream, unsyncByteArrayOutputStream, -1, true);
190    
191                    return unsyncByteArrayOutputStream.toByteArray();
192            }
193    
194            private static java.util.logging.Level _getJdkLevel(String priority) {
195                    if (priority.equalsIgnoreCase(Level.DEBUG.toString())) {
196                            return java.util.logging.Level.FINE;
197                    }
198                    else if (priority.equalsIgnoreCase(Level.ERROR.toString())) {
199                            return java.util.logging.Level.SEVERE;
200                    }
201                    else if (priority.equalsIgnoreCase(Level.WARN.toString())) {
202                            return java.util.logging.Level.WARNING;
203                    }
204                    else {
205                            return java.util.logging.Level.INFO;
206                    }
207            }
208    
209            private static String _getLiferayHome() {
210                    if (_liferayHome == null) {
211                            _liferayHome = PropsUtil.get(PropsKeys.LIFERAY_HOME);
212                    }
213    
214                    return _liferayHome;
215            }
216    
217            private static String _getURLContent(URL url) {
218                    Map<String, String> variables = new HashMap<String, String>();
219    
220                    variables.put("liferay.home", _getLiferayHome());
221    
222                    String urlContent = null;
223    
224                    InputStream inputStream = null;
225    
226                    try {
227                            inputStream = url.openStream();
228    
229                            byte[] bytes = _getBytes(inputStream);
230    
231                            urlContent = new String(bytes, StringPool.UTF8);
232                    }
233                    catch (Exception e) {
234                            e.printStackTrace();
235    
236                            return null;
237                    }
238                    finally {
239                            StreamUtil.cleanUp(inputStream);
240                    }
241    
242                    for (Map.Entry<String, String> variable : variables.entrySet()) {
243                            urlContent = urlContent.replaceAll(
244                                    "@" + variable.getKey() + "@", variable.getValue());
245                    }
246    
247                    if (ServerDetector.getServerId() != null) {
248                            return urlContent;
249                    }
250    
251                    int x = urlContent.indexOf("<appender name=\"FILE\"");
252    
253                    int y = urlContent.indexOf("</appender>", x);
254    
255                    if (y != -1) {
256                            y = urlContent.indexOf("<", y + 1);
257                    }
258    
259                    if ((x != -1) && (y != -1)) {
260                            urlContent = urlContent.substring(0, x) + urlContent.substring(y);
261                    }
262    
263                    urlContent = StringUtil.replace(
264                            urlContent, "<appender-ref ref=\"FILE\" />", StringPool.BLANK);
265    
266                    return urlContent;
267            }
268    
269            private static Map<String, String> _customLogSettings =
270                    new ConcurrentHashMap<String, String>();
271            private static String _liferayHome;
272    
273    }