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