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: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.log;
030:
031: import com.caucho.config.ConfigELContext;
032: import com.caucho.config.ConfigException;
033: import com.caucho.config.types.RawString;
034: import com.caucho.el.AbstractVariableResolver;
035: import com.caucho.el.ELParser;
036: import com.caucho.el.Expr;
037: import com.caucho.util.L10N;
038:
039: import javax.annotation.PostConstruct;
040: import javax.el.ELContext;
041: import javax.el.ELException;
042: import java.util.ResourceBundle;
043: import java.util.logging.Level;
044: import java.util.logging.LogRecord;
045:
046: /**
047: * A Formatter that accepts an EL format string, and.
048: */
049: public class ELFormatter extends MessageFormatter {
050: static final L10N L = new L10N(ELFormatter.class);
051:
052: private String _format;
053: private Expr _expr;
054:
055: public void setFormat(RawString format) {
056: _format = format.getValue();
057: }
058:
059: public String getFormat() {
060: return _format;
061: }
062:
063: @PostConstruct
064: public void init() throws ConfigException {
065: if (_format != null) {
066: try {
067: _expr = (new ELParser(new ConfigELContext(), _format))
068: .parse();
069: } catch (Exception ex) {
070: throw ConfigException.create(ex);
071: }
072: }
073: }
074:
075: public String format(LogRecord logRecord) {
076: if (_expr == null) {
077: return super .format(logRecord);
078: }
079:
080: String ret;
081: if (_expr == null) {
082: ret = super .format(logRecord);
083: } else {
084: try {
085: ELFormatterVariableResolver vr = new ELFormatterVariableResolver();
086: vr.setLogRecord(logRecord);
087:
088: ret = _expr.evalString(new ConfigELContext(vr));
089: } catch (Exception ex) {
090: throw new RuntimeException(ex);
091: }
092: }
093:
094: return ret;
095: }
096:
097: class ELFormatterVariableResolver extends AbstractVariableResolver {
098: ELFormatterLogRecord _logRecord;
099:
100: public void setLogRecord(LogRecord logRecord) {
101: _logRecord = new ELFormatterLogRecord(logRecord);
102: }
103:
104: @Override
105: public Object getValue(ELContext env, Object base,
106: Object property) throws ELException {
107: if (base != null || !(property instanceof String))
108: return null;
109:
110: if ("log".equals(property)) {
111: env.setPropertyResolved(true);
112:
113: return _logRecord;
114: }
115:
116: return null;
117: }
118: }
119:
120: /**
121: * An api similar to java.util.logging.LogRecord that provides more complete
122: * information for logging purposes.
123: */
124: public class ELFormatterLogRecord {
125: LogRecord _logRecord;
126:
127: ELFormatterLogRecord(LogRecord logRecord) {
128: _logRecord = logRecord;
129: }
130:
131: /**
132: * The "formatted" log message, after localization, substitution of
133: * parameters, and the inclusion of an exception stack trace if applicable.
134: * <p>
135: * During formatting, if the source logger has a localization
136: * ResourceBundle and if that ResourceBundle has an entry for
137: * this message string, then the message string is replaced
138: * with the localized value.
139: * <p>
140: * If the message has parameters, java.text.MessageFormat is used to format
141: * the message with the parameters.
142: * <p>
143: * If the log record has an associated exception, the stack trace is
144: * appended to the log message.
145: *
146: * @see java.text.MessageFormat
147: * @see java.lang.Throwable.printStackTrace()
148: */
149: public String getMessage() {
150: /** use the formatMessage() method of the outer class */
151: return formatMessage(_logRecord);
152: }
153:
154: /**
155: * The source Logger's name.
156: *
157: * @return source logger name, which may be null
158: */
159: public String getName() {
160: return _logRecord.getLoggerName();
161: }
162:
163: /**
164: * The source Logger's name.
165: *
166: * @return source logger name, which may be null
167: */
168: public String getLoggerName() {
169: return _logRecord.getLoggerName();
170: }
171:
172: /**
173: * The last component of the source Logger's name. The last component
174: * is everything that occurs after the last `.' character, usually
175: * it is the class name.
176: *
177: *
178: * @return short version of the source logger name, or null
179: */
180: public String getShortName() {
181: String name = _logRecord.getLoggerName();
182:
183: if (name != null) {
184: int index = name.lastIndexOf('.') + 1;
185: if (index > 0 && index < name.length()) {
186: name = name.substring(index);
187: }
188: }
189:
190: return name;
191: }
192:
193: /**
194: * The logging message level, for example Level.INFO.
195: *
196: * @see java.util.logging.Level
197: */
198: public Level getLevel() {
199: return _logRecord.getLevel();
200: }
201:
202: /**
203: * The time of the logging event, in milliseconds since 1970.
204: */
205: public long getMillis() {
206: return _logRecord.getMillis();
207: }
208:
209: /**
210: * An identifier for the thread where the message originated.
211: */
212: public int getThreadID() {
213: return _logRecord.getThreadID();
214: }
215:
216: /**
217: * The throwable associated with the log record, if one was associated.
218: */
219: public Throwable getThrown() {
220: return _logRecord.getThrown();
221: }
222:
223: /**
224: * The sequence number, normally assigned in the constructor of LogRecord.
225: */
226: public long getSequenceNumber() {
227: return _logRecord.getSequenceNumber();
228: }
229:
230: /**
231: * The name of the class that issued the logging request.
232: * This name may be unavailable, or not actually the name of the class that
233: * issued the logging message.
234: */
235: public String getSourceClassName() {
236: return _logRecord.getSourceClassName();
237: }
238:
239: /**
240: * The last component of the name (everthing after the last `.') of the
241: * class that issued the logging request.
242: * This name may be unavailable, or not actually the name of the class that
243: * issued the logging message.
244: *
245: * @return short version of the sourceClassName
246: */
247: public String getShortSourceClassName() {
248: String name = _logRecord.getSourceClassName();
249:
250: if (name != null) {
251: int index = name.lastIndexOf('.') + 1;
252: if (index > 0 && index < name.length()) {
253: name = name.substring(index);
254: }
255: }
256:
257: return name;
258: }
259:
260: /**
261: * The name of the method that issued the logging request. This name
262: * may be unavailable, or not actually the name of the class that issued
263: * the logging message.
264: */
265: public String getSourceMethodName() {
266: return _logRecord.getSourceMethodName();
267: }
268:
269: /**
270: * The "raw" log message, before localization or substitution
271: * of parameters.
272: * <p>
273: * This returned message will be either the final text, text containing
274: * parameter substitution "format elements" (like `{0}') for use by
275: * java.text.MessageFormat, or a localization key.
276: *
277: * @see java.text.MessageFormat
278: */
279: public String getRawMessage() {
280: return _logRecord.getMessage();
281: }
282:
283: /**
284: * The resource bundle for localization.
285: */
286: public ResourceBundle getResourceBundle() {
287: return _logRecord.getResourceBundle();
288: }
289:
290: /**
291: * The name of resource bundle for localization.
292: */
293: public String getResourceBundleName() {
294: return _logRecord.getResourceBundleName();
295: }
296:
297: public Object[] getParameters() {
298: return _logRecord.getParameters();
299: }
300: }
301: }
|