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