1 /*
   2  * Copyright (c) 2001, 2012, 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 int REGISTRY_PORT = -1;
  81     private static String LOCATION;
  82 
  83     private static final ByteArrayOutputStream clientCallOut =
  84         new ByteArrayOutputStream();
  85 
  86     private static final boolean usingOld =
  87         Boolean.getBoolean("sun.rmi.log.useOld");
  88 
  89     static {
  90         System.setProperty("sun.rmi.client.logCalls", "true");
  91         if (usingOld) {
  92             System.err.println("set default stream");
  93             LogStream.setDefaultStream(new PrintStream(clientCallOut));
  94         } else {
  95             Logger.getLogger("sun.rmi.client.call").
  96                 addHandler(new InternalStreamHandler(clientCallOut));
  97         }
  98     }
  99 
 100     /* use registry to generate client & server call log info */
 101     private static Registry registry;
 102     static {
 103         try {
 104             registry = TestLibrary.createRegistryOnUnusedPort();
 105             REGISTRY_PORT = TestLibrary.getRegistryPort(registry);
 106             LOCATION = "rmi://localhost:" + REGISTRY_PORT + "/";
 107         } catch (Exception e) {
 108             TestLibrary.bomb("could not create registry");
 109         }
 110     }
 111 
 112     /**
 113      * Used to collect output from specific loggers
 114      */
 115     private static class InternalStreamHandler extends StreamHandler {
 116         private InternalStreamHandler(OutputStream out) {
 117             super(out, new SimpleFormatter());
 118             setLevel(Level.ALL);
 119         }
 120 
 121         public void publish(LogRecord record) {
 122             super.publish(record);
 123             flush();
 124         }
 125 
 126         public void close() {
 127             flush();
 128         }
 129     }
 130 
 131     /**
 132      * Ensure that a log has some output and that it contains a
 133      * certain string
 134      */
 135     private static void verifyLog(ByteArrayOutputStream bout,
 136                                   String mustContain)
 137     {
 138         byte[] bytes = bout.toByteArray();
 139         if (bytes.length == 0) {
 140             TestLibrary.bomb("log data length is zero");
 141         } else if ((mustContain != null) &&
 142                    (bout.toString().indexOf(mustContain) < 0))
 143         {
 144             TestLibrary.bomb("log output did not contain: " + mustContain);
 145         }
 146     }
 147 
 148     /**
 149      * Check serverCallLog output
 150      */
 151     private static void checkServerCallLog() throws Exception {
 152         ByteArrayOutputStream serverCallLog = new ByteArrayOutputStream();
 153         RemoteServer.setLog(serverCallLog);
 154         Naming.list(LOCATION);
 155         verifyLog(serverCallLog, "list");
 156 
 157         serverCallLog.reset();
 158         RemoteServer.setLog(null);
 159         PrintStream callStream = RemoteServer.getLog();
 160         if (callStream != null) {
 161             TestLibrary.bomb("call stream not null after calling " +
 162                              "setLog(null)");
 163         } else {
 164             System.err.println("call stream should be null and it is");
 165         }
 166         Naming.list(LOCATION);
 167 
 168         if (usingOld) {
 169             if (serverCallLog.toString().indexOf("UnicastServerRef") >= 0) {
 170                 TestLibrary.bomb("server call logging not turned off");
 171             }
 172         } else if (serverCallLog.toByteArray().length != 0) {
 173             TestLibrary.bomb("call log contains output but it " +
 174                              "should be empty");
 175         }
 176 
 177         serverCallLog.reset();
 178         RemoteServer.setLog(serverCallLog);
 179         try {
 180             // generates a notbound exception
 181             Naming.lookup(LOCATION + "notthere");
 182         } catch (Exception e) {
 183         }
 184         verifyLog(serverCallLog, "exception");
 185 
 186         serverCallLog.reset();
 187         RemoteServer.setLog(serverCallLog);
 188         callStream = RemoteServer.getLog();
 189         callStream.println("bingo, this is a getLog test");
 190         verifyLog(serverCallLog, "bingo");
 191     }
 192 
 193     private static void checkPermissions() {
 194         SecurityException ex = null;
 195         try {
 196             // should fail for lack of LoggingPermission "control"
 197             RemoteServer.setLog(System.err);
 198         } catch (SecurityException e) {
 199             System.err.println("security excepton caught correctly");
 200             ex = e;
 201         }
 202         if (ex == null) {
 203             TestLibrary.bomb("able to set log without permission");
 204         }
 205     }
 206 
 207     public static void main(String[] args) {
 208         try {
 209             checkServerCallLog();
 210 
 211             if (!usingOld) {
 212                 verifyLog(clientCallOut, "outbound call");
 213                 System.setSecurityManager(new java.lang.SecurityManager());
 214                 checkPermissions();
 215             }
 216             System.err.println("TEST PASSED");
 217 
 218         } catch (Exception e) {
 219             if (e instanceof RuntimeException) {
 220                 throw (RuntimeException) e;
 221             }
 222             TestLibrary.bomb("unexpected exception", e);
 223         } finally {
 224             TestLibrary.unexport(registry);
 225         }
 226     }
 227 }