1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.impl;
18
19 import java.io.IOException;
20 import java.io.InvalidObjectException;
21 import java.io.ObjectInputStream;
22 import java.io.Serializable;
23 import java.rmi.MarshalledObject;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Objects;
27
28 import org.apache.logging.log4j.Level;
29 import org.apache.logging.log4j.Marker;
30 import org.apache.logging.log4j.ThreadContext;
31 import org.apache.logging.log4j.core.ContextDataInjector;
32 import org.apache.logging.log4j.util.ReadOnlyStringMap;
33 import org.apache.logging.log4j.core.LogEvent;
34 import org.apache.logging.log4j.core.async.RingBufferLogEvent;
35 import org.apache.logging.log4j.core.config.LoggerConfig;
36 import org.apache.logging.log4j.core.config.Property;
37 import org.apache.logging.log4j.core.util.Clock;
38 import org.apache.logging.log4j.core.util.ClockFactory;
39 import org.apache.logging.log4j.core.util.DummyNanoClock;
40 import org.apache.logging.log4j.core.util.NanoClock;
41 import org.apache.logging.log4j.message.LoggerNameAwareMessage;
42 import org.apache.logging.log4j.message.Message;
43 import org.apache.logging.log4j.message.ReusableMessage;
44 import org.apache.logging.log4j.message.SimpleMessage;
45 import org.apache.logging.log4j.message.TimestampMessage;
46 import org.apache.logging.log4j.util.StringMap;
47 import org.apache.logging.log4j.status.StatusLogger;
48 import org.apache.logging.log4j.util.Strings;
49
50
51
52
53 public class Log4jLogEvent implements LogEvent {
54
55 private static final long serialVersionUID = -8393305700508709443L;
56 private static final Clock CLOCK = ClockFactory.getClock();
57 private static volatile NanoClock nanoClock = new DummyNanoClock();
58 private static final ContextDataInjector CONTEXT_DATA_INJECTOR = ContextDataInjectorFactory.createInjector();
59
60 private final String loggerFqcn;
61 private final Marker marker;
62 private final Level level;
63 private final String loggerName;
64 private Message message;
65 private final long timeMillis;
66 private final transient Throwable thrown;
67 private ThrowableProxy thrownProxy;
68 private final StringMap contextData;
69 private final ThreadContext.ContextStack contextStack;
70 private long threadId;
71 private String threadName;
72 private int threadPriority;
73 private StackTraceElement source;
74 private boolean includeLocation;
75 private boolean endOfBatch = false;
76
77 private final transient long nanoTime;
78
79
80 public static class Builder implements org.apache.logging.log4j.core.util.Builder<LogEvent> {
81
82 private String loggerFqcn;
83 private Marker marker;
84 private Level level;
85 private String loggerName;
86 private Message message;
87 private Throwable thrown;
88 private long timeMillis = CLOCK.currentTimeMillis();
89 private ThrowableProxy thrownProxy;
90 private StringMap contextData = createContextData((List<Property>) null);
91 private ThreadContext.ContextStack contextStack = ThreadContext.getImmutableStack();
92 private long threadId;
93 private String threadName;
94 private int threadPriority;
95 private StackTraceElement source;
96 private boolean includeLocation;
97 private boolean endOfBatch = false;
98 private long nanoTime;
99
100 public Builder() {
101 }
102
103 public Builder(final LogEvent other) {
104 Objects.requireNonNull(other);
105 if (other instanceof RingBufferLogEvent) {
106 ((RingBufferLogEvent) other).initializeBuilder(this);
107 return;
108 }
109 if (other instanceof MutableLogEvent) {
110 ((MutableLogEvent) other).initializeBuilder(this);
111 return;
112 }
113 this.loggerFqcn = other.getLoggerFqcn();
114 this.marker = other.getMarker();
115 this.level = other.getLevel();
116 this.loggerName = other.getLoggerName();
117 this.message = other.getMessage();
118 this.timeMillis = other.getTimeMillis();
119 this.thrown = other.getThrown();
120 this.contextStack = other.getContextStack();
121 this.includeLocation = other.isIncludeLocation();
122 this.endOfBatch = other.isEndOfBatch();
123 this.nanoTime = other.getNanoTime();
124
125
126 if (other instanceof Log4jLogEvent) {
127 final Log4jLogEvent evt = (Log4jLogEvent) other;
128 this.contextData = evt.contextData;
129 this.thrownProxy = evt.thrownProxy;
130 this.source = evt.source;
131 this.threadId = evt.threadId;
132 this.threadName = evt.threadName;
133 this.threadPriority = evt.threadPriority;
134 } else {
135 if (other.getContextData() instanceof StringMap) {
136 this.contextData = (StringMap) other.getContextData();
137 } else {
138 if (this.contextData.isFrozen()) {
139 this.contextData = ContextDataFactory.createContextData();
140 } else {
141 this.contextData.clear();
142 }
143 this.contextData.putAll(other.getContextData());
144
145 }
146 this.thrownProxy = other.getThrownProxy();
147 this.source = other.getSource();
148 this.threadId = other.getThreadId();
149 this.threadName = other.getThreadName();
150 this.threadPriority = other.getThreadPriority();
151 }
152 }
153
154 public Builder setLevel(final Level level) {
155 this.level = level;
156 return this;
157 }
158
159 public Builder setLoggerFqcn(final String loggerFqcn) {
160 this.loggerFqcn = loggerFqcn;
161 return this;
162 }
163
164 public Builder setLoggerName(final String loggerName) {
165 this.loggerName = loggerName;
166 return this;
167 }
168
169 public Builder setMarker(final Marker marker) {
170 this.marker = marker;
171 return this;
172 }
173
174 public Builder setMessage(final Message message) {
175 this.message = message;
176 return this;
177 }
178
179 public Builder setThrown(final Throwable thrown) {
180 this.thrown = thrown;
181 return this;
182 }
183
184 public Builder setTimeMillis(final long timeMillis) {
185 this.timeMillis = timeMillis;
186 return this;
187 }
188
189 public Builder setThrownProxy(final ThrowableProxy thrownProxy) {
190 this.thrownProxy = thrownProxy;
191 return this;
192 }
193
194 @Deprecated
195 public Builder setContextMap(final Map<String, String> contextMap) {
196 contextData = ContextDataFactory.createContextData();
197 if (contextMap != null) {
198 for (final Map.Entry<String, String> entry : contextMap.entrySet()) {
199 contextData.putValue(entry.getKey(), entry.getValue());
200 }
201 }
202 return this;
203 }
204
205 public Builder setContextData(final StringMap contextData) {
206 this.contextData = contextData;
207 return this;
208 }
209
210 public Builder setContextStack(final ThreadContext.ContextStack contextStack) {
211 this.contextStack = contextStack;
212 return this;
213 }
214
215 public Builder setThreadId(final long threadId) {
216 this.threadId = threadId;
217 return this;
218 }
219
220 public Builder setThreadName(final String threadName) {
221 this.threadName = threadName;
222 return this;
223 }
224
225 public Builder setThreadPriority(final int threadPriority) {
226 this.threadPriority = threadPriority;
227 return this;
228 }
229
230 public Builder setSource(final StackTraceElement source) {
231 this.source = source;
232 return this;
233 }
234
235 public Builder setIncludeLocation(final boolean includeLocation) {
236 this.includeLocation = includeLocation;
237 return this;
238 }
239
240 public Builder setEndOfBatch(final boolean endOfBatch) {
241 this.endOfBatch = endOfBatch;
242 return this;
243 }
244
245
246
247
248
249
250
251 public Builder setNanoTime(final long nanoTime) {
252 this.nanoTime = nanoTime;
253 return this;
254 }
255
256 @Override
257 public Log4jLogEvent build() {
258 final Log4jLogEvent result = new Log4jLogEvent(loggerName, marker, loggerFqcn, level, message, thrown,
259 thrownProxy, contextData, contextStack, threadId, threadName, threadPriority, source, timeMillis,
260 nanoTime);
261 result.setIncludeLocation(includeLocation);
262 result.setEndOfBatch(endOfBatch);
263 return result;
264 }
265 }
266
267
268
269
270
271 public static Builder newBuilder() {
272 return new Builder();
273 }
274
275 public Log4jLogEvent() {
276 this(Strings.EMPTY, null, Strings.EMPTY, null, null, (Throwable) null, null, null, null, 0, null,
277 0, null, CLOCK.currentTimeMillis(), nanoClock.nanoTime());
278 }
279
280
281
282
283
284 @Deprecated
285 public Log4jLogEvent(final long timestamp) {
286 this(Strings.EMPTY, null, Strings.EMPTY, null, null, (Throwable) null, null, null, null, 0, null,
287 0, null, timestamp, nanoClock.nanoTime());
288 }
289
290
291
292
293
294
295
296
297
298
299
300 @Deprecated
301 public Log4jLogEvent(final String loggerName, final Marker marker, final String loggerFQCN, final Level level,
302 final Message message, final Throwable t) {
303 this(loggerName, marker, loggerFQCN, level, message, null, t);
304 }
305
306
307
308
309
310
311
312
313
314
315
316
317 public Log4jLogEvent(final String loggerName, final Marker marker, final String loggerFQCN, final Level level,
318 final Message message, final List<Property> properties, final Throwable t) {
319 this(loggerName, marker, loggerFQCN, level, message, t, null, createContextData(properties),
320 ThreadContext.getDepth() == 0 ? null : ThreadContext.cloneStack(),
321 0,
322 null,
323 0,
324 null,
325
326 message instanceof TimestampMessage ? ((TimestampMessage) message).getTimestamp() :
327 CLOCK.currentTimeMillis(), nanoClock.nanoTime());
328 }
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345 @Deprecated
346 public Log4jLogEvent(final String loggerName, final Marker marker, final String loggerFQCN, final Level level,
347 final Message message, final Throwable t, final Map<String, String> mdc,
348 final ThreadContext.ContextStack ndc, final String threadName,
349 final StackTraceElement location, final long timestampMillis) {
350 this(loggerName, marker, loggerFQCN, level, message, t, null, createContextData(mdc), ndc, 0,
351 threadName, 0, location, timestampMillis, nanoClock.nanoTime());
352 }
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371 @Deprecated
372 public static Log4jLogEvent createEvent(final String loggerName, final Marker marker, final String loggerFQCN,
373 final Level level, final Message message, final Throwable thrown,
374 final ThrowableProxy thrownProxy,
375 final Map<String, String> mdc, final ThreadContext.ContextStack ndc,
376 final String threadName, final StackTraceElement location,
377 final long timestamp) {
378 final Log4jLogEvent result = new Log4jLogEvent(loggerName, marker, loggerFQCN, level, message, thrown,
379 thrownProxy, createContextData(mdc), ndc, 0, threadName, 0, location, timestamp, nanoClock.nanoTime());
380 return result;
381 }
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402 private Log4jLogEvent(final String loggerName, final Marker marker, final String loggerFQCN, final Level level,
403 final Message message, final Throwable thrown, final ThrowableProxy thrownProxy,
404 final StringMap contextData, final ThreadContext.ContextStack contextStack, final long threadId,
405 final String threadName, final int threadPriority, final StackTraceElement source,
406 final long timestampMillis, final long nanoTime) {
407 this.loggerName = loggerName;
408 this.marker = marker;
409 this.loggerFqcn = loggerFQCN;
410 this.level = level == null ? Level.OFF : level;
411 this.message = message;
412 this.thrown = thrown;
413 this.thrownProxy = thrownProxy;
414 this.contextData = contextData == null ? ContextDataFactory.createContextData() : contextData;
415 this.contextStack = contextStack == null ? ThreadContext.EMPTY_STACK : contextStack;
416 this.timeMillis = message instanceof TimestampMessage
417 ? ((TimestampMessage) message).getTimestamp()
418 : timestampMillis;
419 this.threadId = threadId;
420 this.threadName = threadName;
421 this.threadPriority = threadPriority;
422 this.source = source;
423 if (message != null && message instanceof LoggerNameAwareMessage) {
424 ((LoggerNameAwareMessage) message).setLoggerName(loggerName);
425 }
426 this.nanoTime = nanoTime;
427 }
428
429 private static StringMap createContextData(final Map<String, String> contextMap) {
430 final StringMap result = ContextDataFactory.createContextData();
431 if (contextMap != null) {
432 for (final Map.Entry<String, String> entry : contextMap.entrySet()) {
433 result.putValue(entry.getKey(), entry.getValue());
434 }
435 }
436 return result;
437 }
438
439 private static StringMap createContextData(final List<Property> properties) {
440 final StringMap reusable = ContextDataFactory.createContextData();
441 return CONTEXT_DATA_INJECTOR.injectContextData(properties, reusable);
442 }
443
444
445
446
447
448 public static NanoClock getNanoClock() {
449 return nanoClock;
450 }
451
452
453
454
455
456
457
458
459
460 public static void setNanoClock(final NanoClock nanoClock) {
461 Log4jLogEvent.nanoClock = Objects.requireNonNull(nanoClock, "NanoClock must be non-null");
462 StatusLogger.getLogger().trace("Using {} for nanosecond timestamps.", nanoClock.getClass().getSimpleName());
463 }
464
465
466
467
468
469 public Builder asBuilder() {
470 return new Builder(this);
471 }
472
473 public Log4jLogEvent toImmutable() {
474 if (getMessage() instanceof ReusableMessage) {
475 makeMessageImmutable();
476 }
477 return this;
478 }
479
480
481
482
483
484 @Override
485 public Level getLevel() {
486 return level;
487 }
488
489
490
491
492
493 @Override
494 public String getLoggerName() {
495 return loggerName;
496 }
497
498
499
500
501
502 @Override
503 public Message getMessage() {
504 return message;
505 }
506
507 public void makeMessageImmutable() {
508 message = new SimpleMessage(message.getFormattedMessage());
509 }
510
511 @Override
512 public long getThreadId() {
513 if (threadId == 0) {
514 threadId = Thread.currentThread().getId();
515 }
516 return threadId;
517 }
518
519
520
521
522
523 @Override
524 public String getThreadName() {
525 if (threadName == null) {
526 threadName = Thread.currentThread().getName();
527 }
528 return threadName;
529 }
530
531 @Override
532 public int getThreadPriority() {
533 if (threadPriority == 0) {
534 threadPriority = Thread.currentThread().getPriority();
535 }
536 return threadPriority;
537 }
538
539
540
541
542
543 @Override
544 public long getTimeMillis() {
545 return timeMillis;
546 }
547
548
549
550
551
552 @Override
553 public Throwable getThrown() {
554 return thrown;
555 }
556
557
558
559
560
561 @Override
562 public ThrowableProxy getThrownProxy() {
563 if (thrownProxy == null && thrown != null) {
564 thrownProxy = new ThrowableProxy(thrown);
565 }
566 return thrownProxy;
567 }
568
569
570
571
572
573
574 @Override
575 public Marker getMarker() {
576 return marker;
577 }
578
579
580
581
582
583 @Override
584 public String getLoggerFqcn() {
585 return loggerFqcn;
586 }
587
588
589
590
591
592
593 @Override
594 public ReadOnlyStringMap getContextData() {
595 return contextData;
596 }
597
598
599
600
601 @Override
602 public Map<String, String> getContextMap() {
603 return contextData.toMap();
604 }
605
606
607
608
609
610 @Override
611 public ThreadContext.ContextStack getContextStack() {
612 return contextStack;
613 }
614
615
616
617
618
619
620 @Override
621 public StackTraceElement getSource() {
622 if (source != null) {
623 return source;
624 }
625 if (loggerFqcn == null || !includeLocation) {
626 return null;
627 }
628 source = calcLocation(loggerFqcn);
629 return source;
630 }
631
632 public static StackTraceElement calcLocation(final String fqcnOfLogger) {
633 if (fqcnOfLogger == null) {
634 return null;
635 }
636
637 final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
638 StackTraceElement last = null;
639 for (int i = stackTrace.length - 1; i > 0; i--) {
640 final String className = stackTrace[i].getClassName();
641 if (fqcnOfLogger.equals(className)) {
642 return last;
643 }
644 last = stackTrace[i];
645 }
646 return null;
647 }
648
649 @Override
650 public boolean isIncludeLocation() {
651 return includeLocation;
652 }
653
654 @Override
655 public void setIncludeLocation(final boolean includeLocation) {
656 this.includeLocation = includeLocation;
657 }
658
659 @Override
660 public boolean isEndOfBatch() {
661 return endOfBatch;
662 }
663
664 @Override
665 public void setEndOfBatch(final boolean endOfBatch) {
666 this.endOfBatch = endOfBatch;
667 }
668
669 @Override
670 public long getNanoTime() {
671 return nanoTime;
672 }
673
674
675
676
677
678 protected Object writeReplace() {
679 getThrownProxy();
680 return new LogEventProxy(this, this.includeLocation);
681 }
682
683
684
685
686
687
688
689
690
691
692 public static Serializable serialize(final LogEvent event, final boolean includeLocation) {
693 if (event instanceof Log4jLogEvent) {
694 event.getThrownProxy();
695 return new LogEventProxy((Log4jLogEvent) event, includeLocation);
696 }
697 return new LogEventProxy(event, includeLocation);
698 }
699
700
701
702
703
704
705
706
707
708
709 public static Serializable serialize(final Log4jLogEvent event, final boolean includeLocation) {
710 event.getThrownProxy();
711 return new LogEventProxy(event, includeLocation);
712 }
713
714 public static boolean canDeserialize(final Serializable event) {
715 return event instanceof LogEventProxy;
716 }
717
718 public static Log4jLogEvent deserialize(final Serializable event) {
719 Objects.requireNonNull(event, "Event cannot be null");
720 if (event instanceof LogEventProxy) {
721 final LogEventProxy proxy = (LogEventProxy) event;
722 final Log4jLogEvent result = new Log4jLogEvent(proxy.loggerName, proxy.marker,
723 proxy.loggerFQCN, proxy.level, proxy.message,
724 proxy.thrown, proxy.thrownProxy, proxy.contextData, proxy.contextStack, proxy.threadId,
725 proxy.threadName, proxy.threadPriority, proxy.source, proxy.timeMillis, proxy.nanoTime);
726 result.setEndOfBatch(proxy.isEndOfBatch);
727 result.setIncludeLocation(proxy.isLocationRequired);
728 return result;
729 }
730 throw new IllegalArgumentException("Event is not a serialized LogEvent: " + event.toString());
731 }
732
733 private void readObject(final ObjectInputStream stream) throws InvalidObjectException {
734 throw new InvalidObjectException("Proxy required");
735 }
736
737 public LogEvent createMemento() {
738 return createMemento(this);
739 }
740
741 public static LogEvent createMemento(final LogEvent logEvent) {
742 return new Log4jLogEvent.Builder(logEvent).build();
743 }
744
745
746
747
748
749
750 public static Log4jLogEvent createMemento(final LogEvent event, final boolean includeLocation) {
751 return deserialize(serialize(event, includeLocation));
752 }
753
754 @Override
755 public String toString() {
756 final StringBuilder sb = new StringBuilder();
757 final String n = loggerName.isEmpty() ? LoggerConfig.ROOT : loggerName;
758 sb.append("Logger=").append(n);
759 sb.append(" Level=").append(level.name());
760 sb.append(" Message=").append(message == null ? null : message.getFormattedMessage());
761 return sb.toString();
762 }
763
764 @Override
765 public boolean equals(final Object o) {
766 if (this == o) {
767 return true;
768 }
769 if (o == null || getClass() != o.getClass()) {
770 return false;
771 }
772
773 final Log4jLogEvent that = (Log4jLogEvent) o;
774
775 if (endOfBatch != that.endOfBatch) {
776 return false;
777 }
778 if (includeLocation != that.includeLocation) {
779 return false;
780 }
781 if (timeMillis != that.timeMillis) {
782 return false;
783 }
784 if (nanoTime != that.nanoTime) {
785 return false;
786 }
787 if (loggerFqcn != null ? !loggerFqcn.equals(that.loggerFqcn) : that.loggerFqcn != null) {
788 return false;
789 }
790 if (level != null ? !level.equals(that.level) : that.level != null) {
791 return false;
792 }
793 if (source != null ? !source.equals(that.source) : that.source != null) {
794 return false;
795 }
796 if (marker != null ? !marker.equals(that.marker) : that.marker != null) {
797 return false;
798 }
799 if (contextData != null ? !contextData.equals(that.contextData) : that.contextData != null) {
800 return false;
801 }
802 if (!message.equals(that.message)) {
803 return false;
804 }
805 if (!loggerName.equals(that.loggerName)) {
806 return false;
807 }
808 if (contextStack != null ? !contextStack.equals(that.contextStack) : that.contextStack != null) {
809 return false;
810 }
811 if (threadId != that.threadId) {
812 return false;
813 }
814 if (threadName != null ? !threadName.equals(that.threadName) : that.threadName != null) {
815 return false;
816 }
817 if (threadPriority != that.threadPriority) {
818 return false;
819 }
820 if (thrown != null ? !thrown.equals(that.thrown) : that.thrown != null) {
821 return false;
822 }
823 if (thrownProxy != null ? !thrownProxy.equals(that.thrownProxy) : that.thrownProxy != null) {
824 return false;
825 }
826
827 return true;
828 }
829
830 @Override
831 public int hashCode() {
832
833 int result = loggerFqcn != null ? loggerFqcn.hashCode() : 0;
834 result = 31 * result + (marker != null ? marker.hashCode() : 0);
835 result = 31 * result + (level != null ? level.hashCode() : 0);
836 result = 31 * result + loggerName.hashCode();
837 result = 31 * result + message.hashCode();
838 result = 31 * result + (int) (timeMillis ^ (timeMillis >>> 32));
839 result = 31 * result + (int) (nanoTime ^ (nanoTime >>> 32));
840 result = 31 * result + (thrown != null ? thrown.hashCode() : 0);
841 result = 31 * result + (thrownProxy != null ? thrownProxy.hashCode() : 0);
842 result = 31 * result + (contextData != null ? contextData.hashCode() : 0);
843 result = 31 * result + (contextStack != null ? contextStack.hashCode() : 0);
844 result = 31 * result + (int) (threadId ^ (threadId >>> 32));
845 result = 31 * result + (threadName != null ? threadName.hashCode() : 0);
846 result = 31 * result + (threadPriority ^ (threadPriority >>> 32));
847 result = 31 * result + (source != null ? source.hashCode() : 0);
848 result = 31 * result + (includeLocation ? 1 : 0);
849 result = 31 * result + (endOfBatch ? 1 : 0);
850
851 return result;
852 }
853
854
855
856
857 static class LogEventProxy implements Serializable {
858
859 private static final long serialVersionUID = -8634075037355293699L;
860 private final String loggerFQCN;
861 private final Marker marker;
862 private final Level level;
863 private final String loggerName;
864
865 private final transient Message message;
866
867 private MarshalledObject<Message> marshalledMessage;
868
869 private String messageString;
870 private final long timeMillis;
871 private final transient Throwable thrown;
872 private final ThrowableProxy thrownProxy;
873
874 private final StringMap contextData;
875 private final ThreadContext.ContextStack contextStack;
876
877 private final long threadId;
878 private final String threadName;
879
880 private final int threadPriority;
881 private final StackTraceElement source;
882 private final boolean isLocationRequired;
883 private final boolean isEndOfBatch;
884
885 private final transient long nanoTime;
886
887 public LogEventProxy(final Log4jLogEvent event, final boolean includeLocation) {
888 this.loggerFQCN = event.loggerFqcn;
889 this.marker = event.marker;
890 this.level = event.level;
891 this.loggerName = event.loggerName;
892 this.message = event.message instanceof ReusableMessage
893 ? memento((ReusableMessage) event.message)
894 : event.message;
895 this.timeMillis = event.timeMillis;
896 this.thrown = event.thrown;
897 this.thrownProxy = event.thrownProxy;
898 this.contextData = event.contextData;
899 this.contextStack = event.contextStack;
900 this.source = includeLocation ? event.getSource() : null;
901 this.threadId = event.getThreadId();
902 this.threadName = event.getThreadName();
903 this.threadPriority = event.getThreadPriority();
904 this.isLocationRequired = includeLocation;
905 this.isEndOfBatch = event.endOfBatch;
906 this.nanoTime = event.nanoTime;
907 }
908
909 public LogEventProxy(final LogEvent event, final boolean includeLocation) {
910 this.loggerFQCN = event.getLoggerFqcn();
911 this.marker = event.getMarker();
912 this.level = event.getLevel();
913 this.loggerName = event.getLoggerName();
914
915 final Message temp = event.getMessage();
916 message = temp instanceof ReusableMessage
917 ? memento((ReusableMessage) temp)
918 : temp;
919 this.timeMillis = event.getTimeMillis();
920 this.thrown = event.getThrown();
921 this.thrownProxy = event.getThrownProxy();
922 this.contextData = memento(event.getContextData());
923 this.contextStack = event.getContextStack();
924 this.source = includeLocation ? event.getSource() : null;
925 this.threadId = event.getThreadId();
926 this.threadName = event.getThreadName();
927 this.threadPriority = event.getThreadPriority();
928 this.isLocationRequired = includeLocation;
929 this.isEndOfBatch = event.isEndOfBatch();
930 this.nanoTime = event.getNanoTime();
931 }
932
933 private static Message memento(final ReusableMessage message) {
934 return message.memento();
935 }
936
937 private static StringMap memento(final ReadOnlyStringMap data) {
938 final StringMap result = ContextDataFactory.createContextData();
939 result.putAll(data);
940 return result;
941 }
942
943 private static MarshalledObject<Message> marshall(final Message msg) {
944 try {
945 return new MarshalledObject<>(msg);
946 } catch (final Exception ex) {
947 return null;
948 }
949 }
950
951 private void writeObject(final java.io.ObjectOutputStream s) throws IOException {
952 this.messageString = message.getFormattedMessage();
953 this.marshalledMessage = marshall(message);
954 s.defaultWriteObject();
955 }
956
957
958
959
960
961 protected Object readResolve() {
962 final Log4jLogEvent result = new Log4jLogEvent(loggerName, marker, loggerFQCN, level, message(), thrown,
963 thrownProxy, contextData, contextStack, threadId, threadName, threadPriority, source, timeMillis,
964 nanoTime);
965 result.setEndOfBatch(isEndOfBatch);
966 result.setIncludeLocation(isLocationRequired);
967 return result;
968 }
969
970 private Message message() {
971 if (marshalledMessage != null) {
972 try {
973 return marshalledMessage.get();
974 } catch (final Exception ex) {
975 }
976 }
977 return new SimpleMessage(messageString);
978 }
979 }
980
981 }