1 /*
   2  * Copyright (c) 2001, 2013, 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 /* @test
  25  * @bug 4402649
  26  * @summary RMI should use new logging APIs. Unit test to exercise
  27  * RMI's use of the java.util.logging API.
  28  * @author Laird Dornin
  29  *
  30  * @library ../../../../../java/rmi/testlibrary
  31  * @modules java.rmi/sun.rmi.registry
  32  *          java.rmi/sun.rmi.server
  33  *          java.rmi/sun.rmi.transport
  34  *          java.rmi/sun.rmi.transport.tcp
  35  * @build TestLibrary
  36  * @run main/othervm CheckLogging
  37  */
  38 
  39 import java.util.logging.Level;
  40 import java.util.logging.LogRecord;
  41 import java.util.logging.Logger;
  42 import java.util.logging.SimpleFormatter;
  43 import java.util.logging.StreamHandler;
  44 
  45 import java.io.ByteArrayOutputStream;
  46 import java.io.IOException;
  47 import java.io.PrintStream;
  48 import java.io.OutputStream;
  49 
  50 import java.rmi.RemoteException;
  51 import java.rmi.Remote;
  52 import java.rmi.Naming;
  53 import java.rmi.registry.LocateRegistry;
  54 import java.rmi.server.LogStream;
  55 import java.rmi.server.RemoteServer;
  56 
  57 import java.rmi.registry.Registry;
  58 
  59 /**
  60  * Perform following checks:
  61  *
  62  * 1. If using java.util.logging, turn on client call logger using
  63  * system property, "sun.rmi.client.logCalls".  Collect client call
  64  * output using a custom stream handler. Verify client call output is
  65  * generated and contains the string "outbound call".
  66  *
  67  * 2. Turn on server call using
  68  * RemoteServer.setLog(ByteArrayOutputStream). Invoke some remote
  69  * method calls verify logger output is non-null.
  70  *
  71  * Turn off server call log by doing setLog(null), verify output is
  72  * zero length.  Verify that RemoteServer.getLog == null
  73  *
  74  * Use setLog to turn call log back on.  Invoke remote method that
  75  * throws an exception and contains the string "exception".
  76  *
  77  * 3. Print directly to return value of RemoteServer.getLog(), verify
  78  * logger output is non-null.
  79  */
  80 public class CheckLogging {
  81     private static int REGISTRY_PORT = -1;
  82     private static String LOCATION;
  83     private static Logger logger;
  84 
  85     private static final ByteArrayOutputStream clientCallOut =
  86         new ByteArrayOutputStream();
  87 
  88     private static final boolean usingOld =
  89         Boolean.getBoolean("sun.rmi.log.useOld");
  90 
  91     static {
  92         System.setProperty("sun.rmi.client.logCalls", "true");
  93         if (usingOld) {
  94             System.err.println("set default stream");
  95             LogStream.setDefaultStream(new PrintStream(clientCallOut));
  96         } else {
  97             logger = Logger.getLogger("sun.rmi.client.call");
  98             logger.addHandler(new InternalStreamHandler(clientCallOut));
  99         }
 100     }
 101 
 102     /* use registry to generate client & server call log info */
 103     private static Registry registry;
 104     static {
 105         try {
 106             registry = TestLibrary.createRegistryOnUnusedPort();
 107             REGISTRY_PORT = TestLibrary.getRegistryPort(registry);
 108             LOCATION = "rmi://localhost:" + REGISTRY_PORT + "/";
 109         } catch (Exception e) {
 110             TestLibrary.bomb("could not create registry");
 111         }
 112     }
 113 
 114     /**
 115      * Used to collect output from specific loggers
 116      */
 117     private static class InternalStreamHandler extends StreamHandler {
 118         private InternalStreamHandler(OutputStream out) {
 119             super(out, new SimpleFormatter());
 120             setLevel(Level.ALL);
 121         }
 122 
 123         public void publish(LogRecord record) {
 124             super.publish(record);
 125             flush();
 126         }
 127 
 128         public void close() {
 129             flush();
 130         }
 131     }
 132 
 133     /**
 134      * Ensure that a log has some output and that it contains a
 135      * certain string
 136      */
 137     private static void verifyLog(ByteArrayOutputStream bout,
 138                                   String mustContain)
 139     {
 140         byte[] bytes = bout.toByteArray();
 141         if (bytes.length == 0) {
 142             TestLibrary.bomb("log data length is zero");
 143         } else if ((mustContain != null) &&
 144                    (bout.toString().indexOf(mustContain) < 0))
 145         {
 146             TestLibrary.bomb("log output did not contain: " + mustContain);
 147         }
 148     }
 149 
 150     /**
 151      * Check serverCallLog output
 152      */
 153     private static void checkServerCallLog() throws Exception {
 154         ByteArrayOutputStream serverCallLog = new ByteArrayOutputStream();
 155         RemoteServer.setLog(serverCallLog);
 156         Naming.list(LOCATION);
 157         verifyLog(serverCallLog, "list");
 158 
 159         serverCallLog.reset();
 160         RemoteServer.setLog(null);
 161         PrintStream callStream = RemoteServer.getLog();
 162         if (callStream != null) {
 163             TestLibrary.bomb("call stream not null after calling " +
 164                              "setLog(null)");
 165         } else {
 166             System.err.println("call stream should be null and it is");
 167         }
 168         Naming.list(LOCATION);
 169 
 170         if (usingOld) {
 171             if (serverCallLog.toString().indexOf("UnicastServerRef") >= 0) {
 172                 TestLibrary.bomb("server call logging not turned off");
 173             }
 174         } else if (serverCallLog.toByteArray().length != 0) {
 175             TestLibrary.bomb("call log contains output but it " +
 176                              "should be empty");
 177         }
 178 
 179         serverCallLog.reset();
 180         RemoteServer.setLog(serverCallLog);
 181         try {
 182             // generates a notbound exception
 183             Naming.lookup(LOCATION + "notthere");
 184         } catch (Exception e) {
 185         }
 186         verifyLog(serverCallLog, "exception");
 187 
 188         serverCallLog.reset();
 189         RemoteServer.setLog(serverCallLog);
 190         callStream = RemoteServer.getLog();
 191         callStream.println("bingo, this is a getLog test");
 192         verifyLog(serverCallLog, "bingo");
 193     }
 194 
 195     private static void checkPermissions() {
 196         SecurityException ex = null;
 197         try {
 198             // should fail for lack of LoggingPermission "control"
 199             RemoteServer.setLog(System.err);
 200         } catch (SecurityException e) {
 201             System.err.println("security excepton caught correctly");
 202             ex = e;
 203         }
 204         if (ex == null) {
 205             TestLibrary.bomb("able to set log without permission");
 206         }
 207     }
 208 
 209     public static void main(String[] args) {
 210         try {
 211             checkServerCallLog();
 212 
 213             if (!usingOld) {
 214                 verifyLog(clientCallOut, "outbound call");
 215                 System.setSecurityManager(new java.lang.SecurityManager());
 216                 checkPermissions();
 217             }
 218             System.err.println("TEST PASSED");
 219 
 220         } catch (Exception e) {
 221             if (e instanceof RuntimeException) {
 222                 throw (RuntimeException) e;
 223             }
 224             TestLibrary.bomb("unexpected exception", e);
 225         } finally {
 226             TestLibrary.unexport(registry);
 227         }
 228     }
 229 }