blob: 83129be00d35596c2a2a58ce87905ccead301e56 [file] [log] [blame]
package org.eclipse.jdi.internal.connect;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.util.LinkedList;
import java.util.ListIterator;
import org.eclipse.jdi.TimeoutException;
import org.eclipse.jdi.internal.VirtualMachineImpl;
import org.eclipse.jdi.internal.jdwp.JdwpCommandPacket;
import org.eclipse.jdi.internal.jdwp.JdwpPacket;
import org.eclipse.jdi.internal.jdwp.JdwpReplyPacket;
import com.sun.jdi.VMDisconnectedException;
/**
* This class implements a thread that receives packets from the Virtual Machine.
*
*/
public class PacketReceiveManager extends PacketManager {
/** Generic timeout value for not blocking. */
public static final int TIMEOUT_NOT_BLOCKING = 0;
/** Generic timeout value for infinite timeout. */
public static final int TIMEOUT_INFINITE = -1;
/** Virtual Machine. */
private VirtualMachineImpl fVM;
/** Input Stream from Virtual Machine. */
private InputStream fInStream;
/** List of Command packets received from Virtual Machine. */
private LinkedList fCommandPackets;
/** List of Reply packets received from Virtual Machine. */
private LinkedList fReplyPackets;
/**
* Create a new thread that receives packets from the Virtual Machine.
*/
public PacketReceiveManager(ConnectorImpl connector) {
super(connector);
try {
fVM = connector.virtualMachine();
fInStream = connector.getInputStream();
fCommandPackets = new LinkedList();
fReplyPackets = new LinkedList();
} catch (IOException e) {
disconnectVM();
}
}
/**
* Thread's run method.
*/
public void run() {
try {
while (true) {
// Read a packet from the input stream.
readAvailablePacket();
}
} catch (InterruptedIOException e) {
// Stop running.
} catch (IOException e) {
disconnectVM();
}
}
/**
* @return Returns a specified Command Packet from the Virtual Machine.
*/
public synchronized JdwpCommandPacket getCommand(int command, long timeToWait) throws InterruptedException {
JdwpCommandPacket packet = null;
long remainingTime = timeToWait;
long timeBeforeWait;
long waitedTime;
// Wait until command is available.
while (!VMIsDisconnected()
&& (packet = removeCommandPacket(command)) == null
&& (timeToWait < 0 || remainingTime > 0)) {
timeBeforeWait = System.currentTimeMillis();
waitForPacketAvailable(timeToWait);
waitedTime = System.currentTimeMillis() - timeBeforeWait;
remainingTime -= waitedTime;
}
// Check for an IO Exception.
if (VMIsDisconnected())
throw new VMDisconnectedException(ConnectMessages.getString("PacketReceiveManager.Got_IOException_from_Virtual_Machine_1")); //$NON-NLS-1$
// Check for a timeout.
if (packet == null)
throw new TimeoutException();
return packet;
}
/**
* @return Returns a specified Reply Packet from the Virtual Machine.
*/
public synchronized JdwpReplyPacket getReply(int id, long timeToWait) {
JdwpReplyPacket packet = null;
long remainingTime = timeToWait;
long timeBeforeWait;
long waitedTime;
// Wait until reply is available.
while (!VMIsDisconnected()
&& (packet = removeReplyPacket(id)) == null
&& (timeToWait < 0 || remainingTime > 0)) {
timeBeforeWait = System.currentTimeMillis();
try {
waitForPacketAvailable(remainingTime);
} catch (InterruptedException e) {
}
waitedTime = System.currentTimeMillis() - timeBeforeWait;
remainingTime -= waitedTime;
}
// Check for an IO Exception.
if (VMIsDisconnected())
throw new VMDisconnectedException(ConnectMessages.getString("PacketReceiveManager.Got_IOException_from_Virtual_Machine_2")); //$NON-NLS-1$
// Check for a timeout.
if (packet == null)
throw new TimeoutException();
return packet;
}
/**
* @return Returns a specified Reply Packet from the Virtual Machine.
*/
public JdwpReplyPacket getReply(JdwpCommandPacket commandPacket) {
return getReply(commandPacket.getId(), fVM.getRequestTimeout());
}
/**
* Wait for an available packet from the Virtual Machine.
*/
private void waitForPacketAvailable(long timeToWait) throws InterruptedException {
if (timeToWait == 0)
return;
else if (timeToWait < 0)
wait();
else
wait(timeToWait);
}
/**
* @return Returns and removes a specified command packet from the command packet list.
*/
private JdwpCommandPacket removeCommandPacket(int command) {
ListIterator iter = fCommandPackets.listIterator();
while (iter.hasNext()) {
JdwpCommandPacket packet = (JdwpCommandPacket)iter.next();
if (packet.getCommand() == command) {
iter.remove();
return packet;
}
}
return null;
}
/**
* @return Returns a specified reply packet from the reply packet list.
*/
private JdwpReplyPacket removeReplyPacket(int id) {
ListIterator iter = fReplyPackets.listIterator();
while (iter.hasNext()) {
JdwpReplyPacket packet = (JdwpReplyPacket)iter.next();
if (packet.getId() == id) {
iter.remove();
return packet;
}
}
return null;
}
/**
* Add a command packet to the command packet list.
*/
private synchronized void addCommandPacket(JdwpCommandPacket packet) {
fCommandPackets.add(packet);
notifyAll();
}
/**
* Add a reply packet to the reply packet list.
*/
private synchronized void addReplyPacket(JdwpReplyPacket packet) {
fReplyPackets.add(packet);
notifyAll();
}
/**
* Read a packet from the input stream and add it to the appropriate packet list.
*/
private void readAvailablePacket() throws IOException {
// Read a packet from the Input Stream.
JdwpPacket packet = JdwpPacket.read(fInStream);
// Add packet to command or reply queue.
if (packet instanceof JdwpCommandPacket)
addCommandPacket((JdwpCommandPacket)packet);
else
addReplyPacket((JdwpReplyPacket)packet);
}
}