15f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes/*
25f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * Licensed to the Apache Software Foundation (ASF) under one or more
35f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * contributor license agreements.  See the NOTICE file distributed with
45f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * this work for additional information regarding copyright ownership.
55f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * The ASF licenses this file to You under the Apache License, Version 2.0
65f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * (the "License"); you may not use this file except in compliance with
75f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * the License.  You may obtain a copy of the License at
85f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes *
95f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes *     http://www.apache.org/licenses/LICENSE-2.0
105f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes *
115f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes *  Unless required by applicable law or agreed to in writing, software
125f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes *  distributed under the License is distributed on an "AS IS" BASIS,
135f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
145f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes *
155f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes *  See the License for the specific language governing permissions and
165f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes *  limitations under the License.
175f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes */
185f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
195f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes/**
205f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * @author Anton V. Karnachuk
215f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes */
225f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
235f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes/**
245f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * Created on 16.03.2005
255f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes */
265f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughespackage org.apache.harmony.jpda.tests.framework.jdwp;
275f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
285f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesimport java.util.List;
295f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesimport java.io.IOException;
305f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesimport java.io.InterruptedIOException;
315f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesimport java.util.ArrayList;
325f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesimport java.util.Enumeration;
335f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesimport java.util.Hashtable;
345f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
355f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesimport org.apache.harmony.jpda.tests.framework.LogWriter;
365f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesimport org.apache.harmony.jpda.tests.framework.TestOptions;
375f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesimport org.apache.harmony.jpda.tests.framework.jdwp.exceptions.TimeoutException;
385f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
395f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes/**
405f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * This class provides asynchronous sending JDWP commands and receiving JDWP
415f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * events through established JDWP connection and supports timeout for these
425f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * operations.
435f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes */
445f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughespublic class PacketDispatcher extends Thread {
455f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
465f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    /**
475f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * Variables below are intended only to help with tests failures
485f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * investigation. They turn on/off some kinds of trace during
495f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * tests execution which can clear up details of test failure.
505f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *
515f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * commandsNumberForTrace and begCommandIdForTrace define trace
525f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * of sent JDWP commands and received replies for these commands:
535f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * - begCommandIdForTrace defines starting command ID for trace
545f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *   (the first command has ID=1, the second - ID=2 and so on).
555f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *   if <= 0 then the same as = 1.
565f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * - commandsNumberForTrace defines number of command for trace.
575f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *   if <= 0 then commands' trace is off.
585f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *
595f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * - eventRequestIDForTrace defines trace of received events
605f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *   according to request ID value:
615f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *   if < 0 then this trace is off;
625f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *   if = 0 then trace is for all received events;
635f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *   if > 0 then trace is for received events, which are triggered
645f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *          by this specified request ID value;
655f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *
665f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * - eventKindForTrace defines trace of received events
675f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *   according to this specified kind of event.
685f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *   if = 0 then this trace is off;
695f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *   See JDWPConstants.EventKind class for values of
705f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *   event kinds.
715f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     */
725f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    int begCommandIdForTrace = 1;
735f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
745f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    int commandsNumberForTrace = 0;
755f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
765f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    int eventRequestIDForTrace = -1;
775f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
785f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    byte eventKindForTrace = 0;
795f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
805f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    /**
815f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * Internal class to synchronize jdwp events. When an event is received it
825f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * is stored in eventQueue. If there are any thread that waits for event it
835f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * is notified.
845f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     */
855f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    private class EventsSynchronyzer {
865f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
875f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        /**
885f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * List of received events.
895f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         */
905f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        private List<EventPacket> eventQueue;
915f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
925f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        /**
935f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * A default constructor.
945f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         */
955f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        EventsSynchronyzer() {
965f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            // initialize eventQueue
975f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            eventQueue = new ArrayList<EventPacket>();
985f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        }
995f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
1005f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        /**
1015f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * Notifies thread that the new event has been received.
1025f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         *
1035f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @param eventPacket
1045f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         *            instance of EventPacket
1055f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @throws InterruptedException
1065f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         */
1075f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        public void notifyThread(EventPacket eventPacket)
1085f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                throws InterruptedException {
1095f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
1105f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            // use this object as lock
1115f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            synchronized (this) {
1125f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // add the event to eventQueue
1135f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                eventQueue.add(eventPacket);
1145f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
1155f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // notify next waiting thread
1165f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                this.notify();
1175f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            }
1185f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        }
1195f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
1205f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        /**
1215f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * Waits for new event during timeout.
1225f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         *
1235f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @param timeout
1245f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         *            wait timeout
1255f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @return EventPacket
1265f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @throws InterruptedException
1275f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @throws IOException
1285f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @throws TimeoutException
1295f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         *             if no event was received
1305f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         */
1315f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        public EventPacket waitForNextEvent(long timeout)
1325f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                throws InterruptedException, IOException {
1335f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
1345f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            // use this object as lock
1355f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            synchronized (this) {
1365f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
1375f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // if there is already received event in eventQueue,
1385f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // then return it
1395f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                synchronized (eventQueue) {
1405f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    if (!eventQueue.isEmpty()) {
1415f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        return (EventPacket) eventQueue.remove(0);
1425f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    }
1435f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
1445f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    // if eventQueue is empty and connection is already closed
1455f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    // reraise the exception
1465f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    if (connectionException != null)
1475f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        throw connectionException;
1485f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                }
1495f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
1505f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // wait for the next event
1515f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                this.wait(timeout);
1525f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
1535f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // We have the following opportunities here -
1545f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // next event was received, exception in main cyrcle or timeout
1555f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // happens
1565f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                synchronized (eventQueue) {
1575f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    if (!eventQueue.isEmpty()) {
1585f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        // event received
1595f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        EventPacket event = (EventPacket) eventQueue.remove(0);
1605f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        return event;
1615f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    }
1625f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
1635f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    if (connectionException != null) {
1645f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        // if eventQueue is empty and connection is already
1655f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        // closed
1665f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        // reraise the exception
1675f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        throw connectionException;
1685f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    }
1695f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                }
1705f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            }
1715f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
1725f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            // no events were occurred during timeout
1735f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            throw new TimeoutException(false);
1745f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        }
1755f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
1765f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        /**
1775f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * This method is called when connection is closed. It notifies all the
1785f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * waiting threads.
1795f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         */
1805f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        public void terminate() {
1815f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            synchronized (this) {
1825f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                this.notifyAll();
1835f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            }
1845f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        }
1855f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    }
1865f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
1875f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    /**
1885f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * Internal class to synchronize jdwp commands. It sends command packets
1895f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * through connection and returns replies.
1905f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     */
1915f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    class CommandsSynchronyzer {
1925f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
1935f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        private int commandId;
1945f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
1955f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        private Hashtable<Integer, CommandPacket> commands;
1965f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
1975f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        private Hashtable<Integer, ReplyPacket> replies;
1985f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
1995f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        /**
2005f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * A default constructor.
2015f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         */
2025f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        CommandsSynchronyzer() {
2035f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            commands = new Hashtable<Integer, CommandPacket>();
2045f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            replies = new Hashtable<Integer, ReplyPacket>();
2055f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
2065f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            // set first command id to 1
2075f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            commandId = 1;
2085f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        }
2095f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
2105f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        /**
2115f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * Gets the next new id for a command.
2125f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         *
2135f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @return int
2145f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         */
2155f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        private synchronized int getNextId() {
2165f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            return commandId++;
2175f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        }
2185f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
2195f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        /**
2205f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * Notifies thread that reply packet was received.
2215f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         *
2225f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @param replyPacket
2235f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         *            instance of ReplyPacket
2245f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @throws IOException
2255f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @throws InterruptedException
2265f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         */
2275f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        public void notifyThread(ReplyPacket replyPacket) throws IOException,
2285f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                InterruptedException {
2295f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
2305f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            synchronized (commands) {
2315f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
2325f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // obtain the current command id
2335f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                Integer Id = new Integer(replyPacket.getId());
2345f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
2355f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // obtain the current command packet by command id
2365f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                CommandPacket command = (CommandPacket) commands.remove(Id);
2375f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                if (command == null) {
2385f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    // we received reply's id that does not correspond to any
2395f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    // command
2405f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    throw new IOException(
2415f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            "Reply id is corresponded to no command. Id = "
2425f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                    + Id);
2435f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                }
2445f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
2455f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                synchronized (command) {
2465f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    // put the reply in replies queue
2475f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    synchronized (replies) {
2485f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        replies.put(new Integer(replyPacket.getId()),
2495f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                replyPacket);
2505f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    }
2515f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    // notify waiting thread
2525f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    command.notifyAll();
2535f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                }
2545f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            }
2555f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        }
2565f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
2575f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        /**
2585f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * Sends command and waits for the reply during timeout.
2595f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         *
2605f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @param command
2615f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         *            instance of CommandPacket
2625f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @param timeout
2635f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         *            reply wait timeout
2645f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @return
2655f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @throws TimeoutException
2665f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         *             if no reply was received
2675f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         */
2685f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        public ReplyPacket waitForReply(CommandPacket command, long timeout)
2695f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                throws InterruptedException, IOException {
2705f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
2715f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            synchronized (command) {
2725f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
2735f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // if connection is already closed reraise the exception
2745f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                if (connectionException != null)
2755f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    throw connectionException;
2765f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
2775f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // obtain new command id
2785f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                Integer Id = new Integer(getNextId());
2795f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                command.setId(Id.intValue());
2805f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
2815f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // add command into commands hashtable
2825f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                synchronized (commands) {
2835f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    commands.put(Id, command);
2845f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
2855f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    // below is trace for sent coomasnds
2865f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    if (commandsNumberForTrace > 0) {
2875f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        int begCommandId = begCommandIdForTrace > 1 ? begCommandIdForTrace
2885f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                : 1;
2895f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        if (Id.intValue() >= begCommandId) {
2905f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            if ((Id.intValue() - begCommandId) < commandsNumberForTrace) {
2915f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                logWriter
2925f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                        .println(">>>>>>>>>> PacketDispatcher: PERFORM command: ID = "
2935f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                                + Id.intValue()
2945f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                                + "; CommandSet = "
2955f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                                + command.getCommandSet()
2965f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                                + "; Command = "
2975f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                                + command.getCommand() + "...");
2985f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            }
2995f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        }
3005f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    }
3015f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
3025f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    // write this package to connection
3035f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    connection.writePacket(command.toBytesArray());
3045f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                }
3055f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
3065f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // if connection is already closed reraise the exception
3075f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                if (connectionException != null)
3085f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    throw connectionException;
3095f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
3105f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // wait for reply
3115f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                command.wait(timeout);
3125f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
3135f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // receive the reply
3145f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                ReplyPacket currentReply = null;
3155f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                synchronized (replies) {
3165f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    currentReply = (ReplyPacket) replies.remove(Id);
3175f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                }
3185f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
3195f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // if reply is ok, return it
3205f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                if (currentReply != null) {
3215f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    return currentReply;
3225f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                }
3235f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
3245f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // if connection is already closed reraise the exception
3255f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                if (connectionException != null)
3265f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    throw connectionException;
3275f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            }
3285f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
3295f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            // no event was occurred during timeout
3305f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            throw new TimeoutException(false);
3315f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        }
3325f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
3335f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        /**
3345f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * Sends command without waiting for the reply and returns id of the
3355f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * sent command.
3365f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         *
3375f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @param command
3385f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         *            instance of CommandPacket
3395f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @return command id
3405f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @throws IOException
3415f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         */
3425f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        public int sendCommand(CommandPacket command) throws IOException {
3435f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
3445f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            // if connection is already closed reraise the exception
3455f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            if (connectionException != null)
3465f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                throw connectionException;
3475f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
3485f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            // obtain new command id
3495f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            Integer Id = new Integer(getNextId());
3505f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            command.setId(Id.intValue());
3515f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
3525f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            // add command into commands hashtable
3535f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            synchronized (commands) {
3545f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                commands.put(Id, command);
3555f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
3565f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // below is trace for sent coomasnds
3575f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                if (commandsNumberForTrace > 0) {
3585f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    int begCommandId = begCommandIdForTrace > 1 ? begCommandIdForTrace
3595f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            : 1;
3605f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    if (Id.intValue() >= begCommandId) {
3615f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        if ((Id.intValue() - begCommandId) < commandsNumberForTrace) {
3625f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            logWriter
3635f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                    .println(">>>>>>>>>> PacketDispatcher: PERFORM command: ID = "
3645f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                            + Id.intValue()
3655f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                            + "; CommandSet = "
3665f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                            + command.getCommandSet()
3675f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                            + "; Command = "
3685f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                            + command.getCommand() + "...");
3695f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        }
3705f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    }
3715f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                }
3725f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
3735f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // write this package to connection
3745f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                connection.writePacket(command.toBytesArray());
3755f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            }
3765f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
3775f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            // if connection is already closed reraise the exception
3785f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            if (connectionException != null) {
3795f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                throw connectionException;
3805f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            }
3815f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
3825f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            return Id.intValue();
3835f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
3845f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        }
3855f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
3865f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        /**
3875f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * Receives the reply during timeout for command with specified command
3885f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * ID.
3895f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         *
3905f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @param commandId
3915f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         *            id of previously sent commend
3925f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @param timeout
3935f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         *            receive timeout
3945f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @return received ReplyPacket
3955f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * @throws TimeoutException
3965f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         *             if no reply was received
3975f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         */
3985f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        public ReplyPacket receiveReply(int commandId, long timeout)
3995f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                throws InterruptedException, IOException {
4005f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
4015f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            // if connection is already closed reraise the exception
4025f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            if (connectionException != null)
4035f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                throw connectionException;
4045f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
4055f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            // receive the reply
4065f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            ReplyPacket currentReply = null;
4075f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            long endTimeMlsecForWait = System.currentTimeMillis() + timeout;
4085f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            synchronized (replies) {
4095f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                while (true) {
4105f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    currentReply = (ReplyPacket) replies.remove(new Integer(
4115f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            commandId));
4125f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    // if reply is ok, return it
4135f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    if (currentReply != null) {
4145f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        return currentReply;
4155f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    }
4165f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    // if connection is already closed reraise the exception
4175f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    if (connectionException != null) {
4185f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        throw connectionException;
4195f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    }
4205f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    if (System.currentTimeMillis() >= endTimeMlsecForWait) {
4215f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        break;
4225f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    }
4235f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    replies.wait(100);
4245f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                }
4255f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            }
4265f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            // no expected reply was found during timeout
4275f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            throw new TimeoutException(false);
4285f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        }
4295f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
4305f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        /**
4315f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * This method is called when connection is closed. It notifies all the
4325f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         * waiting threads.
4335f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         *
4345f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes         */
4355f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        public void terminate() {
4365f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
4375f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            synchronized (commands) {
4385f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // enumerate all waiting commands
4395f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                for (Enumeration en = commands.keys(); en.hasMoreElements();) {
4405f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    CommandPacket command = (CommandPacket) commands.get(en
4415f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            .nextElement());
4425f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    synchronized (command) {
4435f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        // notify the waiting object
4445f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        command.notifyAll();
4455f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    }
4465f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                }
4475f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            }
4485f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        }
4495f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    }
4505f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
4515f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    /** Transport which is used to sent and receive packets. */
4525f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    private TransportWrapper connection;
4535f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
4545f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    /** Current test run configuration. */
4555f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    TestOptions config;
4565f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
4575f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    private CommandsSynchronyzer commandsSynchronyzer;
4585f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
4595f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    private EventsSynchronyzer eventsSynchronyzer;
4605f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
4615f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    private LogWriter logWriter;
4625f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
4635f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    private IOException connectionException;
4645f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
4655f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    /**
4665f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * Creates new PacketDispatcher instance.
4675f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *
4685f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @param connection
4695f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *            open connection for reading and writing packets
4705f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @param config
4715f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *            test run options
4725f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @param logWriter
4735f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *            LogWriter object
4745f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     */
4755f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    public PacketDispatcher(TransportWrapper connection, TestOptions config,
4765f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            LogWriter logWriter) {
4775f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
4785f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        this.connection = connection;
4795f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        this.config = config;
4805f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        this.logWriter = logWriter;
4815f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
4825f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        commandsSynchronyzer = new CommandsSynchronyzer();
4835f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        eventsSynchronyzer = new EventsSynchronyzer();
4845f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
4855f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        // make thread daemon
4865f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        setDaemon(true);
4875f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
4885f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        // start the thread
4895f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        start();
4905f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    }
4915f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
4925f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    /**
4935f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * Reads packets from connection and dispatches them between waiting
4945f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * threads.
4955f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     */
4965f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    public void run() {
4975f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
4985f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        connectionException = null;
4995f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
5005f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        try {
5015f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            // start listening for replies
5025f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            while (!isInterrupted()) {
5035f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
5045f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // read packet from transport
5055f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                byte[] packet = connection.readPacket();
5065f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
5075f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // break cycle if empty packet
5085f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                if (packet == null || packet.length == 0)
5095f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    break;
5105f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
5115f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // check flags
5125f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                if (packet.length < Packet.FLAGS_INDEX) {
5135f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    logWriter
5145f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            .println(">>>>>>>>>> PacketDispatcher WARNING: WRONG received packet size = "
5155f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                    + packet.length);
5165f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                } else {
5175f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    int flag = packet[Packet.FLAGS_INDEX] & 0xFF;
5185f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    if (flag != 0) {
5195f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        if (flag != Packet.REPLY_PACKET_FLAG) {
5205f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            logWriter
5215f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                    .println(">>>>>>>>>> PacketDispatcher WARNING: WRONG received packet flags = "
5225f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                            + Integer.toHexString(flag));
5235f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        }
5245f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    }
5255f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                }
5265f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
5275f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                // check the reply flag
5285f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                if (Packet.isReply(packet)) {
5295f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    // new reply
5305f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    ReplyPacket replyPacket = new ReplyPacket(packet);
5315f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
5325f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    // check for received reply packet length
5335f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    int packetLength = replyPacket.getLength();
5345f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    if (packetLength < Packet.HEADER_SIZE) {
5355f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        logWriter
5365f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                .println(">>>>>>>>>> PacketDispatcher WARNING: WRONG received packet length = "
5375f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                        + packetLength);
5385f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    }
5395f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
5405f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    // below is trace for received coomasnds
5415f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    if (commandsNumberForTrace > 0) {
5425f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        int replyID = replyPacket.getId();
5435f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        int begCommandId = begCommandIdForTrace > 1 ? begCommandIdForTrace
5445f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                : 1;
5455f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        if (replyID >= begCommandId) {
5465f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            if ((replyID - begCommandId) < commandsNumberForTrace) {
5475f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                logWriter
5485f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                        .println(">>>>>>>>>> PacketDispatcher: Received REPLY ID = "
5495f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                                + replyID);
5505f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            }
5515f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        }
5525f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    }
5535f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
5545f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    commandsSynchronyzer.notifyThread(replyPacket);
5555f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                } else {
5565f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    // new event
5575f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    EventPacket eventPacket = new EventPacket(packet);
5585f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    // below is to check received events for correctness
5595f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
5605f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    // below is trace for received events
5615f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    ParsedEvent[] parsedEvents = ParsedEvent
5625f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            .parseEventPacket(eventPacket);
5635f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    if ((eventRequestIDForTrace >= 0)
5645f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            || (eventKindForTrace > 0)) {
5655f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        for (int i = 0; i < parsedEvents.length; i++) {
5665f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            boolean trace = false;
5675f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            int eventRequestID = parsedEvents[i].getRequestID();
5685f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            if (eventRequestIDForTrace == 0) {
5695f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                trace = true;
5705f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            } else {
5715f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                if (eventRequestID == eventRequestIDForTrace) {
5725f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                    trace = true;
5735f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                }
5745f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            }
5755f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            byte eventKind = parsedEvents[i].getEventKind();
5765f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            if (eventKind == eventKindForTrace) {
5775f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                trace = true;
5785f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            }
5795f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            if (trace) {
5805f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                logWriter
5815f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                        .println(">>>>>>>>>> PacketDispatcher: Received_EVENT["
5825f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                                + i
5835f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                                + "]: eventRequestID= "
5845f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                                + eventRequestID
5855f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                                + "; eventKind =  "
5865f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                                + eventKind
5875f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                                + "("
5885f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                                + JDWPConstants.EventKind
5895f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                                        .getName(eventKind)
5905f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                                                + ")");
5915f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                            }
5925f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                        }
5935f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    }
5945f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                    eventsSynchronyzer.notifyThread(eventPacket);
5955f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes                }
5965f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            }
5975f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
5985f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            // this exception is send for all waiting threads
5995f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            connectionException = new TimeoutException(true);
6005f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        } catch (IOException e) {
6015f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            // connection exception is send for all waiting threads
6025f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            connectionException = e;
6035f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
6045f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            // print stack trace
6055f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            e.printStackTrace();
6065f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        } catch (InterruptedException e) {
6075f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            // connection exception is send for all waiting threads
6085f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            connectionException = new InterruptedIOException(e.getMessage());
6095f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            connectionException.initCause(e);
6105f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
6115f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            // print stack trace
6125f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            e.printStackTrace();
6135f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        }
6145f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
6155f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        // notify all the waiting threads
6165f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        eventsSynchronyzer.terminate();
6175f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        commandsSynchronyzer.terminate();
6185f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    }
6195f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
6205f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    /**
6215f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * Receives event from event queue if there are any events or waits during
6225f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * timeout for any event occurrence. This method should not be used
6235f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * simultaneously from different threads. If there were no reply during the
6245f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * timeout, TimeoutException is thrown.
6255f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *
6265f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @param timeout
6275f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *            timeout in milliseconds
6285f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @return received event packet
6295f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @throws IOException
6305f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *             is any connection error occurred
6315f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @throws InterruptedException
6325f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *             if reading packet was interrupted
6335f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @throws TimeoutException
6345f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *             if timeout exceeded
6355f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     */
6365f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    public EventPacket receiveEvent(long timeout) throws IOException,
6375f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            InterruptedException, TimeoutException {
6385f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
6395f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        return eventsSynchronyzer.waitForNextEvent(timeout);
6405f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    }
6415f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
6425f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    /**
6435f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * Sends JDWP command packet and waits for reply packet during default
6445f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * timeout. If there were no reply packet during the timeout,
6455f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * TimeoutException is thrown.
6465f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *
6475f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @return received reply packet
6485f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @throws InterruptedException
6495f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *             if reading packet was interrupted
6505f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @throws IOException
6515f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *             if any connection error occurred
6525f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @throws TimeoutException
6535f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *             if timeout exceeded
6545f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     */
6555f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    public ReplyPacket performCommand(CommandPacket command)
6565f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            throws InterruptedException, IOException, TimeoutException {
6575f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
6585f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        return performCommand(command, config.getTimeout());
6595f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    }
6605f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
6615f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    /**
6625f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * Sends JDWP command packet and waits for reply packet during certain
6635f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * timeout. If there were no reply packet during the timeout,
6645f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * TimeoutException is thrown.
6655f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *
6665f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @param command
6675f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *            command packet to send
6685f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @param timeout
6695f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *            timeout in milliseconds
6705f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @return received reply packet
6715f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @throws InterruptedException
6725f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *             if packet reading was interrupted
6735f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @throws IOException
6745f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *             if any connection error occurred
6755f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @throws TimeoutException
6765f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *             if timeout exceeded
6775f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     */
6785f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    public ReplyPacket performCommand(CommandPacket command, long timeout)
6795f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            throws InterruptedException, IOException, TimeoutException {
6805f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
6815f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        return commandsSynchronyzer.waitForReply(command, timeout);
6825f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    }
6835f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
6845f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    /**
6855f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * Sends CommandPacket to debuggee VM without waiting for the reply. This
6865f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * method is intended for special cases when there is need to divide
6875f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * command's performing into two actions: command's sending and receiving
6885f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * reply (e.g. for asynchronous JDWP commands' testing). After this method
6895f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * the 'receiveReply()' method must be used latter for receiving reply for
6905f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * sent command. It is NOT recommended to use this method for usual cases -
6915f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * 'performCommand()' method must be used.
6925f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *
6935f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @param command
6945f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *            Command packet to be sent
6955f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @return command ID of sent command
6965f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @throws IOException
6975f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *             if any connection error occurred
6985f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     */
6995f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    public int sendCommand(CommandPacket command) throws IOException {
7005f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        return commandsSynchronyzer.sendCommand(command);
7015f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    }
7025f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
7035f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    /**
7045f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * Waits for reply for command which was sent before by 'sendCommand()'
7055f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * method. Specified timeout is used as time limit for waiting. This method
7065f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * (jointly with 'sendCommand()') is intended for special cases when there
7075f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * is need to divide command's performing into two actions: command's
7085f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * sending and receiving reply (e.g. for asynchronous JDWP commands'
7095f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * testing). It is NOT recommended to use 'sendCommand()- receiveReply()'
7105f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * pair for usual cases - 'performCommand()' method must be used.
7115f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *
7125f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @param commandId
7135f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *            Command ID of sent before command, reply from which is
7145f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *            expected to be received
7155f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @param timeout
7165f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *            Specified timeout in milliseconds to wait for reply
7175f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @return received ReplyPacket
7185f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @throws IOException
7195f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *             if any connection error occurred
7205f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @throws InterruptedException
7215f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *             if reply packet's waiting was interrupted
7225f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     * @throws TimeoutException
7235f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     *             if timeout exceeded
7245f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes     */
7255f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    public ReplyPacket receiveReply(int commandId, long timeout)
7265f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes            throws InterruptedException, IOException, TimeoutException {
7275f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes        return commandsSynchronyzer.receiveReply(commandId, timeout);
7285f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes    }
7295f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
7305f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes}
731