1 /*
   2  * Copyright (c) 1998, 2000, 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  *
  26  * @bug 4105043
  27  * @summary cannot set java.rmi.server.hostname on children of rmid in time
  28  *
  29  * @bug 4097357
  30  * @summary activation group should not overwrite system properties
  31  *
  32  * @bug 4107184
  33  * @summary activation groups should be able to control their JVM properties
  34  *
  35  * @author Adrian Colley
  36  *
  37  * @library ../../testlibrary
  38  * @build TestLibrary RMID JavaVM StreamPipe
  39  * @build Eliza Retireable Doctor Doctor_Stub SetChildEnv
  40  * @run main/othervm/timeout=240/policy=security.policy -Djava.compiler=NONE  SetChildEnv
  41  */
  42 import java.rmi.*;
  43 import java.util.Properties;
  44 import java.io.*;
  45 import java.util.StringTokenizer;
  46 import java.util.Set;
  47 import java.util.HashSet;
  48 import java.util.Arrays;
  49 import java.rmi.activation.*;
  50 
  51 public class SetChildEnv
  52 {
  53     public static void main(String argv[])
  54         throws Exception
  55     {
  56         System.out.println("java.compiler=" + System.getProperty("java.compiler"));
  57         // don't embed spaces in any of the test args/props, because
  58         // they won't be parsed properly
  59         runwith (new String[0], new String[0]);
  60 
  61         runwith (
  62             new String[] { "-verbosegc" },
  63             new String[] { "foo.bar=SetChildEnvTest",
  64                            "sun.rmi.server.doSomething=true" }
  65             );
  66 
  67         runwith (
  68             new String[] { },
  69             new String[] { "parameter.count=zero" }
  70             );
  71 
  72         runwith (
  73             new String[] { "-Xmx32m" },
  74             new String[] { }
  75             );
  76     }
  77 
  78     private static void runwith(
  79         String[] params,        // extra args
  80         String[] props          // extra system properties
  81     )
  82         throws Exception
  83     {
  84         TestLibrary.suggestSecurityManager(TestParams.defaultSecurityManager);
  85 
  86         // make a "watcher" which listens on a pipe and searches for
  87         // the debugExec line while teeing to System.err
  88         DebugExecWatcher watcher = DebugExecWatcher.makeWithPipe();
  89 
  90         RMID.removeLog();
  91         RMID rmid = RMID.createRMID(watcher.otherEnd(), watcher.otherEnd(),
  92                                     true); // debugExec turned on
  93 
  94         rmid.start();
  95 
  96         // compile props
  97         Properties p = new Properties();
  98         p.put("java.security.policy", TestParams.defaultGroupPolicy);
  99         p.put("java.security.manager", TestParams.defaultSecurityManager);
 100         //p.put("java.rmi.server.logCalls", "true");
 101         int i;
 102         for (i = 0; i < props.length; i++) {
 103             p.put(props[i].substring(0, props[i].indexOf('=')),
 104                   props[i].substring(props[i].indexOf('=')+1));
 105         }
 106 
 107         // create CommandEnvironment and ActivationGroupDesc
 108         ActivationGroupDesc.CommandEnvironment cmdenv =
 109                 new ActivationGroupDesc.CommandEnvironment(
 110                     null,
 111                     params);
 112 
 113         ActivationGroupDesc gdesc = new ActivationGroupDesc(
 114                 p, cmdenv);
 115 
 116         // register group
 117         ActivationSystem actsys = ActivationGroup.getSystem();
 118         ActivationGroupID gid = actsys.registerGroup(gdesc);
 119 
 120         // create ActivationDesc
 121         ActivationDesc odesc = new ActivationDesc(gid, // group
 122                                                   "Doctor", // class
 123                                                   null, // codesource
 124                                                   null); // closure data
 125 
 126         // register activatable object
 127         Eliza doctor = (Eliza)Activatable.register(odesc);
 128 
 129         // invoke a call with oh-so-humorous sample text
 130         System.out.println ("Invoking complain()...");
 131         String complaint =
 132                 "HELP ME, DOCTOR.  I FEEL VIOLENT TOWARDS PEOPLE " +
 133                 "WHO INQUIRE ABOUT MY PARENTS.";
 134 
 135         System.out.println(complaint);
 136         //Runtime.getRuntime().traceMethodCalls(true);
 137         String res = doctor.complain(complaint);
 138         //Runtime.getRuntime().traceMethodCalls(false);
 139         System.out.println (" => " + res);
 140 
 141         // Get debugExec line, allowing 15 seconds for it to flush
 142         // through the buffers and pipes.
 143         String found = watcher.found;
 144         if (found == null) {
 145             int fudge = 15;
 146             while (found == null && --fudge > 0) {
 147                 Thread.sleep(1000);
 148                 found = watcher.found;
 149             }
 150             if (found == null) {
 151                 TestLibrary.bomb("rmid subprocess produced no " +
 152                                  "recognizable debugExec line");
 153             }
 154         }
 155 
 156         System.err.println("debugExec found: <<" + found + ">>");
 157         // q: first double-quote after debugExec
 158         int q = found.indexOf('"', found.indexOf("rmid: debugExec"));
 159         // qe: last double-quote on debugExec line
 160         int qe = found.lastIndexOf('"');
 161         if (q <= 1 || qe <= q) {
 162             TestLibrary.bomb("rmid subprocess produced " +
 163                              "mangled debugExec line");
 164         }
 165 
 166         // split args by whitespace
 167         StringTokenizer tk = new StringTokenizer(found.substring(q+1, qe));
 168         tk.nextToken();         // skip command path/name
 169 
 170         // Now check off the requested args.  Order isn't important, and
 171         // any extra args are ignored, even if they're inconsistent or
 172         // bargage, or duplicates.
 173 
 174         Set argset = new HashSet(tk.countTokens());
 175         while (tk.hasMoreTokens()) {
 176             argset.add(tk.nextToken());
 177         }
 178 
 179         int m;
 180         for (m = 0; m < params.length; m++) {
 181             if(!argset.contains(params[m]))
 182                 TestLibrary.bomb("Parameter \"" + params[m] + "\" not set");
 183         }
 184 
 185         for (m = 0; m < props.length; m++) {
 186             if (!argset.contains("-D" + props[m])) {
 187                 TestLibrary.bomb("Property binding \"" + props[m] +
 188                                  "\" not set");
 189             }
 190         }
 191 
 192         // End doctor
 193         if (doctor instanceof Retireable)
 194             ((Retireable)doctor).retire();
 195         actsys.unregisterGroup(gid);
 196 
 197         Thread.sleep(5000);
 198         rmid.destroy();
 199     }
 200 
 201     public static class DebugExecWatcher
 202         extends Thread
 203     {
 204         public String found;
 205         private BufferedReader str;
 206         private OutputStream otherEnd;
 207 
 208         private DebugExecWatcher(InputStream readStream, OutputStream wrStream)
 209         {
 210             super("DebugExecWatcher");
 211             found = null;
 212             str = new BufferedReader(new InputStreamReader(readStream));
 213             otherEnd = wrStream;
 214         }
 215 
 216         static public DebugExecWatcher makeWithPipe()
 217             throws IOException
 218         {
 219             PipedOutputStream wr = new PipedOutputStream();
 220             PipedInputStream rd = new PipedInputStream(wr);
 221             DebugExecWatcher embryo = new DebugExecWatcher(rd, wr);
 222             embryo.start();
 223             return embryo;
 224         }
 225 
 226         public OutputStream otherEnd()
 227         {
 228             return otherEnd;
 229         }
 230 
 231         public synchronized void notifyLine(String s)
 232         {
 233             if (s != null && s.indexOf("rmid: debugExec") != -1)
 234                 found = s;
 235         }
 236 
 237         public void run()
 238         {
 239             try {
 240                 String line;
 241                 while ((line = str.readLine()) != null) {
 242                     this.notifyLine(line);
 243                     System.err.println(line);
 244                 }
 245             } catch (IOException e) {
 246                 e.printStackTrace();
 247             }
 248         }
 249     }
 250 }
 251 
 252 /*
 253    code graveyard
 254 
 255         // activation should have proceeded by writing a wrapper.out
 256         // when test.src/actgrpwrapper was run.
 257 
 258         // Read and check wrapper.out
 259         BufferedReader r = new BufferedReader(new FileReader(wrapout));
 260         String[] realArgs = null;
 261         String line;
 262 
 263         while ( (line = r.readLine()) != null) {
 264             StringTokenizer tkz = new StringTokenizer(line);
 265             if (!tkz.nextToken().equals("actgrpwrapper")) {
 266                 // could throw an exception, but let's benignly
 267                 // assume that something unrelated is spewing.
 268                 continue;
 269             }
 270             String x;   // writer's block
 271             x = tkz.nextToken();
 272             if (x.equals("argc")) {
 273                 if (realArgs != null) {
 274                     throw new RuntimeException(
 275                             "SetChildEnv: two argc lines in wrapper.out");
 276                 }
 277                 realArgs = new String[Integer.parseInt(tkz.nextToken())];
 278             } else if (x.equals("argv")) {
 279                 if (realArgs == null)
 280                     throw new RuntimeException("SetChildEnv: missing argc");
 281                 int n = Integer.parseInt(tkz.nextToken());
 282                 if (n < 1 || n > realArgs.length) {
 283                     throw new RuntimeException("SetChildEnv: argc=" +
 284                             realArgs.length + "; argv[" + n + "]");
 285                 }
 286                 // Hack: manually skip the "actgrpwrapper argv 5 "
 287                 String remainder = line.substring(
 288                         1 + line.indexOf(' ',
 289                                 1 + line.indexOf(' ',
 290                                         1 + line.indexOf(' '))));
 291                 realArgs[n-1] = remainder;
 292             } else {
 293                 throw new RuntimeException("SetChildEnv: bad token \"" + x + "\"");
 294             }
 295         }
 296         r.close();
 297 
 298     private static void ensureLocalExecutable(String fname)
 299         throws Exception
 300     {
 301         File target = new File(fname);
 302         File source = new File(Dot, fname);
 303         if (!target.exists()) {
 304             // copy from source
 305             System.err.println("Copying " + source.getPath() +
 306                                " to " + target.getPath());
 307             java.io.InputStream in = new java.io.FileInputStream(source);
 308             java.io.OutputStream out = new java.io.FileOutputStream(target);
 309             byte[] buf = new byte[512];
 310             int n;
 311             while ((n = in.read(buf, 0, 512)) > 0) {
 312                 out.write(buf, 0, n);
 313             }
 314             out.close();
 315             in.close();
 316         }
 317         // chmod
 318         System.err.println("Doing: /bin/chmod 755 " + fname);
 319         Runtime.getRuntime().exec("/bin/chmod 755 " + fname).waitFor();
 320     }
 321 
 322 */