1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.spf4j.test.log;
17
18 import java.lang.reflect.InvocationTargetException;
19 import java.util.function.BiConsumer;
20 import java.util.function.Consumer;
21 import java.util.function.Function;
22 import java.util.stream.Collector;
23 import javax.annotation.Nullable;
24 import javax.annotation.concurrent.GuardedBy;
25 import javax.annotation.concurrent.ThreadSafe;
26 import org.spf4j.log.Level;
27
28
29
30
31
32 @ThreadSafe
33 final class LogCollectorHandler<A, T> implements LogHandler, LogCollection<T> {
34
35 private final Level fromLevel;
36 private final Level toLevel;
37 private final boolean passThrough;
38 private final Object sync = new Object();
39 @GuardedBy("sync")
40 private A accObj;
41 private final BiConsumer<A, TestLogRecord> acc;
42 private final Function<A, T> finisher;
43 private final Consumer<LogCollectorHandler<A, T>> onClose;
44 private boolean isClosed;
45
46 LogCollectorHandler(final Level fromLevel, final Level toLevel,
47 final boolean passThrough,
48 final Collector<TestLogRecord, A, T> collector, final Consumer<LogCollectorHandler<A, T>> onClose) {
49 this.fromLevel = fromLevel;
50 this.toLevel = toLevel;
51 this.passThrough = passThrough;
52 this.accObj = collector.supplier().get();
53 this.acc = collector.accumulator();
54 this.finisher = collector.finisher();
55 this.onClose = onClose;
56 this.isClosed = false;
57 }
58
59 @Override
60 public LogHandler.Handling handles(final Level level) {
61 if (level.ordinal() >= fromLevel.ordinal() && level.ordinal() <= toLevel.ordinal()) {
62 return passThrough ? LogHandler.Handling.HANDLE_PASS : LogHandler.Handling.HANDLE_CONSUME;
63 } else {
64 return LogHandler.Handling.NONE;
65 }
66 }
67
68 @Override
69 @Nullable
70 public TestLogRecord handle(final TestLogRecord record) {
71 synchronized (sync) {
72 if (!isClosed) {
73 acc.accept(accObj, record);
74 }
75 }
76 if (passThrough) {
77 return record;
78 } else {
79 return null;
80 }
81 }
82
83 @Override
84 public T get() {
85 synchronized (sync) {
86 T result = finisher.apply(accObj);
87 if (result == accObj) {
88 try {
89 return (T) result.getClass().getMethod("clone").invoke(result);
90 } catch (NoSuchMethodException | SecurityException | IllegalAccessException | InvocationTargetException ex) {
91 throw new RuntimeException(ex);
92 }
93 }
94 return result;
95 }
96 }
97
98
99 @Override
100 public void close() {
101 synchronized (sync) {
102 if (!isClosed) {
103 try {
104 onClose.accept(this);
105 } finally {
106 isClosed = true;
107 }
108 }
109 }
110 }
111
112 @Override
113 public String toString() {
114 return "LogCollectorHandler{" + "accObj=" + accObj + ", fromLevel="
115 + fromLevel + ", toLevel=" + toLevel + ", passThrough=" + passThrough + '}';
116 }
117
118 }