PageRenderTime 26ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 0ms

/contrib/initial/nof/retired/dotnet/trunk/lib/src/log4j/org/apache/log4j/spi/LoggingEvent.java

#
Java | 442 lines | 173 code | 60 blank | 209 comment | 32 complexity | 61433ff9c1ca67da88f919229ee5ea9a MD5 | raw file
Possible License(s): CC-BY-SA-3.0, MPL-2.0-no-copyleft-exception, LGPL-3.0, LGPL-2.1, BSD-3-Clause, Apache-2.0, GPL-2.0
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. /*
  20. * Copyright (C) The Apache Software Foundation. All rights reserved.
  21. *
  22. * This software is published under the terms of the Apache Software
  23. * License version 1.1, a copy of which has been included with this
  24. * distribution in the LICENSE.txt file. */
  25. package org.apache.log4j.spi;
  26. import org.apache.log4j.*;
  27. import org.apache.log4j.helpers.LogLog;
  28. import org.apache.log4j.helpers.Loader;
  29. import java.lang.reflect.Method;
  30. import java.io.ObjectOutputStream;
  31. import java.io.ObjectInputStream;
  32. import java.util.Hashtable;
  33. // Contributors: Nelson Minar <nelson@monkey.org>
  34. // Wolf Siberski
  35. // Anders Kristensen <akristensen@dynamicsoft.com>
  36. /**
  37. The internal representation of logging events. When an affirmative
  38. decision is made to log then a <code>LoggingEvent</code> instance
  39. is created. This instance is passed around to the different log4j
  40. components.
  41. <p>This class is of concern to those wishing to extend log4j.
  42. @author Ceki G&uuml;lc&uuml;
  43. @author James P. Cakalic
  44. @since 0.8.2 */
  45. public class LoggingEvent implements java.io.Serializable {
  46. private static long startTime = System.currentTimeMillis();
  47. /** Fully qualified name of the calling category class. */
  48. transient public final String fqnOfCategoryClass;
  49. /**
  50. * The category of the logging event. This field is not serialized
  51. * for performance reasons.
  52. *
  53. * <p>It is set by the LoggingEvent constructor or set by a remote
  54. * entity after deserialization.
  55. *
  56. * @deprecated This field will be marked as private or be completely
  57. * removed in future releases. Please do not use it.
  58. * */
  59. transient private Category logger;
  60. /**
  61. * <p>The category (logger) name.
  62. *
  63. * @deprecated This field will be marked as private in future
  64. * releases. Please do not access it directly. Use the {@link
  65. * #getLoggerName} method instead.
  66. * */
  67. final public String categoryName;
  68. /**
  69. * Level of logging event. Level cannot be serializable because it
  70. * is a flyweight. Due to its special seralization it cannot be
  71. * declared final either.
  72. *
  73. * <p> This field should not be accessed directly. You shoud use the
  74. * {@link #getLevel} method instead.
  75. *
  76. * @deprecated This field will be marked as private in future
  77. * releases. Please do not access it directly. Use the {@link
  78. * #getLevel} method instead.
  79. * */
  80. transient public Priority level;
  81. /** The nested diagnostic context (NDC) of logging event. */
  82. private String ndc;
  83. /** The mapped diagnostic context (MDC) of logging event. */
  84. private Hashtable mdcCopy;
  85. /** Have we tried to do an NDC lookup? If we did, there is no need
  86. * to do it again. Note that its value is always false when
  87. * serialized. Thus, a receiving SocketNode will never use it's own
  88. * (incorrect) NDC. See also writeObject method. */
  89. private boolean ndcLookupRequired = true;
  90. /** Have we tried to do an MDC lookup? If we did, there is no need
  91. * to do it again. Note that its value is always false when
  92. * serialized. See also the getMDC and getMDCCopy methods. */
  93. private boolean mdcCopyLookupRequired = true;
  94. /** The application supplied message of logging event. */
  95. transient private Object message;
  96. /** The application supplied message rendered through the log4j
  97. objet rendering mechanism.*/
  98. private String renderedMessage;
  99. /** The name of thread in which this logging event was generated. */
  100. private String threadName;
  101. /** This
  102. variable contains information about this event's throwable
  103. */
  104. private ThrowableInformation throwableInfo;
  105. /** The number of milliseconds elapsed from 1/1/1970 until logging event
  106. was created. */
  107. public final long timeStamp;
  108. /** Location information for the caller. */
  109. private LocationInfo locationInfo;
  110. // Serialization
  111. static final long serialVersionUID = -868428216207166145L;
  112. static final Integer[] PARAM_ARRAY = new Integer[1];
  113. static final String TO_LEVEL = "toLevel";
  114. static final Class[] TO_LEVEL_PARAMS = new Class[] {int.class};
  115. static final Hashtable methodCache = new Hashtable(3); // use a tiny table
  116. /**
  117. Instantiate a LoggingEvent from the supplied parameters.
  118. <p>Except {@link #timeStamp} all the other fields of
  119. <code>LoggingEvent</code> are filled when actually needed.
  120. <p>
  121. @param category The category of this event.
  122. @param level The level of this event.
  123. @param message The message of this event.
  124. @param throwable The throwable of this event. */
  125. public LoggingEvent(String fqnOfCategoryClass, Category logger,
  126. Priority priority, Object message, Throwable throwable) {
  127. this.fqnOfCategoryClass = fqnOfCategoryClass;
  128. this.logger = logger;
  129. this.categoryName = logger.getName();
  130. this.level = priority;
  131. this.message = message;
  132. if(throwable != null) {
  133. this.throwableInfo = new ThrowableInformation(throwable);
  134. }
  135. timeStamp = System.currentTimeMillis();
  136. }
  137. /**
  138. Instantiate a LoggingEvent from the supplied parameters.
  139. <p>Except {@link #timeStamp} all the other fields of
  140. <code>LoggingEvent</code> are filled when actually needed.
  141. <p>
  142. @param category The category of this event.
  143. @param timeStamp the timestamp of this logging event
  144. @param level The level of this event.
  145. @param message The message of this event.
  146. @param throwable The throwable of this event. */
  147. public LoggingEvent(String fqnOfCategoryClass, Category logger,
  148. long timeStamp, Priority priority, Object message,
  149. Throwable throwable) {
  150. this.fqnOfCategoryClass = fqnOfCategoryClass;
  151. this.logger = logger;
  152. this.categoryName = logger.getName();
  153. this.level = priority;
  154. this.message = message;
  155. if(throwable != null) {
  156. this.throwableInfo = new ThrowableInformation(throwable);
  157. }
  158. this.timeStamp = timeStamp;
  159. }
  160. /**
  161. Set the location information for this logging event. The collected
  162. information is cached for future use.
  163. */
  164. public LocationInfo getLocationInformation() {
  165. if(locationInfo == null) {
  166. locationInfo = new LocationInfo(new Throwable(), fqnOfCategoryClass);
  167. }
  168. return locationInfo;
  169. }
  170. /**
  171. * Return the level of this event. Use this form instead of directly
  172. * accessing the <code>level</code> field. */
  173. public Level getLevel() {
  174. return (Level) level;
  175. }
  176. /**
  177. * Return the name of the logger. Use this form instead of directly
  178. * accessing the <code>categoryName</code> field.
  179. */
  180. public String getLoggerName() {
  181. return categoryName;
  182. }
  183. /**
  184. Return the message for this logging event.
  185. <p>Before serialization, the returned object is the message
  186. passed by the user to generate the logging event. After
  187. serialization, the returned value equals the String form of the
  188. message possibly after object rendering.
  189. @since 1.1 */
  190. public
  191. Object getMessage() {
  192. if(message != null) {
  193. return message;
  194. } else {
  195. return getRenderedMessage();
  196. }
  197. }
  198. /**
  199. * This method returns the NDC for this event. It will return the
  200. * correct content even if the event was generated in a different
  201. * thread or even on a different machine. The {@link NDC#get} method
  202. * should <em>never</em> be called directly. */
  203. public
  204. String getNDC() {
  205. if(ndcLookupRequired) {
  206. ndcLookupRequired = false;
  207. ndc = NDC.get();
  208. }
  209. return ndc;
  210. }
  211. // .NET port
  212. // /**
  213. // Returns the the context corresponding to the <code>key</code>
  214. // parameter. If there is a local MDC copy, possibly because we are
  215. // in a logging server or running inside AsyncAppender, then we
  216. // search for the key in MDC copy, if a value is found it is
  217. // returned. Otherwise, if the search in MDC copy returns a null
  218. // result, then the current thread's <code>MDC</code> is used.
  219. //
  220. // <p>Note that <em>both</em> the local MDC copy and the current
  221. // thread's MDC are searched.
  222. //
  223. // */
  224. // public
  225. // Object getMDC(String key) {
  226. // Object r;
  227. // // Note the mdcCopy is used if it exists. Otherwise we use the MDC
  228. // // that is associated with the thread.
  229. // if(mdcCopy != null) {
  230. // r = mdcCopy.get(key);
  231. // if(r != null) {
  232. // return r;
  233. // }
  234. // }
  235. // return MDC.get(key);
  236. // }
  237. /**
  238. Obtain a copy of this thread's MDC prior to serialization or
  239. asynchronous logging.
  240. */
  241. public
  242. void getMDCCopy() {
  243. // .NET port
  244. // if(mdcCopyLookupRequired) {
  245. // mdcCopyLookupRequired = false;
  246. // // the clone call is required for asynchronous logging.
  247. // // See also bug #5932.
  248. // Hashtable t = (Hashtable) MDC.getContext();
  249. // if(t != null) {
  250. // mdcCopy = (Hashtable) t.clone();
  251. // }
  252. // }
  253. }
  254. public
  255. String getRenderedMessage() {
  256. if(renderedMessage == null && message != null) {
  257. if(message instanceof String)
  258. renderedMessage = (String) message;
  259. else {
  260. LoggerRepository repository = logger.getHierarchy();
  261. if(repository instanceof RendererSupport) {
  262. RendererSupport rs = (RendererSupport) repository;
  263. renderedMessage= rs.getRendererMap().findAndRender(message);
  264. } else {
  265. renderedMessage = message.toString();
  266. }
  267. }
  268. }
  269. return renderedMessage;
  270. }
  271. /**
  272. Returns the time when the application started, in milliseconds
  273. elapsed since 01.01.1970. */
  274. public static long getStartTime() {
  275. return startTime;
  276. }
  277. public
  278. String getThreadName() {
  279. if(threadName == null)
  280. threadName = (Thread.currentThread()).getName();
  281. return threadName;
  282. }
  283. /**
  284. Returns the throwable information contained within this
  285. event. May be <code>null</code> if there is no such information.
  286. <p>Note that the {@link Throwable} object contained within a
  287. {@link ThrowableInformation} does not survive serialization.
  288. @since 1.1 */
  289. public
  290. ThrowableInformation getThrowableInformation() {
  291. return throwableInfo;
  292. }
  293. /**
  294. Return this event's throwable's string[] representaion.
  295. */
  296. public
  297. String[] getThrowableStrRep() {
  298. if(throwableInfo == null)
  299. return null;
  300. else
  301. return throwableInfo.getThrowableStrRep();
  302. }
  303. private
  304. void readLevel(ObjectInputStream ois)
  305. throws java.io.IOException, ClassNotFoundException {
  306. int p = ois.readInt();
  307. try {
  308. String className = (String) ois.readObject();
  309. if(className == null) {
  310. level = Level.toLevel(p);
  311. } else {
  312. Method m = (Method) methodCache.get(className);
  313. if(m == null) {
  314. Class clazz = Loader.loadClass(className);
  315. // Note that we use Class.getDeclaredMethod instead of
  316. // Class.getMethod. This assumes that the Level subclass
  317. // implements the toLevel(int) method which is a
  318. // requirement. Actually, it does not make sense for Level
  319. // subclasses NOT to implement this method. Also note that
  320. // only Level can be subclassed and not Priority.
  321. m = clazz.getDeclaredMethod(TO_LEVEL, TO_LEVEL_PARAMS);
  322. methodCache.put(className, m);
  323. }
  324. PARAM_ARRAY[0] = new Integer(p);
  325. level = (Level) m.invoke(null, PARAM_ARRAY);
  326. }
  327. } catch(Exception e) {
  328. LogLog.warn("Level deserialization failed, reverting to default.", e);
  329. level = Level.toLevel(p);
  330. }
  331. }
  332. private void readObject(ObjectInputStream ois)
  333. throws java.io.IOException, ClassNotFoundException {
  334. ois.defaultReadObject();
  335. readLevel(ois);
  336. // Make sure that no location info is available to Layouts
  337. if(locationInfo == null)
  338. locationInfo = new LocationInfo(null, null);
  339. }
  340. private
  341. void writeObject(ObjectOutputStream oos) throws java.io.IOException {
  342. // Aside from returning the current thread name the wgetThreadName
  343. // method sets the threadName variable.
  344. this.getThreadName();
  345. // This sets the renders the message in case it wasn't up to now.
  346. this.getRenderedMessage();
  347. // This call has a side effect of setting this.ndc and
  348. // setting ndcLookupRequired to false if not already false.
  349. this.getNDC();
  350. // This call has a side effect of setting this.mdcCopy and
  351. // setting mdcLookupRequired to false if not already false.
  352. this.getMDCCopy();
  353. // This sets the throwable sting representation of the event throwable.
  354. this.getThrowableStrRep();
  355. oos.defaultWriteObject();
  356. // serialize this event's level
  357. writeLevel(oos);
  358. }
  359. private
  360. void writeLevel(ObjectOutputStream oos) throws java.io.IOException {
  361. oos.writeInt(level.toInt());
  362. Class clazz = level.getClass();
  363. if(clazz == Level.class) {
  364. oos.writeObject(null);
  365. } else {
  366. // writing directly the Class object would be nicer, except that
  367. // serialized a Class object can not be read back by JDK
  368. // 1.1.x. We have to resort to this hack instead.
  369. oos.writeObject(clazz.getName());
  370. }
  371. }
  372. }