You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ge...@apache.org on 2006/11/28 18:49:31 UTC

svn commit: r480141 [19/38] - in /harmony/enhanced/jdktools/trunk/modules/jpda: ./ doc/ doc/images/ make/ src/ src/common/ src/common/other/ src/common/other/jpda/ src/common/other/jpda/jdwp/ src/common/other/jpda/jdwp/agent/ src/common/other/jpda/jdwp...

Added: harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/PacketDispatcher.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/PacketDispatcher.java?view=auto&rev=480141
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/PacketDispatcher.java (added)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/PacketDispatcher.java Tue Nov 28 09:49:08 2006
@@ -0,0 +1,730 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Anton V. Karnachuk
+ * @version $Revision: 1.5 $
+ */
+
+/**
+ * Created on 16.03.2005
+ */
+package org.apache.harmony.jpda.tests.framework.jdwp;
+
+import java.util.List;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.apache.harmony.jpda.tests.framework.LogWriter;
+import org.apache.harmony.jpda.tests.framework.TestOptions;
+import org.apache.harmony.jpda.tests.framework.jdwp.exceptions.TimeoutException;
+
+/**
+ * This class provides asynchronous sending JDWP commands and receiving JDWP
+ * events through established JDWP connection and supports timeout for these
+ * operations.
+ */
+public class PacketDispatcher extends Thread {
+
+    /**
+     * Variables below are intended only to help with tests failures
+     * investigation. They turn on/off some kinds of trace during
+     * tests execution which can clear up details of test failure.
+     * 
+     * commandsNumberForTrace and begCommandIdForTrace define trace
+     * of sent JDWP commands and received replies for these commands:
+     * - begCommandIdForTrace defines starting command ID for trace
+     *   (the first command has ID=1, the second - ID=2 and so on).
+     *   if <= 0 then the same as = 1.
+     * - commandsNumberForTrace defines number of command for trace.
+     *   if <= 0 then commands' trace is off.
+     * 
+     * - eventRequestIDForTrace defines trace of received events
+     *   according to request ID value:
+     *   if < 0 then this trace is off;
+     *   if = 0 then trace is for all received events;
+     *   if > 0 then trace is for received events, which are triggered
+     *          by this specified request ID value;
+     * 
+     * - eventKindForTrace defines trace of received events
+     *   according to this specified kind of event.
+     *   if = 0 then this trace is off;
+     *   See JDWPConstants.EventKind class for values of
+     *   event kinds.
+     */  
+    int begCommandIdForTrace = 1;
+
+    int commandsNumberForTrace = 0;
+
+    int eventRequestIDForTrace = -1;
+
+    byte eventKindForTrace = 0;
+
+    /**
+     * Internal class to synchronize jdwp events. When an event is received it
+     * is stored in eventQueue. If there are any thread that waits for event it
+     * is notified.
+     */
+    private class EventsSynchronyzer {
+
+        /**
+         * List of received events.
+         */
+        private List eventQueue;
+
+        /**
+         * A default constructor.
+         */
+        EventsSynchronyzer() {
+            // initialize eventQueue
+            eventQueue = new ArrayList();
+        }
+
+        /**
+         * Notifies thread that the new event has been received.
+         * 
+         * @param eventPacket
+         *            instance of EventPacket
+         * @throws InterruptedException
+         */
+        public void notifyThread(EventPacket eventPacket)
+                throws InterruptedException {
+
+            // use this object as lock
+            synchronized (this) {
+                // add the event to eventQueue
+                eventQueue.add(eventPacket);
+
+                // notify next waiting thread
+                this.notify();
+            }
+        }
+
+        /**
+         * Waits for new event during timeout.
+         * 
+         * @param timeout
+         *            wait timeout
+         * @return EventPacket
+         * @throws InterruptedException
+         * @throws IOException
+         * @throws TimeoutException
+         *             if no event was received
+         */
+        public EventPacket waitForNextEvent(long timeout)
+                throws InterruptedException, IOException {
+
+            // use this object as lock
+            synchronized (this) {
+
+                // if there is already received event in eventQueue,
+                // then return it
+                synchronized (eventQueue) {
+                    if (!eventQueue.isEmpty()) {
+                        return (EventPacket) eventQueue.remove(0);
+                    }
+
+                    // if eventQueue is empty and connection is already closed
+                    // reraise the exception
+                    if (connectionException != null)
+                        throw connectionException;
+                }
+
+                // wait for the next event
+                this.wait(timeout);
+
+                // We have the following opportunities here -
+                // next event was received, exception in main cyrcle or timeout
+                // happens
+                synchronized (eventQueue) {
+                    if (!eventQueue.isEmpty()) {
+                        // event received
+                        EventPacket event = (EventPacket) eventQueue.remove(0);
+                        return event;
+                    }
+
+                    if (connectionException != null) {
+                        // if eventQueue is empty and connection is already
+                        // closed
+                        // reraise the exception
+                        throw connectionException;
+                    }
+                }
+            }
+
+            // no events were occurred during timeout
+            throw new TimeoutException(false);
+        }
+
+        /**
+         * This method is called when connection is closed. It notifies all the
+         * waiting threads.
+         */
+        public void terminate() {
+            synchronized (this) {
+                this.notifyAll();
+            }
+        }
+    }
+
+    /**
+     * Internal class to synchronize jdwp commands. It sends command packets
+     * through connection and returns replies.
+     */
+    class CommandsSynchronyzer {
+
+        private int commandId;
+
+        private Hashtable commands;
+
+        private Hashtable replies;
+
+        /**
+         * A default constructor.
+         */
+        CommandsSynchronyzer() {
+            commands = new Hashtable();
+            replies = new Hashtable();
+
+            // set first command id to 1
+            commandId = 1;
+        }
+
+        /**
+         * Gets the next new id for a command.
+         * 
+         * @return int
+         */
+        private synchronized int getNextId() {
+            return commandId++;
+        }
+
+        /**
+         * Notifies thread that reply packet was received.
+         * 
+         * @param replyPacket
+         *            instance of ReplyPacket
+         * @throws IOException
+         * @throws InterruptedException
+         */
+        public void notifyThread(ReplyPacket replyPacket) throws IOException,
+                InterruptedException {
+
+            synchronized (commands) {
+
+                // obtain the current command id
+                Integer Id = new Integer(replyPacket.getId());
+
+                // obtain the current command packet by command id
+                CommandPacket command = (CommandPacket) commands.remove(Id);
+                if (command == null) {
+                    // we received reply's id that does not correspond to any
+                    // command
+                    throw new IOException(
+                            "Reply id is corresponded to no command. Id = "
+                                    + Id);
+                }
+
+                synchronized (command) {
+                    // put the reply in replies queue
+                    synchronized (replies) {
+                        replies.put(new Integer(replyPacket.getId()),
+                                replyPacket);
+                    }
+                    // notify waiting thread
+                    command.notifyAll();
+                }
+            }
+        }
+
+        /**
+         * Sends command and waits for the reply during timeout.
+         * 
+         * @param command
+         *            instance of CommandPacket
+         * @param timeout
+         *            reply wait timeout
+         * @return
+         * @throws TimeoutException
+         *             if no reply was received
+         */
+        public ReplyPacket waitForReply(CommandPacket command, long timeout)
+                throws InterruptedException, IOException {
+
+            synchronized (command) {
+
+                // if connection is already closed reraise the exception
+                if (connectionException != null)
+                    throw connectionException;
+
+                // obtain new command id
+                Integer Id = new Integer(getNextId());
+                command.setId(Id.intValue());
+
+                // add command into commands hashtable
+                synchronized (commands) {
+                    commands.put(Id, command);
+
+                    // below is trace for sent coomasnds
+                    if (commandsNumberForTrace > 0) {
+                        int begCommandId = begCommandIdForTrace > 1 ? begCommandIdForTrace
+                                : 1;
+                        if (Id.intValue() >= begCommandId) {
+                            if ((Id.intValue() - begCommandId) < commandsNumberForTrace) {
+                                logWriter
+                                        .println(">>>>>>>>>> PacketDispatcher: PERFORM command: ID = "
+                                                + Id.intValue()
+                                                + "; CommandSet = "
+                                                + command.getCommandSet()
+                                                + "; Command = "
+                                                + command.getCommand() + "...");
+                            }
+                        }
+                    }
+
+                    // write this package to connection
+                    connection.writePacket(command.toBytesArray());
+                }
+
+                // if connection is already closed reraise the exception
+                if (connectionException != null)
+                    throw connectionException;
+
+                // wait for reply
+                command.wait(timeout);
+
+                // receive the reply
+                ReplyPacket currentReply = null;
+                synchronized (replies) {
+                    currentReply = (ReplyPacket) replies.remove(Id);
+                }
+
+                // if reply is ok, return it
+                if (currentReply != null) {
+                    return currentReply;
+                }
+
+                // if connection is already closed reraise the exception
+                if (connectionException != null)
+                    throw connectionException;
+            }
+
+            // no event was occurred during timeout
+            throw new TimeoutException(false);
+        }
+
+        /**
+         * Sends command without waiting for the reply and returns id of the
+         * sent command.
+         * 
+         * @param command
+         *            instance of CommandPacket
+         * @return command id
+         * @throws IOException
+         */
+        public int sendCommand(CommandPacket command) throws IOException {
+
+            // if connection is already closed reraise the exception
+            if (connectionException != null)
+                throw connectionException;
+
+            // obtain new command id
+            Integer Id = new Integer(getNextId());
+            command.setId(Id.intValue());
+
+            // add command into commands hashtable
+            synchronized (commands) {
+                commands.put(Id, command);
+
+                // below is trace for sent coomasnds
+                if (commandsNumberForTrace > 0) {
+                    int begCommandId = begCommandIdForTrace > 1 ? begCommandIdForTrace
+                            : 1;
+                    if (Id.intValue() >= begCommandId) {
+                        if ((Id.intValue() - begCommandId) < commandsNumberForTrace) {
+                            logWriter
+                                    .println(">>>>>>>>>> PacketDispatcher: PERFORM command: ID = "
+                                            + Id.intValue()
+                                            + "; CommandSet = "
+                                            + command.getCommandSet()
+                                            + "; Command = "
+                                            + command.getCommand() + "...");
+                        }
+                    }
+                }
+
+                // write this package to connection
+                connection.writePacket(command.toBytesArray());
+            }
+
+            // if connection is already closed reraise the exception
+            if (connectionException != null) {
+                throw connectionException;
+            }
+
+            return Id.intValue();
+
+        }
+
+        /**
+         * Receives the reply during timeout for command with specified command
+         * ID.
+         * 
+         * @param commandId
+         *            id of previously sent commend
+         * @param timeout
+         *            receive timeout
+         * @return received ReplyPacket
+         * @throws TimeoutException
+         *             if no reply was received
+         */
+        public ReplyPacket receiveReply(int commandId, long timeout)
+                throws InterruptedException, IOException {
+
+            // if connection is already closed reraise the exception
+            if (connectionException != null)
+                throw connectionException;
+
+            // receive the reply
+            ReplyPacket currentReply = null;
+            long endTimeMlsecForWait = System.currentTimeMillis() + timeout;
+            synchronized (replies) {
+                while (true) {
+                    currentReply = (ReplyPacket) replies.remove(new Integer(
+                            commandId));
+                    // if reply is ok, return it
+                    if (currentReply != null) {
+                        return currentReply;
+                    }
+                    // if connection is already closed reraise the exception
+                    if (connectionException != null) {
+                        throw connectionException;
+                    }
+                    if (System.currentTimeMillis() >= endTimeMlsecForWait) {
+                        break;
+                    }
+                    replies.wait(100);
+                }
+            }
+            // no expected reply was found during timeout
+            throw new TimeoutException(false);
+        }
+
+        /**
+         * This method is called when connection is closed. It notifies all the
+         * waiting threads.
+         * 
+         */
+        public void terminate() {
+
+            synchronized (commands) {
+                // enumerate all waiting commands
+                for (Enumeration en = commands.keys(); en.hasMoreElements();) {
+                    CommandPacket command = (CommandPacket) commands.get(en
+                            .nextElement());
+                    synchronized (command) {
+                        // notify the waiting object
+                        command.notifyAll();
+                    }
+                }
+            }
+        }
+    }
+
+    /** Transport which is used to sent and receive packets. */
+    private TransportWrapper connection;
+
+    /** Current test run configuration. */
+    TestOptions config;
+
+    private CommandsSynchronyzer commandsSynchronyzer;
+
+    private EventsSynchronyzer eventsSynchronyzer;
+
+    private LogWriter logWriter;
+
+    private IOException connectionException;
+
+    /**
+     * Creates new PacketDispatcher instance.
+     * 
+     * @param connection
+     *            open connection for reading and writing packets
+     * @param config
+     *            test run options
+     * @param logWriter
+     *            LogWriter object
+     */
+    public PacketDispatcher(TransportWrapper connection, TestOptions config,
+            LogWriter logWriter) {
+
+        this.connection = connection;
+        this.config = config;
+        this.logWriter = logWriter;
+
+        commandsSynchronyzer = new CommandsSynchronyzer();
+        eventsSynchronyzer = new EventsSynchronyzer();
+
+        // make thread daemon
+        setDaemon(true);
+
+        // start the thread
+        start();
+    }
+
+    /**
+     * Reads packets from connection and dispatches them between waiting
+     * threads.
+     */
+    public void run() {
+
+        connectionException = null;
+
+        try {
+            // start listening for replies
+            while (!isInterrupted()) {
+
+                // read packet from transport
+                byte[] packet = connection.readPacket();
+
+                // break cycle if empty packet
+                if (packet == null || packet.length == 0)
+                    break;
+
+                // check flags
+                if (packet.length < Packet.FLAGS_INDEX) {
+                    logWriter
+                            .println(">>>>>>>>>> PacketDispatcher WARNING: WRONG received packet size = "
+                                    + packet.length);
+                } else {
+                    int flag = packet[Packet.FLAGS_INDEX] & 0xFF;
+                    if (flag != 0) {
+                        if (flag != Packet.REPLY_PACKET_FLAG) {
+                            logWriter
+                                    .println(">>>>>>>>>> PacketDispatcher WARNING: WRONG received packet flags = "
+                                            + Integer.toHexString(flag));
+                        }
+                    }
+                }
+
+                // check the reply flag
+                if (Packet.isReply(packet)) {
+                    // new reply
+                    ReplyPacket replyPacket = new ReplyPacket(packet);
+
+                    // check for received reply packet length
+                    int packetLength = replyPacket.getLength();
+                    if (packetLength < Packet.HEADER_SIZE) {
+                        logWriter
+                                .println(">>>>>>>>>> PacketDispatcher WARNING: WRONG received packet length = "
+                                        + packetLength);
+                    }
+
+                    // below is trace for received coomasnds
+                    if (commandsNumberForTrace > 0) {
+                        int replyID = replyPacket.getId();
+                        int begCommandId = begCommandIdForTrace > 1 ? begCommandIdForTrace
+                                : 1;
+                        if (replyID >= begCommandId) {
+                            if ((replyID - begCommandId) < commandsNumberForTrace) {
+                                logWriter
+                                        .println(">>>>>>>>>> PacketDispatcher: Received REPLY ID = "
+                                                + replyID);
+                            }
+                        }
+                    }
+
+                    commandsSynchronyzer.notifyThread(replyPacket);
+                } else {
+                    // new event
+                    EventPacket eventPacket = new EventPacket(packet);
+                    // below is to check received events for correctness
+
+                    // below is trace for received events
+                    ParsedEvent[] parsedEvents = ParsedEvent
+                            .parseEventPacket(eventPacket);
+                    if ((eventRequestIDForTrace >= 0)
+                            || (eventKindForTrace > 0)) {
+                        for (int i = 0; i < parsedEvents.length; i++) {
+                            boolean trace = false;
+                            int eventRequestID = parsedEvents[i].getRequestID();
+                            if (eventRequestIDForTrace == 0) {
+                                trace = true;
+                            } else {
+                                if (eventRequestID == eventRequestIDForTrace) {
+                                    trace = true;
+                                }
+                            }
+                            byte eventKind = parsedEvents[i].getEventKind();
+                            if (eventKind == eventKindForTrace) {
+                                trace = true;
+                            }
+                            if (trace) {
+                                logWriter
+                                        .println(">>>>>>>>>> PacketDispatcher: Received_EVENT["
+                                                + i
+                                                + "]: eventRequestID= "
+                                                + eventRequestID
+                                                + "; eventKind =  "
+                                                + eventKind
+                                                + "("
+                                                + JDWPConstants.EventKind
+                                                        .getName(eventKind)
+                                                + ")");
+                            }
+                        }
+                    }
+                    eventsSynchronyzer.notifyThread(eventPacket);
+                }
+            }
+
+            // this exception is send for all waiting threads
+            connectionException = new TimeoutException(true);
+        } catch (IOException e) {
+            // connection exception is send for all waiting threads
+            connectionException = e;
+
+            // print stack trace
+            e.printStackTrace();
+        } catch (InterruptedException e) {
+            // connection exception is send for all waiting threads
+            connectionException = new InterruptedIOException(e.getMessage());
+            connectionException.initCause(e);
+
+            // print stack trace
+            e.printStackTrace();
+        }
+
+        // notify all the waiting threads
+        eventsSynchronyzer.terminate();
+        commandsSynchronyzer.terminate();
+    }
+
+    /**
+     * Receives event from event queue if there are any events or waits during
+     * timeout for any event occurrence. This method should not be used
+     * simultaneously from different threads. If there were no reply during the
+     * timeout, TimeoutException is thrown.
+     * 
+     * @param timeout
+     *            timeout in milliseconds
+     * @return received event packet
+     * @throws IOException
+     *             is any connection error occurred
+     * @throws InterruptedException
+     *             if reading packet was interrupted
+     * @throws TimeoutException
+     *             if timeout exceeded
+     */
+    public EventPacket receiveEvent(long timeout) throws IOException,
+            InterruptedException, TimeoutException {
+
+        return eventsSynchronyzer.waitForNextEvent(timeout);
+    }
+
+    /**
+     * Sends JDWP command packet and waits for reply packet during default
+     * timeout. If there were no reply packet during the timeout,
+     * TimeoutException is thrown.
+     * 
+     * @return received reply packet
+     * @throws InterruptedException
+     *             if reading packet was interrupted
+     * @throws IOException
+     *             if any connection error occurred
+     * @throws TimeoutException
+     *             if timeout exceeded
+     */
+    public ReplyPacket performCommand(CommandPacket command)
+            throws InterruptedException, IOException, TimeoutException {
+
+        return performCommand(command, config.getTimeout());
+    }
+
+    /**
+     * Sends JDWP command packet and waits for reply packet during certain
+     * timeout. If there were no reply packet during the timeout,
+     * TimeoutException is thrown.
+     * 
+     * @param command
+     *            command packet to send
+     * @param timeout
+     *            timeout in milliseconds
+     * @return received reply packet
+     * @throws InterruptedException
+     *             if packet reading was interrupted
+     * @throws IOException
+     *             if any connection error occurred
+     * @throws TimeoutException
+     *             if timeout exceeded
+     */
+    public ReplyPacket performCommand(CommandPacket command, long timeout)
+            throws InterruptedException, IOException, TimeoutException {
+
+        return commandsSynchronyzer.waitForReply(command, timeout);
+    }
+
+    /**
+     * Sends CommandPacket to debuggee VM without waiting for the reply. This
+     * method is intended for special cases when there is need to divide
+     * command's performing into two actions: command's sending and receiving
+     * reply (e.g. for asynchronous JDWP commands' testing). After this method
+     * the 'receiveReply()' method must be used latter for receiving reply for
+     * sent command. It is NOT recommended to use this method for usual cases -
+     * 'performCommand()' method must be used.
+     * 
+     * @param command
+     *            Command packet to be sent
+     * @return command ID of sent command
+     * @throws IOException
+     *             if any connection error occurred
+     */
+    public int sendCommand(CommandPacket command) throws IOException {
+        return commandsSynchronyzer.sendCommand(command);
+    }
+
+    /**
+     * Waits for reply for command which was sent before by 'sendCommand()'
+     * method. Specified timeout is used as time limit for waiting. This method
+     * (jointly with 'sendCommand()') is intended for special cases when there
+     * is need to divide command's performing into two actions: command's
+     * sending and receiving reply (e.g. for asynchronous JDWP commands'
+     * testing). It is NOT recommended to use 'sendCommand()- receiveReply()'
+     * pair for usual cases - 'performCommand()' method must be used.
+     * 
+     * @param commandId
+     *            Command ID of sent before command, reply from which is
+     *            expected to be received
+     * @param timeout
+     *            Specified timeout in milliseconds to wait for reply
+     * @return received ReplyPacket
+     * @throws IOException
+     *             if any connection error occurred
+     * @throws InterruptedException
+     *             if reply packet's waiting was interrupted
+     * @throws TimeoutException
+     *             if timeout exceeded
+     */
+    public ReplyPacket receiveReply(int commandId, long timeout)
+            throws InterruptedException, IOException, TimeoutException {
+        return commandsSynchronyzer.receiveReply(commandId, timeout);
+    }
+
+}

Propchange: harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/PacketDispatcher.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/ParsedEvent.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/ParsedEvent.java?view=auto&rev=480141
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/ParsedEvent.java (added)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/ParsedEvent.java Tue Nov 28 09:49:08 2006
@@ -0,0 +1,579 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Anton V. Karnachuk
+ * @version $Revision: 1.3 $
+ */
+
+/**
+ * Created on 17.03.2005
+ */
+package org.apache.harmony.jpda.tests.framework.jdwp;
+
+import org.apache.harmony.jpda.tests.framework.TestErrorException;
+
+/**
+ * This class represent parsed EventPacket with received event set data.
+ */
+public class ParsedEvent {
+
+    private byte suspendPolicy;
+
+    private int requestID;
+
+    private byte eventKind;
+
+    /**
+     * Create new instance with specified data.
+     */
+    protected ParsedEvent(byte suspendPolicy, Packet packet, byte eventKind) {
+        this.suspendPolicy = suspendPolicy;
+        this.requestID = packet.getNextValueAsInt();
+        this.eventKind = eventKind;
+    }
+
+    /**
+     * Returns RequestID of this event set.
+     * 
+     * @return RequestID of this event set
+     */
+    public int getRequestID() {
+        return requestID;
+    }
+
+    /**
+     * Returns suspend policy of this event set.
+     * 
+     * @return suspend policy of this event set
+     */
+    public byte getSuspendPolicy() {
+        return suspendPolicy;
+    }
+
+    /**
+     * @return Returns the eventKind.
+     */
+    public byte getEventKind() {
+        return eventKind;
+    }
+
+    /**
+     * The class extends ParsedEvent by associating it with a thread.
+     */
+    public static class EventThread extends ParsedEvent {
+
+        private long threadID;
+
+        /**
+         * A constructor.
+         * 
+         * @param suspendPolicy
+         * @param packet
+         */
+        protected EventThread(byte suspendPolicy, Packet packet, byte eventKind) {
+            super(suspendPolicy, packet, eventKind);
+            this.threadID = packet.getNextValueAsThreadID();
+        }
+
+        /**
+         * @return Returns the thread id.
+         */
+        public long getThreadID() {
+            return threadID;
+        }
+    }
+
+    /**
+     * The class extends EventThread by associating it with a location.
+     */
+    private static class EventThreadLocation extends EventThread {
+
+        private Location location;
+
+        /**
+         * A constructor.
+         * 
+         * @param suspendPolicy
+         * @param packet
+         */
+        protected EventThreadLocation(byte suspendPolicy, Packet packet,
+                byte eventKind) {
+            super(suspendPolicy, packet, eventKind);
+            this.location = packet.getNextValueAsLocation();
+        }
+
+        /**
+         * @return Returns the location.
+         */
+        public Location getLocation() {
+            return location;
+        }
+    }
+
+    /**
+     * The class implements JDWP VM_START event.
+     */
+    public static final class Event_VM_START extends EventThread {
+
+        /**
+         * A constructor.
+         * 
+         * @param suspendPolicy
+         * @param packet
+         */
+        private Event_VM_START(byte suspendPolicy, Packet packet) {
+            super(suspendPolicy, packet, JDWPConstants.EventKind.VM_START);
+        }
+    };
+
+    /**
+     * The class implements JDWP SINGLE_STEP event.
+     */
+    public static final class Event_SINGLE_STEP extends EventThreadLocation {
+
+        /**
+         * A constructor.
+         * 
+         * @param suspendPolicy
+         * @param packet
+         */
+        private Event_SINGLE_STEP(byte suspendPolicy, Packet packet) {
+            super(suspendPolicy, packet, JDWPConstants.EventKind.SINGLE_STEP);
+        }
+    }
+
+    /**
+     * The class implements JDWP BREAKPOINT event.
+     */
+    public static final class Event_BREAKPOINT extends EventThreadLocation {
+
+        /**
+         * A constructor.
+         * 
+         * @param suspendPolicy
+         * @param packet
+         */
+        private Event_BREAKPOINT(byte suspendPolicy, Packet packet) {
+            super(suspendPolicy, packet, JDWPConstants.EventKind.BREAKPOINT);
+        }
+    }
+
+    /**
+     * The class implements JDWP METHOD_ENTRY event.
+     */
+    public static final class Event_METHOD_ENTRY extends EventThreadLocation {
+
+        /**
+         * A constructor.
+         * 
+         * @param suspendPolicy
+         * @param packet
+         */
+        private Event_METHOD_ENTRY(byte suspendPolicy, Packet packet) {
+            super(suspendPolicy, packet, JDWPConstants.EventKind.METHOD_ENTRY);
+        }
+    }
+
+    /**
+     * The class implements JDWP METHOD_EXIT event.
+     */
+    public static final class Event_METHOD_EXIT extends EventThreadLocation {
+
+        /**
+         * A constructor.
+         * 
+         * @param suspendPolicy
+         * @param packet
+         */
+        private Event_METHOD_EXIT(byte suspendPolicy, Packet packet) {
+            super(suspendPolicy, packet, JDWPConstants.EventKind.METHOD_EXIT);
+        }
+    }
+
+    /**
+     * The class implements JDWP EXCEPTION event.
+     */
+    public static final class Event_EXCEPTION extends EventThreadLocation {
+
+        private TaggedObject exception;
+
+        private Location catchLocation;
+
+        /**
+         * A constructor.
+         * 
+         * @param suspendPolicy
+         * @param packet
+         */
+        private Event_EXCEPTION(byte suspendPolicy, Packet packet) {
+            super(suspendPolicy, packet, JDWPConstants.EventKind.EXCEPTION);
+            exception = packet.getNextValueAsTaggedObject();
+            catchLocation = packet.getNextValueAsLocation();
+        }
+
+        /**
+         * @return Returns the location of the caught exception.
+         */
+        public Location getCatchLocation() {
+            return catchLocation;
+        }
+
+        /**
+         * @return Returns the exception.
+         */
+        public TaggedObject getException() {
+            return exception;
+        }
+    }
+
+    /**
+     * The class implements JDWP THREAD_START event.
+     */
+    public static final class Event_THREAD_START extends EventThread {
+
+        /**
+         * A constructor.
+         * 
+         * @param suspendPolicy
+         * @param packet
+         */
+        private Event_THREAD_START(byte suspendPolicy, Packet packet) {
+            super(suspendPolicy, packet, JDWPConstants.EventKind.THREAD_START);
+        }
+    };
+
+    /**
+     * The class implements JDWP THREAD_DEATH event.
+     */
+    public static final class Event_THREAD_DEATH extends EventThread {
+
+        /**
+         * A constructor.
+         * 
+         * @param suspendPolicy
+         * @param packet
+         */
+        private Event_THREAD_DEATH(byte suspendPolicy, Packet packet) {
+            super(suspendPolicy, packet, JDWPConstants.EventKind.THREAD_DEATH);
+        }
+    };
+
+    /**
+     * The class implements JDWP CLASS_PREPARE event.
+     */
+    public static final class Event_CLASS_PREPARE extends EventThread {
+
+        private byte refTypeTag;
+
+        private long typeID;
+
+        private String signature;
+
+        private int status;
+
+        /**
+         * A constructor.
+         * 
+         * @param suspendPolicy
+         * @param packet
+         */
+        protected Event_CLASS_PREPARE(byte suspendPolicy, Packet packet) {
+            super(suspendPolicy, packet, JDWPConstants.EventKind.CLASS_PREPARE);
+            refTypeTag = packet.getNextValueAsByte();
+            typeID = packet.getNextValueAsReferenceTypeID();
+            signature = packet.getNextValueAsString();
+            status = packet.getNextValueAsInt();
+        }
+
+        /**
+         * @return Returns the refTypeTag.
+         */
+        public byte getRefTypeTag() {
+            return refTypeTag;
+        }
+
+        /**
+         * @return Returns the signature.
+         */
+        public String getSignature() {
+            return signature;
+        }
+
+        /**
+         * @return Returns the status.
+         */
+        public int getStatus() {
+            return status;
+        }
+
+        /**
+         * @return Returns the typeID.
+         */
+        public long getTypeID() {
+            return typeID;
+        }
+    };
+
+    /**
+     * The class implements JDWP CLASS_UNLOAD event.
+     */
+    public static final class Event_CLASS_UNLOAD extends ParsedEvent {
+
+        private String signature;
+
+        /**
+         * A constructor.
+         * 
+         * @param suspendPolicy
+         * @param packet
+         */
+        private Event_CLASS_UNLOAD(byte suspendPolicy, Packet packet) {
+            super(suspendPolicy, packet, JDWPConstants.EventKind.CLASS_UNLOAD);
+            signature = packet.getNextValueAsString();
+        }
+
+        /**
+         * @return Returns the signature.
+         */
+        public String getSignature() {
+            return signature;
+        }
+    };
+
+    /**
+     * The class implements JDWP FIELD_ACCESS event.
+     */
+    public static final class Event_FIELD_ACCESS extends EventThreadLocation {
+
+        private byte refTypeTag;
+
+        private long typeID;
+
+        private long fieldID;
+
+        private TaggedObject object;
+
+        /**
+         * A constructor.
+         * 
+         * @param suspendPolicy
+         * @param packet
+         */
+        private Event_FIELD_ACCESS(byte suspendPolicy, Packet packet) {
+            super(suspendPolicy, packet, JDWPConstants.EventKind.FIELD_ACCESS);
+            refTypeTag = packet.getNextValueAsByte();
+            typeID = packet.getNextValueAsReferenceTypeID();
+            fieldID = packet.getNextValueAsFieldID();
+            object = packet.getNextValueAsTaggedObject();
+        }
+
+        /**
+         * @return Returns the fieldID.
+         */
+        public long getFieldID() {
+            return fieldID;
+        }
+
+        /**
+         * @return Returns the object.
+         */
+        public TaggedObject getObject() {
+            return object;
+        }
+
+        /**
+         * @return Returns the refTypeTag.
+         */
+        public byte getRefTypeTag() {
+            return refTypeTag;
+        }
+
+        /**
+         * @return Returns the typeID.
+         */
+        public long getTypeID() {
+            return typeID;
+        }
+    };
+
+    /**
+     * The class implements JDWP FIELD_MODIFICATION event.
+     */
+    public static final class Event_FIELD_MODIFICATION extends
+            EventThreadLocation {
+        private byte refTypeTag;
+
+        private long typeID;
+
+        private long fieldID;
+
+        private TaggedObject object;
+
+        private Value valueToBe;
+
+        /**
+         * A constructor.
+         * @param suspendPolicy
+         * @param packet
+         */
+        private Event_FIELD_MODIFICATION(byte suspendPolicy, Packet packet) {
+            super(suspendPolicy, packet,
+                    JDWPConstants.EventKind.FIELD_MODIFICATION);
+            refTypeTag = packet.getNextValueAsByte();
+            typeID = packet.getNextValueAsReferenceTypeID();
+            fieldID = packet.getNextValueAsFieldID();
+            object = packet.getNextValueAsTaggedObject();
+            valueToBe = packet.getNextValueAsValue();
+        }
+
+        /**
+         * @return Returns the fieldID.
+         */
+        public long getFieldID() {
+            return fieldID;
+        }
+
+        /**
+         * @return Returns the object.
+         */
+        public TaggedObject getObject() {
+            return object;
+        }
+
+        /**
+         * @return Returns the refTypeTag.
+         */
+        public byte getRefTypeTag() {
+            return refTypeTag;
+        }
+
+        /**
+         * @return Returns the typeID.
+         */
+        public long getTypeID() {
+            return typeID;
+        }
+
+        /**
+         * @return Returns the valueToBe.
+         */
+        public Value getValueToBe() {
+            return valueToBe;
+        }
+    };
+
+    /**
+     * The class implements JDWP VM_DEATH event.
+     */
+    public static final class Event_VM_DEATH extends ParsedEvent {
+        /**
+         * A constructor.
+         * @param suspendPolicy
+         * @param packet
+         */
+        private Event_VM_DEATH(byte suspendPolicy, Packet packet) {
+            super(suspendPolicy, packet, JDWPConstants.EventKind.VM_DEATH);
+        }
+    };
+
+    /**
+     * Returns array of ParsedEvent extracted from given EventPacket.
+     * 
+     * @param packet
+     *            EventPacket to parse events
+     * @return array of extracted ParsedEvents
+     */
+    public static ParsedEvent[] parseEventPacket(Packet packet) {
+
+        Packet packetCopy = new Packet(packet.toBytesArray());
+
+        // Suspend Policy field
+        byte suspendPolicy = packetCopy.getNextValueAsByte();
+
+        // Number of events
+        int eventCount = packetCopy.getNextValueAsInt();
+
+        ParsedEvent[] events = new ParsedEvent[eventCount];
+
+        // For all events in packet
+        for (int i = 0; i < eventCount; i++) {
+            byte eventKind = packetCopy.getNextValueAsByte();
+            switch (eventKind) {
+            case JDWPConstants.EventKind.VM_START: {
+                events[i] = new Event_VM_START(suspendPolicy, packetCopy);
+                break;
+            }
+            case JDWPConstants.EventKind.SINGLE_STEP: {
+                events[i] = new Event_SINGLE_STEP(suspendPolicy, packetCopy);
+                break;
+            }
+            case JDWPConstants.EventKind.BREAKPOINT: {
+                events[i] = new Event_BREAKPOINT(suspendPolicy, packetCopy);
+                break;
+            }
+            case JDWPConstants.EventKind.METHOD_ENTRY: {
+                events[i] = new Event_METHOD_ENTRY(suspendPolicy, packetCopy);
+                break;
+            }
+            case JDWPConstants.EventKind.METHOD_EXIT: {
+                events[i] = new Event_METHOD_EXIT(suspendPolicy, packetCopy);
+                break;
+            }
+            case JDWPConstants.EventKind.EXCEPTION: {
+                events[i] = new Event_EXCEPTION(suspendPolicy, packetCopy);
+                break;
+            }
+            case JDWPConstants.EventKind.THREAD_START: {
+                events[i] = new Event_THREAD_START(suspendPolicy, packetCopy);
+                break;
+            }
+            case JDWPConstants.EventKind.THREAD_DEATH: {
+                events[i] = new Event_THREAD_DEATH(suspendPolicy, packetCopy);
+                break;
+            }
+            case JDWPConstants.EventKind.CLASS_PREPARE: {
+                events[i] = new Event_CLASS_PREPARE(suspendPolicy, packetCopy);
+                break;
+            }
+            case JDWPConstants.EventKind.CLASS_UNLOAD: {
+                events[i] = new Event_CLASS_UNLOAD(suspendPolicy, packetCopy);
+                break;
+            }
+            case JDWPConstants.EventKind.FIELD_ACCESS: {
+                events[i] = new Event_FIELD_ACCESS(suspendPolicy, packetCopy);
+                break;
+            }
+            case JDWPConstants.EventKind.FIELD_MODIFICATION: {
+                events[i] = new Event_FIELD_MODIFICATION(suspendPolicy,
+                        packetCopy);
+                break;
+            }
+            case JDWPConstants.EventKind.VM_DEATH: {
+                events[i] = new Event_VM_DEATH(suspendPolicy, packetCopy);
+                break;
+            }
+            default: {
+                throw new TestErrorException("Unexpected kind of event: "
+                        + eventKind);
+            }
+            }
+        }
+        return events;
+    }
+
+}

Propchange: harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/ParsedEvent.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/ReplyPacket.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/ReplyPacket.java?view=auto&rev=480141
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/ReplyPacket.java (added)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/ReplyPacket.java Tue Nov 28 09:49:08 2006
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Khen G. Kim
+ * @version $Revision: 1.3 $
+ */
+
+/**
+ * Created on 10.01.2004
+ */
+package org.apache.harmony.jpda.tests.framework.jdwp;
+
+import org.apache.harmony.jpda.tests.framework.jdwp.Packet;
+
+/**
+ * This class represents JDWP reply packet.
+ */
+public class ReplyPacket extends Packet {
+
+    private final int ERROR_CODE_INDEX = 9;
+
+    private short error_code;
+
+    /**
+     * A default constructor that creates an empty ReplyPacket with empty header
+     * and no data.
+     */
+    public ReplyPacket() {
+        super();
+    }
+
+    /**
+     * A constructor that creates ReplyPacket from array of bytes including
+     * header and data sections.
+     * 
+     * @param p
+     *            the JDWP packet, given as array of bytes.
+     */
+    public ReplyPacket(byte p[]) {
+        super(p);
+        error_code = (short) super.readFromByteArray(p, ERROR_CODE_INDEX,
+                Packet.SHORT_SIZE);
+    }
+
+    /**
+     * Sets the error code value of the header of the ReplyPacket as short.
+     * 
+     * @param val
+     *            the error code.
+     */
+    public void setErrorCode(short val) {
+        error_code = val;
+    }
+
+    /**
+     * Gets the error code value of the header of the ReplyPacket.
+     * 
+     * @return the error code value of the header of the ReplyPacket.
+     */
+    public short getErrorCode() {
+        return error_code;
+    }
+
+    /**
+     * Gets the representation of the ReplyPacket as array of bytes in the JDWP
+     * format including header and data sections.
+     * 
+     * @return the representation of the ReplyPacket as array of bytes in the
+     *         JDWP format.
+     */
+    public byte[] toBytesArray() {
+        byte res[] = super.toBytesArray();
+        super.writeAtByteArray(error_code, res, ERROR_CODE_INDEX,
+                Packet.SHORT_SIZE);
+        return res;
+    }
+}

Propchange: harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/ReplyPacket.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/SocketTransportWrapper.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/SocketTransportWrapper.java?view=auto&rev=480141
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/SocketTransportWrapper.java (added)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/SocketTransportWrapper.java Tue Nov 28 09:49:08 2006
@@ -0,0 +1,320 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Ivan G. Popov
+ * @version $Revision: 1.5 $
+ */
+
+/**
+ * Created on 05.23.2004
+ */
+package org.apache.harmony.jpda.tests.framework.jdwp;
+
+
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.io.OutputStream;
+import java.io.IOException;
+
+import org.apache.harmony.jpda.tests.framework.jdwp.Packet;
+
+/**
+ * This class provides TransportWrapper for row TCP/IP socket connection.
+ *  
+ */
+public class SocketTransportWrapper implements TransportWrapper {
+
+    public static final String HANDSHAKE_STRING = "JDWP-Handshake";
+
+    private ServerSocket serverSocket;
+    private Socket transportSocket;
+    private InputStream input;
+    private OutputStream output;
+
+    /**
+     * Starts listening for connection on given or default address.
+     * 
+     * @param address address to listen or null for default address
+     * @return string representation of listening address 
+     */
+    public String startListening(String address) throws IOException {
+        String hostName = null;
+        InetAddress hostAddr = null;
+        int port = 0;
+        if (address != null) {
+            String portName = null;
+            int i = address.indexOf(':');
+            if (i < 0) {
+                portName = address;
+            } else {
+                hostName = address.substring(0, i);
+                portName = address.substring(i+1);
+            }
+            try {
+                port = Integer.parseInt(portName);
+            } catch (NumberFormatException e) {
+                throw new IOException("Illegal port number in socket address: " + address);
+            }
+        }
+
+        if (hostName != null) {
+            hostAddr = InetAddress.getByName(hostName);
+            serverSocket = new ServerSocket(port, 0, hostAddr);
+        } else {
+            serverSocket = new ServerSocket(port);
+        }
+        
+        // use as workaround for unspecified behaviour of isAnyLocalAddress()
+        InetAddress iAddress = null;
+        if (hostName != null) {
+            iAddress = serverSocket.getInetAddress();
+        } else {
+            iAddress = InetAddress.getLocalHost();
+        }
+        
+        address = iAddress.getHostName() + ":" + serverSocket.getLocalPort();
+        return address;
+    }
+    
+    /**
+     * Stops listening for connection on current address.
+     */
+    public void stopListening() throws IOException {
+        if (serverSocket != null) {
+            serverSocket.close();
+        }
+    }
+
+    /**
+     * Accepts transport connection for currently listened address and performs handshaking 
+     * for specified timeout.
+     * 
+     * @param acceptTimeout timeout for accepting in milliseconds
+     * @param handshakeTimeout timeout for handshaking in milliseconds
+     */
+    public void accept(long acceptTimeout, long handshakeTimeout) throws IOException {
+        synchronized (serverSocket) {
+            serverSocket.setSoTimeout((int) acceptTimeout);
+            try {
+                transportSocket = serverSocket.accept();
+            } finally {
+                serverSocket.setSoTimeout(0);
+            }
+        }
+        createStreams();
+        handshake(handshakeTimeout);
+    }
+    
+    /**
+     * Attaches transport connection to given address and performs handshaking 
+     * for specified timeout.
+     * 
+     * @param address address for attaching
+     * @param attachTimeout timeout for attaching in milliseconds
+     * @param handshakeTimeout timeout for handshaking in milliseconds
+     */
+    public void attach(String address, long attachTimeout, long handshakeTimeout) throws IOException {
+        if (address == null) {
+            throw new IOException("Illegal socket address: " + address);
+        }
+
+        String hostName = null;
+        int port = 0;
+        {
+            String portName = null;
+            int i = address.indexOf(':');
+            if (i < 0) {
+                throw new IOException("Illegal socket address: " + address);
+            } else {
+                hostName = address.substring(0, i);
+                portName = address.substring(i+1);
+            }
+            try {
+                port = Integer.parseInt(portName);
+            } catch (NumberFormatException e) {
+                throw new IOException("Illegal port number in socket address: " + address);
+            }
+        }
+
+        long finishTime = System.currentTimeMillis() + attachTimeout;
+        long sleepTime = 4 * 1000; // millesecinds
+        IOException exception = null;
+        try {
+            do {
+                try {
+                    transportSocket = new Socket(hostName, port);
+                    break;
+                } catch (IOException e) {
+                    Thread.sleep(sleepTime);
+                }
+            } while (attachTimeout == 0 || System.currentTimeMillis() < finishTime);
+        } catch (InterruptedException e) {
+            throw new InterruptedIOException("Interruption in attaching to " + address);
+        }
+        
+        if (transportSocket == null) {
+            if (exception != null) {
+                throw exception;
+            } else {
+                throw new SocketTimeoutException("Timeout exceeded in attaching to " + address);
+            }
+        }
+        
+        createStreams();
+        handshake(handshakeTimeout);
+    }
+
+    /**
+     * Closes transport connection.
+     */
+    public void close() throws IOException {
+        if (input != null) {
+            input.close();
+        }
+        if (output != null) {
+            output.close();
+        }
+        
+        if (transportSocket != null && input == null && output == null && !transportSocket.isClosed()) {
+            transportSocket.close();
+        }
+        if (serverSocket != null) {
+            serverSocket.close();
+        }
+    }
+
+    /**
+     * Checks if transport connection is open.
+     * 
+     * @return true if transport connection is open
+     */
+    public boolean isOpen() {
+        return (transportSocket != null 
+                    && transportSocket.isConnected() 
+                    && !transportSocket.isClosed());
+    }
+
+    /**
+     * Reads packet bytes from transport connection.
+     * 
+     * @return packet as byte array or null or empty packet if connection was closed
+     */
+    public byte[] readPacket() throws IOException {
+
+        // read packet header
+        byte[] header = new byte[Packet.HEADER_SIZE];
+        int off = 0;
+
+        while (off < Packet.HEADER_SIZE) {
+            try {
+                int bytesRead = input.read(header, off, Packet.HEADER_SIZE - off);
+                if (bytesRead < 0) {
+                    break;
+                }
+                off += bytesRead;
+            } catch (IOException e) {
+                // workaround for "Socket Closed" exception if connection was closed
+                break;
+            }
+        }
+
+        if (off == 0) {
+            return null;
+        }
+        if (off < Packet.HEADER_SIZE) {
+            throw new IOException("Connection closed in reading packet header");
+        }
+
+        // extract packet length
+        int len = Packet.getPacketLength(header);
+        if (len < Packet.HEADER_SIZE) {
+            throw new IOException("Wrong packet size detected: " + len);
+        }
+        
+        // allocate packet bytes and store header there 
+        byte[] bytes = new byte[len];
+        System.arraycopy(header, 0, bytes, 0, Packet.HEADER_SIZE);
+
+        // read packet data
+        while (off < len) {
+            int bytesRead = input.read(bytes, off, len - off);
+            if (bytesRead < 0) {
+                break;
+            }
+            off += bytesRead;
+        }
+        if (off < len) {
+            throw new IOException("Connection closed in reading packet data");
+        }
+
+        return bytes;
+    }
+
+    /**
+     * Writes packet bytes to transport connection.
+     * 
+     * @param packet
+     *            packet as byte array
+     */
+    public void writePacket(byte[] packet) throws IOException {
+        output.write(packet);
+        output.flush();
+    }
+
+    /**
+     * Performs handshaking for given timeout.
+     * 
+     * @param handshakeTimeout timeout for handshaking in milliseconds
+     */
+    protected void handshake(long handshakeTimeout) throws IOException {
+        transportSocket.setSoTimeout((int) handshakeTimeout);
+        
+        try {
+            output.write(HANDSHAKE_STRING.getBytes());
+            output.flush();
+            int len = HANDSHAKE_STRING.length();
+            byte[] bytes = new byte[len];
+            int off = 0;
+            while (off < len) {
+                int bytesRead = input.read(bytes, off, len - off);
+                if (bytesRead < 0) {
+                    break;
+                }
+                off += bytesRead;
+            }
+            String response = new String(bytes, 0, off);
+            if (!response.equals(HANDSHAKE_STRING)) {
+                throw new IOException("Unexpected handshake response: " + response);
+            }
+        } finally {
+            transportSocket.setSoTimeout(0);
+        }
+    }
+
+    /**
+     * Creates input/output streams for connection socket.
+     */
+    protected void createStreams() throws IOException {
+        input = transportSocket.getInputStream();
+        output = transportSocket.getOutputStream();
+    }
+}

Propchange: harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/SocketTransportWrapper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/TaggedObject.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/TaggedObject.java?view=auto&rev=480141
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/TaggedObject.java (added)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/TaggedObject.java Tue Nov 28 09:49:08 2006
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Aleksey V. Yantsen
+ * @version $Revision: 1.2 $
+ */
+
+/**
+ * Created on 10.25.2004
+ */
+package org.apache.harmony.jpda.tests.framework.jdwp;
+
+import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
+
+/**
+ * This class represents tagged-objectID value in JDWP packet.
+ */
+public class TaggedObject {
+    public byte tag;
+    public long objectID;
+
+    /**
+     * Creates new value with empty tag.
+     */
+    public TaggedObject() {
+        tag = JDWPConstants.Tag.NO_TAG;
+        objectID = 0;
+    }
+
+    /**
+     * Creates new value with specified data.
+     */
+    public TaggedObject(byte tag, long objectID) {
+        this.tag = tag;
+        this.objectID = objectID;
+    }
+}
\ No newline at end of file

Propchange: harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/TaggedObject.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/TransportWrapper.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/TransportWrapper.java?view=auto&rev=480141
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/TransportWrapper.java (added)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/TransportWrapper.java Tue Nov 28 09:49:08 2006
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Ivan G. Popov
+ * @version $Revision: 1.5 $
+ */
+
+/**
+ * Created on 05.23.2004
+ */
+package org.apache.harmony.jpda.tests.framework.jdwp;
+
+import java.io.IOException;
+
+/**
+ * This interface provides wrapper around JDWP transport connection.
+ * Particular implementation can interact directly with raw connection
+ * like SocketTransportWrapper or use JDI service provider interfaces
+ * to support all pluggable JDI transports.
+ *  
+ */
+public interface TransportWrapper {
+
+    /**
+     * Starts listening for connection on given or default address.
+     * 
+     * @param address address to listen or null for default address
+     * @return string representation of listening address 
+     */
+    public String startListening(String address) throws IOException;
+    
+    /**
+     * Stops listening for connection on current address.
+     */
+    public void stopListening() throws IOException;
+
+    /**
+     * Accepts transport connection for currently listened address and performs handshaking 
+     * for specified timeout.
+     * 
+     * @param acceptTimeout timeout for accepting in milliseconds
+     * @param handshakeTimeout timeout for handshaking in milliseconds
+     */
+    public void accept(long acceptTimeout, long handshakeTimeout) throws IOException;
+    
+    /**
+     * Attaches transport connection to given address and performs handshaking 
+     * for specified timeout.
+     * 
+     * @param address address for attaching
+     * @param attachTimeout timeout for attaching in milliseconds
+     * @param handshakeTimeout timeout for handshaking in milliseconds
+     */
+    public void attach(String address, long attachTimeout, long handshakeTimeout) throws IOException;
+
+    /**
+     * Closes transport connection.
+     */
+    public void close() throws IOException;
+
+    /**
+     * Checks if transport connection is open.
+     * 
+     * @return true if transport connection is open
+     */
+    public boolean isOpen();
+
+    /**
+     * Reads packet from transport connection.
+     * 
+     * @return packet as byte array or null or empty packet if connection was closed
+     */
+    public byte[] readPacket() throws IOException;
+
+    /**
+     * Writes packet to transport connection.
+     * 
+     * @param packet packet as byte array
+     */
+    public void writePacket(byte[] packet) throws IOException;
+}

Propchange: harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/TransportWrapper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/TypesLengths.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/TypesLengths.java?view=auto&rev=480141
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/TypesLengths.java (added)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/TypesLengths.java Tue Nov 28 09:49:08 2006
@@ -0,0 +1,309 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Aleksey V. Yantsen
+ * @version $Revision: 1.6 $
+ */
+
+/**
+ * Created on 12.23.2004
+ */
+package org.apache.harmony.jpda.tests.framework.jdwp;
+
+import org.apache.harmony.jpda.tests.framework.TestErrorException;
+
+/**
+ * This class provides types length for VM-independent and VM-dependent types.
+ */
+public class TypesLengths {
+
+    // Type IDs
+    public static final byte BYTE_ID = 1;
+
+    public static final byte BOOLEAN_ID = 2;
+
+    public static final byte INT_ID = 3;
+
+    public static final byte LONG_ID = 4;
+
+    public static final byte SHORT_ID = 5;
+
+    public static final byte FLOAT_ID = 6;
+
+    public static final byte DOUBLE_ID = 7;
+
+    public static final byte VOID_ID = 8;
+
+    public static final byte OBJECT_ID = 9;
+
+    public static final byte ARRAY_ID = 10;
+
+    public static final byte STRING_ID = 11;
+
+    public static final byte THREAD_ID = 12;
+
+    public static final byte THREADGROUP_ID = 13;
+
+    public static final byte METHOD_ID = 14;
+
+    public static final byte FIELD_ID = 15;
+
+    public static final byte FRAME_ID = 16;
+
+    public static final byte LOCATION_ID = 17;
+
+    public static final byte REFERENCE_TYPE_ID = 18;
+
+    public static final byte CLASS_ID = 19;
+
+    public static final byte CLASSLOADER_ID = 20;
+
+    public static final byte CLASSOBJECT_ID = 21;
+
+    public static final byte CHAR_ID = 22;
+
+    // Type lengths in bytes (VM-independent)
+
+    private static int byteLength = 1;
+
+    private static int booleanLength = 1;
+
+    private static int intLength = 4;
+
+    private static int longLength = 8;
+
+    private static int shortLength = 2;
+
+    private static int floatLength = 4;
+
+    private static int doubleLength = 8;
+
+    private static int voidLength = 0;
+
+    private static int charLength = 2;
+
+    // Type lengths in bytes (VM-dependent)
+
+    private static int objectLength;
+
+    private static int arrayLength;
+
+    private static int stringLength;
+
+    private static int threadLength;
+
+    private static int threadGroupLength;
+
+    private static int methodLength;
+
+    private static int fieldLength;
+
+    private static int frameLength;
+
+    private static int locationLength;
+
+    private static int referenceLength;
+
+    private static int classLength;
+
+    private static int classLoaderLength;
+
+    private static int classObjectLength;
+
+    /**
+     * Gets types length for type ID.
+     * 
+     * @param typeID
+     *            Type ID
+     * @return type length
+     */
+    public static int getTypeLength(byte typeID) throws TestErrorException {
+        switch (typeID) {
+        case BYTE_ID: {
+            return byteLength;
+        }
+        case BOOLEAN_ID: {
+            return booleanLength;
+        }
+        case INT_ID: {
+            return intLength;
+        }
+        case LONG_ID: {
+            return longLength;
+        }
+        case SHORT_ID: {
+            return shortLength;
+        }
+        case FLOAT_ID: {
+            return floatLength;
+        }
+        case DOUBLE_ID: {
+            return doubleLength;
+        }
+        case VOID_ID: {
+            return voidLength;
+        }
+        case OBJECT_ID: {
+            return objectLength;
+        }
+        case ARRAY_ID: {
+            return arrayLength;
+        }
+        case STRING_ID: {
+            return stringLength;
+        }
+        case THREAD_ID: {
+            return threadLength;
+        }
+        case THREADGROUP_ID: {
+            return threadGroupLength;
+        }
+        case METHOD_ID: {
+            return methodLength;
+        }
+        case FIELD_ID: {
+            return fieldLength;
+        }
+        case FRAME_ID: {
+            return frameLength;
+        }
+        case LOCATION_ID: {
+            return locationLength;
+        }
+        case REFERENCE_TYPE_ID: {
+            return referenceLength;
+        }
+        case CLASS_ID: {
+            return classLength;
+        }
+        case CLASSLOADER_ID: {
+            return classLoaderLength;
+        }
+        case CLASSOBJECT_ID: {
+            return classObjectLength;
+        }
+        case CHAR_ID: {
+            return charLength;
+        }
+        default:
+            throw new TestErrorException("Unexpected type ID: " + typeID);
+        }
+    }
+
+    /**
+     * Sets types length for type ID
+     * 
+     * @param typeID Type ID
+     * @param typeLength type length
+     */
+    public static void setTypeLength(byte typeID, int typeLength)
+            throws TestErrorException {
+        switch (typeID) {
+        case BYTE_ID: {
+            byteLength = typeLength;
+            return;
+        }
+        case BOOLEAN_ID: {
+            booleanLength = typeLength;
+            return;
+        }
+        case INT_ID: {
+            intLength = typeLength;
+            return;
+        }
+        case LONG_ID: {
+            longLength = typeLength;
+            return;
+        }
+        case SHORT_ID: {
+            shortLength = typeLength;
+            return;
+        }
+        case FLOAT_ID: {
+            floatLength = typeLength;
+            return;
+        }
+        case DOUBLE_ID: {
+            doubleLength = typeLength;
+            return;
+        }
+        case VOID_ID: {
+            voidLength = typeLength;
+            return;
+        }
+        case OBJECT_ID: {
+            objectLength = typeLength;
+            return;
+        }
+        case ARRAY_ID: {
+            arrayLength = typeLength;
+            return;
+        }
+        case STRING_ID: {
+            stringLength = typeLength;
+            return;
+        }
+        case THREAD_ID: {
+            threadLength = typeLength;
+            return;
+        }
+        case THREADGROUP_ID: {
+            threadGroupLength = typeLength;
+            return;
+        }
+        case METHOD_ID: {
+            methodLength = typeLength;
+            return;
+        }
+        case FIELD_ID: {
+            fieldLength = typeLength;
+            return;
+        }
+        case FRAME_ID: {
+            frameLength = typeLength;
+            return;
+        }
+        case LOCATION_ID: {
+            locationLength = typeLength;
+            return;
+        }
+        case REFERENCE_TYPE_ID: {
+            referenceLength = typeLength;
+            return;
+        }
+        case CLASS_ID: {
+            classLength = typeLength;
+            return;
+        }
+        case CLASSLOADER_ID: {
+            classLoaderLength = typeLength;
+            return;
+        }
+        case CLASSOBJECT_ID: {
+            classObjectLength = typeLength;
+            return;
+        }
+        case CHAR_ID: {
+            classObjectLength = charLength;
+            return;
+        }
+        default:
+            throw new TestErrorException("Unexpected type ID: " + typeID);
+        }
+    }
+}

Propchange: harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/TypesLengths.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/Value.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/Value.java?view=auto&rev=480141
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/Value.java (added)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/Value.java Tue Nov 28 09:49:08 2006
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * @author Aleksey V. Yantsen
+ * @version $Revision: 1.4 $
+ */
+
+/**
+ * Created on 10.25.2004
+ */
+package org.apache.harmony.jpda.tests.framework.jdwp;
+
+import org.apache.harmony.jpda.tests.framework.TestErrorException;
+import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
+
+/**
+ * This class represents generic value used in JDWP packets.
+ */
+public class Value {
+
+    private byte tag;
+
+    private Number numberValue;
+
+    private boolean booleanValue;
+
+    private char charValue;
+
+    /**
+     * Creates new value with no tag.
+     */
+    public Value() {
+        tag = JDWPConstants.Tag.NO_TAG;
+    }
+
+    /**
+     * Creates new ID value with specified tag.
+     */
+    public Value(byte tag, long value) {
+        this.tag = tag;
+        this.numberValue = new Long(value);
+    }
+
+    /**
+     * Creates new byte value.
+     */
+    public Value(byte value) {
+        this.tag = JDWPConstants.Tag.BYTE_TAG;
+        this.numberValue = new Byte(value);
+    }
+
+    /**
+     * Creates new short value.
+     */
+    public Value(short value) {
+        this.tag = JDWPConstants.Tag.SHORT_TAG;
+        this.numberValue = new Short(value);
+    }
+
+    /**
+     * Creates new int value.
+     */
+    public Value(int value) {
+        this.tag = JDWPConstants.Tag.INT_TAG;
+        this.numberValue = new Integer(value);
+    }
+
+    /**
+     * Creates new long value.
+     */
+    public Value(long value) {
+        this.tag = JDWPConstants.Tag.LONG_TAG;
+        this.numberValue = new Long(value);
+    }
+
+    /**
+     * Creates new short value.
+     */
+    public Value(float value) {
+        this.tag = JDWPConstants.Tag.FLOAT_TAG;
+        this.numberValue = new Float(value);
+    }
+
+    /**
+     * Creates new double value.
+     */
+    public Value(double value) {
+        this.tag = JDWPConstants.Tag.DOUBLE_TAG;
+        this.numberValue = new Double(value);
+    }
+
+    /**
+     * Creates new boolean value.
+     */
+    public Value(boolean value) {
+        this.tag = JDWPConstants.Tag.BOOLEAN_TAG;
+        this.booleanValue = value;
+    }
+
+    /**
+     * Creates new char value.
+     */
+    public Value(char value) {
+        this.tag = JDWPConstants.Tag.CHAR_TAG;
+        this.charValue = value;
+    }
+
+    /**
+     * Returns tag of this value.
+     * 
+     * @return Returns the tag.
+     */
+    public byte getTag() {
+        return tag;
+    }
+
+    /**
+     * Returns byte representation of this value.
+     * 
+     * @return byte value
+     */
+    public byte getByteValue() {
+        return numberValue.byteValue();
+    }
+
+    /**
+     * Returns short representation of this value.
+     * 
+     * @return short value
+     */
+    public short getShortValue() {
+        return numberValue.shortValue();
+    }
+
+    /**
+     * Returns int representation of this value.
+     * 
+     * @return int value
+     */
+    public int getIntValue() {
+        return numberValue.intValue();
+    }
+
+    /**
+     * Returns long representation of this value.
+     * 
+     * @return long value
+     */
+    public long getLongValue() {
+        return numberValue.longValue();
+    }
+
+    /**
+     * Returns float representation of this value.
+     * 
+     * @return float value
+     */
+    public float getFloatValue() {
+        return numberValue.floatValue();
+    }
+
+    /**
+     * Returns double representation of this value.
+     * 
+     * @return double value
+     */
+    public double getDoubleValue() {
+        return numberValue.doubleValue();
+    }
+
+    /**
+     * Returns boolean representation of this value.
+     * 
+     * @return boolean value
+     */
+    public boolean getBooleanValue() {
+        return booleanValue;
+    }
+
+    /**
+     * Returns char representation of this value.
+     * 
+     * @return char value
+     */
+    public char getCharValue() {
+        return charValue;
+    }
+
+    /**
+     * Compares with other value.
+     */
+    public boolean equals(Object arg0) {
+        if (!(arg0 instanceof Value))
+            return false;
+
+        Value value0 = (Value) arg0;
+        if (value0.tag != value0.tag)
+            return false;
+
+        switch (tag) {
+        case JDWPConstants.Tag.BOOLEAN_TAG:
+            return getBooleanValue() == value0.getBooleanValue();
+        case JDWPConstants.Tag.BYTE_TAG:
+            return getByteValue() == value0.getByteValue();
+        case JDWPConstants.Tag.CHAR_TAG:
+            return getCharValue() == value0.getCharValue();
+        case JDWPConstants.Tag.DOUBLE_TAG:
+            if (Double.isNaN(getDoubleValue())
+                    && (Double.isNaN(value0.getDoubleValue())))
+                return true;
+            return getDoubleValue() == value0.getDoubleValue();
+        case JDWPConstants.Tag.FLOAT_TAG:
+            if (Float.isNaN(getFloatValue())
+                    && (Float.isNaN(value0.getFloatValue())))
+                return true;
+            return getFloatValue() == value0.getFloatValue();
+        case JDWPConstants.Tag.INT_TAG:
+            return getIntValue() == value0.getIntValue();
+        case JDWPConstants.Tag.LONG_TAG:
+            return getLongValue() == value0.getLongValue();
+        case JDWPConstants.Tag.SHORT_TAG:
+            return getShortValue() == value0.getShortValue();
+        case JDWPConstants.Tag.STRING_TAG:
+        case JDWPConstants.Tag.ARRAY_TAG:
+        case JDWPConstants.Tag.CLASS_LOADER_TAG:
+        case JDWPConstants.Tag.CLASS_OBJECT_TAG:
+        case JDWPConstants.Tag.OBJECT_TAG:
+        case JDWPConstants.Tag.THREAD_GROUP_TAG:
+        case JDWPConstants.Tag.THREAD_TAG:
+            return getLongValue() == value0.getLongValue();
+        }
+
+        throw new TestErrorException("Illegal tag value");
+    }
+
+    /**
+     * Converts this value to string representation for printing.
+     */
+    public String toString() {
+
+        switch (tag) {
+        case JDWPConstants.Tag.BOOLEAN_TAG:
+            return "boolean: " + getBooleanValue();
+        case JDWPConstants.Tag.BYTE_TAG:
+            return "byte: " + getByteValue();
+        case JDWPConstants.Tag.CHAR_TAG:
+            return "char: " + getCharValue();
+        case JDWPConstants.Tag.DOUBLE_TAG:
+            return "double: " + getDoubleValue();
+        case JDWPConstants.Tag.FLOAT_TAG:
+            return "float: " + getFloatValue();
+        case JDWPConstants.Tag.INT_TAG:
+            return "int: " + getIntValue();
+        case JDWPConstants.Tag.LONG_TAG:
+            return "long: " + getLongValue();
+        case JDWPConstants.Tag.SHORT_TAG:
+            return "short: " + getShortValue();
+        case JDWPConstants.Tag.STRING_TAG:
+            return "StringID: " + getLongValue();
+        case JDWPConstants.Tag.ARRAY_TAG:
+            return "ObjectID: " + getLongValue();
+
+        case JDWPConstants.Tag.CLASS_LOADER_TAG:
+            return "ClassLoaderID: " + getLongValue();
+        case JDWPConstants.Tag.CLASS_OBJECT_TAG:
+            return "ClassObjectID: " + getLongValue();
+        case JDWPConstants.Tag.OBJECT_TAG:
+            return "ObjectID: " + getLongValue();
+        case JDWPConstants.Tag.THREAD_GROUP_TAG:
+            return "ThreadGroupID: " + getLongValue();
+        case JDWPConstants.Tag.THREAD_TAG:
+            return "ThreadID: " + getLongValue();
+        }
+
+        throw new TestErrorException("Illegal tag value: " + tag);
+    }
+}

Propchange: harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/jdwp/Value.java
------------------------------------------------------------------------------
    svn:eol-style = native