1 /*
   2  * Copyright (c) 1998, 2006, 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 /**
  25  *
  26  */
  27 
  28 import java.io.*;
  29 import java.rmi.*;
  30 import java.rmi.activation.*;
  31 import java.util.Properties;
  32 
  33 /**
  34  * Utility class that creates an instance of rmid with a policy
  35  * file of name <code>TestParams.defaultPolicy</code>.
  36  *
  37  * Activation groups should run with the same security manager as the
  38  * test.
  39  */
  40 public class RMID extends JavaVM {
  41 
  42     public static String MANAGER_OPTION="-Djava.security.manager=";
  43 
  44     /** Test port for rmid */
  45     private final int port;
  46 
  47     /** Initial log name */
  48     protected static String log = "log";
  49     /** rmid's logfile directory; currently must be "." */
  50     protected static String LOGDIR = ".";
  51 
  52     private static void mesg(Object mesg) {
  53         System.err.println("RMID: " + mesg.toString());
  54     }
  55 
  56     /** make test options and arguments */
  57     private static String makeOptions(boolean debugExec) {
  58 
  59         String options = " -Dsun.rmi.server.activation.debugExec=" +
  60             debugExec;
  61         // +
  62         //" -Djava.compiler= ";
  63 
  64         // if test params set, want to propagate them
  65         if (!TestParams.testSrc.equals("")) {
  66             options += " -Dtest.src=" + TestParams.testSrc + " ";
  67         }
  68         //if (!TestParams.testClasses.equals("")) {
  69         //    options += " -Dtest.classes=" + TestParams.testClasses + " ";
  70         //}
  71         options += " -Dtest.classes=" + TestParams.testClasses //;
  72          +
  73          " -Djava.rmi.server.logLevel=v ";
  74 
  75         // +
  76         // " -Djava.security.debug=all ";
  77 
  78         return options;
  79     }
  80 
  81     private static String makeArgs(boolean includePortArg, int port) {
  82         String propagateManager = null;
  83 
  84         // rmid will run with a security manager set, but no policy
  85         // file - it should not need one.
  86         if (System.getSecurityManager() == null) {
  87             propagateManager = MANAGER_OPTION +
  88                 TestParams.defaultSecurityManager;
  89         } else {
  90             propagateManager = MANAGER_OPTION +
  91                 System.getSecurityManager().getClass().getName();
  92         }
  93 
  94         // getAbsolutePath requires permission to read user.dir
  95         String args =
  96             " -log " + (new File(LOGDIR, log)).getAbsolutePath();
  97 
  98         if (includePortArg) {
  99             args += " -port " + port;
 100         }
 101 
 102         // +
 103         //      " -C-Djava.compiler= ";
 104 
 105         // if test params set, want to propagate them
 106         if (!TestParams.testSrc.equals("")) {
 107             args += " -C-Dtest.src=" + TestParams.testSrc;
 108         }
 109         if (!TestParams.testClasses.equals("")) {
 110             args += " -C-Dtest.classes=" + TestParams.testClasses;
 111         }
 112         args += " " + getCodeCoverageArgs();
 113         return args;
 114     }
 115 
 116     /**
 117      * Routine that creates an rmid that will run with or without a
 118      * policy file.
 119      */
 120     public static RMID createRMID() {
 121         return createRMID(System.out, System.err, true);
 122     }
 123 
 124     public static RMID createRMID(boolean debugExec) {
 125         return createRMID(System.out, System.err, debugExec);
 126     }
 127 
 128     public static RMID createRMID(OutputStream out, OutputStream err) {
 129         return createRMID(out, err, true);
 130     }
 131 
 132     public static RMID createRMID(OutputStream out, OutputStream err,
 133                                   boolean debugExec)
 134     {
 135         return createRMID(out, err, debugExec, true,
 136                           TestLibrary.RMID_PORT);
 137     }
 138 
 139     public static RMID createRMID(OutputStream out, OutputStream err,
 140                                   boolean debugExec, boolean includePortArg,
 141                                   int port)
 142     {
 143         String options = makeOptions(debugExec);
 144         String args = makeArgs(includePortArg, port);
 145         RMID rmid = new RMID("sun.rmi.server.Activation", options, args,
 146                              out, err, port);
 147         rmid.setPolicyFile(TestParams.defaultRmidPolicy);
 148 
 149         return rmid;
 150     }
 151 
 152 
 153     /**
 154      * Test RMID should be created with the createRMID method.
 155      */
 156     protected RMID(String classname, String options, String args,
 157                    OutputStream out, OutputStream err, int port)
 158     {
 159         super(classname, options, args, out, err);
 160         this.port = port;
 161     }
 162 
 163     public static void removeLog() {
 164         /*
 165          * Remove previous log file directory before
 166          * starting up rmid.
 167          */
 168         File f = new File(LOGDIR, log);
 169 
 170         if (f.exists()) {
 171             mesg("removing rmid's old log file...");
 172             String[] files = f.list();
 173 
 174             if (files != null) {
 175                 for (int i=0; i<files.length; i++) {
 176                     (new File(f, files[i])).delete();
 177                 }
 178             }
 179 
 180             if (f.delete() != true) {
 181                 mesg("\t" + " unable to delete old log file.");
 182             }
 183         }
 184     }
 185 
 186     /**
 187      * This method is used for adding arguments to rmid (not its VM)
 188      * for passing as VM options to its child group VMs.
 189      * Returns the extra command line arguments required
 190      * to turn on jcov code coverage analysis for rmid child VMs.
 191      */
 192     protected static String getCodeCoverageArgs() {
 193         return TestLibrary.getExtraProperty("rmid.jcov.args","");
 194     }
 195 
 196     public void start() throws IOException {
 197         start(10000);
 198     }
 199 
 200     public void slowStart() throws IOException {
 201         start(60000);
 202     }
 203 
 204     public void start(long waitTime) throws IOException {
 205 
 206         if (getVM() != null) return;
 207 
 208         // if rmid is already running, then the test will fail with
 209         // a well recognized exception (port already in use...).
 210 
 211         mesg("starting rmid...");
 212         super.start();
 213 
 214         int slopFactor = 1;
 215         try {
 216             slopFactor = Integer.valueOf(
 217                 TestLibrary.getExtraProperty("jcov.sleep.multiplier","1"));
 218         } catch (NumberFormatException ignore) {}
 219         waitTime = waitTime * slopFactor;
 220 
 221         // give rmid time to come up
 222         do {
 223             try {
 224                 Thread.sleep(Math.min(waitTime, 10000));
 225             } catch (InterruptedException ie) {
 226                 Thread.currentThread().interrupt();
 227             }
 228             waitTime -= 10000;
 229 
 230             // is rmid present?
 231             if (ActivationLibrary.rmidRunning(port)) {
 232                 mesg("finished starting rmid.");
 233                 return;
 234             }
 235         } while (waitTime > 0);
 236         TestLibrary.bomb("start rmid failed... giving up", null);
 237     }
 238 
 239     public void restart() throws IOException {
 240         destroy();
 241         start();
 242     }
 243 
 244     /**
 245      * Ask rmid to shutdown gracefully using a remote method call.
 246      * catch any errors that might occur from rmid not being present
 247      * at time of shutdown invocation.
 248      *
 249      * Shutdown does not nullify possible references to the rmid
 250      * process object (destroy does though).
 251      */
 252     public static void shutdown() {
 253         shutdown(TestLibrary.RMID_PORT);
 254     }
 255 
 256     public static void shutdown(int port) {
 257 
 258         try {
 259             ActivationSystem system = null;
 260 
 261             try {
 262                 mesg("getting a reference to the activation system");
 263                 system = (ActivationSystem) Naming.lookup("//:" +
 264                     port +
 265                     "/java.rmi.activation.ActivationSystem");
 266                 mesg("obtained a reference to the activation system");
 267             } catch (java.net.MalformedURLException mue) {
 268             }
 269 
 270             if (system == null) {
 271                 TestLibrary.bomb("reference to the activation system was null");
 272             }
 273             system.shutdown();
 274 
 275         } catch (Exception e) {
 276             mesg("caught exception trying to shutdown rmid");
 277             mesg(e.getMessage());
 278             e.printStackTrace();
 279         }
 280 
 281         try {
 282             // wait for the shutdown to happen
 283             Thread.sleep(5000);
 284         } catch (InterruptedException ie) {
 285             Thread.currentThread().interrupt();
 286         }
 287 
 288         mesg("testlibrary finished shutting down rmid");
 289     }
 290 
 291     /**
 292      * Ask rmid to shutdown gracefully but then destroy the rmid
 293      * process if it does not exit by itself.  This method only works
 294      * if rmid is a child process of the current VM.
 295      */
 296     public void destroy() {
 297 
 298         // attempt graceful shutdown of the activation system on
 299         // TestLibrary.RMID_PORT
 300         shutdown(port);
 301 
 302         if (vm != null) {
 303             try {
 304                 // destroy rmid if it is still running...
 305                 try {
 306                     vm.exitValue();
 307                     mesg("rmid exited on shutdown request");
 308                 } catch (IllegalThreadStateException illegal) {
 309                     mesg("Had to destroy RMID's process " +
 310                          "using Process.destroy()");
 311                     super.destroy();
 312                 }
 313 
 314             } catch (Exception e) {
 315                 mesg("caught exception trying to destroy rmid: " +
 316                      e.getMessage());
 317                 e.printStackTrace();
 318             }
 319 
 320             // rmid will not restart if its process is not null
 321             vm = null;
 322         }
 323     }
 324 }