KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > rice > cs > util > newjvm > SlaveJVMRunner


1 /*BEGIN_COPYRIGHT_BLOCK
2  *
3  * This file is part of DrJava. Download the current version of this project from http://www.drjava.org/
4  * or http://sourceforge.net/projects/drjava/
5  *
6  * DrJava Open Source License
7  *
8  * Copyright (C) 2001-2006 JavaPLT group at Rice University (javaplt@rice.edu). All rights reserved.
9  *
10  * Developed by: Java Programming Languages Team, Rice University, http://www.cs.rice.edu/~javaplt/
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
13  * documentation files (the "Software"), to deal with the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
15  * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
16  *
17  * - Redistributions of source code must retain the above copyright notice, this list of conditions and the
18  * following disclaimers.
19  * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
20  * following disclaimers in the documentation and/or other materials provided with the distribution.
21  * - Neither the names of DrJava, the JavaPLT, Rice University, nor the names of its contributors may be used to
22  * endorse or promote products derived from this Software without specific prior written permission.
23  * - Products derived from this software may not be called "DrJava" nor use the term "DrJava" as part of their
24  * names without prior written permission from the JavaPLT group. For permission, write to javaplt@rice.edu.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
27  * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28  * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
29  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30  * WITH THE SOFTWARE.
31  *
32  *END_COPYRIGHT_BLOCK*/

33
34 package edu.rice.cs.util.newjvm;
35
36 import java.io.*;
37 //import java.net.InetAddress;
38
//import java.net.InetSocketAddress;
39
import java.rmi.server.UnicastRemoteObject JavaDoc;
40 import java.rmi.RemoteException JavaDoc;
41
42 import java.util.Arrays JavaDoc;
43   
44 import edu.rice.cs.util.Log;
45 import edu.rice.cs.util.StringOps;
46 import edu.rice.cs.util.UnexpectedException;
47 import edu.rice.cs.util.swing.ScrollableDialog;
48 import edu.rice.cs.util.swing.Utilities;
49 //import edu.rice.cs.util.PreventExitSecurityManager;
50

51 import static edu.rice.cs.drjava.config.OptionConstants.*;
52
53 /** This class is the root class for the Slave JVM. The Master JVM invokes the {@link #main} method of this class,
54  * which is never instantiated. See the {@link #main} method documentation for information on the command line
55  * parameters this class requires. If there is an error setting up the slave JVM before the RMI links can be
56  * established, this JVM process will exit with an error code according to the following list:
57  * <DL>
58  * <DT>1</DT><DD>Invalid number of command line arguments.</DD>
59  * <DT>2</DT><DD>Error deserializing remote stub</DD>
60  * <DT>3</DT><DD>Error instantiating slave implementation class</DD>
61  * </DL>
62  * If the slave JVM completes successfully, it will exit with code 0.
63  *
64  * @version $Id: SlaveJVMRunner.java 4011 2006-09-22 15:31:42Z rcartwright $
65  */

66 public final class SlaveJVMRunner {
67
68   /** Whether Swing dialogs should be displayed with diagnostic
69    * information if the slave is unable to register or contact the
70    * main JVM. If false, the information will be printed to (the
71    * usually invisible) System.err.
72    *
73    * Note that the master JVM will always be notified if possible if
74    * there is a problem instantiating or registering the slave, so
75    * it can take appropriate action. This flag only affects those
76    * situations in which the master JVM cannot be contacted.
77    */

78   public static final boolean SHOW_DEBUG_DIALOGS = false;
79   
80   protected static final Log _log = new Log("MasterSlave.txt", false);
81   
82   private static final long RMI_TIMEOUT = 5000L;
83   
84   private static Thread JavaDoc _main;
85   
86   private static volatile boolean _notDone;
87  
88   /** Private constructor to prevent instantiation. */
89   private SlaveJVMRunner() { }
90
91   private static AbstractSlaveJVM _getInstance(Class JavaDoc clazz) throws Exception JavaDoc {
92     try { return (AbstractSlaveJVM) clazz.getField("ONLY").get(null); }
93     catch (Throwable JavaDoc t) {
94       _log.log("SlaveRemote class does not have an ONLY field!");
95       return (AbstractSlaveJVM) clazz.newInstance();
96     }
97   }
98
99   /** The main method for invoking a slave JVM.
100    *
101    * @param args Command-line parameters, of which there must be two or three. The first is the absolute path to the
102    * file containing the serialized MasterRemote stub, and the second is the fully-qualified class name of the
103    * slave JVM implementation class.
104    */

105   public synchronized static void main(String JavaDoc[] args) {
106     try {
107       // Make sure RMI doesn't use an IP address that might change
108
System.setProperty("java.rmi.server.hostname", "127.0.0.1");
109       
110       if (args.length != 3 && args.length != 2) System.exit(1);
111       
112       _notDone = true;
113         
114       _main = Thread.currentThread();
115       
116
117       // get the master remote
118
final FileInputStream fstream = new FileInputStream(args[0]);
119       final ObjectInputStream ostream = new ObjectInputStream(new BufferedInputStream(fstream));
120       
121       _log.log("Slave JVM reading master remote stub from file " + args[0] + " with " +
122                  fstream.getChannel().size() + " bytes");
123       
124 /* The following code currently breaks unit tests and DrJava itself when it detects the hanging
125  * of readObject(...). It can be commented back if the calling code is revised to handle this form
126  * of exit. */

127       
128 // Thread timeout = new Thread("RMI Timeout Thread") {
129
// public void run() {
130
// _log.log("RMI timer started");
131
//
132
// final Object lock = new Object();
133
// try { synchronized(lock) { lock.wait(RMI_TIMEOUT); } }
134
// catch(InterruptedException e) { throw new UnexpectedException(e); }
135
// // Abort starting this slave JVM if readObject has hung
136
// if (_notDone) {
137
// StackTraceElement[] trace = Thread.getAllStackTraces().get(_main);
138
// _log.log("DUMP of hung deserializing thread:", trace);
139
// System.exit(9);
140
// }
141
// else _log.log(this + " TERMINATED normally");
142
// }
143
// };
144
//
145
// timeout.setDaemon(true);
146
// timeout.start();
147

148       
149 // // Loading the class that intermittently hangs first readObject(...) call below
150
// Class psi = Class.forName("java.net.PlainSocketImpl");
151

152       final MasterRemote masterRemote = (MasterRemote) ostream.readObject();
153       _notDone = false;
154       _log.log("SlaveJVMRunner completed reading " + masterRemote);
155       fstream.close();
156       ostream.close();
157       
158       AbstractSlaveJVM slave = null;
159
160       try {
161         Class JavaDoc slaveClass = Class.forName(args[1]);
162 // _log.log("Slave JVM created singleton of " + args[1]);
163
slave = _getInstance(slaveClass);
164         
165         //Export slave object to RMI, passing stub to the master JVM (how does stub get there? Transitivity?
166
// _log.log("Slave JVM exporting " + slave + " to RMI");
167
SlaveRemote slaveRemote = (SlaveRemote) UnicastRemoteObject.exportObject(slave);
168         _log.log("SlaveJVMRunner exported stub " + slaveRemote);
169
170         // start the slave and then notify the master
171
// _log.log("Slave JVM invoking the method " + slave + ".start(" + masterRemote + ")");
172
slave.start(masterRemote);
173         _log.log("SlaveJVMRunner invoking the method registerSlave(" + slave + ") in the Master JVM");
174         masterRemote.registerSlave(slave);
175       }
176       catch (Exception JavaDoc e) {
177         // Couldn't instantiate the slave.
178
_log.log("SlaveJVMRunner could not instantiate and start slave class '" + slave + "'. Threw exception: " + e);
179         try {
180           // Try to show the error properly, through the master
181
masterRemote.errorStartingSlave(e);
182         }
183         catch (RemoteException JavaDoc re) {
184           // Couldn't show the error properly, so use another approach
185
String JavaDoc msg = "SlaveJVMRunner could not instantiate and register the slave.\n" +
186             " Also failed to display error through master JVM, because:\n" +
187             StringOps.getStackTrace(re) + "\n";
188           _showErrorMessage(msg, e);
189         }
190         System.exit(3);
191       }
192     }
193     catch (Exception JavaDoc e) { // IOException, ClassNotFoundException
194
// There's no master to display the error, so we'll do it ourselves
195
_showErrorMessage("SlaveJVMRunner could not set up the Slave JVM.", e);
196       _log.log("SlaveJVMRunner could not set up the Slave JVM. Calling System.exit(2) in response to: " + e);
197       System.exit(2);
198     }
199   }
200
201   /** Displays a graphical error message to notify the user of a problem encountered while starting the slave JVM.
202    * @param cause A message indicating where the error took place.
203    * @param t The Throwable which caused the error.
204    */

205   private static void _showErrorMessage(String JavaDoc cause, Throwable JavaDoc t) {
206     String JavaDoc msg = "An error occurred in SlaveJVMRunner while starting the slave JVM:\n " +
207       cause + "\n\nOriginal error:\n" + StringOps.getStackTrace(t);
208     
209     _log.log("ERROR in SlaveJVMRunner: " + cause + "; threw " + t);
210
211     if (SHOW_DEBUG_DIALOGS) new ScrollableDialog(null, "Error", "Error details:", msg).show();
212     else if (! Utilities.TEST_MODE) System.out.println(msg);
213   }
214 }
215
Popular Tags