1/*
2 * Copyright (c) 1998, 2016, 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 * @bug 4109103
26 * @summary rmid should annotate child process output
27 *
28 * @author Laird Dornin; code borrowed from Ann Wollrath
29 *
30 * @library ../../../testlibrary
31 * @modules java.rmi/sun.rmi.registry
32 *          java.rmi/sun.rmi.server
33 *          java.rmi/sun.rmi.transport
34 *          java.rmi/sun.rmi.transport.tcp
35 *          java.base/sun.nio.ch
36 * @build TestLibrary RMID RMIDSelectorProvider MyRMI CheckAnnotations_Stub
37 * @run main/othervm/policy=security.policy/timeout=480 CheckAnnotations
38 */
39
40import java.io.*;
41import java.rmi.*;
42import java.rmi.server.*;
43import java.rmi.activation.*;
44import java.security.CodeSource;
45import java.util.Properties;
46import java.util.StringTokenizer;
47
48
49public class CheckAnnotations
50    extends Activatable implements MyRMI, Runnable
51{
52    private static final double TIME_FACTOR = TestLibrary.getTimeoutFactor();
53
54    private static Object dummy = new Object();
55    private static MyRMI myRMI = null;
56
57    // buffers to store rmid output.
58    private static ByteArrayOutputStream rmidOut = new ByteArrayOutputStream();
59    private static ByteArrayOutputStream rmidErr = new ByteArrayOutputStream();
60
61    public static void main(String args[]) {
62        /*
63         * The following line is required with the JDK 1.2 VM so that the
64         * VM can exit gracefully when this test completes.  Otherwise, the
65         * conservative garbage collector will find a handle to the server
66         * object on the native stack and not clear the weak reference to
67         * it in the RMI runtime's object table.
68         */
69        Object dummy1 = new Object();
70        RMID rmid = null;
71
72        System.err.println("\nRegression test for bug/rfe 4109103\n");
73
74        try {
75
76            // Set security manager according to the
77            // testlibrary.
78            TestLibrary.suggestSecurityManager(TestParams.defaultSecurityManager);
79
80            // start an rmid.
81            RMID.removeLog();
82            rmid = RMID.createRMIDOnEphemeralPort(rmidOut, rmidErr, false);
83            rmid.start();
84
85            /* Cause activation groups to have a security policy that will
86             * allow security managers to be downloaded and installed
87             */
88            Properties p = new Properties();
89            // this test must always set policies/managers in its
90            // activation groups
91            p.put("java.security.policy",
92                  TestParams.defaultGroupPolicy);
93            p.put("java.security.manager",
94                  TestParams.defaultSecurityManager);
95
96            /* new desc - we will reuse in order to get multiple vms.*/
97            System.err.println("Create activation group in this VM");
98            ActivationGroupDesc groupDesc =
99                new ActivationGroupDesc(p, null);
100            ActivationSystem system = ActivationGroup.getSystem();
101            ActivationGroupID groupID = system.registerGroup(groupDesc);
102            ActivationGroup.createGroup(groupID, groupDesc, 0);
103
104            ActivationDesc desc = new ActivationDesc
105                ("CheckAnnotations", null, null);
106            myRMI = (MyRMI) Activatable.register(desc);
107
108            /* The test-
109             * Loop a bunch of times to force activator to
110             * spawn VMs (groups)
111             */
112            for (int i = 0; i < 3; i++) {
113
114                // object activated in annotation check via method call
115                checkAnnotations(i-1);
116
117                /*
118                 * Clean up object too.
119                 */
120                System.err.println
121                    ("Deactivate object via method call");
122                myRMI.shutdown();
123            }
124            System.err.println
125                ("\nsuccess: CheckAnnotations test passed ");
126
127        } catch (Exception e) {
128            TestLibrary.bomb("\nfailure: unexpected exception ", e);
129        } finally {
130            try {
131                Thread.sleep(4000);
132            } catch (InterruptedException e) {
133            }
134
135            myRMI = null;
136            System.err.println("rmid shut down");
137            rmid.cleanup();
138        }
139    }
140
141    /**
142     * check to make sure that the output from a spawned vm is
143     * formatted/annotated properly.
144     */
145    public static void checkAnnotations(int iteration)
146        throws IOException
147    {
148        try {
149            Thread.sleep((long)(5000 * TIME_FACTOR));
150        } catch(Exception e) {
151            System.err.println(e.getMessage());
152        }
153
154        final String FAIL_MSG = "Test failed: output improperly annotated.";
155        final String OUT = "outABC";
156        final String ERR = "errXYZ";
157        /**
158         * cause the spawned vm to generate output that will
159         * be checked for proper annotation.  printOut is
160         * actually being called on an activated implementation.
161         */
162        myRMI.printOut(OUT + iteration);
163        myRMI.printErr(ERR + iteration);
164        myRMI.printOut(OUT + iteration);
165        myRMI.printErr(ERR + iteration);
166
167        /* we have to wait for output to filter down
168         * from children so we can read it before we
169         * kill rmid.
170         */
171
172        String outString = null;
173        String errString = null;
174
175        for (int i = 0 ; i < 5 ; i ++ ) {
176            // have to give output from rmid time to trickle down to
177            // this process
178            try {
179                Thread.sleep((long)(4000 * TIME_FACTOR));
180            } catch(InterruptedException e) {
181            }
182
183            outString = rmidOut.toString();
184            errString = rmidErr.toString();
185
186            if ((!outString.equals("")) &&
187                (!errString.equals("")))
188            {
189                System.err.println("obtained annotations");
190                break;
191            }
192            System.err.println("rmid output not yet received, retrying...");
193        }
194
195        rmidOut.reset();
196        rmidErr.reset();
197
198        // only test when we are annotating..., first run does not annotate
199        if (iteration >= 0) {
200            System.err.println("Checking annotations...");
201            System.err.println(outString);
202            System.err.println(errString);
203
204            StringTokenizer stOut = new StringTokenizer(outString, ":");
205            StringTokenizer stErr = new StringTokenizer(errString, ":");
206
207            String execErr = null;
208            String execOut = null;
209            String destOut = null;
210            String destErr = null;
211            String outTmp  = null;
212            String errTmp  = null;
213
214            while (stOut.hasMoreTokens()) {
215                execOut = outTmp;
216                outTmp  = destOut;
217                destOut = stOut.nextToken();
218            }
219            while (stErr.hasMoreTokens()) {
220                execErr = errTmp;
221                errTmp  = destErr;
222                destErr = stErr.nextToken();
223            }
224
225            if ((execErr == null)||(errTmp == null)||
226                (destErr == null)) {
227                TestLibrary.bomb(FAIL_MSG);
228            }
229            if ((execOut == null)||(outTmp == null)||
230                (destOut == null)) {
231                TestLibrary.bomb(FAIL_MSG);
232            }
233
234
235            // just make sure that last two strings are what we expect.
236            if (!execOut.equals("ExecGroup-" + iteration)
237                || !(new String(destOut.substring(0,OUT.length()+1)).equals(OUT +
238                                                              iteration))
239                || !(execErr.equals("ExecGroup-"+iteration))
240                || !(new String(destErr.substring(0,ERR.length()+1)).equals(ERR +
241                                                              iteration)) ) {
242                TestLibrary.bomb(FAIL_MSG);
243            }
244        }
245    }
246
247    // implementation of MyRMI, make this object activatable.
248    public CheckAnnotations
249        (ActivationID id, MarshalledObject mo)
250     throws RemoteException {
251
252        // register/export anonymously
253        super(id,0);
254    }
255
256    public void printOut(String toPrint) {
257        System.out.println(toPrint);
258    }
259
260    public void printErr(String toPrint) {
261        System.err.println(toPrint);
262    }
263
264    /**
265     * Spawns a thread to deactivate the object.
266     */
267    public void shutdown() throws Exception {
268        (new Thread(this,"CheckAnnotations")).start();
269    }
270
271    /**
272     * Thread to deactivate object. First attempts to make object
273     * inactive (via the inactive method).  If that fails (the
274     * object may still have pending/executing calls), then
275     * unexport the object forcibly.
276     */
277    public void run() {
278        ActivationLibrary.deactivate(this, getID());
279    }
280}
281