Path: blob/master/test/jdk/java/lang/System/LoggerFinder/internal/LoggerFinderLoaderTest/LoggerFinderLoaderTest.java
66648 views
/*1* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/22import java.io.ByteArrayOutputStream;23import java.io.IOException;24import java.io.PrintStream;25import java.io.UncheckedIOException;26import java.security.AccessControlException;27import java.security.CodeSource;28import java.security.Permission;29import java.security.PermissionCollection;30import java.security.Permissions;31import java.security.Policy;32import java.security.ProtectionDomain;33import java.util.Collections;34import java.util.Enumeration;35import java.util.HashMap;36import java.util.Map;37import java.util.ResourceBundle;38import java.util.stream.Collectors;39import java.util.stream.Stream;40import java.util.concurrent.ConcurrentHashMap;41import java.util.concurrent.atomic.AtomicBoolean;42import java.util.concurrent.atomic.AtomicLong;43import java.util.function.Supplier;44import java.lang.System.LoggerFinder;45import java.lang.System.Logger;46import java.lang.System.Logger.Level;47import java.util.EnumSet;48import java.util.Iterator;49import java.util.Locale;50import java.util.ServiceLoader;51import java.util.concurrent.atomic.AtomicReference;5253/**54* @test55* @bug 8140364 818929156* @summary JDK implementation specific unit test for LoggerFinderLoader.57* Tests the behavior of LoggerFinderLoader with respect to the58* value of the internal diagnosability switches. Also test the59* DefaultLoggerFinder and SimpleConsoleLogger implementation.60* @modules java.base/sun.util.logging61* java.base/jdk.internal.logger62* @build AccessSystemLogger LoggerFinderLoaderTest CustomSystemClassLoader BaseLoggerFinder BaseLoggerFinder263* @run driver AccessSystemLogger64* @run main/othervm -Xbootclasspath/a:boot -Djava.system.class.loader=CustomSystemClassLoader LoggerFinderLoaderTest NOSECURITY65* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader LoggerFinderLoaderTest NOPERMISSIONS66* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader LoggerFinderLoaderTest WITHPERMISSIONS67* @run main/othervm -Xbootclasspath/a:boot -Djava.system.class.loader=CustomSystemClassLoader -Dtest.fails=true LoggerFinderLoaderTest NOSECURITY68* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader -Dtest.fails=true LoggerFinderLoaderTest NOPERMISSIONS69* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader -Dtest.fails=true LoggerFinderLoaderTest WITHPERMISSIONS70* @run main/othervm -Xbootclasspath/a:boot -Djava.system.class.loader=CustomSystemClassLoader -Dtest.fails=true -Djdk.logger.finder.error=ERROR LoggerFinderLoaderTest NOSECURITY71* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader -Dtest.fails=true -Djdk.logger.finder.error=ERROR LoggerFinderLoaderTest NOPERMISSIONS72* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader -Dtest.fails=true -Djdk.logger.finder.error=ERROR LoggerFinderLoaderTest WITHPERMISSIONS73* @run main/othervm -Xbootclasspath/a:boot -Djava.system.class.loader=CustomSystemClassLoader -Dtest.fails=true -Djdk.logger.finder.error=DEBUG LoggerFinderLoaderTest NOSECURITY74* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader -Dtest.fails=true -Djdk.logger.finder.error=DEBUG LoggerFinderLoaderTest NOPERMISSIONS75* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader -Dtest.fails=true -Djdk.logger.finder.error=DEBUG LoggerFinderLoaderTest WITHPERMISSIONS76* @run main/othervm -Xbootclasspath/a:boot -Djava.system.class.loader=CustomSystemClassLoader -Dtest.fails=true -Djdk.logger.finder.error=QUIET LoggerFinderLoaderTest NOSECURITY77* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader -Dtest.fails=true -Djdk.logger.finder.error=QUIET LoggerFinderLoaderTest NOPERMISSIONS78* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader -Dtest.fails=true -Djdk.logger.finder.error=QUIET LoggerFinderLoaderTest WITHPERMISSIONS79* @run main/othervm -Xbootclasspath/a:boot -Djava.system.class.loader=CustomSystemClassLoader -Djdk.logger.finder.singleton=true LoggerFinderLoaderTest NOSECURITY80* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader -Djdk.logger.finder.singleton=true LoggerFinderLoaderTest NOPERMISSIONS81* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader -Djdk.logger.finder.singleton=true LoggerFinderLoaderTest WITHPERMISSIONS82* @run main/othervm -Xbootclasspath/a:boot -Djava.system.class.loader=CustomSystemClassLoader -Djdk.logger.finder.singleton=true -Djdk.logger.finder.error=ERROR LoggerFinderLoaderTest NOSECURITY83* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader -Djdk.logger.finder.singleton=true -Djdk.logger.finder.error=ERROR LoggerFinderLoaderTest NOPERMISSIONS84* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader -Djdk.logger.finder.singleton=true -Djdk.logger.finder.error=ERROR LoggerFinderLoaderTest WITHPERMISSIONS85* @run main/othervm -Xbootclasspath/a:boot -Djava.system.class.loader=CustomSystemClassLoader -Djdk.logger.finder.singleton=true -Djdk.logger.finder.error=DEBUG LoggerFinderLoaderTest NOSECURITY86* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader -Djdk.logger.finder.singleton=true -Djdk.logger.finder.error=DEBUG LoggerFinderLoaderTest NOPERMISSIONS87* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader -Djdk.logger.finder.singleton=true -Djdk.logger.finder.error=DEBUG LoggerFinderLoaderTest WITHPERMISSIONS88* @run main/othervm -Xbootclasspath/a:boot -Djava.system.class.loader=CustomSystemClassLoader -Djdk.logger.finder.singleton=true -Djdk.logger.finder.error=QUIET LoggerFinderLoaderTest NOSECURITY89* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader -Djdk.logger.finder.singleton=true -Djdk.logger.finder.error=QUIET LoggerFinderLoaderTest NOPERMISSIONS90* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader -Djdk.logger.finder.singleton=true -Djdk.logger.finder.error=QUIET LoggerFinderLoaderTest WITHPERMISSIONS91* @author danielfuchs92*/93public class LoggerFinderLoaderTest {9495static final Policy DEFAULT_POLICY = Policy.getPolicy();96static final RuntimePermission LOGGERFINDER_PERMISSION =97new RuntimePermission("loggerFinder");98final static boolean VERBOSE = false;99static final ThreadLocal<AtomicBoolean> allowControl = new ThreadLocal<AtomicBoolean>() {100@Override101protected AtomicBoolean initialValue() {102return new AtomicBoolean(false);103}104};105static final ThreadLocal<AtomicBoolean> allowAccess = new ThreadLocal<AtomicBoolean>() {106@Override107protected AtomicBoolean initialValue() {108return new AtomicBoolean(false);109}110};111112final static AccessSystemLogger accessSystemLogger = new AccessSystemLogger();113static final Class<?>[] providerClass;114static {115try {116providerClass = new Class<?>[] {117ClassLoader.getSystemClassLoader().loadClass("BaseLoggerFinder"),118ClassLoader.getSystemClassLoader().loadClass("BaseLoggerFinder2")119};120} catch (ClassNotFoundException ex) {121throw new ExceptionInInitializerError(ex);122}123}124125/**126* What our test provider needs to implement.127*/128public static interface TestLoggerFinder {129public final static AtomicBoolean fails = new AtomicBoolean();130public final static AtomicReference<String> conf = new AtomicReference<>("");131public final static AtomicLong sequencer = new AtomicLong();132public final ConcurrentHashMap<String, LoggerImpl> system = new ConcurrentHashMap<>();133public final ConcurrentHashMap<String, LoggerImpl> user = new ConcurrentHashMap<>();134135public class LoggerImpl implements System.Logger {136final String name;137final Logger logger;138139public LoggerImpl(String name, Logger logger) {140this.name = name;141this.logger = logger;142}143144@Override145public String getName() {146return name;147}148149@Override150public boolean isLoggable(Logger.Level level) {151return logger.isLoggable(level);152}153154@Override155public void log(Logger.Level level, ResourceBundle bundle, String key, Throwable thrown) {156logger.log(level, bundle, key, thrown);157}158159@Override160public void log(Logger.Level level, ResourceBundle bundle, String format, Object... params) {161logger.log(level, bundle, format, params);162}163164}165166public Logger getLogger(String name, Module caller);167public Logger getLocalizedLogger(String name, ResourceBundle bundle, Module caller);168}169170public static class MyBundle extends ResourceBundle {171172final ConcurrentHashMap<String,String> map = new ConcurrentHashMap<>();173174@Override175protected Object handleGetObject(String key) {176if (key.contains(" (translated)")) {177throw new RuntimeException("Unexpected key: " + key);178}179return map.computeIfAbsent(key, k -> k.toUpperCase(Locale.ROOT) + " (translated)");180}181182@Override183public Enumeration<String> getKeys() {184return Collections.enumeration(map.keySet());185}186187}188public static class MyLoggerBundle extends MyBundle {189190}191192static enum TestCases {NOSECURITY, NOPERMISSIONS, WITHPERMISSIONS};193194static void setSecurityManager() {195if (System.getSecurityManager() == null) {196Policy.setPolicy(new SimplePolicy(allowControl, allowAccess));197System.setSecurityManager(new SecurityManager());198}199}200201private static String withoutWarning(String in) {202return in.lines().filter(s -> !s.startsWith("WARNING:")).collect(Collectors.joining());203}204205static LoggerFinder getLoggerFinder(Class<?> expectedClass,206String errorPolicy, boolean singleton) {207LoggerFinder provider = null;208try {209TestLoggerFinder.sequencer.incrementAndGet();210provider = LoggerFinder.getLoggerFinder();211if (TestLoggerFinder.fails.get() || singleton) {212if ("ERROR".equals(errorPolicy.toUpperCase(Locale.ROOT))) {213throw new RuntimeException("Expected exception not thrown");214} else if ("WARNING".equals(errorPolicy.toUpperCase(Locale.ROOT))) {215String warning = ErrorStream.errorStream.peek();216if (!warning.contains("WARNING: Failed to instantiate LoggerFinder provider; Using default.")) {217throw new RuntimeException("Expected message not found. Error stream contained: " + warning);218}219} else if ("DEBUG".equals(errorPolicy.toUpperCase(Locale.ROOT))) {220String warning = ErrorStream.errorStream.peek();221if (!warning.contains("WARNING: Failed to instantiate LoggerFinder provider; Using default.")) {222throw new RuntimeException("Expected message not found. Error stream contained: " + warning);223}224if (!warning.contains("WARNING: Exception raised trying to instantiate LoggerFinder")) {225throw new RuntimeException("Expected message not found. Error stream contained: " + warning);226}227if (TestLoggerFinder.fails.get()) {228if (!warning.contains("java.util.ServiceConfigurationError: java.lang.System$LoggerFinder: Provider BaseLoggerFinder could not be instantiated")) {229throw new RuntimeException("Expected message not found. Error stream contained: " + warning);230}231} else if (singleton) {232if (!warning.contains("java.util.ServiceConfigurationError: More than on LoggerFinder implementation")) {233throw new RuntimeException("Expected message not found. Error stream contained: " + warning);234}235}236} else if ("QUIET".equals(errorPolicy.toUpperCase(Locale.ROOT))) {237String warning = ErrorStream.errorStream.peek();238warning = withoutWarning(warning);239if (!warning.isEmpty()) {240throw new RuntimeException("Unexpected error message found: "241+ ErrorStream.errorStream.peek());242}243}244}245} catch(AccessControlException a) {246throw a;247} catch(Throwable t) {248if (TestLoggerFinder.fails.get() || singleton) {249// must check System.err250if ("ERROR".equals(errorPolicy.toUpperCase(Locale.ROOT))) {251provider = LoggerFinder.getLoggerFinder();252} else {253Throwable orig = t.getCause();254while (orig != null && orig.getCause() != null) orig = orig.getCause();255if (orig != null) orig.printStackTrace(ErrorStream.err);256throw new RuntimeException("Unexpected exception: " + t, t);257}258} else {259throw new RuntimeException("Unexpected exception: " + t, t);260}261}262expectedClass.cast(provider);263ErrorStream.errorStream.store();264System.out.println("*** Actual LoggerFinder class is: " + provider.getClass().getName());265return provider;266}267268269static class ErrorStream extends PrintStream {270271static AtomicBoolean forward = new AtomicBoolean();272ByteArrayOutputStream out;273String saved = "";274public ErrorStream(ByteArrayOutputStream out) {275super(out);276this.out = out;277}278279@Override280public void write(int b) {281super.write(b);282if (forward.get()) err.write(b);283}284285@Override286public void write(byte[] b) throws IOException {287super.write(b);288if (forward.get()) err.write(b);289}290291@Override292public void write(byte[] buf, int off, int len) {293super.write(buf, off, len);294if (forward.get()) err.write(buf, off, len);295}296297public String peek() {298flush();299return out.toString();300}301302public String drain() {303flush();304String res = out.toString();305out.reset();306return res;307}308309public void store() {310flush();311saved = out.toString();312out.reset();313}314315public void restore() {316out.reset();317try {318out.write(saved.getBytes());319} catch(IOException io) {320throw new UncheckedIOException(io);321}322}323324static final PrintStream err = System.err;325static final ErrorStream errorStream = new ErrorStream(new ByteArrayOutputStream());326}327328private static StringBuilder appendProperty(StringBuilder b, String name) {329String value = System.getProperty(name);330if (value == null) return b;331return b.append(name).append("=").append(value).append('\n');332}333334public static void main(String[] args) {335if (args.length == 0) {336args = new String[] {337"NOSECURITY",338"NOPERMISSIONS",339"WITHPERMISSIONS"340};341}342Locale.setDefault(Locale.ENGLISH);343System.setErr(ErrorStream.errorStream);344System.setProperty("jdk.logger.packages", TestLoggerFinder.LoggerImpl.class.getName());345//System.setProperty("jdk.logger.finder.error", "ERROR");346//System.setProperty("jdk.logger.finder.singleton", "true");347//System.setProperty("test.fails", "true");348TestLoggerFinder.fails.set(Boolean.getBoolean("test.fails"));349StringBuilder c = new StringBuilder();350appendProperty(c, "jdk.logger.packages");351appendProperty(c, "jdk.logger.finder.error");352appendProperty(c, "jdk.logger.finder.singleton");353appendProperty(c, "test.fails");354TestLoggerFinder.conf.set(c.toString());355try {356test(args);357} finally {358try {359System.setErr(ErrorStream.err);360} catch (Error | RuntimeException x) {361x.printStackTrace(ErrorStream.err);362}363}364}365366367public static void test(String[] args) {368369final String errorPolicy = System.getProperty("jdk.logger.finder.error", "WARNING");370final Boolean ensureSingleton = Boolean.getBoolean("jdk.logger.finder.singleton");371372final Class<?> expectedClass =373TestLoggerFinder.fails.get() || ensureSingleton374? jdk.internal.logger.DefaultLoggerFinder.class375: TestLoggerFinder.class;376377System.out.println("Declared provider class: " + providerClass[0]378+ "[" + providerClass[0].getClassLoader() + "]");379380if (!TestLoggerFinder.fails.get()) {381ServiceLoader<LoggerFinder> serviceLoader =382ServiceLoader.load(LoggerFinder.class, ClassLoader.getSystemClassLoader());383Iterator<LoggerFinder> iterator = serviceLoader.iterator();384Object firstProvider = iterator.next();385if (!firstProvider.getClass().getName().equals("BaseLoggerFinder")) {386throw new RuntimeException("Unexpected provider: " + firstProvider.getClass().getName());387}388if (!iterator.hasNext()) {389throw new RuntimeException("Expected two providers");390}391}392393Stream.of(args).map(TestCases::valueOf).forEach((testCase) -> {394LoggerFinder provider;395ErrorStream.errorStream.restore();396switch (testCase) {397case NOSECURITY:398System.out.println("\n*** Without Security Manager\n");399System.out.println(TestLoggerFinder.conf.get());400provider = getLoggerFinder(expectedClass, errorPolicy, ensureSingleton);401test(provider, true);402System.out.println("Tetscase count: " + TestLoggerFinder.sequencer.get());403break;404case NOPERMISSIONS:405System.out.println("\n*** With Security Manager, without permissions\n");406System.out.println(TestLoggerFinder.conf.get());407setSecurityManager();408try {409provider = getLoggerFinder(expectedClass, errorPolicy, ensureSingleton);410throw new RuntimeException("Expected exception not raised");411} catch (AccessControlException x) {412if (!LOGGERFINDER_PERMISSION.equals(x.getPermission())) {413throw new RuntimeException("Unexpected permission check", x);414}415final boolean control = allowControl.get().get();416try {417allowControl.get().set(true);418provider = getLoggerFinder(expectedClass, errorPolicy, ensureSingleton);419} finally {420allowControl.get().set(control);421}422}423test(provider, false);424System.out.println("Tetscase count: " + TestLoggerFinder.sequencer.get());425break;426case WITHPERMISSIONS:427System.out.println("\n*** With Security Manager, with control permission\n");428System.out.println(TestLoggerFinder.conf.get());429setSecurityManager();430final boolean control = allowControl.get().get();431try {432allowControl.get().set(true);433provider = getLoggerFinder(expectedClass, errorPolicy, ensureSingleton);434test(provider, true);435} finally {436allowControl.get().set(control);437}438break;439default:440throw new RuntimeException("Unknown test case: " + testCase);441}442});443System.out.println("\nPASSED: Tested " + TestLoggerFinder.sequencer.get() + " cases.");444}445446public static void test(LoggerFinder provider, boolean hasRequiredPermissions) {447448ResourceBundle loggerBundle = ResourceBundle.getBundle(MyLoggerBundle.class.getName());449final Map<Logger, String> loggerDescMap = new HashMap<>();450451System.Logger sysLogger = accessSystemLogger.getLogger("foo");452loggerDescMap.put(sysLogger, "accessSystemLogger.getLogger(\"foo\")");453System.Logger localizedSysLogger = accessSystemLogger.getLogger("fox", loggerBundle);454loggerDescMap.put(localizedSysLogger, "accessSystemLogger.getLogger(\"fox\", loggerBundle)");455System.Logger appLogger = System.getLogger("bar");456loggerDescMap.put(appLogger,"System.getLogger(\"bar\")");457System.Logger localizedAppLogger = System.getLogger("baz", loggerBundle);458loggerDescMap.put(localizedAppLogger,"System.getLogger(\"baz\", loggerBundle)");459460testLogger(provider, loggerDescMap, "foo", null, sysLogger);461testLogger(provider, loggerDescMap, "foo", loggerBundle, localizedSysLogger);462testLogger(provider, loggerDescMap, "foo", null, appLogger);463testLogger(provider, loggerDescMap, "foo", loggerBundle, localizedAppLogger);464}465466public static class Foo {467468}469470static void verbose(String msg) {471if (VERBOSE) {472System.out.println(msg);473}474}475476// Calls the 8 methods defined on Logger and verify the477// parameters received by the underlying TestProvider.LoggerImpl478// logger.479private static void testLogger(LoggerFinder provider,480Map<Logger, String> loggerDescMap,481String name,482ResourceBundle loggerBundle,483Logger logger) {484485System.out.println("Testing " + loggerDescMap.get(logger) + " [" + logger +"]");486AtomicLong sequencer = TestLoggerFinder.sequencer;487488Foo foo = new Foo();489String fooMsg = foo.toString();490for (Level loggerLevel : EnumSet.of(Level.INFO)) {491for (Level messageLevel : Level.values()) {492ErrorStream.errorStream.drain();493String desc = "logger.log(messageLevel, foo): loggerLevel="494+ loggerLevel+", messageLevel="+messageLevel;495sequencer.incrementAndGet();496logger.log(messageLevel, foo);497if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {498if (!ErrorStream.errorStream.peek().isEmpty()) {499throw new RuntimeException("unexpected event in queue for "500+ desc +": " + "\n\t" + ErrorStream.errorStream.drain());501}502} else {503String logged = ErrorStream.errorStream.drain();504if (!logged.contains("LoggerFinderLoaderTest testLogger")505|| !logged.contains(messageLevel.getName() + ": " + fooMsg)) {506throw new RuntimeException("mismatch for " + desc507+ "\n\texpected:" + "\n<<<<\n"508+ "[date] LoggerFinderLoaderTest testLogger\n"509+ messageLevel.getName() + " " + fooMsg510+ "\n>>>>"511+ "\n\t actual:"512+ "\n<<<<\n" + logged + ">>>>\n");513} else {514verbose("Got expected results for "515+ desc + "\n<<<<\n" + logged + ">>>>\n");516}517}518}519}520521String msg = "blah";522for (Level loggerLevel : EnumSet.of(Level.INFO)) {523for (Level messageLevel : Level.values()) {524String desc = "logger.log(messageLevel, \"blah\"): loggerLevel="525+ loggerLevel+", messageLevel="+messageLevel;526sequencer.incrementAndGet();527logger.log(messageLevel, msg);528if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {529if (!ErrorStream.errorStream.peek().isEmpty()) {530throw new RuntimeException("unexpected event in queue for "531+ desc +": " + "\n\t" + ErrorStream.errorStream.drain());532}533} else {534String logged = ErrorStream.errorStream.drain();535String msgText = loggerBundle == null ? msg : loggerBundle.getString(msg);536if (!logged.contains("LoggerFinderLoaderTest testLogger")537|| !logged.contains(messageLevel.getName() + ": " + msgText)) {538throw new RuntimeException("mismatch for " + desc539+ "\n\texpected:" + "\n<<<<\n"540+ "[date] LoggerFinderLoaderTest testLogger\n"541+ messageLevel.getName() + " " + msgText542+ "\n>>>>"543+ "\n\t actual:"544+ "\n<<<<\n" + logged + ">>>>\n");545} else {546verbose("Got expected results for "547+ desc + "\n<<<<\n" + logged + ">>>>\n");548}549}550}551}552553Supplier<String> fooSupplier = new Supplier<String>() {554@Override555public String get() {556return this.toString();557}558};559560for (Level loggerLevel : EnumSet.of(Level.INFO)) {561for (Level messageLevel : Level.values()) {562String desc = "logger.log(messageLevel, fooSupplier): loggerLevel="563+ loggerLevel+", messageLevel="+messageLevel;564sequencer.incrementAndGet();565logger.log(messageLevel, fooSupplier);566if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {567if (!ErrorStream.errorStream.peek().isEmpty()) {568throw new RuntimeException("unexpected event in queue for "569+ desc +": " + "\n\t" + ErrorStream.errorStream.drain());570}571} else {572String logged = ErrorStream.errorStream.drain();573if (!logged.contains("LoggerFinderLoaderTest testLogger")574|| !logged.contains(messageLevel.getName() + ": " + fooSupplier.get())) {575throw new RuntimeException("mismatch for " + desc576+ "\n\texpected:" + "\n<<<<\n"577+ "[date] LoggerFinderLoaderTest testLogger\n"578+ messageLevel.getName() + " " + fooSupplier.get()579+ "\n>>>>"580+ "\n\t actual:"581+ "\n<<<<\n" + logged + ">>>>\n");582} else {583verbose("Got expected results for "584+ desc + "\n<<<<\n" + logged + ">>>>\n");585}586}587}588}589590591String format = "two params [{1} {2}]";592Object arg1 = foo;593Object arg2 = msg;594for (Level loggerLevel : EnumSet.of(Level.INFO)) {595for (Level messageLevel : Level.values()) {596String desc = "logger.log(messageLevel, format, params...): loggerLevel="597+ loggerLevel+", messageLevel="+messageLevel;598sequencer.incrementAndGet();599logger.log(messageLevel, format, foo, msg);600if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {601if (!ErrorStream.errorStream.peek().isEmpty()) {602throw new RuntimeException("unexpected event in queue for "603+ desc +": " + "\n\t" + ErrorStream.errorStream.drain());604}605} else {606String logged = ErrorStream.errorStream.drain();607String msgFormat = loggerBundle == null ? format : loggerBundle.getString(format);608String text = java.text.MessageFormat.format(msgFormat, foo, msg);609if (!logged.contains("LoggerFinderLoaderTest testLogger")610|| !logged.contains(messageLevel.getName() + ": " + text)) {611throw new RuntimeException("mismatch for " + desc612+ "\n\texpected:" + "\n<<<<\n"613+ "[date] LoggerFinderLoaderTest testLogger\n"614+ messageLevel.getName() + " " + text615+ "\n>>>>"616+ "\n\t actual:"617+ "\n<<<<\n" + logged + ">>>>\n");618} else {619verbose("Got expected results for "620+ desc + "\n<<<<\n" + logged + ">>>>\n");621}622}623}624}625626Throwable thrown = new Exception("OK: log me!");627for (Level loggerLevel : EnumSet.of(Level.INFO)) {628for (Level messageLevel : Level.values()) {629String desc = "logger.log(messageLevel, \"blah\", thrown): loggerLevel="630+ loggerLevel+", messageLevel="+messageLevel;631sequencer.incrementAndGet();632logger.log(messageLevel, msg, thrown);633if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {634if (!ErrorStream.errorStream.peek().isEmpty()) {635throw new RuntimeException("unexpected event in queue for "636+ desc +": " + "\n\t" + ErrorStream.errorStream.drain());637}638} else {639String logged = ErrorStream.errorStream.drain();640ByteArrayOutputStream baos = new ByteArrayOutputStream();641thrown.printStackTrace(new PrintStream(baos));642String text = baos.toString();643String msgText = loggerBundle == null ? msg : loggerBundle.getString(msg);644if (!logged.contains("LoggerFinderLoaderTest testLogger")645|| !logged.contains(messageLevel.getName() + ": " + msgText)646|| !logged.contains(text)) {647throw new RuntimeException("mismatch for " + desc648+ "\n\texpected:" + "\n<<<<\n"649+ "[date] LoggerFinderLoaderTest testLogger\n"650+ messageLevel.getName() + " " + msgText +"\n"651+ text652+ ">>>>"653+ "\n\t actual:"654+ "\n<<<<\n" + logged + ">>>>\n");655} else {656verbose("Got expected results for "657+ desc + "\n<<<<\n" + logged + ">>>>\n");658}659}660}661}662663664for (Level loggerLevel : EnumSet.of(Level.INFO)) {665for (Level messageLevel : Level.values()) {666String desc = "logger.log(messageLevel, thrown, fooSupplier): loggerLevel="667+ loggerLevel+", messageLevel="+messageLevel;668sequencer.incrementAndGet();669logger.log(messageLevel, fooSupplier, thrown);670if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {671if (!ErrorStream.errorStream.peek().isEmpty()) {672throw new RuntimeException("unexpected event in queue for "673+ desc +": " + "\n\t" + ErrorStream.errorStream.drain());674}675} else {676String logged = ErrorStream.errorStream.drain();677ByteArrayOutputStream baos = new ByteArrayOutputStream();678thrown.printStackTrace(new PrintStream(baos));679String text = baos.toString();680if (!logged.contains("LoggerFinderLoaderTest testLogger")681|| !logged.contains(messageLevel.getName() + ": " + fooSupplier.get())682|| !logged.contains(text)) {683throw new RuntimeException("mismatch for " + desc684+ "\n\texpected:" + "\n<<<<\n"685+ "[date] LoggerFinderLoaderTest testLogger\n"686+ messageLevel.getName() + " " + fooSupplier.get() +"\n"687+ text688+ ">>>>"689+ "\n\t actual:"690+ "\n<<<<\n" + logged + ">>>>\n");691} else {692verbose("Got expected results for "693+ desc + "\n<<<<\n" + logged + ">>>>\n");694}695}696}697}698699ResourceBundle bundle = ResourceBundle.getBundle(MyBundle.class.getName());700for (Level loggerLevel : EnumSet.of(Level.INFO)) {701for (Level messageLevel : Level.values()) {702String desc = "logger.log(messageLevel, bundle, format, params...): loggerLevel="703+ loggerLevel+", messageLevel="+messageLevel;704sequencer.incrementAndGet();705logger.log(messageLevel, bundle, format, foo, msg);706if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {707if (!ErrorStream.errorStream.peek().isEmpty()) {708throw new RuntimeException("unexpected event in queue for "709+ desc +": " + "\n\t" + ErrorStream.errorStream.drain());710}711} else {712String logged = ErrorStream.errorStream.drain();713String text = java.text.MessageFormat.format(bundle.getString(format), foo, msg);714if (!logged.contains("LoggerFinderLoaderTest testLogger")715|| !logged.contains(messageLevel.getName() + ": " + text)) {716throw new RuntimeException("mismatch for " + desc717+ "\n\texpected:" + "\n<<<<\n"718+ "[date] LoggerFinderLoaderTest testLogger\n"719+ messageLevel.getName() + " " + text720+ "\n>>>>"721+ "\n\t actual:"722+ "\n<<<<\n" + logged + ">>>>\n");723} else {724verbose("Got expected results for "725+ desc + "\n<<<<\n" + logged + ">>>>\n");726}727}728}729}730731for (Level loggerLevel : EnumSet.of(Level.INFO)) {732for (Level messageLevel : Level.values()) {733String desc = "logger.log(messageLevel, bundle, \"blah\", thrown): loggerLevel="734+ loggerLevel+", messageLevel="+messageLevel;735sequencer.incrementAndGet();736logger.log(messageLevel, bundle, msg, thrown);737if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {738if (!ErrorStream.errorStream.peek().isEmpty()) {739throw new RuntimeException("unexpected event in queue for "740+ desc +": " + "\n\t" + ErrorStream.errorStream.drain());741}742} else {743String logged = ErrorStream.errorStream.drain();744String textMsg = bundle.getString(msg);745ByteArrayOutputStream baos = new ByteArrayOutputStream();746thrown.printStackTrace(new PrintStream(baos));747String text = baos.toString();748if (!logged.contains("LoggerFinderLoaderTest testLogger")749|| !logged.contains(messageLevel.getName() + ": " + textMsg)750|| !logged.contains(text)) {751throw new RuntimeException("mismatch for " + desc752+ "\n\texpected:" + "\n<<<<\n"753+ "[date] LoggerFinderLoaderTest testLogger\n"754+ messageLevel.getName() + " " + textMsg +"\n"755+ text756+ ">>>>"757+ "\n\t actual:"758+ "\n<<<<\n" + logged + ">>>>\n");759} else {760verbose("Got expected results for "761+ desc + "\n<<<<\n" + logged + ">>>>\n");762}763}764}765}766767}768769final static class PermissionsBuilder {770final Permissions perms;771public PermissionsBuilder() {772this(new Permissions());773}774public PermissionsBuilder(Permissions perms) {775this.perms = perms;776}777public PermissionsBuilder add(Permission p) {778perms.add(p);779return this;780}781public PermissionsBuilder addAll(PermissionCollection col) {782if (col != null) {783for (Enumeration<Permission> e = col.elements(); e.hasMoreElements(); ) {784perms.add(e.nextElement());785}786}787return this;788}789public Permissions toPermissions() {790final PermissionsBuilder builder = new PermissionsBuilder();791builder.addAll(perms);792return builder.perms;793}794}795796public static class SimplePolicy extends Policy {797final static RuntimePermission CONTROL = LOGGERFINDER_PERMISSION;798final static RuntimePermission ACCESS = new RuntimePermission("accessClassInPackage.jdk.internal.logger");799800final Permissions permissions;801final ThreadLocal<AtomicBoolean> allowControl;802final ThreadLocal<AtomicBoolean> allowAccess;803public SimplePolicy(ThreadLocal<AtomicBoolean> allowControl, ThreadLocal<AtomicBoolean> allowAccess) {804this.allowControl = allowControl;805this.allowAccess = allowAccess;806permissions = new Permissions();807permissions.add(new RuntimePermission("setIO"));808}809810Permissions getPermissions() {811if (allowControl.get().get() || allowAccess.get().get()) {812PermissionsBuilder builder = new PermissionsBuilder()813.addAll(permissions);814if (allowControl.get().get()) {815builder.add(CONTROL);816}817if (allowAccess.get().get()) {818builder.add(ACCESS);819}820return builder.toPermissions();821}822return permissions;823}824825@Override826public boolean implies(ProtectionDomain domain, Permission permission) {827return getPermissions().implies(permission) ||828DEFAULT_POLICY.implies(domain, permission);829}830831@Override832public PermissionCollection getPermissions(CodeSource codesource) {833return new PermissionsBuilder().addAll(getPermissions()).toPermissions();834}835836@Override837public PermissionCollection getPermissions(ProtectionDomain domain) {838return new PermissionsBuilder().addAll(getPermissions()).toPermissions();839}840}841}842843844