001/**
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
004 *
005 * This program and the accompanying materials are dual-licensed under
006 * either the terms of the Eclipse Public License v1.0 as published by
007 * the Eclipse Foundation
008 *
009 *   or (per the licensee's choosing)
010 *
011 * under the terms of the GNU Lesser General Public License version 2.1
012 * as published by the Free Software Foundation.
013 */
014package ch.qos.logback.classic.spi;
015
016import java.io.IOException;
017import java.io.ObjectInputStream;
018import java.io.ObjectOutputStream;
019import java.io.Serializable;
020import java.util.Map;
021
022import org.slf4j.Marker;
023import org.slf4j.helpers.MessageFormatter;
024
025import ch.qos.logback.classic.Level;
026
027/**
028 * A read/write and serializable implementation of {@link ILoggingEvent}.
029 * 
030 * @author Ceki Gülcü
031 */
032public class PubLoggingEventVO implements ILoggingEvent, Serializable {
033
034    private static final long serialVersionUID = -3385765861078946218L;
035
036    private static final int NULL_ARGUMENT_ARRAY = -1;
037    private static final String NULL_ARGUMENT_ARRAY_ELEMENT = "NULL_ARGUMENT_ARRAY_ELEMENT";
038
039    public String threadName;
040    public String loggerName;
041    public LoggerContextVO loggerContextVO;
042
043    public transient Level level;
044    public String message;
045
046    private transient String formattedMessage;
047
048    public Object[] argumentArray;
049
050    public IThrowableProxy throwableProxy;
051    public StackTraceElement[] callerDataArray;
052    public Marker marker;
053    public Map<String, String> mdcPropertyMap;
054    public long timeStamp;
055    public long sequenceNumber;
056
057    public String getThreadName() {
058        return threadName;
059    }
060
061    public LoggerContextVO getLoggerContextVO() {
062        return loggerContextVO;
063    }
064
065    public String getLoggerName() {
066        return loggerName;
067    }
068
069    public Level getLevel() {
070        return level;
071    }
072
073    public String getMessage() {
074        return message;
075    }
076
077    public String getFormattedMessage() {
078        if (formattedMessage != null) {
079            return formattedMessage;
080        }
081
082        if (argumentArray != null) {
083            formattedMessage = MessageFormatter.arrayFormat(message, argumentArray).getMessage();
084        } else {
085            formattedMessage = message;
086        }
087
088        return formattedMessage;
089    }
090
091    public Object[] getArgumentArray() {
092        return argumentArray;
093    }
094
095    public IThrowableProxy getThrowableProxy() {
096        return throwableProxy;
097    }
098
099    public StackTraceElement[] getCallerData() {
100        return callerDataArray;
101    }
102
103    public boolean hasCallerData() {
104        return callerDataArray != null;
105    }
106
107    public Marker getMarker() {
108        return marker;
109    }
110
111    public long getTimeStamp() {
112        return timeStamp;
113    }
114
115    public long getSequenceNumber() {
116        return sequenceNumber;
117    }
118
119    public void setSequenceNumber(long sequenceNumber) {
120        this.sequenceNumber = sequenceNumber;
121    }
122    
123    public long getContextBirthTime() {
124        return loggerContextVO.getBirthTime();
125    }
126
127    public LoggerContextVO getContextLoggerRemoteView() {
128        return loggerContextVO;
129    }
130
131    public Map<String, String> getMDCPropertyMap() {
132        return mdcPropertyMap;
133    }
134
135    public Map<String, String> getMdc() {
136        return mdcPropertyMap;
137    }
138
139    public void prepareForDeferredProcessing() {
140    }
141
142    private void writeObject(ObjectOutputStream out) throws IOException {
143        out.defaultWriteObject();
144        out.writeInt(level.levelInt);
145        if (argumentArray != null) {
146            int len = argumentArray.length;
147            out.writeInt(len);
148            for (int i = 0; i < argumentArray.length; i++) {
149                if (argumentArray[i] != null) {
150                    out.writeObject(argumentArray[i].toString());
151                } else {
152                    out.writeObject(NULL_ARGUMENT_ARRAY_ELEMENT);
153                }
154            }
155        } else {
156            out.writeInt(NULL_ARGUMENT_ARRAY);
157        }
158
159    }
160
161    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
162        in.defaultReadObject();
163        int levelInt = in.readInt();
164        level = Level.toLevel(levelInt);
165
166        int argArrayLen = in.readInt();
167        if (argArrayLen != NULL_ARGUMENT_ARRAY) {
168            argumentArray = new String[argArrayLen];
169            for (int i = 0; i < argArrayLen; i++) {
170                Object val = in.readObject();
171                if (!NULL_ARGUMENT_ARRAY_ELEMENT.equals(val)) {
172                    argumentArray[i] = val;
173                }
174            }
175        }
176    }
177
178    @Override
179    public int hashCode() {
180        final int prime = 31;
181        int result = 1;
182        result = prime * result + ((message == null) ? 0 : message.hashCode());
183        result = prime * result + ((threadName == null) ? 0 : threadName.hashCode());
184        result = prime * result + (int) (timeStamp ^ (timeStamp >>> 32));
185        return result;
186    }
187
188    @Override
189    public boolean equals(Object obj) {
190        if (this == obj)
191            return true;
192        if (obj == null)
193            return false;
194        if (getClass() != obj.getClass())
195            return false;
196        final PubLoggingEventVO other = (PubLoggingEventVO) obj;
197        if (message == null) {
198            if (other.message != null)
199                return false;
200        } else if (!message.equals(other.message))
201            return false;
202
203        if (loggerName == null) {
204            if (other.loggerName != null)
205                return false;
206        } else if (!loggerName.equals(other.loggerName))
207            return false;
208
209        if (threadName == null) {
210            if (other.threadName != null)
211                return false;
212        } else if (!threadName.equals(other.threadName))
213            return false;
214        if (timeStamp != other.timeStamp)
215            return false;
216
217        if (marker == null) {
218            if (other.marker != null)
219                return false;
220        } else if (!marker.equals(other.marker))
221            return false;
222
223        if (mdcPropertyMap == null) {
224            if (other.mdcPropertyMap != null)
225                return false;
226        } else if (!mdcPropertyMap.equals(other.mdcPropertyMap))
227            return false;
228        return true;
229    }
230
231    public String toString() {
232        StringBuilder sb = new StringBuilder();
233        sb.append(timeStamp);
234        sb.append(" ");
235        sb.append(level);
236        sb.append(" [");
237        sb.append(threadName);
238        sb.append("] ");
239        sb.append(loggerName);
240        sb.append(" - ");
241        sb.append(getFormattedMessage());
242        return sb.toString();
243    }
244
245}