ActivationLibrary.java revision 0:37a05a11f281
1/*
2 * Copyright 1998-2006 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/**
25 *
26 */
27
28import java.io.File;
29import java.rmi.Naming;
30import java.rmi.NoSuchObjectException;
31import java.rmi.NotBoundException;
32import java.rmi.Remote;
33import java.rmi.activation.Activatable;
34import java.rmi.activation.ActivationID;
35import java.rmi.activation.ActivationSystem;
36import java.rmi.registry.LocateRegistry;
37
38/**
39 * Class of test utility/library methods related to Activatable
40 * objects.
41 */
42public class ActivationLibrary {
43    /** time safeDestroy should wait before failing on shutdown rmid */
44    private static final int SAFE_WAIT_TIME;
45    static {
46        int slopFactor = 1;
47        try {
48            slopFactor = Integer.valueOf(
49                TestLibrary.getExtraProperty("jcov.sleep.multiplier","1"));
50        } catch (NumberFormatException ignore) {}
51        SAFE_WAIT_TIME = 60000 * slopFactor;
52    }
53
54    private static final String SYSTEM_NAME =
55        ActivationSystem.class.getName();
56
57    private static void mesg(Object mesg) {
58        System.err.println("ACTIVATION_LIBRARY: " + mesg.toString());
59    }
60
61    /**
62     * Deactivate an activated Activatable
63     */
64    public static void deactivate(Remote remote,
65                                  ActivationID id) {
66        for (int i = 0; i < 5; i ++) {
67            try {
68                if (Activatable.inactive(id) == true) {
69                    mesg("inactive successful");
70                    return;
71                } else {
72                    Thread.sleep(1000);
73                }
74            } catch (InterruptedException e) {
75                continue;
76            } catch (Exception e) {
77                try {
78                    // forcibly unexport the object
79                    Activatable.unexportObject(remote, true);
80                } catch (NoSuchObjectException ex) {
81                }
82                return;
83            }
84        }
85
86        mesg("unable to inactivate after several attempts");
87        mesg("unexporting object forcibly instead");
88
89        try {
90            Activatable.unexportObject(remote, true);
91        } catch (NoSuchObjectException e) {
92        }
93    }
94
95    /**
96     * Simple method call to see if rmid is running.
97     *
98     * This method intentionally avoids performing a lookup on the
99     * activation system.
100     */
101    public static boolean rmidRunning(int port) {
102        int allowedNotReady = 10;
103        int connectionRefusedExceptions = 0;
104
105        for (int i = 0; i < 15 ; i++) {
106
107            try {
108                Thread.sleep(500);
109                LocateRegistry.getRegistry(port).lookup(SYSTEM_NAME);
110                return true;
111
112            } catch (java.rmi.ConnectException e) {
113                // ignore connect exceptions until we decide rmid is not up
114
115                if ((connectionRefusedExceptions ++) >= allowedNotReady) {
116                    return false;
117                }
118
119            } catch (NotBoundException e) {
120
121                return false;
122
123            } catch (Exception e) {
124                // print out other types of exceptions as an FYI.
125                // test should not fail as rmid is likely to be in an
126                // undetermined state at this point.
127
128                mesg("caught an exception trying to" +
129                     " start rmid, last exception was: " +
130                     e.getMessage());
131                e.printStackTrace();
132            }
133        }
134        return false;
135    }
136
137    /**
138     * Check to see if an arry of Strings contains a given string.
139     */
140    private static boolean
141        containsString(String[] strings, String contained)
142    {
143        if (strings == null) {
144            if (contained == null) {
145                return true;
146            }
147            return false;
148        }
149
150        for (int i = 0 ; i < strings.length ; i ++ ) {
151            if ((strings[i] != null) &&
152                (strings[i].indexOf(contained) >= 0))
153            {
154                return true;
155            }
156        }
157        return false;
158    }
159
160    /** cleanup after rmid */
161    public static void rmidCleanup(RMID rmid) {
162        rmidCleanup(rmid, TestLibrary.RMID_PORT);
163    }
164
165    public static void rmidCleanup(RMID rmid, int port) {
166        if (rmid != null) {
167            if (!ActivationLibrary.safeDestroy(rmid, port, SAFE_WAIT_TIME)) {
168                TestLibrary.bomb("rmid not destroyed in: " +
169                                 SAFE_WAIT_TIME +
170                                 " milliseconds");
171            }
172        }
173        RMID.removeLog();
174    }
175
176    /**
177     * Invoke shutdown on rmid in a way that will not cause a test
178     * to hang.
179     *
180     * @return whether or not shutdown completed succesfully in the
181     *         timeAllowed
182     */
183    private static boolean safeDestroy(RMID rmid, int port, long timeAllowed) {
184        DestroyThread destroyThread = new DestroyThread(rmid, port);
185        destroyThread.start();
186
187        try {
188            destroyThread.join(timeAllowed);
189        } catch (InterruptedException ie) {
190            Thread.currentThread().interrupt();
191        }
192
193        return destroyThread.shutdownSucceeded();
194    }
195
196    /**
197     * Thread class to handle the destruction of rmid
198     */
199    private static class DestroyThread extends Thread {
200        private final RMID rmid;
201        private final int port;
202        private boolean succeeded = false;
203
204        DestroyThread(RMID rmid, int port) {
205            this.rmid = rmid;
206            this.port = port;
207            this.setDaemon(true);
208        }
209
210        public void run() {
211            if (ActivationLibrary.rmidRunning(port)) {
212                rmid.destroy();
213                synchronized (this) {
214                    // flag that the test was able to shutdown rmid
215                    succeeded = true;
216                }
217                mesg("finished destroying rmid");
218            } else {
219                mesg("tried to shutdown when rmid was not running");
220            }
221        }
222
223        public synchronized boolean shutdownSucceeded() {
224            return succeeded;
225        }
226    }
227}
228