2015-11-20 19:26:16 +01:00
/ *
* Copyright ( c ) 2015 , Oracle and / or its affiliates . All rights reserved .
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER .
*
* This code is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License version 2 only , as
* published by the Free Software Foundation .
*
* This code is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
* version 2 for more details ( a copy is included in the LICENSE file that
* accompanied this code ) .
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work ; if not , write to the Free Software Foundation ,
* Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA .
*
* Please contact Oracle , 500 Oracle Parkway , Redwood Shores , CA 94065 USA
* or visit www . oracle . com if you need additional information or have any
* questions .
* /
import java.io.ByteArrayOutputStream ;
import java.io.IOException ;
import java.io.PrintStream ;
import java.io.UncheckedIOException ;
import java.security.AccessControlException ;
import java.security.CodeSource ;
import java.security.Permission ;
import java.security.PermissionCollection ;
import java.security.Permissions ;
import java.security.Policy ;
import java.security.ProtectionDomain ;
import java.util.Collections ;
import java.util.Enumeration ;
import java.util.HashMap ;
import java.util.Map ;
import java.util.ResourceBundle ;
import java.util.stream.Stream ;
import java.util.concurrent.ConcurrentHashMap ;
import java.util.concurrent.atomic.AtomicBoolean ;
import java.util.concurrent.atomic.AtomicLong ;
import java.util.function.Supplier ;
import java.lang.System.LoggerFinder ;
import java.lang.System.Logger ;
import java.lang.System.Logger.Level ;
import java.security.AccessController ;
import java.security.PrivilegedAction ;
import java.util.EnumSet ;
import java.util.Iterator ;
import java.util.Locale ;
import java.util.ServiceConfigurationError ;
import java.util.ServiceLoader ;
import java.util.concurrent.atomic.AtomicReference ;
import jdk.internal.logger.SimpleConsoleLogger ;
2016-04-27 18:04:16 +02:00
import java.lang.reflect.Module ;
2015-11-20 19:26:16 +01:00
/ * *
* @test
* @bug 8140364
* @summary JDK implementation specific unit test for LoggerFinderLoader .
* Tests the behavior of LoggerFinderLoader with respect to the
* value of the internal diagnosability switches . Also test the
* DefaultLoggerFinder and SimpleConsoleLogger implementation .
* @modules java . base / sun . util . logging
* java . base / jdk . internal . logger
* @build AccessSystemLogger LoggerFinderLoaderTest CustomSystemClassLoader
* @run driver AccessSystemLogger
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader LoggerFinderLoaderTest NOSECURITY
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader LoggerFinderLoaderTest NOPERMISSIONS
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader LoggerFinderLoaderTest WITHPERMISSIONS
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Dtest . fails = true LoggerFinderLoaderTest NOSECURITY
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Dtest . fails = true LoggerFinderLoaderTest NOPERMISSIONS
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Dtest . fails = true LoggerFinderLoaderTest WITHPERMISSIONS
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Dtest . fails = true - Djdk . logger . finder . error = ERROR LoggerFinderLoaderTest NOSECURITY
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Dtest . fails = true - Djdk . logger . finder . error = ERROR LoggerFinderLoaderTest NOPERMISSIONS
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Dtest . fails = true - Djdk . logger . finder . error = ERROR LoggerFinderLoaderTest WITHPERMISSIONS
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Dtest . fails = true - Djdk . logger . finder . error = DEBUG LoggerFinderLoaderTest NOSECURITY
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Dtest . fails = true - Djdk . logger . finder . error = DEBUG LoggerFinderLoaderTest NOPERMISSIONS
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Dtest . fails = true - Djdk . logger . finder . error = DEBUG LoggerFinderLoaderTest WITHPERMISSIONS
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Dtest . fails = true - Djdk . logger . finder . error = QUIET LoggerFinderLoaderTest NOSECURITY
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Dtest . fails = true - Djdk . logger . finder . error = QUIET LoggerFinderLoaderTest NOPERMISSIONS
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Dtest . fails = true - Djdk . logger . finder . error = QUIET LoggerFinderLoaderTest WITHPERMISSIONS
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Djdk . logger . finder . singleton = true LoggerFinderLoaderTest NOSECURITY
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Djdk . logger . finder . singleton = true LoggerFinderLoaderTest NOPERMISSIONS
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Djdk . logger . finder . singleton = true LoggerFinderLoaderTest WITHPERMISSIONS
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Djdk . logger . finder . singleton = true - Djdk . logger . finder . error = ERROR LoggerFinderLoaderTest NOSECURITY
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Djdk . logger . finder . singleton = true - Djdk . logger . finder . error = ERROR LoggerFinderLoaderTest NOPERMISSIONS
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Djdk . logger . finder . singleton = true - Djdk . logger . finder . error = ERROR LoggerFinderLoaderTest WITHPERMISSIONS
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Djdk . logger . finder . singleton = true - Djdk . logger . finder . error = DEBUG LoggerFinderLoaderTest NOSECURITY
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Djdk . logger . finder . singleton = true - Djdk . logger . finder . error = DEBUG LoggerFinderLoaderTest NOPERMISSIONS
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Djdk . logger . finder . singleton = true - Djdk . logger . finder . error = DEBUG LoggerFinderLoaderTest WITHPERMISSIONS
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Djdk . logger . finder . singleton = true - Djdk . logger . finder . error = QUIET LoggerFinderLoaderTest NOSECURITY
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Djdk . logger . finder . singleton = true - Djdk . logger . finder . error = QUIET LoggerFinderLoaderTest NOPERMISSIONS
* @run main / othervm - Xbootclasspath / a : boot - Djava . system . class . loader = CustomSystemClassLoader - Djdk . logger . finder . singleton = true - Djdk . logger . finder . error = QUIET LoggerFinderLoaderTest WITHPERMISSIONS
* @author danielfuchs
* /
public class LoggerFinderLoaderTest {
static final RuntimePermission LOGGERFINDER_PERMISSION =
new RuntimePermission ( " loggerFinder " ) ;
final static boolean VERBOSE = false ;
static final ThreadLocal < AtomicBoolean > allowControl = new ThreadLocal < AtomicBoolean > ( ) {
@Override
protected AtomicBoolean initialValue ( ) {
return new AtomicBoolean ( false ) ;
}
} ;
static final ThreadLocal < AtomicBoolean > allowAccess = new ThreadLocal < AtomicBoolean > ( ) {
@Override
protected AtomicBoolean initialValue ( ) {
return new AtomicBoolean ( false ) ;
}
} ;
final static AccessSystemLogger accessSystemLogger = new AccessSystemLogger ( ) ;
static final Class < ? > [ ] providerClass ;
static {
try {
providerClass = new Class < ? > [ ] {
ClassLoader . getSystemClassLoader ( ) . loadClass ( " LoggerFinderLoaderTest$BaseLoggerFinder " ) ,
ClassLoader . getSystemClassLoader ( ) . loadClass ( " LoggerFinderLoaderTest$BaseLoggerFinder2 " )
} ;
} catch ( ClassNotFoundException ex ) {
throw new ExceptionInInitializerError ( ex ) ;
}
}
/ * *
* What our test provider needs to implement .
* /
public static interface TestLoggerFinder {
public final static AtomicBoolean fails = new AtomicBoolean ( ) ;
public final static AtomicReference < String > conf = new AtomicReference < > ( " " ) ;
public final static AtomicLong sequencer = new AtomicLong ( ) ;
public final ConcurrentHashMap < String , LoggerImpl > system = new ConcurrentHashMap < > ( ) ;
public final ConcurrentHashMap < String , LoggerImpl > user = new ConcurrentHashMap < > ( ) ;
public class LoggerImpl implements System . Logger {
final String name ;
final Logger logger ;
public LoggerImpl ( String name , Logger logger ) {
this . name = name ;
this . logger = logger ;
}
@Override
public String getName ( ) {
return name ;
}
@Override
public boolean isLoggable ( Logger . Level level ) {
return logger . isLoggable ( level ) ;
}
@Override
public void log ( Logger . Level level , ResourceBundle bundle , String key , Throwable thrown ) {
logger . log ( level , bundle , key , thrown ) ;
}
@Override
public void log ( Logger . Level level , ResourceBundle bundle , String format , Object . . . params ) {
logger . log ( level , bundle , format , params ) ;
}
}
2016-04-27 18:04:16 +02:00
public Logger getLogger ( String name , Module caller ) ;
public Logger getLocalizedLogger ( String name , ResourceBundle bundle , Module caller ) ;
2015-11-20 19:26:16 +01:00
}
public static class BaseLoggerFinder extends LoggerFinder implements TestLoggerFinder {
static final RuntimePermission LOGGERFINDER_PERMISSION =
new RuntimePermission ( " loggerFinder " ) ;
public BaseLoggerFinder ( ) {
if ( fails . get ( ) ) {
throw new RuntimeException ( " Simulate exception while loading provider " ) ;
}
}
System . Logger createSimpleLogger ( String name ) {
2016-03-25 17:12:18 +01:00
PrivilegedAction < System . Logger > pa = ( ) - > SimpleConsoleLogger . makeSimpleLogger ( name ) ;
2015-11-20 19:26:16 +01:00
return AccessController . doPrivileged ( pa ) ;
}
@Override
2016-04-27 18:04:16 +02:00
public Logger getLogger ( String name , Module caller ) {
2015-11-20 19:26:16 +01:00
SecurityManager sm = System . getSecurityManager ( ) ;
if ( sm ! = null ) {
sm . checkPermission ( LOGGERFINDER_PERMISSION ) ;
}
PrivilegedAction < ClassLoader > pa = ( ) - > caller . getClassLoader ( ) ;
ClassLoader callerLoader = AccessController . doPrivileged ( pa ) ;
if ( callerLoader = = null ) {
return system . computeIfAbsent ( name , ( n ) - > new LoggerImpl ( n , createSimpleLogger ( name ) ) ) ;
} else {
return user . computeIfAbsent ( name , ( n ) - > new LoggerImpl ( n , createSimpleLogger ( name ) ) ) ;
}
}
}
public static class BaseLoggerFinder2 extends LoggerFinder implements TestLoggerFinder {
static final RuntimePermission LOGGERFINDER_PERMISSION =
new RuntimePermission ( " loggerFinder " ) ;
public BaseLoggerFinder2 ( ) {
throw new ServiceConfigurationError ( " Should not come here " ) ;
}
@Override
2016-04-27 18:04:16 +02:00
public Logger getLogger ( String name , Module caller ) {
2015-11-20 19:26:16 +01:00
throw new ServiceConfigurationError ( " Should not come here " ) ;
}
}
public static class MyBundle extends ResourceBundle {
final ConcurrentHashMap < String , String > map = new ConcurrentHashMap < > ( ) ;
@Override
protected Object handleGetObject ( String key ) {
if ( key . contains ( " (translated) " ) ) {
throw new RuntimeException ( " Unexpected key: " + key ) ;
}
return map . computeIfAbsent ( key , k - > k . toUpperCase ( Locale . ROOT ) + " (translated) " ) ;
}
@Override
public Enumeration < String > getKeys ( ) {
return Collections . enumeration ( map . keySet ( ) ) ;
}
}
public static class MyLoggerBundle extends MyBundle {
}
static enum TestCases { NOSECURITY , NOPERMISSIONS , WITHPERMISSIONS } ;
static void setSecurityManager ( ) {
if ( System . getSecurityManager ( ) = = null ) {
Policy . setPolicy ( new SimplePolicy ( allowControl , allowAccess ) ) ;
System . setSecurityManager ( new SecurityManager ( ) ) ;
}
}
static LoggerFinder getLoggerFinder ( Class < ? > expectedClass ,
String errorPolicy , boolean singleton ) {
LoggerFinder provider = null ;
try {
TestLoggerFinder . sequencer . incrementAndGet ( ) ;
provider = LoggerFinder . getLoggerFinder ( ) ;
if ( TestLoggerFinder . fails . get ( ) | | singleton ) {
if ( " ERROR " . equals ( errorPolicy . toUpperCase ( Locale . ROOT ) ) ) {
throw new RuntimeException ( " Expected exception not thrown " ) ;
} else if ( " WARNING " . equals ( errorPolicy . toUpperCase ( Locale . ROOT ) ) ) {
String warning = ErrorStream . errorStream . peek ( ) ;
if ( ! warning . contains ( " WARNING: Failed to instantiate LoggerFinder provider; Using default. " ) ) {
throw new RuntimeException ( " Expected message not found. Error stream contained: " + warning ) ;
}
} else if ( " DEBUG " . equals ( errorPolicy . toUpperCase ( Locale . ROOT ) ) ) {
String warning = ErrorStream . errorStream . peek ( ) ;
if ( ! warning . contains ( " WARNING: Failed to instantiate LoggerFinder provider; Using default. " ) ) {
throw new RuntimeException ( " Expected message not found. Error stream contained: " + warning ) ;
}
if ( ! warning . contains ( " WARNING: Exception raised trying to instantiate LoggerFinder " ) ) {
throw new RuntimeException ( " Expected message not found. Error stream contained: " + warning ) ;
}
if ( TestLoggerFinder . fails . get ( ) ) {
if ( ! warning . contains ( " java.util.ServiceConfigurationError: java.lang.System$LoggerFinder: Provider LoggerFinderLoaderTest$BaseLoggerFinder could not be instantiated " ) ) {
throw new RuntimeException ( " Expected message not found. Error stream contained: " + warning ) ;
}
} else if ( singleton ) {
if ( ! warning . contains ( " java.util.ServiceConfigurationError: More than on LoggerFinder implementation " ) ) {
throw new RuntimeException ( " Expected message not found. Error stream contained: " + warning ) ;
}
}
} else if ( " QUIET " . equals ( errorPolicy . toUpperCase ( Locale . ROOT ) ) ) {
if ( ! ErrorStream . errorStream . peek ( ) . isEmpty ( ) ) {
throw new RuntimeException ( " Unexpected error message found: "
+ ErrorStream . errorStream . peek ( ) ) ;
}
}
}
} catch ( AccessControlException a ) {
throw a ;
} catch ( Throwable t ) {
if ( TestLoggerFinder . fails . get ( ) | | singleton ) {
// must check System.err
if ( " ERROR " . equals ( errorPolicy . toUpperCase ( Locale . ROOT ) ) ) {
provider = LoggerFinder . getLoggerFinder ( ) ;
} else {
Throwable orig = t . getCause ( ) ;
while ( orig ! = null & & orig . getCause ( ) ! = null ) orig = orig . getCause ( ) ;
if ( orig ! = null ) orig . printStackTrace ( ErrorStream . err ) ;
throw new RuntimeException ( " Unexpected exception: " + t , t ) ;
}
} else {
throw new RuntimeException ( " Unexpected exception: " + t , t ) ;
}
}
expectedClass . cast ( provider ) ;
ErrorStream . errorStream . store ( ) ;
System . out . println ( " *** Actual LoggerFinder class is: " + provider . getClass ( ) . getName ( ) ) ;
return provider ;
}
static class ErrorStream extends PrintStream {
static AtomicBoolean forward = new AtomicBoolean ( ) ;
ByteArrayOutputStream out ;
String saved = " " ;
public ErrorStream ( ByteArrayOutputStream out ) {
super ( out ) ;
this . out = out ;
}
@Override
public void write ( int b ) {
super . write ( b ) ;
if ( forward . get ( ) ) err . write ( b ) ;
}
@Override
public void write ( byte [ ] b ) throws IOException {
super . write ( b ) ;
if ( forward . get ( ) ) err . write ( b ) ;
}
@Override
public void write ( byte [ ] buf , int off , int len ) {
super . write ( buf , off , len ) ;
if ( forward . get ( ) ) err . write ( buf , off , len ) ;
}
public String peek ( ) {
flush ( ) ;
return out . toString ( ) ;
}
public String drain ( ) {
flush ( ) ;
String res = out . toString ( ) ;
out . reset ( ) ;
return res ;
}
public void store ( ) {
flush ( ) ;
saved = out . toString ( ) ;
out . reset ( ) ;
}
public void restore ( ) {
out . reset ( ) ;
try {
out . write ( saved . getBytes ( ) ) ;
} catch ( IOException io ) {
throw new UncheckedIOException ( io ) ;
}
}
static final PrintStream err = System . err ;
static final ErrorStream errorStream = new ErrorStream ( new ByteArrayOutputStream ( ) ) ;
}
private static StringBuilder appendProperty ( StringBuilder b , String name ) {
String value = System . getProperty ( name ) ;
if ( value = = null ) return b ;
return b . append ( name ) . append ( " = " ) . append ( value ) . append ( '\n' ) ;
}
public static void main ( String [ ] args ) {
if ( args . length = = 0 ) {
args = new String [ ] {
" NOSECURITY " ,
" NOPERMISSIONS " ,
" WITHPERMISSIONS "
} ;
}
Locale . setDefault ( Locale . ENGLISH ) ;
System . setErr ( ErrorStream . errorStream ) ;
System . setProperty ( " jdk.logger.packages " , TestLoggerFinder . LoggerImpl . class . getName ( ) ) ;
//System.setProperty("jdk.logger.finder.error", "ERROR");
//System.setProperty("jdk.logger.finder.singleton", "true");
//System.setProperty("test.fails", "true");
TestLoggerFinder . fails . set ( Boolean . getBoolean ( " test.fails " ) ) ;
StringBuilder c = new StringBuilder ( ) ;
appendProperty ( c , " jdk.logger.packages " ) ;
appendProperty ( c , " jdk.logger.finder.error " ) ;
appendProperty ( c , " jdk.logger.finder.singleton " ) ;
appendProperty ( c , " test.fails " ) ;
TestLoggerFinder . conf . set ( c . toString ( ) ) ;
try {
test ( args ) ;
} finally {
try {
System . setErr ( ErrorStream . err ) ;
} catch ( Error | RuntimeException x ) {
x . printStackTrace ( ErrorStream . err ) ;
}
}
}
public static void test ( String [ ] args ) {
final String errorPolicy = System . getProperty ( " jdk.logger.finder.error " , " WARNING " ) ;
final Boolean ensureSingleton = Boolean . getBoolean ( " jdk.logger.finder.singleton " ) ;
final Class < ? > expectedClass =
TestLoggerFinder . fails . get ( ) | | ensureSingleton
? jdk . internal . logger . DefaultLoggerFinder . class
: TestLoggerFinder . class ;
System . out . println ( " Declared provider class: " + providerClass [ 0 ]
+ " [ " + providerClass [ 0 ] . getClassLoader ( ) + " ] " ) ;
if ( ! TestLoggerFinder . fails . get ( ) ) {
ServiceLoader < LoggerFinder > serviceLoader =
ServiceLoader . load ( LoggerFinder . class , ClassLoader . getSystemClassLoader ( ) ) ;
Iterator < LoggerFinder > iterator = serviceLoader . iterator ( ) ;
Object firstProvider = iterator . next ( ) ;
if ( ! firstProvider . getClass ( ) . getName ( ) . equals ( " LoggerFinderLoaderTest$BaseLoggerFinder " ) ) {
throw new RuntimeException ( " Unexpected provider: " + firstProvider . getClass ( ) . getName ( ) ) ;
}
if ( ! iterator . hasNext ( ) ) {
throw new RuntimeException ( " Expected two providers " ) ;
}
}
Stream . of ( args ) . map ( TestCases : : valueOf ) . forEach ( ( testCase ) - > {
LoggerFinder provider ;
ErrorStream . errorStream . restore ( ) ;
switch ( testCase ) {
case NOSECURITY :
System . out . println ( " \ n*** Without Security Manager \ n " ) ;
System . out . println ( TestLoggerFinder . conf . get ( ) ) ;
provider = getLoggerFinder ( expectedClass , errorPolicy , ensureSingleton ) ;
test ( provider , true ) ;
System . out . println ( " Tetscase count: " + TestLoggerFinder . sequencer . get ( ) ) ;
break ;
case NOPERMISSIONS :
System . out . println ( " \ n*** With Security Manager, without permissions \ n " ) ;
System . out . println ( TestLoggerFinder . conf . get ( ) ) ;
setSecurityManager ( ) ;
try {
provider = getLoggerFinder ( expectedClass , errorPolicy , ensureSingleton ) ;
throw new RuntimeException ( " Expected exception not raised " ) ;
} catch ( AccessControlException x ) {
if ( ! LOGGERFINDER_PERMISSION . equals ( x . getPermission ( ) ) ) {
throw new RuntimeException ( " Unexpected permission check " , x ) ;
}
final boolean control = allowControl . get ( ) . get ( ) ;
try {
allowControl . get ( ) . set ( true ) ;
provider = getLoggerFinder ( expectedClass , errorPolicy , ensureSingleton ) ;
} finally {
allowControl . get ( ) . set ( control ) ;
}
}
test ( provider , false ) ;
System . out . println ( " Tetscase count: " + TestLoggerFinder . sequencer . get ( ) ) ;
break ;
case WITHPERMISSIONS :
System . out . println ( " \ n*** With Security Manager, with control permission \ n " ) ;
System . out . println ( TestLoggerFinder . conf . get ( ) ) ;
setSecurityManager ( ) ;
final boolean control = allowControl . get ( ) . get ( ) ;
try {
allowControl . get ( ) . set ( true ) ;
provider = getLoggerFinder ( expectedClass , errorPolicy , ensureSingleton ) ;
test ( provider , true ) ;
} finally {
allowControl . get ( ) . set ( control ) ;
}
break ;
default :
throw new RuntimeException ( " Unknown test case: " + testCase ) ;
}
} ) ;
System . out . println ( " \ nPASSED: Tested " + TestLoggerFinder . sequencer . get ( ) + " cases. " ) ;
}
public static void test ( LoggerFinder provider , boolean hasRequiredPermissions ) {
ResourceBundle loggerBundle = ResourceBundle . getBundle ( MyLoggerBundle . class . getName ( ) ) ;
final Map < Logger , String > loggerDescMap = new HashMap < > ( ) ;
System . Logger sysLogger = accessSystemLogger . getLogger ( " foo " ) ;
loggerDescMap . put ( sysLogger , " accessSystemLogger.getLogger( \" foo \" ) " ) ;
System . Logger localizedSysLogger = accessSystemLogger . getLogger ( " fox " , loggerBundle ) ;
loggerDescMap . put ( localizedSysLogger , " accessSystemLogger.getLogger( \" fox \" , loggerBundle) " ) ;
System . Logger appLogger = System . getLogger ( " bar " ) ;
loggerDescMap . put ( appLogger , " System.getLogger( \" bar \" ) " ) ;
System . Logger localizedAppLogger = System . getLogger ( " baz " , loggerBundle ) ;
loggerDescMap . put ( localizedAppLogger , " System.getLogger( \" baz \" , loggerBundle) " ) ;
testLogger ( provider , loggerDescMap , " foo " , null , sysLogger ) ;
testLogger ( provider , loggerDescMap , " foo " , loggerBundle , localizedSysLogger ) ;
testLogger ( provider , loggerDescMap , " foo " , null , appLogger ) ;
testLogger ( provider , loggerDescMap , " foo " , loggerBundle , localizedAppLogger ) ;
}
public static class Foo {
}
static void verbose ( String msg ) {
if ( VERBOSE ) {
System . out . println ( msg ) ;
}
}
// Calls the 8 methods defined on Logger and verify the
// parameters received by the underlying TestProvider.LoggerImpl
// logger.
private static void testLogger ( LoggerFinder provider ,
Map < Logger , String > loggerDescMap ,
String name ,
ResourceBundle loggerBundle ,
Logger logger ) {
System . out . println ( " Testing " + loggerDescMap . get ( logger ) + " [ " + logger + " ] " ) ;
AtomicLong sequencer = TestLoggerFinder . sequencer ;
Foo foo = new Foo ( ) ;
String fooMsg = foo . toString ( ) ;
for ( Level loggerLevel : EnumSet . of ( Level . INFO ) ) {
for ( Level messageLevel : Level . values ( ) ) {
ErrorStream . errorStream . drain ( ) ;
String desc = " logger.log(messageLevel, foo): loggerLevel= "
+ loggerLevel + " , messageLevel= " + messageLevel ;
sequencer . incrementAndGet ( ) ;
logger . log ( messageLevel , foo ) ;
if ( loggerLevel = = Level . OFF | | messageLevel = = Level . OFF | | messageLevel . compareTo ( loggerLevel ) < 0 ) {
if ( ! ErrorStream . errorStream . peek ( ) . isEmpty ( ) ) {
throw new RuntimeException ( " unexpected event in queue for "
+ desc + " : " + " \ n \ t " + ErrorStream . errorStream . drain ( ) ) ;
}
} else {
String logged = ErrorStream . errorStream . drain ( ) ;
if ( ! logged . contains ( " LoggerFinderLoaderTest testLogger " )
| | ! logged . contains ( messageLevel . getName ( ) + " : " + fooMsg ) ) {
throw new RuntimeException ( " mismatch for " + desc
+ " \ n \ texpected: " + " \ n<<<< \ n "
+ " [date] LoggerFinderLoaderTest testLogger \ n "
+ messageLevel . getName ( ) + " " + fooMsg
+ " \ n>>>> "
+ " \ n \ t actual: "
+ " \ n<<<< \ n " + logged + " >>>> \ n " ) ;
} else {
verbose ( " Got expected results for "
+ desc + " \ n<<<< \ n " + logged + " >>>> \ n " ) ;
}
}
}
}
String msg = " blah " ;
for ( Level loggerLevel : EnumSet . of ( Level . INFO ) ) {
for ( Level messageLevel : Level . values ( ) ) {
String desc = " logger.log(messageLevel, \" blah \" ): loggerLevel= "
+ loggerLevel + " , messageLevel= " + messageLevel ;
sequencer . incrementAndGet ( ) ;
logger . log ( messageLevel , msg ) ;
if ( loggerLevel = = Level . OFF | | messageLevel = = Level . OFF | | messageLevel . compareTo ( loggerLevel ) < 0 ) {
if ( ! ErrorStream . errorStream . peek ( ) . isEmpty ( ) ) {
throw new RuntimeException ( " unexpected event in queue for "
+ desc + " : " + " \ n \ t " + ErrorStream . errorStream . drain ( ) ) ;
}
} else {
String logged = ErrorStream . errorStream . drain ( ) ;
String msgText = loggerBundle = = null ? msg : loggerBundle . getString ( msg ) ;
if ( ! logged . contains ( " LoggerFinderLoaderTest testLogger " )
| | ! logged . contains ( messageLevel . getName ( ) + " : " + msgText ) ) {
throw new RuntimeException ( " mismatch for " + desc
+ " \ n \ texpected: " + " \ n<<<< \ n "
+ " [date] LoggerFinderLoaderTest testLogger \ n "
+ messageLevel . getName ( ) + " " + msgText
+ " \ n>>>> "
+ " \ n \ t actual: "
+ " \ n<<<< \ n " + logged + " >>>> \ n " ) ;
} else {
verbose ( " Got expected results for "
+ desc + " \ n<<<< \ n " + logged + " >>>> \ n " ) ;
}
}
}
}
Supplier < String > fooSupplier = new Supplier < String > ( ) {
@Override
public String get ( ) {
return this . toString ( ) ;
}
} ;
for ( Level loggerLevel : EnumSet . of ( Level . INFO ) ) {
for ( Level messageLevel : Level . values ( ) ) {
String desc = " logger.log(messageLevel, fooSupplier): loggerLevel= "
+ loggerLevel + " , messageLevel= " + messageLevel ;
sequencer . incrementAndGet ( ) ;
logger . log ( messageLevel , fooSupplier ) ;
if ( loggerLevel = = Level . OFF | | messageLevel = = Level . OFF | | messageLevel . compareTo ( loggerLevel ) < 0 ) {
if ( ! ErrorStream . errorStream . peek ( ) . isEmpty ( ) ) {
throw new RuntimeException ( " unexpected event in queue for "
+ desc + " : " + " \ n \ t " + ErrorStream . errorStream . drain ( ) ) ;
}
} else {
String logged = ErrorStream . errorStream . drain ( ) ;
if ( ! logged . contains ( " LoggerFinderLoaderTest testLogger " )
| | ! logged . contains ( messageLevel . getName ( ) + " : " + fooSupplier . get ( ) ) ) {
throw new RuntimeException ( " mismatch for " + desc
+ " \ n \ texpected: " + " \ n<<<< \ n "
+ " [date] LoggerFinderLoaderTest testLogger \ n "
+ messageLevel . getName ( ) + " " + fooSupplier . get ( )
+ " \ n>>>> "
+ " \ n \ t actual: "
+ " \ n<<<< \ n " + logged + " >>>> \ n " ) ;
} else {
verbose ( " Got expected results for "
+ desc + " \ n<<<< \ n " + logged + " >>>> \ n " ) ;
}
}
}
}
String format = " two params [{1} {2}] " ;
Object arg1 = foo ;
Object arg2 = msg ;
for ( Level loggerLevel : EnumSet . of ( Level . INFO ) ) {
for ( Level messageLevel : Level . values ( ) ) {
String desc = " logger.log(messageLevel, format, params...): loggerLevel= "
+ loggerLevel + " , messageLevel= " + messageLevel ;
sequencer . incrementAndGet ( ) ;
logger . log ( messageLevel , format , foo , msg ) ;
if ( loggerLevel = = Level . OFF | | messageLevel = = Level . OFF | | messageLevel . compareTo ( loggerLevel ) < 0 ) {
if ( ! ErrorStream . errorStream . peek ( ) . isEmpty ( ) ) {
throw new RuntimeException ( " unexpected event in queue for "
+ desc + " : " + " \ n \ t " + ErrorStream . errorStream . drain ( ) ) ;
}
} else {
String logged = ErrorStream . errorStream . drain ( ) ;
String msgFormat = loggerBundle = = null ? format : loggerBundle . getString ( format ) ;
String text = java . text . MessageFormat . format ( msgFormat , foo , msg ) ;
if ( ! logged . contains ( " LoggerFinderLoaderTest testLogger " )
| | ! logged . contains ( messageLevel . getName ( ) + " : " + text ) ) {
throw new RuntimeException ( " mismatch for " + desc
+ " \ n \ texpected: " + " \ n<<<< \ n "
+ " [date] LoggerFinderLoaderTest testLogger \ n "
+ messageLevel . getName ( ) + " " + text
+ " \ n>>>> "
+ " \ n \ t actual: "
+ " \ n<<<< \ n " + logged + " >>>> \ n " ) ;
} else {
verbose ( " Got expected results for "
+ desc + " \ n<<<< \ n " + logged + " >>>> \ n " ) ;
}
}
}
}
Throwable thrown = new Exception ( " OK: log me! " ) ;
for ( Level loggerLevel : EnumSet . of ( Level . INFO ) ) {
for ( Level messageLevel : Level . values ( ) ) {
String desc = " logger.log(messageLevel, \" blah \" , thrown): loggerLevel= "
+ loggerLevel + " , messageLevel= " + messageLevel ;
sequencer . incrementAndGet ( ) ;
logger . log ( messageLevel , msg , thrown ) ;
if ( loggerLevel = = Level . OFF | | messageLevel = = Level . OFF | | messageLevel . compareTo ( loggerLevel ) < 0 ) {
if ( ! ErrorStream . errorStream . peek ( ) . isEmpty ( ) ) {
throw new RuntimeException ( " unexpected event in queue for "
+ desc + " : " + " \ n \ t " + ErrorStream . errorStream . drain ( ) ) ;
}
} else {
String logged = ErrorStream . errorStream . drain ( ) ;
ByteArrayOutputStream baos = new ByteArrayOutputStream ( ) ;
thrown . printStackTrace ( new PrintStream ( baos ) ) ;
String text = baos . toString ( ) ;
String msgText = loggerBundle = = null ? msg : loggerBundle . getString ( msg ) ;
if ( ! logged . contains ( " LoggerFinderLoaderTest testLogger " )
| | ! logged . contains ( messageLevel . getName ( ) + " : " + msgText )
| | ! logged . contains ( text ) ) {
throw new RuntimeException ( " mismatch for " + desc
+ " \ n \ texpected: " + " \ n<<<< \ n "
+ " [date] LoggerFinderLoaderTest testLogger \ n "
+ messageLevel . getName ( ) + " " + msgText + " \ n "
+ text
+ " >>>> "
+ " \ n \ t actual: "
+ " \ n<<<< \ n " + logged + " >>>> \ n " ) ;
} else {
verbose ( " Got expected results for "
+ desc + " \ n<<<< \ n " + logged + " >>>> \ n " ) ;
}
}
}
}
for ( Level loggerLevel : EnumSet . of ( Level . INFO ) ) {
for ( Level messageLevel : Level . values ( ) ) {
String desc = " logger.log(messageLevel, thrown, fooSupplier): loggerLevel= "
+ loggerLevel + " , messageLevel= " + messageLevel ;
sequencer . incrementAndGet ( ) ;
logger . log ( messageLevel , fooSupplier , thrown ) ;
if ( loggerLevel = = Level . OFF | | messageLevel = = Level . OFF | | messageLevel . compareTo ( loggerLevel ) < 0 ) {
if ( ! ErrorStream . errorStream . peek ( ) . isEmpty ( ) ) {
throw new RuntimeException ( " unexpected event in queue for "
+ desc + " : " + " \ n \ t " + ErrorStream . errorStream . drain ( ) ) ;
}
} else {
String logged = ErrorStream . errorStream . drain ( ) ;
ByteArrayOutputStream baos = new ByteArrayOutputStream ( ) ;
thrown . printStackTrace ( new PrintStream ( baos ) ) ;
String text = baos . toString ( ) ;
if ( ! logged . contains ( " LoggerFinderLoaderTest testLogger " )
| | ! logged . contains ( messageLevel . getName ( ) + " : " + fooSupplier . get ( ) )
| | ! logged . contains ( text ) ) {
throw new RuntimeException ( " mismatch for " + desc
+ " \ n \ texpected: " + " \ n<<<< \ n "
+ " [date] LoggerFinderLoaderTest testLogger \ n "
+ messageLevel . getName ( ) + " " + fooSupplier . get ( ) + " \ n "
+ text
+ " >>>> "
+ " \ n \ t actual: "
+ " \ n<<<< \ n " + logged + " >>>> \ n " ) ;
} else {
verbose ( " Got expected results for "
+ desc + " \ n<<<< \ n " + logged + " >>>> \ n " ) ;
}
}
}
}
ResourceBundle bundle = ResourceBundle . getBundle ( MyBundle . class . getName ( ) ) ;
for ( Level loggerLevel : EnumSet . of ( Level . INFO ) ) {
for ( Level messageLevel : Level . values ( ) ) {
String desc = " logger.log(messageLevel, bundle, format, params...): loggerLevel= "
+ loggerLevel + " , messageLevel= " + messageLevel ;
sequencer . incrementAndGet ( ) ;
logger . log ( messageLevel , bundle , format , foo , msg ) ;
if ( loggerLevel = = Level . OFF | | messageLevel = = Level . OFF | | messageLevel . compareTo ( loggerLevel ) < 0 ) {
if ( ! ErrorStream . errorStream . peek ( ) . isEmpty ( ) ) {
throw new RuntimeException ( " unexpected event in queue for "
+ desc + " : " + " \ n \ t " + ErrorStream . errorStream . drain ( ) ) ;
}
} else {
String logged = ErrorStream . errorStream . drain ( ) ;
String text = java . text . MessageFormat . format ( bundle . getString ( format ) , foo , msg ) ;
if ( ! logged . contains ( " LoggerFinderLoaderTest testLogger " )
| | ! logged . contains ( messageLevel . getName ( ) + " : " + text ) ) {
throw new RuntimeException ( " mismatch for " + desc
+ " \ n \ texpected: " + " \ n<<<< \ n "
+ " [date] LoggerFinderLoaderTest testLogger \ n "
+ messageLevel . getName ( ) + " " + text
+ " \ n>>>> "
+ " \ n \ t actual: "
+ " \ n<<<< \ n " + logged + " >>>> \ n " ) ;
} else {
verbose ( " Got expected results for "
+ desc + " \ n<<<< \ n " + logged + " >>>> \ n " ) ;
}
}
}
}
for ( Level loggerLevel : EnumSet . of ( Level . INFO ) ) {
for ( Level messageLevel : Level . values ( ) ) {
String desc = " logger.log(messageLevel, bundle, \" blah \" , thrown): loggerLevel= "
+ loggerLevel + " , messageLevel= " + messageLevel ;
sequencer . incrementAndGet ( ) ;
logger . log ( messageLevel , bundle , msg , thrown ) ;
if ( loggerLevel = = Level . OFF | | messageLevel = = Level . OFF | | messageLevel . compareTo ( loggerLevel ) < 0 ) {
if ( ! ErrorStream . errorStream . peek ( ) . isEmpty ( ) ) {
throw new RuntimeException ( " unexpected event in queue for "
+ desc + " : " + " \ n \ t " + ErrorStream . errorStream . drain ( ) ) ;
}
} else {
String logged = ErrorStream . errorStream . drain ( ) ;
String textMsg = bundle . getString ( msg ) ;
ByteArrayOutputStream baos = new ByteArrayOutputStream ( ) ;
thrown . printStackTrace ( new PrintStream ( baos ) ) ;
String text = baos . toString ( ) ;
if ( ! logged . contains ( " LoggerFinderLoaderTest testLogger " )
| | ! logged . contains ( messageLevel . getName ( ) + " : " + textMsg )
| | ! logged . contains ( text ) ) {
throw new RuntimeException ( " mismatch for " + desc
+ " \ n \ texpected: " + " \ n<<<< \ n "
+ " [date] LoggerFinderLoaderTest testLogger \ n "
+ messageLevel . getName ( ) + " " + textMsg + " \ n "
+ text
+ " >>>> "
+ " \ n \ t actual: "
+ " \ n<<<< \ n " + logged + " >>>> \ n " ) ;
} else {
verbose ( " Got expected results for "
+ desc + " \ n<<<< \ n " + logged + " >>>> \ n " ) ;
}
}
}
}
}
final static class PermissionsBuilder {
final Permissions perms ;
public PermissionsBuilder ( ) {
this ( new Permissions ( ) ) ;
}
public PermissionsBuilder ( Permissions perms ) {
this . perms = perms ;
}
public PermissionsBuilder add ( Permission p ) {
perms . add ( p ) ;
return this ;
}
public PermissionsBuilder addAll ( PermissionCollection col ) {
if ( col ! = null ) {
for ( Enumeration < Permission > e = col . elements ( ) ; e . hasMoreElements ( ) ; ) {
perms . add ( e . nextElement ( ) ) ;
}
}
return this ;
}
public Permissions toPermissions ( ) {
final PermissionsBuilder builder = new PermissionsBuilder ( ) ;
builder . addAll ( perms ) ;
return builder . perms ;
}
}
public static class SimplePolicy extends Policy {
final static RuntimePermission CONTROL = LOGGERFINDER_PERMISSION ;
final static RuntimePermission ACCESS = new RuntimePermission ( " accessClassInPackage.jdk.internal.logger " ) ;
final Permissions permissions ;
final ThreadLocal < AtomicBoolean > allowControl ;
final ThreadLocal < AtomicBoolean > allowAccess ;
public SimplePolicy ( ThreadLocal < AtomicBoolean > allowControl , ThreadLocal < AtomicBoolean > allowAccess ) {
this . allowControl = allowControl ;
this . allowAccess = allowAccess ;
permissions = new Permissions ( ) ;
permissions . add ( new RuntimePermission ( " setIO " ) ) ;
}
Permissions getPermissions ( ) {
if ( allowControl . get ( ) . get ( ) | | allowAccess . get ( ) . get ( ) ) {
PermissionsBuilder builder = new PermissionsBuilder ( )
. addAll ( permissions ) ;
if ( allowControl . get ( ) . get ( ) ) {
builder . add ( CONTROL ) ;
}
if ( allowAccess . get ( ) . get ( ) ) {
builder . add ( ACCESS ) ;
}
return builder . toPermissions ( ) ;
}
return permissions ;
}
@Override
public boolean implies ( ProtectionDomain domain , Permission permission ) {
return getPermissions ( ) . implies ( permission ) ;
}
@Override
public PermissionCollection getPermissions ( CodeSource codesource ) {
return new PermissionsBuilder ( ) . addAll ( getPermissions ( ) ) . toPermissions ( ) ;
}
@Override
public PermissionCollection getPermissions ( ProtectionDomain domain ) {
return new PermissionsBuilder ( ) . addAll ( getPermissions ( ) ) . toPermissions ( ) ;
}
}
}