blob: da70385dd9aa92309fe59f4917b246525bde0594 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jem.internal.proxy.remote;
/*
*/
import java.io.*;
import java.net.*;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jem.internal.proxy.core.ProxyPlugin;
import org.eclipse.jem.internal.proxy.common.remote.Commands;
/**
* Master Server thread for the Remote VMs.
*
* It responds to the remote vm requests to this IDE.
*
* It is package-protected because only ProxyRemotePluguin should access it.
* @author richkulp
*/
class REMMasterServerThread extends Thread {
protected ServerSocket masterServerSocket;
protected REMRegistryController registryController;
protected boolean shuttingDown = false;
// Kludge: Bug in Linux 1.3.xxx of JVM. Closing a socket while the socket is being read/accept will not interrupt the
// wait. Need to timeout to the socket read/accept before the socket close will be noticed. This has been fixed
// in Linux 1.4. So on Linux 1.3 need to put timeouts in on those sockets that can be separately closed while reading/accepting.
static boolean LINUX_1_3 = "linux".equalsIgnoreCase(System.getProperty("os.name")) && System.getProperty("java.version","").startsWith("1.3"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
public REMMasterServerThread(REMRegistryController registryController) {
super("Remote Proxy Master Server Thread"); //$NON-NLS-1$
this.registryController = registryController;
try {
masterServerSocket = new ServerSocket(0, 50, InetAddress.getByName("localhost")); // Any available port //$NON-NLS-1$
if (LINUX_1_3)
masterServerSocket.setSoTimeout(1000); // Linux 1.3 bug, see comment on LINUX_1_3
} catch (SocketException e) {
ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.ERROR, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e)); // This is bad. Should be no exceptions creating a socket. //$NON-NLS-1$
} catch (IOException e) {
ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.ERROR, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e)); // This is bad. Should be no exceptions creating a socket. //$NON-NLS-1$
}
}
public ServerSocket getMasterSocket() {
return masterServerSocket;
}
/**
* @see java.lang.Thread#run()
*/
public void run() {
try {
while (masterServerSocket != null) {
Socket incoming = null;
try {
incoming = masterServerSocket.accept();
} catch (InterruptedIOException e) {
continue; // Timeout, try again
} catch (NullPointerException e) {
continue; // In Linux 1.3 case masterServerSocket could of gone null between loop test and try block.
}
boolean close = false; // process request will tell if socket should be closed. it may be passed onto callback thread instead.
try {
close = processRequest(incoming);
} finally {
if (close) {
try {
incoming.close();
} catch (IOException e) {
}
}
}
incoming = null;
}
} catch (Exception e) {
if (!shuttingDown)
ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.ERROR, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e)); //$NON-NLS-1$
}
shutdown(); // Either a bad exception or we were closed. Either way is shutdown.
}
/**
* Use this to request a shutdown.
*/
public void requestShutdown() {
if (masterServerSocket == null)
return;
// Closing the server socket should cause a break.
try {
shuttingDown = true;
masterServerSocket.close();
} catch (Exception e) {
}
return;
}
protected boolean processRequest(Socket remote) throws IOException {
DataInputStream in = new DataInputStream(remote.getInputStream());
DataOutputStream out = new DataOutputStream(remote.getOutputStream());
boolean close = true; // flag indicating socket not given over to callback. Don't close the socket when done because callback has it.
try {
byte cmd = in.readByte();
switch (cmd) {
case Commands.ALIVE:
int registryID = in.readInt();
out.writeBoolean(registryController.getRegistry(new Integer(registryID)) != null); // Return if registry still alive
out.flush();
break;
case Commands.REMOTE_STARTED:
registryID = in.readInt();
int remoteServerPort = in.readInt();
REMProxyFactoryRegistry registry = registryController.getRegistry(new Integer(registryID));
if (registry != null) {
registry.setServerPort(remoteServerPort);
out.writeBoolean(true);
} else
out.writeBoolean(false); // No registry
out.flush();
break;
case Commands.ATTACH_CALLBACK:
registryID = in.readInt();
registry = registryController.getRegistry(new Integer(registryID));
if (registry != null) {
close = !((REMCallbackRegistry) registry.getCallbackRegistry()).createCallback(remote); // close if failed, don't close if good.
out.writeBoolean(!close); // if not close, then return it worked.
} else
out.writeBoolean(false);
out.flush();
break;
}
} catch (Exception e) {
ProxyPlugin.getPlugin().getLogger().log(new Status(IStatus.ERROR, ProxyPlugin.getPlugin().getBundle().getSymbolicName(), 0, "", e)); //$NON-NLS-1$
} finally {
if (close) {
try {
in.close();
} catch (IOException e) {
}
try {
out.close();
} catch (IOException e) {
}
}
}
return close;
}
private void shutdown() {
requestShutdown();
masterServerSocket = null;
}
}