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 
  24 import java.util.Arrays;
  25 import java.util.Objects;
  26 import java.util.Queue;
  27 import java.util.ResourceBundle;
  28 import java.util.concurrent.ArrayBlockingQueue;
  29 import java.util.concurrent.ConcurrentHashMap;
  30 import java.util.concurrent.atomic.AtomicLong;
  31 import java.util.function.Supplier;
  32 import java.lang.System.Logger;
  33 
  34 /**
  35  * What our test provider needs to implement.
  36  * @author danielfuchs
  37  */
  38 public 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, Class<?> caller);
 180     public Logger getLocalizedLogger(String name, ResourceBundle bundle, Class<?> caller);
 181 }