/* * Copyright (c) 1998, 1999, 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 4109103 * @summary rmid should annotate child process output * * @author Laird Dornin; code borrowed from Ann Wollrath * * @library ../../../testlibrary * @build TestLibrary RMID MyRMI CheckAnnotations_Stub * @run main/othervm/policy=security.policy/timeout=480 CheckAnnotations */ import java.io.*; import java.rmi.*; import java.rmi.activation.*; import java.util.Properties; import java.util.StringTokenizer; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class CheckAnnotations extends Activatable implements MyRMI, Runnable { private static MyRMI myRMI = null; static class NotifyOutputStream extends ByteArrayOutputStream { final Lock lock; final Condition signal; NotifyOutputStream(Lock lock, Condition signal) { this.lock = lock; this.signal = signal; } @Override public synchronized void write(int b) { lock.lock(); try{ super.write(b); signal.signal(); } finally { lock.unlock(); } } @Override public synchronized void write(byte b[], int off, int len) { lock.lock(); try{ super.write(b, off, len); if (len != 0) signal.signal(); } finally { lock.unlock(); } } } // buffers to store rmid output. private static final Lock lock = new ReentrantLock(); private static final Condition writeOutSig = lock.newCondition(); private static final Condition writeErrSig = lock.newCondition(); private static final NotifyOutputStream rmidOut = new NotifyOutputStream(lock, writeOutSig); private static final NotifyOutputStream rmidErr = new NotifyOutputStream(lock, writeErrSig); public static void main(String args[]) { RMID rmid = null; System.err.println("\nRegression test for bug/rfe 4109103\n"); try { // Set security manager according to the // testlibrary. TestLibrary.suggestSecurityManager(TestParams.defaultSecurityManager); // start an rmid. RMID.removeLog(); rmid = RMID.createRMID(rmidOut, rmidErr, false); rmid.start(); /* Cause activation groups to have a security policy that will * allow security managers to be downloaded and installed */ Properties p = new Properties(); // this test must always set policies/managers in its // activation groups p.put("java.security.policy", TestParams.defaultGroupPolicy); p.put("java.security.manager", TestParams.defaultSecurityManager); /* new desc - we will reuse in order to get multiple vms.*/ System.err.println("Create activation group in this VM"); ActivationGroupDesc groupDesc = new ActivationGroupDesc(p, null); ActivationSystem system = ActivationGroup.getSystem(); ActivationGroupID groupID = system.registerGroup(groupDesc); ActivationGroup.createGroup(groupID, groupDesc, 0); ActivationDesc desc = new ActivationDesc ("CheckAnnotations", null, null); myRMI = (MyRMI) Activatable.register(desc); /* The test- * Loop a bunch of times to force activator to * spawn VMs (groups) */ for (int i = 0; i < 3; i++) { // object activated in annotation check via method call if(!checkAnnotations(i-1)) { TestLibrary.bomb("Test failed: output improperly annotated."); } /* * Clean up object too. */ System.err.println ("Deactivate object via method call"); myRMI.shutdown(); } System.err.println ("\nsuccess: CheckAnnotations test passed "); } catch (Exception e) { TestLibrary.bomb("\nfailure: unexpected exception ", e); } finally { try { Thread.sleep(4000); } catch (InterruptedException ignore) { } myRMI = null; System.err.println("rmid shut down"); ActivationLibrary.rmidCleanup(rmid); } } /** * check to make sure that the output from a spawned vm is * formatted/annotated properly. * @param iteration * @return * @throws java.io.IOException * @throws java.lang.InterruptedException */ public static boolean checkAnnotations(int iteration) throws IOException, InterruptedException { try { Thread.sleep(1000); } catch(InterruptedException e) { System.err.println(e.getMessage()); } /** * cause the spawned vm to generate output that will * be checked for proper annotation. printOut is * actually being called on an activated implementation. */ myRMI.printOut("out" + iteration); myRMI.printErr("err" + iteration); myRMI.printOut("out" + iteration); myRMI.printErr("err" + iteration); /* we have to wait for output to filter down * from children so we can read it before we * kill rmid. */ String outString, errString; class WaitThread extends Thread{ final Lock lock; final Condition signal; final long timeout; WaitThread(Lock lock, Condition signal, long timeout) { this.lock = lock; this.signal = signal; this.timeout = timeout; } @Override public void run(){ long goTime = timeout; lock.lock(); try{ while(goTime > 0L) { long start = System.currentTimeMillis(); try { if(signal.await(goTime, TimeUnit.MILLISECONDS)) { break; } } catch (InterruptedException e) { throw new RuntimeException("Signal interrupt unexpected:" + e); } goTime = timeout - System.currentTimeMillis() + start; } } finally { lock.unlock(); } } } outString = rmidOut.toString(); errString = rmidErr.toString(); if ((!"".equals(outString)) && (!"".equals(errString))) { System.err.println("obtained annotations"); } else { WaitThread waitOutT = new WaitThread(lock, writeOutSig, 10000); WaitThread waitErrT = new WaitThread(lock, writeErrSig, 10000); waitOutT.start(); waitErrT.start(); waitOutT.join(); waitErrT.join(); outString = rmidOut.toString(); errString = rmidErr.toString(); if ((!"".equals(outString)) && (!"".equals(errString))) { System.err.println("obtained annotations"); } } rmidOut.reset(); rmidErr.reset(); // only test when we are annotating..., first run does not annotate if (iteration >= 0) { System.err.println("Checking annotations..."); System.err.println(outString); System.err.println(errString); StringTokenizer stOut = new StringTokenizer(outString, ":"); StringTokenizer stErr = new StringTokenizer(errString, ":"); String execErr = null; String execOut = null; String destOut = null; String destErr = null; String outTmp = null; String errTmp = null; while (stOut.hasMoreTokens()) { execOut = outTmp; outTmp = destOut; destOut = stOut.nextToken(); } while (stErr.hasMoreTokens()) { execErr = errTmp; errTmp = destErr; destErr = stErr.nextToken(); } if ((execErr == null)||(errTmp == null)|| (destErr == null)) { return false; } if ((execOut == null)||(outTmp == null)|| (destOut == null)) { return false; } // just make sure that last two strings are what we expect. if (execOut.equals("ExecGroup-" + iteration) && (new String(destOut.substring(0,4)).equals("out" + iteration)) && (execErr.equals("ExecGroup-"+iteration)) && (new String(destErr.substring(0,4)).equals("err" + iteration)) ) { return true; } else { return false; } } return true; } // implementation of MyRMI, make this object activatable. public CheckAnnotations (ActivationID id, MarshalledObject mo) throws RemoteException { // register/export anonymously super(id,0); } @Override public void printOut(String toPrint) { System.out.println(toPrint); } @Override public void printErr(String toPrint) { System.err.println(toPrint); } /** * Spawns a thread to deactivate the object. * @throws java.lang.Exception */ @Override public void shutdown() throws Exception { (new Thread(this,"CheckAnnotations")).start(); } /** * Thread to deactivate object. First attempts to make object * inactive (via the inactive method). If that fails (the * object may still have pending/executing calls), then * unexport the object forcibly. */ @Override public void run() { ActivationLibrary.deactivate(this, getID()); } }