/* * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* @test * * @bug 4105043 * @summary cannot set java.rmi.server.hostname on children of rmid in time * * @bug 4097357 * @summary activation group should not overwrite system properties * * @bug 4107184 * @summary activation groups should be able to control their JVM properties * * @author Adrian Colley * * @library ../../testlibrary * @modules java.rmi/sun.rmi.registry * java.rmi/sun.rmi.server * java.rmi/sun.rmi.transport * java.rmi/sun.rmi.transport.tcp * @build TestLibrary RMID ActivationLibrary * Eliza Retireable Doctor Doctor_Stub * @run main/othervm/timeout=240/policy=security.policy * -Djava.compiler=NONE SetChildEnv */ import java.rmi.*; import java.util.Properties; import java.io.*; import java.util.StringTokenizer; import java.util.Set; import java.util.HashSet; import java.util.Arrays; import java.rmi.activation.*; public class SetChildEnv { public static void main(String argv[]) throws Exception { int runningPort = TestLibrary.getUnusedRandomPort(); System.out.println("java.compiler=" + System.getProperty("java.compiler")); // don't embed spaces in any of the test args/props, because // they won't be parsed properly runwith (new String[0], new String[0], runningPort); runwith ( new String[] { "-verbosegc" }, new String[] { "foo.bar=SetChildEnvTest", "sun.rmi.server.doSomething=true" }, runningPort ); runwith ( new String[] { }, new String[] { "parameter.count=zero" }, runningPort ); runwith ( new String[] { "-Xmx32m" }, new String[] { }, runningPort ); } private static void runwith( String[] params, // extra args String[] props, // extra system properties int port // port on which to communicate ) throws Exception { TestLibrary.suggestSecurityManager(TestParams.defaultSecurityManager); // make a "watcher" which listens on a pipe and searches for // the debugExec line while teeing to System.err DebugExecWatcher watcher = DebugExecWatcher.makeWithPipe(); RMID.removeLog(); RMID rmid = RMID.createRMIDOnEphemeralPort(watcher.otherEnd(), watcher.otherEnd(), true, // debugExec turned on true, port); rmid.start(); // compile props Properties p = new Properties(); p.put("java.security.policy", TestParams.defaultGroupPolicy); p.put("java.security.manager", TestParams.defaultSecurityManager); //p.put("java.rmi.server.logCalls", "true"); int i; for (i = 0; i < props.length; i++) { p.put(props[i].substring(0, props[i].indexOf('=')), props[i].substring(props[i].indexOf('=')+1)); } // create CommandEnvironment and ActivationGroupDesc ActivationGroupDesc.CommandEnvironment cmdenv = new ActivationGroupDesc.CommandEnvironment( null, params); ActivationGroupDesc gdesc = new ActivationGroupDesc( p, cmdenv); // register group ActivationSystem actsys = ActivationGroup.getSystem(); ActivationGroupID gid = actsys.registerGroup(gdesc); // create ActivationDesc ActivationDesc odesc = new ActivationDesc(gid, // group "Doctor", // class null, // codesource null); // closure data // register activatable object Eliza doctor = (Eliza)Activatable.register(odesc); // invoke a call with oh-so-humorous sample text System.out.println ("Invoking complain()..."); String complaint = "HELP ME, DOCTOR. I FEEL VIOLENT TOWARDS PEOPLE " + "WHO INQUIRE ABOUT MY PARENTS."; System.out.println(complaint); //Runtime.getRuntime().traceMethodCalls(true); String res = doctor.complain(complaint); //Runtime.getRuntime().traceMethodCalls(false); System.out.println (" => " + res); // Get debugExec line, allowing 15 seconds for it to flush // through the buffers and pipes. String found = watcher.found; if (found == null) { int fudge = 15; while (found == null && --fudge > 0) { Thread.sleep(1000); found = watcher.found; } if (found == null) { TestLibrary.bomb("rmid subprocess produced no " + "recognizable debugExec line"); } } System.err.println("debugExec found: <<" + found + ">>"); // q: first double-quote after debugExec int q = found.indexOf('"', found.indexOf("rmid: debugExec")); // qe: last double-quote on debugExec line int qe = found.lastIndexOf('"'); if (q <= 1 || qe <= q) { TestLibrary.bomb("rmid subprocess produced " + "mangled debugExec line"); } // split args by whitespace StringTokenizer tk = new StringTokenizer(found.substring(q+1, qe)); tk.nextToken(); // skip command path/name // Now check off the requested args. Order isn't important, and // any extra args are ignored, even if they're inconsistent or // bargage, or duplicates. Set argset = new HashSet(tk.countTokens()); while (tk.hasMoreTokens()) { argset.add(tk.nextToken()); } int m; for (m = 0; m < params.length; m++) { if(!argset.contains(params[m])) TestLibrary.bomb("Parameter \"" + params[m] + "\" not set"); } for (m = 0; m < props.length; m++) { if (!argset.contains("-D" + props[m])) { TestLibrary.bomb("Property binding \"" + props[m] + "\" not set"); } } // End doctor if (doctor instanceof Retireable) ((Retireable)doctor).retire(); actsys.unregisterGroup(gid); Thread.sleep(5000); rmid.cleanup(); } public static class DebugExecWatcher extends Thread { public String found; private BufferedReader str; private OutputStream otherEnd; private DebugExecWatcher(InputStream readStream, OutputStream wrStream) { super("DebugExecWatcher"); found = null; str = new BufferedReader(new InputStreamReader(readStream)); otherEnd = wrStream; } static public DebugExecWatcher makeWithPipe() throws IOException { PipedOutputStream wr = new PipedOutputStream(); PipedInputStream rd = new PipedInputStream(wr); DebugExecWatcher embryo = new DebugExecWatcher(rd, wr); embryo.start(); return embryo; } public OutputStream otherEnd() { return otherEnd; } public synchronized void notifyLine(String s) { if (s != null && s.indexOf("rmid: debugExec") != -1) found = s; } public void run() { try { String line; while ((line = str.readLine()) != null) { this.notifyLine(line); System.err.println(line); } } catch (IOException e) { /* During termination of distant rmid, StreamPipes will be broken when * distant vm terminates. A "Pipe broken" exception is expected because * DebugExecWatcher points to the same streams as StreamPipes used by RMID. * If we get this exception. We just terminate the thread. */ if (e.getMessage().equals("Pipe broken")) { try { str.close(); } catch (IOException ioe) {} } else { e.printStackTrace(); } } } } } /* code graveyard // activation should have proceeded by writing a wrapper.out // when test.src/actgrpwrapper was run. // Read and check wrapper.out BufferedReader r = new BufferedReader(new FileReader(wrapout)); String[] realArgs = null; String line; while ( (line = r.readLine()) != null) { StringTokenizer tkz = new StringTokenizer(line); if (!tkz.nextToken().equals("actgrpwrapper")) { // could throw an exception, but let's benignly // assume that something unrelated is spewing. continue; } String x; // writer's block x = tkz.nextToken(); if (x.equals("argc")) { if (realArgs != null) { throw new RuntimeException( "SetChildEnv: two argc lines in wrapper.out"); } realArgs = new String[Integer.parseInt(tkz.nextToken())]; } else if (x.equals("argv")) { if (realArgs == null) throw new RuntimeException("SetChildEnv: missing argc"); int n = Integer.parseInt(tkz.nextToken()); if (n < 1 || n > realArgs.length) { throw new RuntimeException("SetChildEnv: argc=" + realArgs.length + "; argv[" + n + "]"); } // Hack: manually skip the "actgrpwrapper argv 5 " String remainder = line.substring( 1 + line.indexOf(' ', 1 + line.indexOf(' ', 1 + line.indexOf(' ')))); realArgs[n-1] = remainder; } else { throw new RuntimeException("SetChildEnv: bad token \"" + x + "\""); } } r.close(); private static void ensureLocalExecutable(String fname) throws Exception { File target = new File(fname); File source = new File(Dot, fname); if (!target.exists()) { // copy from source System.err.println("Copying " + source.getPath() + " to " + target.getPath()); java.io.InputStream in = new java.io.FileInputStream(source); java.io.OutputStream out = new java.io.FileOutputStream(target); byte[] buf = new byte[512]; int n; while ((n = in.read(buf, 0, 512)) > 0) { out.write(buf, 0, n); } out.close(); in.close(); } // chmod System.err.println("Doing: /bin/chmod 755 " + fname); Runtime.getRuntime().exec("/bin/chmod 755 " + fname).waitFor(); } */