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