Method: DbgpPacketReceiver.ResponcePacketWaiter()

1: /*
2: * #%~
3: * org.overture.ide.debug
4: * %%
5: * Copyright (C) 2008 - 2014 Overture
6: * %%
7: * This program is free software: you can redistribute it and/or modify
8: * it under the terms of the GNU General Public License as
9: * published by the Free Software Foundation, either version 3 of the
10: * License, or (at your option) any later version.
11: *
12: * This program is distributed in the hope that it will be useful,
13: * but WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: * GNU General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public
18: * License along with this program. If not, see
19: * <http://www.gnu.org/licenses/gpl-3.0.html>.
20: * #~%
21: */
22: package org.overture.ide.debug.core.dbgp.internal.packets;
23:
24: import java.io.InputStream;
25: import java.util.HashMap;
26: import java.util.LinkedList;
27:
28: import org.overture.ide.debug.core.dbgp.internal.DbgpRawPacket;
29: import org.overture.ide.debug.core.dbgp.internal.DbgpWorkingThread;
30: import org.overture.ide.debug.core.dbgp.internal.utils.DbgpXmlPacketParser;
31: import org.w3c.dom.Document;
32: import org.w3c.dom.Element;
33:
34: public class DbgpPacketReceiver extends DbgpWorkingThread
35: {
36:         private static class ResponcePacketWaiter
37:         {
38:                 // private static final int MIN_TIMEOUT = 5;
39:                 private final HashMap<Integer, DbgpResponsePacket> map;
40:                 private boolean terminated;
41:
42:                 public ResponcePacketWaiter()
43:                 {
44:                         map = new HashMap<Integer, DbgpResponsePacket>();
45:                         terminated = false;
46:                 }
47:
48:                 public synchronized void put(DbgpResponsePacket packet)
49:                 {
50:                         int id = packet.getTransactionId();
51:                         map.put(new Integer(id), packet);
52:                         notifyAll();
53:                 }
54:
55:                 public synchronized DbgpResponsePacket waitPacket(int id, int timeout)
56:                                 throws InterruptedException
57:                 {
58:                         Integer key = new Integer(id);
59:                         long endTime = 0;
60:                         if (timeout > 0)
61:                         {
62:                                 endTime = System.currentTimeMillis() + timeout;
63:                         }
64:                         while (!terminated && !map.containsKey(key))
65:                         {
66:                                 long current = System.currentTimeMillis();
67:                                 if (endTime != 0 && current >= endTime)
68:                                 {
69:                                         break;
70:                                 }
71:                                 if (endTime == 0)
72:                                 {
73:                                         wait();
74:                                 } else
75:                                 {
76:                                         wait(endTime - current);
77:                                 }
78:                         }
79:
80:                         if (map.containsKey(key))
81:                         {
82:                                 return (DbgpResponsePacket) map.remove(key);
83:                         }
84:
85:                         if (terminated)
86:                         {
87:                                 System.out.println("failed to get response for packet: " + id);
88:                                 throw new InterruptedException("responsePacketWaiterTerminated");
89:                         }
90:                         System.out.println("failed to get response for packet: " + id);
91:                         return null;
92:                 }
93:
94:                 public synchronized void terminate()
95:                 {
96:                         terminated = true;
97:                         notifyAll();
98:                 }
99:         }
100:
101:         private static class PacketWaiter
102:         {
103:                 private final LinkedList<DbgpPacket> queue;
104:                 private boolean terminated;
105:
106:                 public PacketWaiter()
107:                 {
108:                         terminated = false;
109:                         this.queue = new LinkedList<DbgpPacket>();
110:                 }
111:
112:                 public synchronized void put(DbgpPacket obj)
113:                 {
114:                         queue.addLast(obj);
115:                         notifyAll();
116:                 }
117:
118:                 public synchronized DbgpPacket waitPacket() throws InterruptedException
119:                 {
120:                         while (!terminated && queue.isEmpty())
121:                         {
122:                                 wait();
123:                         }
124:
125:                         if (terminated)
126:                         {
127:                                 throw new InterruptedException("packetWaiterTerminated");
128:                         }
129:
130:                         return (DbgpPacket) queue.removeFirst();
131:                 }
132:
133:                 public synchronized void terminate()
134:                 {
135:                         terminated = true;
136:                         notifyAll();
137:                 }
138:         }
139:
140:         private static final String INIT_TAG = "init"; //$NON-NLS-1$
141:         private static final String RESPONSE_TAG = "response"; //$NON-NLS-1$
142:         private static final String STREAM_TAG = "stream"; //$NON-NLS-1$
143:         private static final String NOTIFY_TAG = "notify"; //$NON-NLS-1$
144:         private static final String XCMD_OVERTURE_RESPONSE_TAG = "xcmd_overture_response"; //$NON-NLS-1$
145:
146:         private final ResponcePacketWaiter responseWaiter;
147:         private final PacketWaiter notifyWaiter;
148:         private final PacketWaiter streamWaiter;
149:
150:         private final InputStream input;
151:         private IDbgpRawLogger logger;
152:
153:         protected void workingCycle() throws Exception
154:         {
155:                 try
156:                 {
157:                         while (!Thread.interrupted())
158:                         {
159:                                 DbgpRawPacket packet = DbgpRawPacket.readPacket(input);
160:
161:                                 if (logger != null)
162:                                 {
163:                                         logger.log(packet);
164:                                 }
165:
166:                                 addDocument(packet.getParsedXml());
167:                         }
168:                 } finally
169:                 {
170:                         responseWaiter.terminate();
171:                         notifyWaiter.terminate();
172:                         streamWaiter.terminate();
173:                 }
174:         }
175:
176:         protected void addDocument(Document doc)
177:         {
178:                 Element element = (Element) doc.getFirstChild();
179:                 String tag = element.getTagName();
180:
181:                 // TODO: correct init tag handling without this hack
182:                 if (tag.equals(INIT_TAG))
183:                 {
184:                         responseWaiter.put(new DbgpResponsePacket(element, -1));
185:                 } else if (tag.equals(RESPONSE_TAG))
186:                 {
187:                         DbgpResponsePacket packet = DbgpXmlPacketParser.parseResponsePacket(element);
188:
189:                         responseWaiter.put(packet);
190:                 } else if (tag.equals(STREAM_TAG))
191:                 {
192:                         streamWaiter.put(DbgpXmlPacketParser.parseStreamPacket(element));
193:                 } else if (tag.equals(NOTIFY_TAG))
194:                 {
195:                         notifyWaiter.put(DbgpXmlPacketParser.parseNotifyPacket(element));
196:                 }else if (tag.equals(XCMD_OVERTURE_RESPONSE_TAG)) {
197:                         DbgpResponsePacket packet = DbgpXmlPacketParser.parseResponsePacket(element);
198:
199:                         responseWaiter.put(packet);
200:                 }
201:         }
202:
203:         public DbgpNotifyPacket getNotifyPacket() throws InterruptedException
204:         {
205:                 return (DbgpNotifyPacket) notifyWaiter.waitPacket();
206:         }
207:
208:         public DbgpStreamPacket getStreamPacket() throws InterruptedException
209:         {
210:                 return (DbgpStreamPacket) streamWaiter.waitPacket();
211:         }
212:
213:         public DbgpResponsePacket getResponsePacket(int transactionId, int timeout)
214:                         throws InterruptedException
215:         {
216:                 return responseWaiter.waitPacket(transactionId, timeout);
217:         }
218:
219:         public DbgpPacketReceiver(InputStream input)
220:         {
221:                 super("DBGP - Packet receiver"); //$NON-NLS-1$
222:
223:                 if (input == null)
224:                 {
225:                         throw new IllegalArgumentException();
226:                 }
227:
228:                 this.input = input;
229:                 this.notifyWaiter = new PacketWaiter();
230:                 this.streamWaiter = new PacketWaiter();
231:                 this.responseWaiter = new ResponcePacketWaiter();
232:         }
233:
234:         public void setLogger(IDbgpRawLogger logger)
235:         {
236:                 this.logger = logger;
237:         }
238: }