View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.classic.spi;
15  
16  import java.io.IOException;
17  import java.io.ObjectInputStream;
18  import java.io.ObjectOutputStream;
19  import java.io.Serializable;
20  import java.util.Map;
21  
22  import org.slf4j.Marker;
23  import org.slf4j.helpers.MessageFormatter;
24  
25  import ch.qos.logback.classic.Level;
26  
27  // http://www.riehle.org/computer-science/research/1998/ubilab-tr-1998-10-1.html
28  
29  /**
30   * A read-only and serializable implementation of {@link ILoggingEvent}.
31   * 
32   * @author Ceki Gülcü
33   * @since 0.9.16
34   */
35  public class LoggingEventVO implements ILoggingEvent, Serializable {
36  
37      private static final long serialVersionUID = 6553722650255690312L;
38  
39      private static final int NULL_ARGUMENT_ARRAY = -1;
40      private static final String NULL_ARGUMENT_ARRAY_ELEMENT = "NULL_ARGUMENT_ARRAY_ELEMENT";
41  
42      private String threadName;
43      private String loggerName;
44      private LoggerContextVO loggerContextVO;
45  
46      private transient Level level;
47      private String message;
48  
49      // we gain significant space at serialization time by marking
50      // formattedMessage as transient and constructing it lazily in
51      // getFormattedMessage()
52      private transient String formattedMessage;
53  
54      private transient Object[] argumentArray;
55  
56      private ThrowableProxyVO throwableProxy;
57      private StackTraceElement[] callerDataArray;
58      private Marker marker;
59      private Map<String, String> mdcPropertyMap;
60      private long timeStamp;
61      private long sequenceNumber;
62  
63      public static LoggingEventVO build(ILoggingEvent le) {
64          LoggingEventVO ledo = new LoggingEventVO();
65          ledo.loggerName = le.getLoggerName();
66          ledo.loggerContextVO = le.getLoggerContextVO();
67          ledo.threadName = le.getThreadName();
68          ledo.level = (le.getLevel());
69          ledo.message = (le.getMessage());
70          ledo.argumentArray = (le.getArgumentArray());
71          ledo.marker = le.getMarker();
72          ledo.mdcPropertyMap = le.getMDCPropertyMap();
73          ledo.timeStamp = le.getTimeStamp();
74          ledo.timeStamp = le.getSequenceNumber();
75          ledo.throwableProxy = ThrowableProxyVO.build(le.getThrowableProxy());
76          // add caller data only if it is there already
77          // fixes http://jira.qos.ch/browse/LBCLASSIC-145
78          if (le.hasCallerData()) {
79              ledo.callerDataArray = le.getCallerData();
80          }
81          return ledo;
82      }
83  
84      public String getThreadName() {
85          return threadName;
86      }
87  
88      public LoggerContextVO getLoggerContextVO() {
89          return loggerContextVO;
90      }
91  
92      public String getLoggerName() {
93          return loggerName;
94      }
95  
96      public Level getLevel() {
97          return level;
98      }
99  
100     public String getMessage() {
101         return message;
102     }
103 
104     public String getFormattedMessage() {
105         if (formattedMessage != null) {
106             return formattedMessage;
107         }
108 
109         if (argumentArray != null) {
110             formattedMessage = MessageFormatter.arrayFormat(message, argumentArray).getMessage();
111         } else {
112             formattedMessage = message;
113         }
114 
115         return formattedMessage;
116     }
117 
118     public Object[] getArgumentArray() {
119         return argumentArray;
120     }
121 
122     public IThrowableProxy getThrowableProxy() {
123         return throwableProxy;
124     }
125 
126     public StackTraceElement[] getCallerData() {
127         return callerDataArray;
128     }
129 
130     public boolean hasCallerData() {
131         return callerDataArray != null;
132     }
133 
134     public Marker getMarker() {
135         return marker;
136     }
137 
138     public long getTimeStamp() {
139         return timeStamp;
140     }
141 
142     public long getSequenceNumber() {
143         return sequenceNumber;
144     }
145     
146     public long getContextBirthTime() {
147         return loggerContextVO.getBirthTime();
148     }
149 
150     public LoggerContextVO getContextLoggerRemoteView() {
151         return loggerContextVO;
152     }
153 
154     public Map<String, String> getMDCPropertyMap() {
155         return mdcPropertyMap;
156     }
157 
158     public Map<String, String> getMdc() {
159         return mdcPropertyMap;
160     }
161 
162     public void prepareForDeferredProcessing() {
163     }
164 
165     private void writeObject(ObjectOutputStream out) throws IOException {
166         out.defaultWriteObject();
167         out.writeInt(level.levelInt);
168         if (argumentArray != null) {
169             int len = argumentArray.length;
170             out.writeInt(len);
171             for (int i = 0; i < argumentArray.length; i++) {
172                 if (argumentArray[i] != null) {
173                     out.writeObject(argumentArray[i].toString());
174                 } else {
175                     out.writeObject(NULL_ARGUMENT_ARRAY_ELEMENT);
176                 }
177             }
178         } else {
179             out.writeInt(NULL_ARGUMENT_ARRAY);
180         }
181 
182     }
183 
184     private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
185         in.defaultReadObject();
186         int levelInt = in.readInt();
187         level = Level.toLevel(levelInt);
188 
189         int argArrayLen = in.readInt();
190         if (argArrayLen != NULL_ARGUMENT_ARRAY) {
191             argumentArray = new String[argArrayLen];
192             for (int i = 0; i < argArrayLen; i++) {
193                 Object val = in.readObject();
194                 if (!NULL_ARGUMENT_ARRAY_ELEMENT.equals(val)) {
195                     argumentArray[i] = val;
196                 }
197             }
198         }
199     }
200 
201     @Override
202     public int hashCode() {
203         final int prime = 31;
204         int result = 1;
205         result = prime * result + ((message == null) ? 0 : message.hashCode());
206         result = prime * result + ((threadName == null) ? 0 : threadName.hashCode());
207         result = prime * result + (int) (timeStamp ^ (timeStamp >>> 32));
208         return result;
209     }
210 
211     @Override
212     public boolean equals(Object obj) {
213         if (this == obj)
214             return true;
215         if (obj == null)
216             return false;
217         if (getClass() != obj.getClass())
218             return false;
219         final LoggingEventVO other = (LoggingEventVO) obj;
220         if (message == null) {
221             if (other.message != null)
222                 return false;
223         } else if (!message.equals(other.message))
224             return false;
225 
226         if (loggerName == null) {
227             if (other.loggerName != null)
228                 return false;
229         } else if (!loggerName.equals(other.loggerName))
230             return false;
231 
232         if (threadName == null) {
233             if (other.threadName != null)
234                 return false;
235         } else if (!threadName.equals(other.threadName))
236             return false;
237         if (timeStamp != other.timeStamp)
238             return false;
239 
240         if (marker == null) {
241             if (other.marker != null)
242                 return false;
243         } else if (!marker.equals(other.marker))
244             return false;
245 
246         if (mdcPropertyMap == null) {
247             if (other.mdcPropertyMap != null)
248                 return false;
249         } else if (!mdcPropertyMap.equals(other.mdcPropertyMap))
250             return false;
251         return true;
252     }
253 }