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