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