KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdi > internal > connect > PacketReceiveManager


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdi.internal.connect;
12
13 import java.io.IOException JavaDoc;
14 import java.io.InterruptedIOException JavaDoc;
15 import java.util.ArrayList JavaDoc;
16 import java.util.LinkedList JavaDoc;
17 import java.util.ListIterator JavaDoc;
18
19 import org.eclipse.jdi.TimeoutException;
20 import org.eclipse.jdi.internal.VirtualMachineImpl;
21 import org.eclipse.jdi.internal.jdwp.JdwpCommandPacket;
22 import org.eclipse.jdi.internal.jdwp.JdwpPacket;
23 import org.eclipse.jdi.internal.jdwp.JdwpReplyPacket;
24
25 import com.ibm.icu.text.MessageFormat;
26 import com.sun.jdi.VMDisconnectedException;
27 import com.sun.jdi.connect.spi.Connection;
28
29 /**
30  * This class implements a thread that receives packets from the Virtual
31  * Machine.
32  *
33  */

34 public class PacketReceiveManager extends PacketManager {
35
36     /** Generic timeout value for not blocking. */
37     public static final int TIMEOUT_NOT_BLOCKING = 0;
38
39     /** Generic timeout value for infinite timeout. */
40     public static final int TIMEOUT_INFINITE = -1;
41
42     /** List of Command packets received from Virtual Machine. */
43     private LinkedList JavaDoc fCommandPackets;
44
45     /** List of Reply packets received from Virtual Machine. */
46     private LinkedList JavaDoc fReplyPackets;
47
48     /** List of Packets that have timed out already. Maintained so that responses can be
49      * discarded if/when they are received. */

50     private ArrayList JavaDoc fTimedOutPackets;
51     
52     private VirtualMachineImpl fVM;
53
54     /**
55      * Create a new thread that receives packets from the Virtual Machine.
56      */

57     public PacketReceiveManager(Connection connection, VirtualMachineImpl vmImpl) {
58         super(connection);
59         fVM = vmImpl;
60         fCommandPackets = new LinkedList JavaDoc();
61         fReplyPackets = new LinkedList JavaDoc();
62         fTimedOutPackets = new ArrayList JavaDoc();
63     }
64
65     public void disconnectVM() {
66         super.disconnectVM();
67         synchronized (fCommandPackets) {
68             fCommandPackets.notifyAll();
69         }
70         synchronized (fReplyPackets) {
71             fReplyPackets.notifyAll();
72         }
73     }
74
75     /**
76      * Thread's run method.
77      */

78     public void run() {
79         try {
80             while (!VMIsDisconnected()) {
81                 // Read a packet from the input stream.
82
readAvailablePacket();
83             }//end while
84
}//end try
85
//if the remote VM is interrupted, drop the connection and clean up, don't wait for it to happen on its own
86
catch (InterruptedIOException JavaDoc e) {disconnectVM(e);}
87         catch (IOException JavaDoc e) {disconnectVM(e);}
88     }
89
90     /**
91      * @return Returns a specified Command Packet from the Virtual Machine.
92      */

93     public JdwpCommandPacket getCommand(int command, long timeToWait) throws InterruptedException JavaDoc {
94         JdwpCommandPacket packet = null;
95         synchronized (fCommandPackets) {
96             long remainingTime = timeToWait;
97             long timeBeforeWait;
98             long waitedTime;
99
100             // Wait until command is available.
101
while (!VMIsDisconnected() && (packet = removeCommandPacket(command)) == null && (timeToWait < 0 || remainingTime > 0)) {
102                 timeBeforeWait = System.currentTimeMillis();
103                 waitForPacketAvailable(remainingTime, fCommandPackets);
104                 waitedTime = System.currentTimeMillis() - timeBeforeWait;
105                 remainingTime -= waitedTime;
106             }//end while
107
}//end sync
108
// Check for an IO Exception.
109
if (VMIsDisconnected()) {
110             String JavaDoc message;
111             if (getDisconnectException() == null) {
112                 message = ConnectMessages.PacketReceiveManager_Got_IOException_from_Virtual_Machine_1;
113             }//end if
114
else {
115                 String JavaDoc exMessage = getDisconnectException().getMessage();
116                 if (exMessage == null) {
117                     message = MessageFormat.format(ConnectMessages.PacketReceiveManager_Got__0__from_Virtual_Machine_1, new String JavaDoc[] { getDisconnectException().getClass().getName() });
118                 }//end if
119
else {
120                     message = MessageFormat.format(ConnectMessages.PacketReceiveManager_Got__0__from_Virtual_Machine___1__1, new String JavaDoc[] { getDisconnectException().getClass().getName(), exMessage });
121                 }//end else
122
}//end else
123
throw new VMDisconnectedException(message);
124         }
125         // Check for a timeout.
126
if (packet == null) {
127             throw new TimeoutException();
128         }//end if
129
return packet;
130     }
131
132     /**
133      * @return Returns a specified Reply Packet from the Virtual Machine.
134      */

135     public JdwpReplyPacket getReply(int id, long timeToWait) {
136         JdwpReplyPacket packet = null;
137         long remainingTime = timeToWait;
138         synchronized (fReplyPackets) {
139             final long timeBeforeWait = System.currentTimeMillis();
140             // Wait until reply is available.
141
while (!VMIsDisconnected() && remainingTime > 0) {
142                 packet = removeReplyPacket(id);
143                 if (packet != null) {
144                     break;
145                 }//end if
146
try {
147                     waitForPacketAvailable(remainingTime, fReplyPackets);
148                 }//end try
149
// if the remote VM is interrupted DO NOT drop the connection - see bug 171075
150
// just stop waiting for the reply and treat it as a timeout
151
catch (InterruptedException JavaDoc e) {
152                     break;
153                 }
154                 long waitedTime = System.currentTimeMillis() - timeBeforeWait;
155                 remainingTime = timeToWait - waitedTime;
156             }//end while
157
}//end sync
158
if (packet == null) {
159             synchronized (fReplyPackets) {
160                 packet = removeReplyPacket(id);
161             }//end sync
162
}//end if
163
// Check for an IO Exception.
164
if (VMIsDisconnected())
165             throw new VMDisconnectedException(ConnectMessages.PacketReceiveManager_Got_IOException_from_Virtual_Machine_2);
166         // Check for a timeout.
167
if (packet == null) {
168             synchronized (fTimedOutPackets) {
169                 fTimedOutPackets.add(new Integer JavaDoc(id));
170             }//end sync
171
throw new TimeoutException(MessageFormat.format(ConnectMessages.PacketReceiveManager_0, new String JavaDoc[] {id+""})); //$NON-NLS-1$
172
}//end if
173
return packet;
174     }
175
176     /**
177      * @return Returns a specified Reply Packet from the Virtual Machine.
178      */

179     public JdwpReplyPacket getReply(JdwpCommandPacket commandPacket) {
180         return getReply(commandPacket.getId(), fVM.getRequestTimeout());
181     }
182
183     /**
184      * Wait for an available packet from the Virtual Machine.
185      */

186     private void waitForPacketAvailable(long timeToWait, Object JavaDoc lock) throws InterruptedException JavaDoc {
187         if (timeToWait == 0)
188             return;
189         else if (timeToWait < 0)
190             lock.wait();
191         else
192             lock.wait(timeToWait);
193     }
194
195     /**
196      * @return Returns and removes a specified command packet from the command
197      * packet list.
198      */

199     private JdwpCommandPacket removeCommandPacket(int command) {
200         ListIterator JavaDoc iter = fCommandPackets.listIterator();
201         while (iter.hasNext()) {
202             JdwpCommandPacket packet = (JdwpCommandPacket) iter.next();
203             if (packet.getCommand() == command) {
204                 iter.remove();
205                 return packet;
206             }
207         }
208         return null;
209     }
210
211     /**
212      * @return Returns a specified reply packet from the reply packet list.
213      */

214     private JdwpReplyPacket removeReplyPacket(int id) {
215         ListIterator JavaDoc iter = fReplyPackets.listIterator();
216         while (iter.hasNext()) {
217             JdwpReplyPacket packet = (JdwpReplyPacket) iter.next();
218             if (packet.getId() == id) {
219                 iter.remove();
220                 return packet;
221             }
222         }
223         return null;
224     }
225
226     /**
227      * Add a command packet to the command packet list.
228      */

229     private void addCommandPacket(JdwpCommandPacket packet) {
230         if (isTimedOut(packet)) {
231             return; // already timed out. No need to keep this one
232
}
233         synchronized (fCommandPackets) {
234             fCommandPackets.add(packet);
235             fCommandPackets.notifyAll();
236         }
237     }
238     
239     /**
240      * Returns whether the request for the given packet has already timed out.
241      *
242      * @param packet response packet
243      * @return whether the request for the given packet has already timed out
244      */

245     private boolean isTimedOut(JdwpPacket packet) {
246         synchronized (fTimedOutPackets) {
247             if (fTimedOutPackets.isEmpty()) {
248                 return false;
249             }
250             Integer JavaDoc id = new Integer JavaDoc(packet.getId());
251             return fTimedOutPackets.remove(id);
252         }
253     }
254
255     /**
256      * Add a reply packet to the reply packet list.
257      */

258     private void addReplyPacket(JdwpReplyPacket packet) {
259        if (isTimedOut(packet)) {
260            return; // already timed out. No need to keep this one
261
}
262         synchronized (fReplyPackets) {
263             fReplyPackets.add(packet);
264             fReplyPackets.notifyAll();
265         }
266     }
267
268     /**
269      * Read a packet from the input stream and add it to the appropriate packet
270      * list.
271      */

272     private void readAvailablePacket() throws IOException JavaDoc {
273         // Read a packet from the Input Stream.
274
byte[] bytes = getConnection().readPacket();
275         JdwpPacket packet = JdwpPacket.build(bytes);
276         // Add packet to command or reply queue.
277
if (packet instanceof JdwpCommandPacket)
278             addCommandPacket((JdwpCommandPacket) packet);
279         else
280             addReplyPacket((JdwpReplyPacket) packet);
281     }
282 }
283
Popular Tags