001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 * 
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 * 
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.log4j.lf5;
018
019import java.io.IOException;
020import java.io.PrintWriter;
021import java.io.StringWriter;
022
023/**
024 * LogRecord.  A LogRecord encapsulates the details of your desired log
025 * request.
026 *
027 * @author Michael J. Sikorsky
028 * @author Robert Shaw
029 */
030
031// Contributed by ThoughtWorks Inc.
032
033public abstract class LogRecord implements java.io.Serializable {
034  //--------------------------------------------------------------------------
035  //   Constants:
036  //--------------------------------------------------------------------------
037
038  //--------------------------------------------------------------------------
039  //   Protected Variables:
040  //--------------------------------------------------------------------------
041  protected static long _seqCount = 0;
042
043  protected LogLevel _level;
044  protected String _message;
045  protected long _sequenceNumber;
046  protected long _millis;
047  protected String _category;
048  protected String _thread;
049  protected String _thrownStackTrace;
050  protected Throwable _thrown;
051  protected String _ndc;
052  protected String _location;
053
054  //--------------------------------------------------------------------------
055  //   Private Variables:
056  //--------------------------------------------------------------------------
057
058  //--------------------------------------------------------------------------
059  //   Constructors:
060  //--------------------------------------------------------------------------
061
062  public LogRecord() {
063    super();
064
065    _millis = System.currentTimeMillis();
066    _category = "Debug";
067    _message = "";
068    _level = LogLevel.INFO;
069    _sequenceNumber = getNextId();
070    _thread = Thread.currentThread().toString();
071    _ndc = "";
072    _location = "";
073  }
074
075  //--------------------------------------------------------------------------
076  //   Public Methods:
077  //--------------------------------------------------------------------------
078
079  /**
080   * Get the level of this LogRecord.
081   *
082   * @return The LogLevel of this record.
083   * @see #setLevel(LogLevel)
084   * @see LogLevel
085   */
086  public LogLevel getLevel() {
087    return (_level);
088  }
089
090  /**
091   * Set the level of this LogRecord.
092   *
093   * @param level The LogLevel for this record.
094   * @see #getLevel()
095   * @see LogLevel
096   */
097  public void setLevel(LogLevel level) {
098    _level = level;
099  }
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