1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.log4j.spi;
19
20 import java.util.ArrayList;
21 import java.util.List;
22 import java.util.StringTokenizer;
23 import java.util.Locale;
24
25
26 /***
27 * A singleton helper utility which accepts a field name
28 * and a LoggingEvent and returns the value of that field.
29 *
30 * This class defines a grammar used in creation of an expression-based Rule.
31 *
32 * The only available method is
33 * Object getField(String fieldName, LoggingEvent event).
34 *
35 * Here is a description of the mapping of field names in the grammar
36 * to fields on the logging event. While the getField method returns an Object,
37 * the individual types returned per field are described here:
38 *
39 * Field Name Field value (String representation Return type
40 * LOGGER category name (logger) String
41 * LEVEL level Level
42 * CLASS locationInformation's class name String
43 * FILE locationInformation's file name String
44 * LINE locationInformation's line number String
45 * METHOD locationInformation's method name String
46 * MSG message Object
47 * NDC NDC String
48 * EXCEPTION throwable string representation ThrowableInformation
49 * TIMESTAMP timestamp Long
50 * THREAD thread String
51 * PROP.keyName entry in the Property hashtable String
52 * mapped to the key [keyName]
53
54 * NOTE: the values for the 'keyName' portion of the MDC and PROP mappings must
55 * be an exact match to the key in the hashTable (case sensitive).
56 *
57 * If the passed-in field is null or doesn't match an entry
58 * in the above-described mapping, an exception is thrown.
59 *
60 * @author Scott Deboy (sdeboy@apache.org)
61 * @author Paul Smith (psmith@apache.org)
62 *
63 */
64 public final class LoggingEventFieldResolver {
65 /***
66 * Keyword list.
67 */
68 public static final List KEYWORD_LIST = new ArrayList();
69 /***
70 * LOGGER string literal.
71 */
72 public static final String LOGGER_FIELD = "LOGGER";
73 /***
74 * LEVEL string literal.
75 */
76 public static final String LEVEL_FIELD = "LEVEL";
77 /***
78 * CLASS string literal.
79 */
80 public static final String CLASS_FIELD = "CLASS";
81 /***
82 * FILE string literal.
83 */
84 public static final String FILE_FIELD = "FILE";
85 /***
86 * LINE string literal.
87 */
88 public static final String LINE_FIELD = "LINE";
89 /***
90 * METHOD string literal.
91 */
92 public static final String METHOD_FIELD = "METHOD";
93 /***
94 * MSG string literal.
95 */
96 public static final String MSG_FIELD = "MSG";
97 /***
98 * NDC string literal.
99 */
100 public static final String NDC_FIELD = "NDC";
101 /***
102 * EXCEPTION string literal.
103 */
104 public static final String EXCEPTION_FIELD = "EXCEPTION";
105 /***
106 * TIMESTAMP string literal.
107 */
108 public static final String TIMESTAMP_FIELD = "TIMESTAMP";
109 /***
110 * THREAD string literal.
111 */
112 public static final String THREAD_FIELD = "THREAD";
113 /***
114 * PROP. string literal.
115 */
116 public static final String PROP_FIELD = "PROP.";
117 /***
118 * empty string literal.
119 */
120 public static final String EMPTY_STRING = "";
121 /***
122 * LOGGER string literal.
123 */
124 private static final LoggingEventFieldResolver RESOLVER =
125 new LoggingEventFieldResolver();
126
127 /***
128 * Create new instance.
129 */
130 private LoggingEventFieldResolver() {
131 super();
132 KEYWORD_LIST.add(LOGGER_FIELD);
133 KEYWORD_LIST.add(LEVEL_FIELD);
134 KEYWORD_LIST.add(CLASS_FIELD);
135 KEYWORD_LIST.add(FILE_FIELD);
136 KEYWORD_LIST.add(LINE_FIELD);
137 KEYWORD_LIST.add(METHOD_FIELD);
138 KEYWORD_LIST.add(MSG_FIELD);
139 KEYWORD_LIST.add(NDC_FIELD);
140 KEYWORD_LIST.add(EXCEPTION_FIELD);
141 KEYWORD_LIST.add(TIMESTAMP_FIELD);
142 KEYWORD_LIST.add(THREAD_FIELD);
143 KEYWORD_LIST.add(PROP_FIELD);
144 }
145
146 /***
147 * Apply fields.
148 * @param replaceText replacement text.
149 * @param event logging event.
150 * @return evaluted expression
151 */
152 public String applyFields(final String replaceText,
153 final LoggingEvent event) {
154 if (replaceText == null) {
155 return null;
156 }
157 StringTokenizer tokenizer = new StringTokenizer(replaceText);
158 StringBuffer result = new StringBuffer();
159 boolean found = false;
160
161 while (tokenizer.hasMoreTokens()) {
162 String token = tokenizer.nextToken();
163 if (isField(token) || token.toUpperCase(Locale.US).startsWith(PROP_FIELD)) {
164 result.append(getValue(token, event).toString());
165 found = true;
166 } else {
167 result.append(token);
168 }
169 }
170 if (found) {
171 return result.toString();
172 }
173 return null;
174 }
175
176 /***
177 * Get singleton instance.
178 * @return singleton instance
179 */
180 public static LoggingEventFieldResolver getInstance() {
181 return RESOLVER;
182 }
183
184 /***
185 * Determines if specified string is a recognized field.
186 * @param fieldName field name
187 * @return true if recognized field.
188 */
189 public boolean isField(final String fieldName) {
190 if (fieldName != null) {
191 return (KEYWORD_LIST.contains(
192 fieldName.toUpperCase(Locale.US))
193 || fieldName.toUpperCase().startsWith(PROP_FIELD));
194 }
195 return false;
196 }
197
198 /***
199 * Get value of field.
200 * @param fieldName field
201 * @param event event
202 * @return value of field
203 */
204 public Object getValue(final String fieldName,
205 final LoggingEvent event) {
206 String upperField = fieldName.toUpperCase(Locale.US);
207 if (LOGGER_FIELD.equals(upperField)) {
208 return event.getLoggerName();
209 } else if (LEVEL_FIELD.equals(upperField)) {
210 return event.getLevel();
211 } else if (MSG_FIELD.equals(upperField)) {
212 return event.getMessage();
213 } else if (NDC_FIELD.equals(upperField)) {
214 String ndcValue = event.getNDC();
215 return ((ndcValue == null) ? EMPTY_STRING : ndcValue);
216 } else if (EXCEPTION_FIELD.equals(upperField)) {
217 String[] throwableRep = event.getThrowableStrRep();
218 if (throwableRep == null) {
219 return EMPTY_STRING;
220 } else {
221 return getExceptionMessage(throwableRep);
222 }
223 } else if (TIMESTAMP_FIELD.equals(upperField)) {
224 return new Long(event.timeStamp);
225 } else if (THREAD_FIELD.equals(upperField)) {
226 return event.getThreadName();
227 } else if (upperField.startsWith(PROP_FIELD)) {
228
229 Object propValue = event.getMDC(fieldName.substring(5));
230 return ((propValue == null) ? EMPTY_STRING : propValue.toString());
231 } else {
232 LocationInfo info = event.getLocationInformation();
233 if (CLASS_FIELD.equals(upperField)) {
234 return ((info == null) ? EMPTY_STRING : info.getClassName());
235 } else if (FILE_FIELD.equals(upperField)) {
236 return ((info == null) ? EMPTY_STRING : info.getFileName());
237 } else if (LINE_FIELD.equals(upperField)) {
238 return ((info == null) ? EMPTY_STRING : info.getLineNumber());
239 } else if (METHOD_FIELD.equals(upperField)) {
240 return ((info == null) ? EMPTY_STRING : info.getMethodName());
241 }
242 }
243
244
245 throw new IllegalArgumentException("Unsupported field name: " + fieldName);
246 }
247
248 /***
249 * Get message from throwable representation.
250 * @param exception exception
251 * @return message
252 */
253 private static String getExceptionMessage(final String[] exception) {
254 StringBuffer buff = new StringBuffer();
255 for (int i = 0; i < exception.length; i++) {
256 buff.append(exception[i]);
257 }
258 return buff.toString();
259 }
260 }