gt: 			throw new IllegalArgumentException();
context: /*
   * #%~
   * org.overture.ide.debug
   * %%
   * Copyright (C) 2008 - 2014 Overture
   * %%
   * This program is free software: you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as
   * published by the Free Software Foundation, either version 3 of the
   * License, or (at your option) any later version.
   * 
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   * 
   * You should have received a copy of the GNU General Public
   * License along with this program.  If not, see
   * <http://www.gnu.org/licenses/gpl-3.0.html>.
   * #~%
   */
  package org.overture.ide.debug.core.dbgp.internal.packets;
  
  import java.io.InputStream;
  import java.util.HashMap;
  import java.util.LinkedList;
  
  import org.overture.ide.debug.core.dbgp.internal.DbgpRawPacket;
  import org.overture.ide.debug.core.dbgp.internal.DbgpWorkingThread;
  import org.overture.ide.debug.core.dbgp.internal.utils.DbgpXmlPacketParser;
  import org.w3c.dom.Document;
  import org.w3c.dom.Element;
  
  public class DbgpPacketReceiver extends DbgpWorkingThread
  {
  	private static class ResponcePacketWaiter
  	{
  		// private static final int MIN_TIMEOUT = 5;
  		private final HashMap<Integer, DbgpResponsePacket> map;
  		private boolean terminated;
  
  		public ResponcePacketWaiter()
  		{
  			map = new HashMap<Integer, DbgpResponsePacket>();
  			terminated = false;
  		}
  
  		public synchronized void put(DbgpResponsePacket packet)
  		{
  			int id = packet.getTransactionId();
  			map.put(new Integer(id), packet);
  			notifyAll();
  		}
  
  		public synchronized DbgpResponsePacket waitPacket(int id, int timeout)
  				throws InterruptedException
  		{
  			Integer key = new Integer(id);
  			long endTime = 0;
  			if (timeout > 0)
  			{
  				endTime = System.currentTimeMillis() + timeout;
  			}
  			while (!terminated && !map.containsKey(key))
  			{
  				long current = System.currentTimeMillis();
  				if (endTime != 0 && current >= endTime)
  				{
  					break;
  				}
  				if (endTime == 0)
  				{
  					wait();
  				} else
  				{
  					wait(endTime - current);
  				}
  			}
  
  			if (map.containsKey(key))
  			{
  				return (DbgpResponsePacket) map.remove(key);
  			}
  
  			if (terminated)
  			{
  				System.out.println("failed to get response for packet: " + id);
  				throw new InterruptedException("responsePacketWaiterTerminated");
  			}
  			System.out.println("failed to get response for packet: " + id);
  			return null;
  		}
  
  		public synchronized void terminate()
  		{
  			terminated = true;
  			notifyAll();
  		}
  	}
  
  	private static class PacketWaiter
  	{
  		private final LinkedList<DbgpPacket> queue;
  		private boolean terminated;
  
  		public PacketWaiter()
  		{
  			terminated = false;
  			this.queue = new LinkedList<DbgpPacket>();
  		}
  
  		public synchronized void put(DbgpPacket obj)
  		{
  			queue.addLast(obj);
  			notifyAll();
  		}
  
  		public synchronized DbgpPacket waitPacket() throws InterruptedException
  		{
  			while (!terminated && queue.isEmpty())
  			{
  				wait();
  			}
  
  			if (terminated)
  			{
  				throw new InterruptedException("packetWaiterTerminated");
  			}
  
  			return (DbgpPacket) queue.removeFirst();
  		}
  
  		public synchronized void terminate()
  		{
  			terminated = true;
  			notifyAll();
  		}
  	}
  
  	private static final String INIT_TAG = "init"; //$NON-NLS-1$
  	private static final String RESPONSE_TAG = "response"; //$NON-NLS-1$
  	private static final String STREAM_TAG = "stream"; //$NON-NLS-1$
  	private static final String NOTIFY_TAG = "notify"; //$NON-NLS-1$
  
  	private final ResponcePacketWaiter responseWaiter;
  	private final PacketWaiter notifyWaiter;
  	private final PacketWaiter streamWaiter;
  
  	private final InputStream input;
  	private IDbgpRawLogger logger;
  
  	protected void workingCycle() throws Exception
  	{
  		try
  		{
  			while (!Thread.interrupted())
  			{
  				DbgpRawPacket packet = DbgpRawPacket.readPacket(input);
  
  				if (logger != null)
  				{
  					logger.log(packet);
  				}
  
  				addDocument(packet.getParsedXml());
  			}
  		} finally
  		{
  			responseWaiter.terminate();
  			notifyWaiter.terminate();
  			streamWaiter.terminate();
  		}
  	}
  
  	protected void addDocument(Document doc)
  	{
  		Element element = (Element) doc.getFirstChild();
  		String tag = element.getTagName();
  
  		// TODO: correct init tag handling without this hack
  		if (tag.equals(INIT_TAG))
  		{
  			responseWaiter.put(new DbgpResponsePacket(element, -1));
  		} else if (tag.equals(RESPONSE_TAG))
  		{
  			DbgpResponsePacket packet = DbgpXmlPacketParser.parseResponsePacket(element);
  
  			responseWaiter.put(packet);
  		} else if (tag.equals(STREAM_TAG))
  		{
  			streamWaiter.put(DbgpXmlPacketParser.parseStreamPacket(element));
  		} else if (tag.equals(NOTIFY_TAG))
  		{
  			notifyWaiter.put(DbgpXmlPacketParser.parseNotifyPacket(element));
  		}
  	}
  
  	public DbgpNotifyPacket getNotifyPacket() throws InterruptedException
  	{
  		return (DbgpNotifyPacket) notifyWaiter.waitPacket();
  	}
  
  	public DbgpStreamPacket getStreamPacket() throws InterruptedException
  	{
  		return (DbgpStreamPacket) streamWaiter.waitPacket();
  	}
  
  	public DbgpResponsePacket getResponsePacket(int transactionId, int timeout)
  			throws InterruptedException
  	{
  		return responseWaiter.waitPacket(transactionId, timeout);
  	}
  
  	public DbgpPacketReceiver(InputStream input)
  	{
  		super("DBGP - Packet receiver"); //$NON-NLS-1$
  
  		if (input == null)
  		{
  