1 /*
   2  * Copyright (c) 2017, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 import java.lang.reflect.Method;
  27 import java.lang.System.Logger;
  28 import java.util.ResourceBundle;
  29 import java.util.ListResourceBundle;
  30 
  31 /*
  32  * Tests when logger client is in patched module
  33  */
  34 public class PatchedClient {
  35 
  36     public static void main(String[] args) throws Exception {
  37         assertTrue(args.length >= 2);
  38         String loggerMode = args[0];
  39         String loggerClassName = args[1];
  40         String underlyingLoggerClassName = args.length >= 3 ? args[2] : null;
  41 
  42         testLogger(loggerMode, loggerClassName, underlyingLoggerClassName);
  43         testLog(underlyingLoggerClassName);
  44     }
  45 
  46     /*
  47      * Tests System.getLogger(String) get expected logger.
  48      */
  49     private static void testLogger(String loggerMode, String loggerClassName,
  50                                    String underlyingLoggerClassName) {
  51         String name = "test.patched";
  52         Logger logger = getLogger(name);
  53         printLogger(logger);
  54 
  55         final Module lm = logger.getClass().getModule();
  56         final ClassLoader loggerCL = lm.getClassLoader();
  57         if (loggerMode.equals("system")) {
  58             assertTrue(lm.isNamed());
  59             assertTrue(loggerCL == null);
  60         } else if(loggerMode.equals("unnamed")) {
  61             assertTrue(!lm.isNamed());
  62             assertTrue(loggerCL != null);
  63         } else {
  64             throw new RuntimeException("wrong parameter");
  65         }
  66 
  67         assertTrue(loggerClassName.equals(logger.getClass().getName()));
  68         if (underlyingLoggerClassName != null) {
  69             String loggerName = logger.getName();
  70             if (underlyingLoggerClassName.equals(
  71                     "sun.util.logging.internal.LoggingProviderImpl$JULWrapper")) {
  72                 assertTrue(loggerName.equals(name));
  73             } else {
  74                 assertTrue(loggerName.equals(underlyingLoggerClassName));
  75             }
  76         }
  77     }
  78 
  79     /*
  80      * Tests Logger retrieved by System.getLogger(String, ResourceBundle) and
  81      * System.getLogger(String) works well.
  82      */
  83     private static void testLog(String underlyingLoggerClassName) throws Exception {
  84         if (underlyingLoggerClassName == null) {
  85             return;
  86         }
  87 
  88         if (underlyingLoggerClassName.equals("pkg.a.l.LoggerA")
  89                 || underlyingLoggerClassName.equals("pkg.b.l.LoggerB")) {
  90 
  91             String name = "test.patched.logger";
  92             String plainMsg = "this is test log message #1";
  93             ResourceBundle rb = new MyResourcesPatched();
  94             Throwable ex = new Throwable("this is an expected exception to be logged");
  95             Class<?> clazz = Class.forName(underlyingLoggerClassName);
  96             Method method = clazz.getMethod("checkLog", String.class,
  97                                             System.Logger.Level.class,
  98                                             ResourceBundle.class, String.class,
  99                                             Throwable.class, Object[].class);
 100 
 101             Logger logger = getLogger(name);
 102             printLogger(logger);
 103             assertTrue(logger.getClass().getName()
 104                              .equals("jdk.internal.logger.LazyLoggers$JdkLazyLogger"));
 105             assertTrue(logger.getName().equals(underlyingLoggerClassName));
 106             logger.log(Logger.Level.WARNING, plainMsg);
 107             boolean pass = (boolean)method.invoke(null, name, Logger.Level.WARNING,
 108                                                   null, plainMsg, ex, (Object)null);
 109             assertTrue(pass);
 110             pass = (boolean)method.invoke(null, name, Logger.Level.INFO,
 111                                           rb, MyResourcesPatched.VALUE, (Throwable)null,
 112                                           (Object)null);
 113             assertTrue(!pass);
 114 
 115             logger = getLogger(name, rb);
 116             printLogger(logger);
 117             assertTrue(logger.getClass().getName()
 118                              .equals("jdk.internal.logger.LocalizedLoggerWrapper"));
 119             assertTrue(logger.getName().equals(underlyingLoggerClassName));
 120             logger.log(Logger.Level.INFO, MyResourcesPatched.KEY);
 121             pass = (boolean)method.invoke(null, name, Logger.Level.INFO,
 122                                           rb, MyResourcesPatched.VALUE, (Throwable)null,
 123                                           (Object)null);
 124             assertTrue(pass);
 125             pass = (boolean)method.invoke(null, name, Logger.Level.WARNING,
 126                                           null, plainMsg, ex, (Object)null);
 127             assertTrue(pass);
 128         }
 129     }
 130 
 131     private static class MyResourcesPatched extends ListResourceBundle {
 132         static final String KEY = "this is the key in MyResourcesPatched";
 133         static final String VALUE = "THIS IS THE VALUE IN MyResourcesPatched";
 134 
 135         @Override
 136         protected Object[][] getContents() {
 137             return new Object[][] {
 138                 {KEY, VALUE}
 139             };
 140         }
 141     }
 142 
 143     private static Logger getLogger(String name) {
 144         return PatchedUsage.getLogger(name);
 145     }
 146 
 147     private static Logger getLogger(String name, ResourceBundle rb) {
 148         return PatchedUsage.getLogger(name, rb);
 149     }
 150 
 151     private static void printLogger(Logger logger) {
 152         System.err.println("logger name: " + logger.getName()
 153                            + ", logger class: " + logger.getClass());
 154     }
 155 
 156     private static void assertTrue(boolean b) {
 157         if (!b) {
 158             throw new RuntimeException("expected true, but get false.");
 159         }
 160     }
 161 }