1/*
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24import java.util.Arrays;
25import java.util.Objects;
26import java.util.Queue;
27import java.util.ResourceBundle;
28import java.util.concurrent.ArrayBlockingQueue;
29import java.util.concurrent.ConcurrentHashMap;
30import java.util.concurrent.atomic.AtomicLong;
31import java.util.function.Supplier;
32import java.lang.System.Logger;
33
34/**
35 * What our test provider needs to implement.
36 * @author danielfuchs
37 */
38public interface TestLoggerFinder {
39    public final static AtomicLong sequencer = new AtomicLong();
40    public final ConcurrentHashMap<String, LoggerImpl> system = new ConcurrentHashMap<>();
41    public final ConcurrentHashMap<String, LoggerImpl> user = new ConcurrentHashMap<>();
42    public final Queue<LogEvent> eventQueue = new ArrayBlockingQueue<>(128);
43
44    public static final class LogEvent {
45
46        public LogEvent() {
47            this(sequencer.getAndIncrement());
48        }
49
50        LogEvent(long sequenceNumber) {
51            this.sequenceNumber = sequenceNumber;
52        }
53
54        long sequenceNumber;
55        boolean isLoggable;
56        String loggerName;
57        Logger.Level level;
58        ResourceBundle bundle;
59        Throwable thrown;
60        Object[] args;
61        Supplier<String> supplier;
62        String msg;
63
64        Object[] toArray() {
65            return new Object[] {
66                sequenceNumber,
67                isLoggable,
68                loggerName,
69                level,
70                bundle,
71                thrown,
72                args,
73                supplier,
74                msg,
75            };
76        }
77
78        @Override
79        public String toString() {
80            return Arrays.deepToString(toArray());
81        }
82
83
84
85        @Override
86        public boolean equals(Object obj) {
87            return obj instanceof LogEvent
88                    && Objects.deepEquals(this.toArray(), ((LogEvent)obj).toArray());
89        }
90
91        @Override
92        public int hashCode() {
93            return Objects.hash(toArray());
94        }
95
96
97        public static LogEvent of(boolean isLoggable, String name,
98                Logger.Level level, ResourceBundle bundle,
99                String key, Throwable thrown) {
100            LogEvent evt = new LogEvent();
101            evt.isLoggable = isLoggable;
102            evt.loggerName = name;
103            evt.level = level;
104            evt.args = null;
105            evt.bundle = bundle;
106            evt.thrown = thrown;
107            evt.supplier = null;
108            evt.msg = key;
109            return evt;
110        }
111
112        public static LogEvent of(boolean isLoggable, String name,
113                Logger.Level level, ResourceBundle bundle,
114                String key, Object... params) {
115            LogEvent evt = new LogEvent();
116            evt.isLoggable = isLoggable;
117            evt.loggerName = name;
118            evt.level = level;
119            evt.args = params;
120            evt.bundle = bundle;
121            evt.thrown = null;
122            evt.supplier = null;
123            evt.msg = key;
124            return evt;
125        }
126
127        public static LogEvent of(long sequenceNumber,
128                boolean isLoggable, String name,
129                Logger.Level level, ResourceBundle bundle,
130                String key, Supplier<String> supplier,
131                Throwable thrown, Object... params) {
132            LogEvent evt = new LogEvent(sequenceNumber);
133            evt.loggerName = name;
134            evt.level = level;
135            evt.args = params;
136            evt.bundle = bundle;
137            evt.thrown = thrown;
138            evt.supplier = supplier;
139            evt.msg = key;
140            evt.isLoggable = isLoggable;
141            return evt;
142        }
143
144    }
145
146    public class LoggerImpl implements Logger {
147        final String name;
148        Logger.Level level = Logger.Level.INFO;
149
150        public LoggerImpl(String name) {
151            this.name = name;
152        }
153
154        @Override
155        public String getName() {
156            return name;
157        }
158
159        @Override
160        public boolean isLoggable(Logger.Level level) {
161            return this.level != Logger.Level.OFF && this.level.getSeverity() <= level.getSeverity();
162        }
163
164        @Override
165        public void log(Logger.Level level, ResourceBundle bundle, String key, Throwable thrown) {
166            log(LogEvent.of(isLoggable(level), this.name, level, bundle, key, thrown));
167        }
168
169        @Override
170        public void log(Logger.Level level, ResourceBundle bundle, String format, Object... params) {
171            log(LogEvent.of(isLoggable(level), name, level, bundle, format, params));
172        }
173
174        void log(LogEvent event) {
175            eventQueue.add(event);
176        }
177    }
178
179    public Logger getLogger(String name, Module caller);
180    public Logger getLocalizedLogger(String name, ResourceBundle bundle, Module caller);
181}
182