001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.log;
031:
032: import com.caucho.config.ConfigException;
033: import com.caucho.config.types.RawString;
034: import com.caucho.jmx.Jmx;
035: import com.caucho.loader.CloseListener;
036: import com.caucho.loader.Environment;
037: import com.caucho.management.server.*;
038: import com.caucho.util.L10N;
039: import com.caucho.vfs.WriteStream;
040:
041: import javax.annotation.PostConstruct;
042: import javax.management.*;
043: import java.util.ArrayList;
044: import java.util.logging.Formatter;
045: import java.util.logging.Handler;
046: import java.util.logging.Level;
047: import java.util.logging.Logger;
048:
049: /**
050: * Environment-specific configuration.
051: */
052: public class LogConfig extends RotateLog {
053: private static final Logger log = Logger.getLogger(LogConfig.class
054: .getName());
055: private static final L10N L = new L10N(LogConfig.class);
056:
057: private ArrayList<Handler> _handlers;
058: private Formatter _formatter;
059: private String _timestamp;
060:
061: private ArrayList<SubLogger> _subLoggers = new ArrayList<SubLogger>();
062: private SubLogger _subLogger;
063:
064: private String _mbeanName;
065:
066: private boolean _isInit;
067:
068: public LogConfig() {
069: setTimestamp("[%Y/%m/%d %H:%M:%S.%s] ");
070: }
071:
072: /**
073: * Sets the name of the logger to configure.
074: *
075: * @deprecated Use setName()
076: */
077: public void setId(String name) {
078: // backward compat
079: if (name.equals("/"))
080: name = "";
081:
082: setName(name);
083: }
084:
085: /**
086: * Sets the name of the logger to configure.
087: */
088: public void setName(String name) {
089: getSubLogger().setName(name);
090: }
091:
092: /**
093: * Returns the name of the logger to configure.
094: */
095: public String getName() {
096: return getSubLogger().getName();
097: }
098:
099: /**
100: * Sets the mbean-name of the logger to configure.
101: */
102: public void setMbeanName(String name) {
103: _mbeanName = name;
104: }
105:
106: /**
107: * Sets the use-parent-handlers
108: */
109: public void setUseParentHandlers(boolean useParentHandlers)
110: throws ConfigException {
111: getSubLogger().setUseParentHandlers(useParentHandlers);
112: }
113:
114: /**
115: * Sets the output level.
116: */
117: public void setLevel(String level) throws ConfigException {
118: getSubLogger().setLevel(level);
119:
120: if (_isInit && _handlers != null) {
121: for (Handler handler : _handlers) {
122: handler.setLevel(getSubLogger().getLevel());
123: }
124: }
125: }
126:
127: /**
128: * Sets the output level.
129: */
130: public String getLevel() {
131: Level level = getSubLogger().getLevel();
132:
133: if (level != null)
134: return level.getName();
135: else
136: return Level.INFO.getName();
137: }
138:
139: /**
140: * Sets the sublogger.
141: */
142: private SubLogger getSubLogger() {
143: if (_subLogger == null) {
144: _subLogger = new SubLogger();
145: _subLoggers.add(_subLogger);
146: }
147:
148: return _subLogger;
149: }
150:
151: /**
152: * Sets the timestamp.
153: */
154: public void setTimestamp(String timestamp) {
155: _timestamp = timestamp;
156: }
157:
158: /**
159: * A format string uses EL expressions and the EL variable `log', which is an
160: * instance of LogRecord.
161: */
162: public void setFormat(RawString format) {
163: if (_formatter == null) {
164: _formatter = new ELFormatter();
165: }
166:
167: if (_formatter instanceof ELFormatter)
168: ((ELFormatter) _formatter).setFormat(format);
169: }
170:
171: /**
172: * A format string uses EL expressions and the EL variable `log', which is an
173: * instance of LogRecord.
174: */
175: public String getFormat() {
176: if (_formatter != null && _formatter instanceof ELFormatter)
177: return ((ELFormatter) _formatter).getFormat();
178: else
179: return null;
180: }
181:
182: /**
183: * Sets the formatter.
184: */
185: public void setFormatter(Formatter formatter) {
186: _formatter = formatter;
187: }
188:
189: /**
190: * Adds a handler
191: */
192: public void addHandler(Handler handler) {
193: if (handler == null)
194: throw new NullPointerException();
195:
196: if (_handlers == null)
197: _handlers = new ArrayList<Handler>();
198:
199: _handlers.add(handler);
200: }
201:
202: /**
203: * Returns the tag name.
204: */
205: public String getTagName() {
206: return "log";
207: }
208:
209: /**
210: * Adds a logger.
211: */
212: public void addLogger(LoggerConfig logger) {
213: }
214:
215: /**
216: * Initialize the log.
217: */
218: @PostConstruct
219: public void init() throws ConfigException, java.io.IOException {
220: _isInit = true;
221:
222: if (_handlers == null)
223: super .init();
224:
225: if (_subLoggers.size() == 0)
226: getSubLogger();
227:
228: if (_subLogger != null)
229: _subLogger.init();
230:
231: if (_formatter instanceof ELFormatter) {
232: ((ELFormatter) _formatter).init();
233: }
234:
235: WriteStream os = null;
236:
237: if (_handlers == null) {
238: os = getRotateStream().getStream();
239:
240: if (_timestamp != null) {
241: TimestampFilter filter = new TimestampFilter();
242: filter.setTimestamp(_timestamp);
243: filter.setStream(os);
244: os = new WriteStream(filter);
245: }
246:
247: String encoding = System.getProperty("file.encoding");
248:
249: if (encoding != null)
250: os.setEncoding(encoding);
251:
252: os.setDisableClose(true);
253: }
254:
255: boolean hasCloseListener = false;
256: for (int i = 0; i < _subLoggers.size(); i++) {
257: SubLogger subLogger = _subLoggers.get(i);
258: Logger logger = subLogger.getLogger();
259:
260: Level subLevel = subLogger.getLevel();
261: Level level = logger.getLevel();
262:
263: if (subLevel != null
264: && (level == null
265: && subLevel.intValue() < Level.INFO
266: .intValue() || level != null
267: && subLevel.intValue() < level.intValue())) {
268: logger.setLevel(subLogger.getLevel());
269: }
270:
271: if (_handlers == null) {
272: StreamHandler handler = new StreamHandler(os);
273: handler.setFormatter(_formatter);
274:
275: _handlers = new ArrayList<Handler>();
276: _handlers.add(handler);
277: }
278:
279: for (int j = 0; j < _handlers.size(); j++) {
280: SubHandler subHandler = new SubHandler(_handlers.get(j));
281:
282: if (subLogger.getLevel() != null)
283: subHandler.setLevel(subLogger.getLevel());
284:
285: if (!(logger instanceof EnvironmentLogger)) {
286: CloseListener listener = new CloseListener(
287: subHandler);
288:
289: Environment.addClassLoaderListener(listener);
290: }
291:
292: logger.addHandler(subHandler);
293: }
294: }
295:
296: if (_mbeanName != null) {
297: try {
298: ObjectName objectName = Jmx.getObjectName(_mbeanName);
299:
300: Jmx.register(new LogAdmin(), objectName,
301: LoggerMXBean.class);
302: } catch (Throwable e) {
303: log.log(Level.WARNING, e.toString(), e);
304: }
305: }
306: }
307:
308: static Level toLevel(String level) throws ConfigException {
309: if (level.equals("off"))
310: return Level.OFF;
311: else if (level.equals("severe"))
312: return Level.SEVERE;
313: else if (level.equals("warning"))
314: return Level.WARNING;
315: else if (level.equals("info"))
316: return Level.INFO;
317: else if (level.equals("config"))
318: return Level.CONFIG;
319: else if (level.equals("fine"))
320: return Level.FINE;
321: else if (level.equals("finer"))
322: return Level.FINER;
323: else if (level.equals("finest"))
324: return Level.FINEST;
325: else if (level.equals("all"))
326: return Level.ALL;
327: else
328: throw new ConfigException(
329: L
330: .l(
331: "`{0}' is an unknown log level. Log levels are:\noff - disable logging\nsevere - severe errors only\nwarning - warnings\ninfo - information\nconfig - configuration\nfine - fine debugging\nfiner - finer debugging\nfinest - finest debugging\nall - all debugging",
332: level));
333: }
334:
335: public static class SubLogger {
336: private Logger _logger;
337: private String _name = "";
338: private Level _level;
339: private boolean _useParentHandlers = true;
340:
341: // for mbean management
342: private Handler _handler;
343:
344: /**
345: * Sets the name of the logger to configure.
346: */
347: public void setId(String name) {
348: // backward compat
349: if (name.equals("/"))
350: name = "";
351:
352: setName(name);
353: }
354:
355: /**
356: * Sets the name of the logger to configure.
357: */
358: public void setName(String name) {
359: _name = name;
360: }
361:
362: /**
363: * Gets the name of the logger to configure.
364: */
365: public String getName() {
366: return _name;
367: }
368:
369: /**
370: * Sets the use-parent-handlers
371: */
372: public void setUseParentHandlers(boolean useParentHandlers)
373: throws ConfigException {
374: _logger = Logger.getLogger(_name);
375:
376: _logger.setUseParentHandlers(useParentHandlers);
377:
378: _useParentHandlers = useParentHandlers;
379: }
380:
381: /**
382: * Gets the logger.
383: */
384: public Logger getLogger() {
385: return Logger.getLogger(_name);
386: }
387:
388: /**
389: * Gets the output level.
390: */
391: public Level getLevel() {
392: return _level;
393: }
394:
395: /**
396: * Sets the output level.
397: */
398: public void setLevel(String level) throws ConfigException {
399: if (level.equals("off"))
400: _level = Level.OFF;
401: else if (level.equals("severe"))
402: _level = Level.SEVERE;
403: else if (level.equals("warning"))
404: _level = Level.WARNING;
405: else if (level.equals("info"))
406: _level = Level.INFO;
407: else if (level.equals("config"))
408: _level = Level.CONFIG;
409: else if (level.equals("fine"))
410: _level = Level.FINE;
411: else if (level.equals("finer"))
412: _level = Level.FINER;
413: else if (level.equals("finest"))
414: _level = Level.FINEST;
415: else if (level.equals("all"))
416: _level = Level.ALL;
417: else
418: throw new ConfigException(
419: L
420: .l(
421: "`{0}' is an unknown log level. Log levels are:\noff - disable logging\nsevere - severe errors only\nwarning - warnings\ninfo - information\nconfig - configuration\nfine - fine debugging\nfiner - finer debugging\nfinest - finest debugging\nall - all debugging",
422: level));
423: }
424:
425: /**
426: * Sets the handler.
427: */
428: public void setHandler(Handler handler) {
429: _handler = handler;
430: }
431:
432: /**
433: * Gets the handler.
434: */
435: public Handler getHandler() {
436: return _handler;
437: }
438:
439: @PostConstruct
440: public void init() throws ConfigException {
441: if (_name == null)
442: throw new ConfigException(
443: L
444: .l("`name' is a required attribute.. Each logger must configure the log name, e.g. com.caucho.server.webapp."));
445: }
446: }
447:
448: class LogAdmin extends AbstractManagedObject implements
449: LoggerMXBean {
450: public String getType() {
451: return "Logger";
452: }
453:
454: public String getName() {
455: return LogConfig.this .getName();
456: }
457:
458: public String getLevel() {
459: return LogConfig.this .getLevel();
460: }
461:
462: public void setLevel(String level) {
463: if (_subLogger != null) {
464: _subLogger.setLevel(level);
465: _subLogger.getLogger().setLevel(_subLogger.getLevel());
466: }
467:
468: for (int i = 0; i < _subLoggers.size(); i++) {
469: SubLogger subLogger = _subLoggers.get(i);
470:
471: subLogger.setLevel(level);
472: subLogger.getLogger().setLevel(_subLogger.getLevel());
473: }
474: }
475: }
476: }
|