1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.log4j.lf5;
18
19 import java.io.IOException;
20 import java.io.PrintWriter;
21 import java.io.StringWriter;
22
23 /**
24 * LogRecord. A LogRecord encapsulates the details of your desired log
25 * request.
26 *
27 * @author Michael J. Sikorsky
28 * @author Robert Shaw
29 */
30
31 // Contributed by ThoughtWorks Inc.
32
33 public abstract class LogRecord implements java.io.Serializable {
34 //--------------------------------------------------------------------------
35 // Constants:
36 //--------------------------------------------------------------------------
37
38 //--------------------------------------------------------------------------
39 // Protected Variables:
40 //--------------------------------------------------------------------------
41 protected static long _seqCount = 0;
42
43 protected LogLevel _level;
44 protected String _message;
45 protected long _sequenceNumber;
46 protected long _millis;
47 protected String _category;
48 protected String _thread;
49 protected String _thrownStackTrace;
50 protected Throwable _thrown;
51 protected String _ndc;
52 protected String _location;
53
54 //--------------------------------------------------------------------------
55 // Private Variables:
56 //--------------------------------------------------------------------------
57
58 //--------------------------------------------------------------------------
59 // Constructors:
60 //--------------------------------------------------------------------------
61
62 public LogRecord() {
63 super();
64
65 _millis = System.currentTimeMillis();
66 _category = "Debug";
67 _message = "";
68 _level = LogLevel.INFO;
69 _sequenceNumber = getNextId();
70 _thread = Thread.currentThread().toString();
71 _ndc = "";
72 _location = "";
73 }
74
75 //--------------------------------------------------------------------------
76 // Public Methods:
77 //--------------------------------------------------------------------------
78
79 /**
80 * Get the level of this LogRecord.
81 *
82 * @return The LogLevel of this record.
83 * @see #setLevel(LogLevel)
84 * @see LogLevel
85 */
86 public LogLevel getLevel() {
87 return (_level);
88 }
89
90 /**
91 * Set the level of this LogRecord.
92 *
93 * @param level The LogLevel for this record.
94 * @see #getLevel()
95 * @see LogLevel
96 */
97 public void setLevel(LogLevel level) {
98 _level = level;
99 }
100
101 /**
102 * Abstract method. Must be overridden to indicate what log level
103 * to show in red.
104 */
105 public abstract boolean isSevereLevel();
106
107 /**
108 * @return true if getThrown().toString() is a non-empty string.
109 */
110 public boolean hasThrown() {
111 Throwable thrown = getThrown();
112 if (thrown == null) {
113 return false;
114 }
115 String thrownString = thrown.toString();
116 return thrownString != null && thrownString.trim().length() != 0;
117 }
118
119 /**
120 * @return true if isSevereLevel() or hasThrown() returns true.
121 */
122 public boolean isFatal() {
123 return isSevereLevel() || hasThrown();
124 }
125
126 /**
127 * Get the category asscociated with this LogRecord. For a more detailed
128 * description of what a category is see setCategory().
129 *
130 * @return The category of this record.
131 * @see #setCategory(String)
132 */
133 public String getCategory() {
134 return (_category);
135 }
136
137 /**
138 * Set the category associated with this LogRecord. A category represents
139 * a hierarchical dot (".") separated namespace for messages.
140 * The definition of a category is application specific, but a common convention
141 * is as follows:
142 *
143 * <p>
144 * When logging messages
145 * for a particluar class you can use its class name:
146 * com.thoughtworks.framework.servlet.ServletServiceBroker.<br><br>
147 * Futhermore, to log a message for a particular method in a class
148 * add the method name:
149 * com.thoughtworks.framework.servlet.ServletServiceBroker.init().
150 * </p>
151 *
152 * @param category The category for this record.
153 * @see #getCategory()
154 */
155 public void setCategory(String category) {
156 _category = category;
157 }
158
159 /**
160 * Get the message asscociated with this LogRecord.
161 *
162 * @return The message of this record.
163 * @see #setMessage(String)
164 */
165 public String getMessage() {
166 return (_message);
167 }
168
169 /**
170 * Set the message associated with this LogRecord.
171 *
172 * @param message The message for this record.
173 * @see #getMessage()
174 */
175 public void setMessage(String message) {
176 _message = message;
177 }
178
179 /**
180 * Get the sequence number associated with this LogRecord. Sequence numbers
181 * are generally assigned when a LogRecord is constructed. Sequence numbers
182 * start at 0 and increase with each newly constructed LogRocord.
183 *
184 * @return The sequence number of this record.
185 * @see #setSequenceNumber(long)
186 */
187 public long getSequenceNumber() {
188 return (_sequenceNumber);
189 }
190
191 /**
192 * Set the sequence number assocsiated with this LogRecord. A sequence number
193 * will automatically be assigned to evey newly constructed LogRecord, however,
194 * this method can override the value.
195 *
196 * @param number The sequence number.
197 * @see #getSequenceNumber()
198 */
199 public void setSequenceNumber(long number) {
200 _sequenceNumber = number;
201 }
202
203 /**
204 * Get the event time of this record in milliseconds from 1970.
205 * When a LogRecord is constructed the event time is set but may be
206 * overridden by calling setMillis();
207 *
208 * @return The event time of this record in milliseconds from 1970.
209 * @see #setMillis(long)
210 */
211 public long getMillis() {
212 return _millis;
213 }
214
215 /**
216 * Set the event time of this record. When a LogRecord is constructed
217 * the event time is set but may be overridden by calling this method.
218 *
219 * @param millis The time in milliseconds from 1970.
220 * @see #getMillis()
221 */
222 public void setMillis(long millis) {
223 _millis = millis;
224 }
225
226 /**
227 * Get the thread description asscociated with this LogRecord. When a
228 * LogRecord is constructed, the thread description is set by calling:
229 * Thread.currentThread().toString(). You may supply a thread description
230 * of your own by calling the setThreadDescription(String) method.
231 *
232 * @return The thread description of this record.
233 * @see #setThreadDescription(String)
234 */
235 public String getThreadDescription() {
236 return (_thread);
237 }
238
239 /**
240 * Set the thread description associated with this LogRecord. When a
241 * LogRecord is constructed, the thread description is set by calling:
242 * Thread.currentThread().toString(). You may supply a thread description
243 * of your own by calling this method.
244 *
245 * @param threadDescription The description of the thread for this record.
246 * @see #getThreadDescription()
247 */
248 public void setThreadDescription(String threadDescription) {
249 _thread = threadDescription;
250 }
251
252 /**
253 * Get the stack trace in a String-based format for the associated Throwable
254 * of this LogRecord. The stack trace in a String-based format is set
255 * when the setThrown(Throwable) method is called.
256 *
257 * <p>
258 * Why do we need this method considering that we
259 * have the getThrown() and setThrown() methods?
260 * A Throwable object may not be serializable, however, a String representation
261 * of it is. Users of LogRecords should generally call this method over
262 * getThrown() for the reasons of serialization.
263 * </p>
264 *
265 * @return The Stack Trace for the asscoiated Throwable of this LogRecord.
266 * @see #setThrown(Throwable)
267 * @see #getThrown()
268 */
269 public String getThrownStackTrace() {
270 return (_thrownStackTrace);
271 }
272
273 /**
274 * Set the ThrownStackTrace for the log record.
275 *
276 * @param trace A String to associate with this LogRecord
277 * @see #getThrownStackTrace()
278 */
279 public void setThrownStackTrace(String trace) {
280 _thrownStackTrace = trace;
281 }
282
283 /**
284 * Get the Throwable associated with this LogRecord.
285 *
286 * @return The LogLevel of this record.
287 * @see #setThrown(Throwable)
288 * @see #getThrownStackTrace()
289 */
290 public Throwable getThrown() {
291 return (_thrown);
292 }
293
294 /**
295 * Set the Throwable associated with this LogRecord. When this method
296 * is called, the stack trace in a String-based format is made
297 * available via the getThrownStackTrace() method.
298 *
299 * @param thrown A Throwable to associate with this LogRecord.
300 * @see #getThrown()
301 * @see #getThrownStackTrace()
302 */
303 public void setThrown(Throwable thrown) {
304 if (thrown == null) {
305 return;
306 }
307 _thrown = thrown;
308 StringWriter sw = new StringWriter();
309 PrintWriter out = new PrintWriter(sw);
310 thrown.printStackTrace(out);
311 out.flush();
312 _thrownStackTrace = sw.toString();
313 try {
314 out.close();
315 sw.close();
316 } catch (IOException e) {
317 // Do nothing, this should not happen as it is StringWriter.
318 }
319 out = null;
320 sw = null;
321 }
322
323 /**
324 * Return a String representation of this LogRecord.
325 */
326 public String toString() {
327 StringBuffer buf = new StringBuffer();
328 buf.append("LogRecord: [" + _level + ", " + _message + "]");
329 return (buf.toString());
330 }
331
332 /**
333 * Get the NDC (nested diagnostic context) for this record.
334 *
335 * @return The string representing the NDC.
336 */
337 public String getNDC() {
338 return _ndc;
339 }
340
341 /**
342 * Set the NDC (nested diagnostic context) for this record.
343 *
344 * @param ndc A string representing the NDC.
345 */
346 public void setNDC(String ndc) {
347 _ndc = ndc;
348 }
349
350 /**
351 * Get the location in code where this LogRecord originated.
352 *
353 * @return The string containing the location information.
354 */
355 public String getLocation() {
356 return _location;
357 }
358
359 /**
360 * Set the location in code where this LogRecord originated.
361 *
362 * @param location A string containing location information.
363 */
364 public void setLocation(String location) {
365 _location = location;
366 }
367
368 /**
369 * Resets that sequence number to 0.
370 *
371 */
372 public static synchronized void resetSequenceNumber() {
373 _seqCount = 0;
374 }
375
376 //--------------------------------------------------------------------------
377 // Protected Methods:
378 //--------------------------------------------------------------------------
379
380 protected static synchronized long getNextId() {
381 _seqCount++;
382 return _seqCount;
383 }
384 //--------------------------------------------------------------------------
385 // Private Methods:
386 //--------------------------------------------------------------------------
387
388 //--------------------------------------------------------------------------
389 // Nested Top-Level Classes or Interfaces:
390 //--------------------------------------------------------------------------
391
392 }
393
394
395