You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by gs...@apache.org on 2007/07/23 18:18:30 UTC

svn commit: r558788 [1/2] - in /harmony/enhanced/jdktools/trunk/modules/jpda: src/main/native/jdwp/common/agent/core/ src/main/native/jdwp/common/transport/dt_socket/ src/main/native/jdwp/unix/agent/ src/main/native/jdwp/unix/agent/core/ src/main/nativ...

Author: gshimansky
Date: Mon Jul 23 09:18:27 2007
New Revision: 558788

URL: http://svn.apache.org/viewvc?view=rev&rev=558788
Log:
Applied patch from HARMONY-2892
[jdktools][jdwp] Support on-demand debugger attach in JDWP agent


Added:
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentManager.cpp   (with props)
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentManager.h   (with props)
    harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/jdwp/DebuggerOnDemand/
    harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/jdwp/DebuggerOnDemand/LaunchedDebugger.java   (with props)
    harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/jdwp/DebuggerOnDemand/OnthowDebuggerLaunchDebuggee.java   (with props)
    harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/jdwp/DebuggerOnDemand/OnthrowDebuggerLaunchTest.java   (with props)
    harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/jdwp/DebuggerOnDemand/OnthrowLaunchDebugger001.java   (with props)
    harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/jdwp/DebuggerOnDemand/OnthrowLaunchDebugger002.java   (with props)
    harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/jdwp/share/JDWPUnitDebuggeeProcessWrapper.java   (with props)
Modified:
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/Agent.cpp
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentBase.h
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentEnv.h
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentException.h
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/OptionParser.cpp
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/OptionParser.h
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/PacketDispatcher.cpp
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/PacketDispatcher.h
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/RequestManager.cpp
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/ThreadManager.cpp
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/ThreadManager.h
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/TransportManager.cpp
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/TransportManager.h
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/transport/dt_socket/SocketTransport.cpp
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/unix/agent/core/TransportManager_pd.cpp
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/unix/agent/makefile
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/unix/transport/makefile
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/windows/agent/core/TransportManager_pd.cpp
    harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/windows/agent/makefile
    harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/TestOptions.java
    harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/jdwp/share/JDWPRawTestCase.java
    harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/jdwp/share/JDWPSyncTestCase.java
    harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/jdwp/share/JDWPTestCase.java
    harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/jdwp/share/JDWPUnitDebuggeeWrapper.java
    harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/share/JPDADebuggeeSynchronizer.java
    harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/share/SyncDebuggee.java

Modified: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/Agent.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/Agent.cpp?view=diff&rev=558788&r1=558787&r2=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/Agent.cpp (original)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/Agent.cpp Mon Jul 23 09:18:27 2007
@@ -41,6 +41,7 @@
 #include "TransportManager.h"
 #include "PacketDispatcher.h"
 #include "EventDispatcher.h"
+#include "AgentManager.h"
 
 using namespace jdwp;
 
@@ -103,50 +104,6 @@
     );
 }
 
-static void InitAgent(jvmtiEnv *jvmti, JNIEnv *jni)
-{
-    JDWP_TRACE_ENTRY("InitAgent(" << jvmti << "," << jni << ")");
-
-    JDWP_TRACE_PROG("InitAgent: init and start all modules");
-
-    //currentSessionID = 0;
-
-    try {
-        AgentBase::SetIsDead(false);
-        AgentBase::GetClassManager().Init(jni);
-        AgentBase::GetObjectManager().Init(jni);
-        AgentBase::GetThreadManager().Init(jni);
-        AgentBase::GetRequestManager().Init(jni);
-        AgentBase::GetEventDispatcher().Init(jni);
-        AgentBase::GetPacketDispatcher().Init(jni);
-
-        char* javaLibraryPath = 0;
-        jvmtiError err;
-        JVMTI_TRACE(err,
-            jvmti->GetSystemProperty("java.library.path", &javaLibraryPath));
-        if (err != JVMTI_ERROR_NONE) {
-            JDWP_INFO("Unable to get system property: java.library.path")
-        }
-        JvmtiAutoFree afv(javaLibraryPath);
-        AgentBase::GetTransportManager().Init(
-            AgentBase::GetOptionParser().GetTransport(),
-            javaLibraryPath);
-
-        AgentBase::GetTransportManager().PrepareConnection(
-            AgentBase::GetOptionParser().GetAddress(),
-            AgentBase::GetOptionParser().GetServer(),
-            AgentBase::GetOptionParser().GetTimeout(),
-            AgentBase::GetOptionParser().GetTimeout()
-        );
-
-        AgentBase::GetEventDispatcher().Start(jni);
-        AgentBase::GetPacketDispatcher().Start(jni);
-    } catch (AgentException& e) {
-        JDWP_INFO("JDWP error: " << e.what() << " [" << e.ErrCode() << "]");
-        jni->FatalError("Unable to initialize agent");
-    }
-}
-
 //-----------------------------------------------------------------------------
 // event callbacks
 //-----------------------------------------------------------------------------
@@ -159,10 +116,20 @@
         jint ver = jni->GetVersion();
         JDWP_LOG("JNI version: 0x" << hex << ver);
 
-        InitAgent(jvmti, jni);
-        RequestManager::HandleVMInit(jvmti, jni, thread);
+        // initialize agent
+        AgentBase::GetAgentManager().Init(jvmti, jni);
+ 
+        // if options onthrow or onuncaught are set, defer starting agent and enable notification of EXCEPTION event
+        if (AgentBase::GetOptionParser().GetOnthrow() || AgentBase::GetOptionParser().GetOnuncaught()) {
+            AgentBase::GetAgentManager().EnableInitialExceptionCatch(jvmti, jni);
+        } else {
+            AgentBase::GetAgentManager().Start(jvmti, jni);
+            RequestManager::HandleVMInit(jvmti, jni, thread);
+        }
+    } catch (TransportException& e) {
+        JDWP_DIE("JDWP transport error in VM_INIT: " << e.TransportErrorMessage() << " [" << e.ErrCode() << "]");
     } catch (AgentException& e) {
-        JDWP_INFO("JDWP error in VM_INIT: " << e.what() << " [" << e.ErrCode() << "]");
+        JDWP_DIE("JDWP error in VM_INIT: " << e.what() << " [" << e.ErrCode() << "]");
     }
 }
 
@@ -170,13 +137,16 @@
 VMDeath(jvmtiEnv *jvmti, JNIEnv *jni)
 {
     try {
-        // don't print entry trace message after shutdown
-        {
+        if (AgentBase::GetAgentManager().IsStarted()) {
+            // don't print entry trace message after cleaning agent
             JDWP_TRACE_ENTRY("VMDeath(" << jvmti << ',' << jni << ')');
+
             RequestManager::HandleVMDeath(jvmti, jni);
+            AgentBase::SetIsDead(true);
+
+            AgentBase::GetAgentManager().Stop(jni);
         }
-        AgentBase::SetIsDead(true);
-        AgentBase::GetPacketDispatcher().ShutdownAll(jni);
+        AgentBase::GetAgentManager().Clean(jni);
     } catch (AgentException& e) {
         JDWP_INFO("JDWP error in VM_DEATH: " << e.what() << " [" << e.ErrCode() << "]");
     }
@@ -324,6 +294,7 @@
         env.transportManager = new TransportManager();
         env.packetDispatcher = new PacketDispatcher();
         env.eventDispatcher = new EventDispatcher();
+        env.agentManager = new AgentManager();
     } catch (IllegalArgumentException&) {
         JDWP_INFO("JDWP error: Bad agent options: " << options);
         delete env.optionParser;
@@ -488,5 +459,6 @@
         delete &AgentBase::GetObjectManager();
         delete &AgentBase::GetClassManager();
         delete &AgentBase::GetOptionParser();
+        delete &AgentBase::GetAgentManager();
     }
 }

Modified: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentBase.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentBase.h?view=diff&rev=558788&r1=558787&r2=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentBase.h (original)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentBase.h Mon Jul 23 09:18:27 2007
@@ -224,6 +224,14 @@
         }
 
         /**
+         * Gets the agent-manager reference from the agent base.
+         */
+        static AgentManager& GetAgentManager() throw() {
+            CHECK_ENV_PTR(m_agentEnv, agentManager);
+            return *m_agentEnv->agentManager;
+        }
+
+        /**
          * Gets the pointer to JVMTI environment from the agent base.
          */
         static jvmtiEnv* GetJvmtiEnv() throw() {

Modified: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentEnv.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentEnv.h?view=diff&rev=558788&r1=558787&r2=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentEnv.h (original)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentEnv.h Mon Jul 23 09:18:27 2007
@@ -46,6 +46,7 @@
     class PacketDispatcher;
     class EventDispatcher;
     class RequestManager;
+    class AgentManager;
 
     /**
      * Agent-environment structure containing all objects participating in
@@ -53,6 +54,7 @@
      */
     struct AgentEnv {
 
+        AgentManager *agentManager;
         MemoryManager *memoryManager;
         LogManager *logManager;
         OptionParser *optionParser;

Modified: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentException.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentException.h?view=diff&rev=558788&r1=558787&r2=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentException.h (original)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentException.h Mon Jul 23 09:18:27 2007
@@ -31,6 +31,7 @@
 #define _AGENT_EXCEPTION_H_
 
 #include <exception>
+#include <sstream>
 
 #include "jdwp.h"
 #include "jvmti.h"
@@ -202,30 +203,40 @@
          * @param transportError - transport error code
          */
         TransportException(jdwpError err = JDWP_ERROR_TRANSPORT_INIT, 
-                jdwpTransportError transportError = JDWPTRANSPORT_ERROR_NONE) 
+                jdwpTransportError transportError = JDWPTRANSPORT_ERROR_NONE,
+                const char* message = 0) 
                 throw() : AgentException(err) 
         {
             this->m_transportError = transportError;
+            this->m_message = message;
         }
 
         /**
-         * Returns transport-error code.
+         * Returns transport error code.
          */
         jdwpTransportError TransportErrorCode() const throw() {
             return m_transportError;
         }
 
         /**
-         * Returns the given exception name.
+         * Returns transport error message.
+         */
+        const char* TransportErrorMessage() const throw() {
+            return m_message;
+        }
+
+        /**
+         * Returns the given exception info.
          */
         const char* what() const throw() {
-            return "TransportException";
+            return (m_message == 0 ? "TransportException" : m_message);
         }
 
     private:
         jdwpTransportError m_transportError;
+        const char* m_message;
     };
 
-}
+};
 
 #endif // _AGENT_EXCEPTION_H_

Added: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentManager.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentManager.cpp?view=auto&rev=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentManager.cpp (added)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentManager.cpp Mon Jul 23 09:18:27 2007
@@ -0,0 +1,145 @@
+/*
+ * 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 Aleksander V. Budniy
+ * @version $Revision: 1.10.2.1 $
+ */
+
+#include "AgentManager.h"
+#include "ClassManager.h"
+#include "ObjectManager.h"
+#include "OptionParser.h"
+#include "ThreadManager.h"
+#include "RequestManager.h"
+#include "TransportManager.h"
+#include "PacketDispatcher.h"
+#include "EventDispatcher.h"
+
+using namespace jdwp;
+
+void AgentManager::Init(jvmtiEnv *jvmti, JNIEnv *jni) throw (AgentException)
+{
+    JDWP_TRACE_ENTRY("Init(" << jvmti << "," << jni << ")");
+
+    JDWP_TRACE_PROG("Init: init agent modules and load transport");
+
+    AgentBase::SetIsDead(false);
+    AgentBase::GetClassManager().Init(jni);
+    AgentBase::GetObjectManager().Init(jni);
+    AgentBase::GetThreadManager().Init(jni);
+    AgentBase::GetRequestManager().Init(jni);
+    AgentBase::GetEventDispatcher().Init(jni);
+    AgentBase::GetPacketDispatcher().Init(jni);
+
+    char* javaLibraryPath = 0;
+    jvmtiError err;
+    JVMTI_TRACE(err,
+        jvmti->GetSystemProperty("java.library.path", &javaLibraryPath));
+    if (err != JVMTI_ERROR_NONE) {
+        JDWP_INFO("Unable to get system property: java.library.path")
+    }
+
+    JvmtiAutoFree afv(javaLibraryPath);
+    AgentBase::GetTransportManager().Init(
+        AgentBase::GetOptionParser().GetTransport(),
+        javaLibraryPath);
+
+} 
+
+void AgentManager::Start(jvmtiEnv *jvmti, JNIEnv *jni) throw (AgentException)
+{
+    JDWP_TRACE_ENTRY("Start(" << jvmti << "," << jni << ")");
+
+    JDWP_TRACE_PROG("Start: prepare connection and start all agent threads");
+
+    // prepare transport connection
+    AgentBase::GetTransportManager().PrepareConnection(
+        AgentBase::GetOptionParser().GetAddress(),
+        AgentBase::GetOptionParser().GetServer(),
+        AgentBase::GetOptionParser().GetTimeout(),
+        AgentBase::GetOptionParser().GetTimeout()
+    );
+
+    // launch debugger if required and disable initial handling of EXCEPTION event
+    const char* launch = AgentBase::GetOptionParser().GetLaunch();
+    if (launch != 0) {
+        AgentBase::GetTransportManager().Launch(launch);
+        DisableInitialExceptionCatch(jvmti, jni);
+    }
+
+    // start agent threads
+    AgentBase::GetEventDispatcher().Start(jni);
+    AgentBase::GetPacketDispatcher().Start(jni);
+    SetStarted(true);
+}
+
+void 
+AgentManager::Stop(JNIEnv *jni) throw(AgentException)
+{
+    JDWP_TRACE_ENTRY("Stop(" << jni << ")");
+
+    // stop PacketDispatcher and EventDispatcher threads, and reset all modules
+    JDWP_TRACE_PROG("Stop: stop all agent threads");
+    GetPacketDispatcher().Stop(jni);
+}
+
+void 
+AgentManager::Clean(JNIEnv *jni) throw(AgentException)
+{
+    // trace entry before cleaning LogManager
+    {
+        JDWP_TRACE_ENTRY("Clean(" << jni << ")");
+
+        // clean all modules
+        JDWP_TRACE_PROG("Clean: clean agent modules");
+        GetPacketDispatcher().Clean(jni);
+        GetThreadManager().Clean(jni);
+        GetRequestManager().Clean(jni);
+        GetEventDispatcher().Clean(jni);
+        GetObjectManager().Clean(jni);
+        GetClassManager().Clean(jni);
+    }
+
+    // clean LogManager and close log
+    GetLogManager().Clean();
+}
+
+void AgentManager::EnableInitialExceptionCatch(jvmtiEnv *jvmti, JNIEnv *jni) throw (AgentException)
+{
+    JDWP_TRACE_PROG("EnableInitialExceptionCatch");
+
+    jvmtiError err;
+    JVMTI_TRACE(err, jvmti->SetEventNotificationMode(
+         JVMTI_ENABLE , JVMTI_EVENT_EXCEPTION, 0));
+    if (err != JVMTI_ERROR_NONE) {
+        throw AgentException(err);
+    }
+}
+
+void AgentManager::DisableInitialExceptionCatch(jvmtiEnv *jvmti, JNIEnv *jni) throw (AgentException)
+{
+    JDWP_TRACE_PROG("DisableInitialExceptionCatch");
+
+    jvmtiError err;
+    JVMTI_TRACE(err, jvmti->SetEventNotificationMode(
+         JVMTI_DISABLE, JVMTI_EVENT_EXCEPTION, 0));
+    if (err != JVMTI_ERROR_NONE) {
+        throw AgentException(err);
+    }
+}

Propchange: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentManager.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentManager.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentManager.h?view=auto&rev=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentManager.h (added)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentManager.h Mon Jul 23 09:18:27 2007
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file
+ * ClassManager.h
+ *
+ * Provides access to certain standard Java classes.
+ */
+
+/**
+ * @author Aleksander V. Budniy
+ * @version $Revision: 1.10.2.1 $
+ */
+
+/**
+ * @file
+ * ClassManager.h
+ *
+ * Provides initialization of JDWP agent.
+ */
+
+#ifndef _AGENT_MANAGER_H_
+#define _AGENT_MANAGER_H_
+
+#include "jni.h"
+#include "jvmti.h"
+#include "AgentBase.h"
+
+namespace jdwp {
+
+    /**
+     * This class provides initialization of JDWP agent.
+     */
+    class AgentManager : public AgentBase {
+
+    public :
+        
+        /**
+         * A constructor.
+         */
+        AgentManager() throw() {
+            m_isStarted = false;
+        }
+
+        /**
+         * A destructor.
+         */
+        ~AgentManager() throw () {
+        }
+        
+        /**
+         * Initializes all agent modules.
+         */
+        void Init(jvmtiEnv *jvmti, JNIEnv *jni) throw (AgentException);
+
+        /**
+         * Start all agent threads.
+         */
+        void Start(jvmtiEnv *jvmti, JNIEnv *jni) throw (AgentException);
+
+        /**
+         * Stop all agent threads.
+         */
+        void Stop(JNIEnv *jni) throw (AgentException);
+
+        /**
+         * Clean all agent modules.
+         */
+        void Clean(JNIEnv *jni) throw (AgentException);
+
+        /*                      
+         * Returns started status of this agent.
+         */
+        bool IsStarted() throw() {
+            return m_isStarted;
+        }
+
+        /*
+         * Sets started status of this agent.
+         */
+        void SetStarted(bool isStarted) throw() {
+            m_isStarted = isStarted;
+        }
+
+        /**
+         * Enables catching initial EXCEPTION event to launch debugger.
+         */
+        void EnableInitialExceptionCatch(jvmtiEnv *jvmti, JNIEnv *jni) throw (AgentException);
+
+        /**
+         * Disables catching initial EXCEPTION event to launch debugger.
+         */
+        void DisableInitialExceptionCatch(jvmtiEnv *jvmti, JNIEnv *jni) throw (AgentException);
+
+    private :
+
+        bool volatile m_isStarted;
+
+    }; //class AgentManager
+
+}// namespace jdwp
+
+#endif //_AGENT_MANAGER_H_

Propchange: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/AgentManager.h
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/OptionParser.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/OptionParser.cpp?view=diff&rev=558788&r1=558787&r2=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/OptionParser.cpp (original)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/OptionParser.cpp Mon Jul 23 09:18:27 2007
@@ -47,6 +47,9 @@
     m_log = 0;
     m_kindFilter = 0;
     m_srcFilter = 0;
+    m_onuncaught = false;
+    m_onthrow = 0;
+    m_launch = 0;
 }
 
 bool OptionParser::AsciiToBool(const char *str) throw(IllegalArgumentException)
@@ -75,12 +78,13 @@
     for (i = 0; i < len; i++) {
         if (str[i] == ',') {
             m_optionCount++;
-        } else if (str[i] == '"') {
+        } else if (str[i] == '"' || str[i] == '\'') {
+            char quote = str[i];
             if (i > 0 && str[i-1] != '=') {
                 throw IllegalArgumentException();
             }
             i++;
-            while (i < len && str[i] != '"') {
+            while (i < len && str[i] != quote) {
                 i++;
             }
             if (i+1 < len && str[i+1] != ',') {
@@ -100,20 +104,24 @@
     m_options[0].name = m_optionString;
     m_options[0].value = "";
     k = 0;
+    bool waitEndOfOption = false;
     for (i = 0; i < len && k < m_optionCount; i++) {
-        if (m_optionString[i] == '=') {
+        if ((m_optionString[i] == '=') && (!waitEndOfOption)) {
+            waitEndOfOption = true; 
             m_optionString[i] = '\0';
             m_options[k].value = &m_optionString[i+1];
         } else if (m_optionString[i] == ',') {
+            waitEndOfOption = false;
             m_optionString[i] = '\0';
             k++;
             m_options[k].name = &m_optionString[i+1];
             m_options[k].value = "";
-        } else if (m_optionString[i] == '"') {
+        } else if (m_optionString[i] == '"' || m_optionString[i] == '\'') {
+            char quote = m_optionString[i];
             m_optionString[i] = '\0';
             m_options[k].value = &m_optionString[i+1];
             i++;
-            while (i < len && m_optionString[i] != '"') {
+            while (i < len && m_optionString[i] != quote) {
                 i++;
             }
             if (i < len) {
@@ -133,6 +141,12 @@
             m_suspend = AsciiToBool(m_options[k].value);
         } else if (strcmp("server", m_options[k].name) == 0) {
             m_server = AsciiToBool(m_options[k].value);
+        } else if (strcmp("launch", m_options[k].name) == 0) {
+            m_launch = m_options[k].value;
+        } else if (strcmp("onuncaught", m_options[k].name) == 0) {
+            m_onuncaught = AsciiToBool(m_options[k].value);
+        } else if (strcmp("onthrow", m_options[k].name) == 0) {
+            m_onthrow = m_options[k].value;
         } else if (strcmp("help", m_options[k].name) == 0) {
             m_help = true;
 #ifndef NDEBUG
@@ -143,6 +157,12 @@
         } else if (strcmp("src", m_options[k].name) == 0) {
             m_srcFilter = m_options[k].value;
 #endif // NDEBUG
+        }
+    }
+    if ((m_onthrow != 0) || (m_onuncaught != 0)) {
+        if (m_launch == 0) {
+            JDWP_ERROR("Specify launch=<command line> when using onthrow or onuncaught option");
+            throw IllegalArgumentException();
         }
     }
 }

Modified: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/OptionParser.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/OptionParser.h?view=diff&rev=558788&r1=558787&r2=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/OptionParser.h (original)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/OptionParser.h Mon Jul 23 09:18:27 2007
@@ -120,6 +120,15 @@
         }
 
         /**
+         * Returns a value for the agent's <code>onuncaught</code> option.
+         *
+         * @return Boolean.
+         */
+        bool GetOnuncaught() const throw() {
+            return m_onuncaught;
+        }
+
+        /**
          * Returns a time-out value for transport operations.
          *
          * @return Java long value.
@@ -173,6 +182,24 @@
             return m_srcFilter;
         }
 
+        /**
+         * Returns a value for the agent's <code>onthrow</code> option.
+         *
+         * @return Zero-terminated string.
+         */
+        const char *GetOnthrow() const throw() {
+            return m_onthrow;
+        }
+
+        /**
+         * Returns a value for the agent's <code>launch</code> option.
+         *
+         * @return Zero-terminated string.
+         */
+        const char *GetLaunch() const throw() {
+            return m_launch;
+        }
+
     private:
 
         /**
@@ -199,12 +226,15 @@
         bool m_help;
         bool m_suspend;
         bool m_server;
+        bool m_onuncaught;
         jlong m_timeout;
         const char *m_transport;
         const char *m_address;
         const char *m_log;
         const char *m_kindFilter;
         const char *m_srcFilter;
+        const char *m_launch;
+        const char *m_onthrow;
     };
 
 } // namespace jdwp

Modified: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/PacketDispatcher.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/PacketDispatcher.cpp?view=diff&rev=558788&r1=558787&r2=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/PacketDispatcher.cpp (original)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/PacketDispatcher.cpp Mon Jul 23 09:18:27 2007
@@ -228,6 +228,13 @@
     // cause thread loop to break
     m_isProcessed = false;
     
+    // close transport first, but not while executing current command
+    JDWP_TRACE_PROG("Stop: close agent connection");
+    if (m_executionMonitor != 0) {
+        MonitorAutoLock lock(m_executionMonitor JDWP_FILE_LINE);
+        GetTransportManager().Clean();
+    }
+
     // wait for loop finished and EventDispatcher is also stopped
     {
         MonitorAutoLock lock(m_completionMonitor JDWP_FILE_LINE);
@@ -289,39 +296,6 @@
         GetObjectManager().Reset(jni);
     }
 }
-
-void 
-PacketDispatcher::ShutdownAll(JNIEnv *jni) throw(AgentException)
-{
-    // trace entry before cleaning LogManager
-    {
-        JDWP_TRACE_ENTRY("ShutdownAll(" << jni << ")");
-
-        // close transport first, but not while executing current command
-        JDWP_TRACE_PROG("ShutdownAll: close agent connection");
-        if (m_executionMonitor != 0) {
-            MonitorAutoLock lock(m_executionMonitor JDWP_FILE_LINE);
-            GetTransportManager().Clean();
-        }
-
-        // stop PacketDispatcher and EventDispatcher threads, and reset all modules
-        JDWP_TRACE_PROG("ShutdownAll: stop agent threads");
-        GetPacketDispatcher().Stop(jni);
-
-        // clean all modules
-        JDWP_TRACE_PROG("ShutdownAll: clean agent modules");
-        GetPacketDispatcher().Clean(jni);
-        GetThreadManager().Clean(jni);
-        GetRequestManager().Clean(jni);
-        GetEventDispatcher().Clean(jni);
-        GetObjectManager().Clean(jni);
-        GetClassManager().Clean(jni);
-    }
-
-    // clean LogManager and close log
-    GetLogManager().Clean();
-}
-
 
 //-----------------------------------------------------------------------------
 

Modified: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/PacketDispatcher.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/PacketDispatcher.h?view=diff&rev=558788&r1=558787&r2=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/PacketDispatcher.h (original)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/PacketDispatcher.h Mon Jul 23 09:18:27 2007
@@ -128,7 +128,7 @@
          *
          * @exception If any error occurs, <code>AgentException</code> is thrown.
          */
-        void ShutdownAll(JNIEnv *jni) throw(AgentException);
+//        void ShutdownAll(JNIEnv *jni) throw(AgentException);
 
         /**
          * Determines if the <code>PacketDispatcher</code> object is already

Modified: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/RequestManager.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/RequestManager.cpp?view=diff&rev=558788&r1=558787&r2=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/RequestManager.cpp (original)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/RequestManager.cpp Mon Jul 23 09:18:27 2007
@@ -28,6 +28,7 @@
 #include "ClassManager.h"
 #include "OptionParser.h"
 #include "Log.h"
+#include "AgentManager.h"
 
 using namespace jdwp;
 
@@ -925,13 +926,84 @@
         << ',' << method << ',' << location
         << ',' << exception << ',' << catch_method << ',' << catch_location << ')');
 
-    // must be non-agent thread
-    if (GetThreadManager().IsAgentThread(jni, thread)) {
-        return;
-    }
-
     try {
         jvmtiError err;
+        jclass exceptionClass = 0;
+        AgentEventRequest* exceptionRequest = 0;
+
+        // if agent was not initialized and this exception is expected, initialize agent
+        if (!GetAgentManager().IsStarted()) {
+            JDWP_TRACE_PROG("HandleException: initial exception cought");
+
+            // if invocation option onuncaught=y is set, check that exception is uncaught, otherwise return
+            if (GetOptionParser().GetOnuncaught() != 0) {
+                if (catch_location != 0) {
+                    JDWP_TRACE_PROG("HandleException: ignore cougth exception");
+                    return;
+                }
+            }
+
+            // if invocation option onthrow=y is set, check that exception class is expected, otherwise return
+            if (GetOptionParser().GetOnthrow() != 0) {
+
+                char* expectedExceptionName = const_cast<char*>(GetOptionParser().GetOnthrow());
+                if (expectedExceptionName != 0) {
+
+                    char* exceptionSignature = 0;
+                    exceptionClass = jni->GetObjectClass(exception);
+
+                    JVMTI_TRACE(err, jvmti->GetClassSignature(exceptionClass, &exceptionSignature, 0)); 
+                    if (err != JVMTI_ERROR_NONE) {
+                        throw AgentException(err);
+                    }
+                    JvmtiAutoFree jafSignature(exceptionSignature);
+
+                    char* exceptionName = GetClassManager().GetClassName(exceptionSignature);
+                    JvmtiAutoFree jafName(exceptionName);
+
+                    JDWP_TRACE_PROG("HandleException: exception: class=" << exceptionName 
+                         << ", signature=" << exceptionSignature);
+
+                    // compare exception class taking into account similar '/' and '.' delimiters
+                    int i;
+                    for (i = 0; ; i++) {
+                        if (expectedExceptionName[i] != exceptionName[i]) {
+                            if ((expectedExceptionName[i] == '.' && exceptionName[i] == '/')
+                                    || (expectedExceptionName[i] == '/' && exceptionName[i] == '.')) {
+                                 continue;
+                            }
+                            // ignore not matched exception
+                            return;
+                        }
+                        if (expectedExceptionName[i] == '\0') {
+                            // matched exception found
+                            break;
+                        }
+                    }
+                }
+            }
+
+            // disable catching initial exception and start agent
+            JDWP_TRACE_PROG("HandleException: start agent");
+            GetAgentManager().DisableInitialExceptionCatch(jvmti, jni);
+            GetAgentManager().Start(jvmti, jni);
+
+            // check if VM should be suspended on initial EXCEPTION event
+            bool needSuspend = GetOptionParser().GetSuspend();
+            if (needSuspend) {
+                // add internal EXCEPTION request
+                exceptionRequest = new AgentEventRequest(JDWP_EVENT_EXCEPTION, JDWP_SUSPEND_ALL);
+                GetRequestManager().AddInternalRequest(jni, exceptionRequest);
+            } else {
+                return;
+            }
+        }
+
+        // must be non-agent thread
+        if (GetThreadManager().IsAgentThread(jni, thread)) {
+            return;
+        }
+
         EventInfo eInfo;
         memset(&eInfo, 0, sizeof(eInfo));
         eInfo.kind = JDWP_EVENT_EXCEPTION;
@@ -952,7 +1024,11 @@
             throw AgentException(err);
         }
 
-        eInfo.auxClass = jni->GetObjectClass(exception);
+        if (exceptionClass != 0) {
+            eInfo.auxClass = exceptionClass;
+        } else {
+            eInfo.auxClass = jni->GetObjectClass(exception);
+        }
         JDWP_ASSERT(eInfo.auxClass != 0);
 
         if (catch_method != 0) {
@@ -1011,6 +1087,12 @@
             JDWP_TRACE_EVENT("Exception: post set of " << eventCount << " events");
             GetEventDispatcher().PostEventSet(jni, ec, JDWP_EVENT_EXCEPTION);
         }
+        // delete internal EXCEPTION request
+        if (exceptionRequest != 0) {
+            GetRequestManager().DeleteRequest(jni, exceptionRequest);
+        }
+      /*  JVMTI_TRACE(err, jvmti->SetEventNotificationMode(
+             JVMTI_ENABLE , JVMTI_EVENT_BREAKPOINT, thread));*/
     } catch (AgentException& e) {
         JDWP_INFO("JDWP error in EXCEPTION: " << e.what() << " [" << e.ErrCode() << "]");
     }

Modified: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/ThreadManager.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/ThreadManager.cpp?view=diff&rev=558788&r1=558787&r2=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/ThreadManager.cpp (original)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/ThreadManager.cpp Mon Jul 23 09:18:27 2007
@@ -243,13 +243,17 @@
 jthread
 ThreadManager::RunAgentThread(JNIEnv *jni, jvmtiStartFunction proc,
                                 const void *arg, jint priority,
-                                const char *name) throw(AgentException)
+                                const char *name, jthread thread) 
+                                throw(AgentException)
 {
     JDWP_TRACE_ENTRY("RunAgentThread(" << jni << ',' << proc 
             << ',' << arg << ',' << priority 
                         << ',' << JDWP_CHECK_NULL(name) << ')');
 
-    jthread thread = CreateAgentThread(jni, name);
+    if (thread == 0) {
+        thread = CreateAgentThread(jni, name);
+    }
+
     jvmtiError err;
     JVMTI_TRACE(err, GetJvmtiEnv()->RunAgentThread(thread, proc, arg, priority));
 

Modified: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/ThreadManager.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/ThreadManager.h?view=diff&rev=558788&r1=558787&r2=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/ThreadManager.h (original)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/ThreadManager.h Mon Jul 23 09:18:27 2007
@@ -109,8 +109,10 @@
          * @param priority - the priority of the started thread
          * @param name     - the default parameter; if defined, then the created
          *                   thread has a specified name
+         * @param name     - the default parameter; if defined, then the created
+         *                   thread is associated with this object
          *
-         * @return Returns the <code>jthread</code> object that holds executed 
+         * @return Returns the <code>jthread</code> object associated with started 
          * thread.
          *
          * @exception OutOfMemoryException is thrown if the system 
@@ -123,7 +125,8 @@
          */
         jthread RunAgentThread(JNIEnv *jni, jvmtiStartFunction proc,
                                 const void *arg, jint priority,
-                                const char *name = 0) throw(AgentException);
+                                const char *name = 0,
+                                jthread thread = 0) throw(AgentException);
 
         /**
          * Adds an information about the thread parameter into

Modified: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/TransportManager.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/TransportManager.cpp?view=diff&rev=558788&r1=558787&r2=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/TransportManager.cpp (original)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/TransportManager.cpp Mon Jul 23 09:18:27 2007
@@ -44,6 +44,7 @@
 
 TransportManager::TransportManager() : AgentBase()
 {
+    m_transportName = 0;
     m_connectTimeout = 0;
     m_handshakeTimeout = 0;
     m_ConnectionPrepared = false;
@@ -52,6 +53,7 @@
     m_env = 0;
     m_isServer = true;
     m_lastErrorMessage = 0;
+    m_isConnected = false;
 } //TransportManager::TransportManager()
 
 TransportManager::~TransportManager()
@@ -75,11 +77,13 @@
 {
     JDWP_TRACE_ENTRY("Init(" << JDWP_CHECK_NULL(transportName) << ',' << JDWP_CHECK_NULL(libPath) << ')');
 
-    JDWP_TRACE_PROG("Init: transport name=" << JDWP_CHECK_NULL(transportName )
-        << " libPath=" << JDWP_CHECK_NULL(libPath));
+    JDWP_TRACE_PROG("Init: transport=" << JDWP_CHECK_NULL(transportName )
+        << ", libPath=" << JDWP_CHECK_NULL(libPath));
 
     JDWP_ASSERT(m_loadedLib == 0);
+    m_isConnected = false;
 
+    m_transportName = transportName;
     const char* begin = libPath;
     do {
         const char* end = strchr(begin, pathSeparator);
@@ -112,7 +116,7 @@
         m_lastErrorMessage = static_cast<char *>(GetMemoryManager().Allocate(length JDWP_FILE_LINE));
         sprintf(m_lastErrorMessage, "Loading of %s failed", transportName);
         JDWP_ERROR("Loading of " << transportName << " failed");
-        throw TransportException(JDWP_ERROR_TRANSPORT_LOAD);
+        throw TransportException(JDWP_ERROR_TRANSPORT_LOAD, JDWPTRANSPORT_ERROR_NONE, m_lastErrorMessage);
     }
 
     jdwpTransport_OnLoad_t transportOnLoad = reinterpret_cast<jdwpTransport_OnLoad_t>
@@ -126,14 +130,14 @@
         m_lastErrorMessage = static_cast<char *>(GetMemoryManager().Allocate(length JDWP_FILE_LINE));
         sprintf(m_lastErrorMessage, "%s function not found in %s", onLoadDecFuncName, transportName);
         JDWP_ERROR(onLoadDecFuncName << " function not found in " << transportName);
-        throw TransportException();
+        throw TransportException(JDWP_ERROR_TRANSPORT_INIT, JDWPTRANSPORT_ERROR_NONE, m_lastErrorMessage);
     }
     jint res = (*transportOnLoad)(GetJavaVM(), &callback, JDWPTRANSPORT_VERSION_1_0, &m_env);
     if (res == JNI_ENOMEM) {
         if (m_lastErrorMessage != 0) {
             GetMemoryManager().Free(m_lastErrorMessage JDWP_FILE_LINE);
         }
-        size_t length = strlen("Out of memeory");
+        size_t length = strlen("Out of memory");
         m_lastErrorMessage = static_cast<char *>(GetMemoryManager().Allocate(length JDWP_FILE_LINE));
         sprintf(m_lastErrorMessage, "Out of memeory");
         throw TransportException(JDWP_ERROR_OUT_OF_MEMORY);
@@ -145,7 +149,7 @@
         m_lastErrorMessage = static_cast<char *>(GetMemoryManager().Allocate(length JDWP_FILE_LINE));
         sprintf(m_lastErrorMessage, "Invoking of %s failed", onLoadDecFuncName);
         JDWP_ERROR("Invoking of " << onLoadDecFuncName << " failed");
-        throw TransportException();
+        throw TransportException(JDWP_ERROR_TRANSPORT_INIT, JDWPTRANSPORT_ERROR_NONE, m_lastErrorMessage);
     }
     if (m_env == 0) {
         if (m_lastErrorMessage != 0) {
@@ -155,7 +159,7 @@
         m_lastErrorMessage = static_cast<char *>(GetMemoryManager().Allocate(length JDWP_FILE_LINE));
         sprintf(m_lastErrorMessage, "Transport provided invalid environment");
         JDWP_ERROR("Transport provided invalid environment");
-        throw TransportException();
+        throw TransportException(JDWP_ERROR_TRANSPORT_INIT, JDWPTRANSPORT_ERROR_NONE, m_lastErrorMessage);
     }
 
 } // TransportManager::Init()
@@ -194,12 +198,10 @@
     }
 
     if (isServer) {
-        char* actualAddress;
-        err = m_env->StartListening(address, &actualAddress); 
+        err = m_env->StartListening(address, &m_address); 
         CheckReturnStatus(err);
-        JDWP_INFO("transport is listening on " << actualAddress);
-        JDWP_TRACE_PROG("PrepareConnection: listening on " << actualAddress);
-        AgentBase::GetMemoryManager().Free(actualAddress JDWP_FILE_LINE);
+        JDWP_INFO("transport is listening on " << m_address);
+        JDWP_TRACE_PROG("PrepareConnection: listening on " << m_address);
     } else {
         m_address = static_cast<char *>(GetMemoryManager().Allocate(strlen(address) + 1 JDWP_FILE_LINE));
         strcpy(m_address, address);
@@ -212,6 +214,10 @@
 void 
 TransportManager::Connect() throw(TransportException)
 {
+    if (m_isConnected) {
+        return;
+    }
+
     JDWP_TRACE_PROG("Connect: isServer=" << m_isServer);
     JDWP_ASSERT(m_ConnectionPrepared);
     jdwpTransportError err;
@@ -222,15 +228,19 @@
         err = m_env->Attach(m_address, m_connectTimeout, m_handshakeTimeout);
         CheckReturnStatus(err);
     }
+    m_isConnected = true;
     JDWP_TRACE_PROG("Connect: connection established");
 } // TransportManager::Connect()
 
 void 
-TransportManager::Launch(const char* command) throw(TransportException)
+TransportManager::Launch(const char* command) throw(AgentException)
 {
     JDWP_TRACE_PROG("Launch: " << JDWP_CHECK_NULL(command));
     JDWP_ASSERT(m_ConnectionPrepared);
-    StartDebugger(command);
+    const char* extra_argv[2];
+    extra_argv[0] = m_transportName;
+    extra_argv[1] = m_address;
+    StartDebugger(command, 2, extra_argv);
     Connect();
 } // TransportManager::Launch()
 
@@ -263,6 +273,7 @@
         jdwpTransportError err = m_env->Close();
         CheckReturnStatus(err);
     }
+    m_isConnected = false;
     JDWP_TRACE_PROG("Reset: connection closed");
 } // TransportManager::Reset()
 
@@ -317,8 +328,8 @@
         throw TransportException(JDWP_ERROR_OUT_OF_MEMORY, JDWPTRANSPORT_ERROR_OUT_OF_MEMORY);
     }
     char* lastErrorMessage = GetLastTransportError();
-    AgentBase::GetMemoryManager().Free(lastErrorMessage JDWP_FILE_LINE);
-    throw TransportException(JDWP_ERROR_TRANSPORT_INIT, err);
+    // AgentBase::GetMemoryManager().Free(lastErrorMessage JDWP_FILE_LINE);
+    throw TransportException(JDWP_ERROR_TRANSPORT_INIT, err, lastErrorMessage);
 } // TransportManager::CheckReturnStatus()
 
 inline void 
@@ -328,7 +339,7 @@
         JDWP_TRACE_PACKET(message 
                 <<" length=" << packet->type.cmd.len 
                 << " Id=" << packet->type.cmd.id 
-                << " flag=REPLY " 
+                << " flag=REPLY" 
                 << " errorCode=" << (short)(packet->type.reply.errorCode));
     } else { 
         JDWP_TRACE_PACKET(message 

Modified: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/TransportManager.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/TransportManager.h?view=diff&rev=558788&r1=558787&r2=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/TransportManager.h (original)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/agent/core/TransportManager.h Mon Jul 23 09:18:27 2007
@@ -100,9 +100,9 @@
          *
          * @param command - a command line to start the debugger
          *
-         * @exception TransportException() - transport error happens.
+         * @exception AgentException() - any error happens.
          */
-        void Launch(const char* command) throw(TransportException);
+        void Launch(const char* command) throw(AgentException);
         
         /**
          * The given function does a blocking read on an open connection.
@@ -153,14 +153,16 @@
         jlong m_connectTimeout;                  // attachTimeout or acceptTimeout timeout
         jlong m_handshakeTimeout;                // handshakeTimeout
         bool m_ConnectionPrepared;               // if true PrepareConnection done
+        bool m_isConnected;                      // true if connection is established
         bool m_isServer;                         // is jdwp agent server or not
+        const char* m_transportName;             // transport name
         char* m_address;                         // transport address
         jdwpTransportEnv* m_env;                 // jdwpTransport environment
         LoadedLibraryHandler m_loadedLib;        // transport library handler
         char* m_lastErrorMessage;                // last error message
 
         void CheckReturnStatus(jdwpTransportError err) throw(TransportException);
-        void StartDebugger(const char* command) throw(AgentException);
+        void StartDebugger(const char* command, int extra_argc, const char* extra_argv[]) throw(AgentException);
         void TracePacket(const char* message, const jdwpPacket* packet);
         LoadedLibraryHandler LoadTransport(const char* dirName, const char* transportName);
 

Modified: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/transport/dt_socket/SocketTransport.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/transport/dt_socket/SocketTransport.cpp?view=diff&rev=558788&r1=558787&r2=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/transport/dt_socket/SocketTransport.cpp (original)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/common/transport/dt_socket/SocketTransport.cpp Mon Jul 23 09:18:27 2007
@@ -496,7 +496,7 @@
 
     err = bind(serverSocket, (struct sockaddr *)&serverSockAddr, sizeof(serverSockAddr));
     if (err == SOCKET_ERROR) {
-        SetLastTranError(env, "connection failed", GetLastErrorStatus());
+        SetLastTranError(env, "binding to port failed", GetLastErrorStatus());
         return JDWPTRANSPORT_ERROR_ILLEGAL_STATE ;
     }
 
@@ -520,6 +520,9 @@
     }
 
     char* retAddress = 0;
+
+    // RI always returns only port number in listening mode
+/*
     char portName[6];
     sprintf(portName, "%d", ntohs(serverSockAddr.sin_port)); //instead of itoa()
 
@@ -530,7 +533,6 @@
     if (strcmp(hostName, "0.0.0.0") == 0) {
         gethostname(hostName, sizeof(hostName));
     }
-
     retAddress = (char*)(((internalEnv*)env->functions->reserved1)
         ->alloc)((jint)(strlen(hostName) + strlen(portName) + 2)); 
     if (retAddress == 0) {
@@ -538,6 +540,14 @@
         return JDWPTRANSPORT_ERROR_OUT_OF_MEMORY;
     }
     sprintf(retAddress, "%s:%s", hostName, portName);
+*/
+    retAddress = (char*)(((internalEnv*)env->functions->reserved1)->alloc)(6 + 1); 
+    if (retAddress == 0) {
+        SetLastTranError(env, "out of memory", 0);
+        return JDWPTRANSPORT_ERROR_OUT_OF_MEMORY;
+    }
+    sprintf(retAddress, "%d", ntohs(serverSockAddr.sin_port));
+
     *actualAddress = retAddress;
 
     return JDWPTRANSPORT_ERROR_NONE;

Modified: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/unix/agent/core/TransportManager_pd.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/unix/agent/core/TransportManager_pd.cpp?view=diff&rev=558788&r1=558787&r2=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/unix/agent/core/TransportManager_pd.cpp (original)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/unix/agent/core/TransportManager_pd.cpp Mon Jul 23 09:18:27 2007
@@ -28,6 +28,8 @@
  * constants, include statements and functions for Linux platform.
  */
 
+#include <unistd.h>
+#include <errno.h>
 #include "TransportManager_pd.h"
 #include "TransportManager.h"
 
@@ -37,27 +39,121 @@
 const char* TransportManager::unLoadDecFuncName = "jdwpTransport_UnLoad";
 const char TransportManager::pathSeparator = ':';
 
-void TransportManager::StartDebugger(const char* command) throw(AgentException)
+void TransportManager::StartDebugger(const char* command, int extra_argc, const char* extra_argv[]) throw(AgentException)
 {
-    throw NotImplementedException();
+    JDWP_TRACE_ENTRY("StartDebugger(" << JDWP_CHECK_NULL(command) << ',' << extra_argc << ',' << extra_argv << ')');
+
+    // allocate array for parsed arguments
+
+    int max_argc = 250 + extra_argc;
+    char** argv = static_cast<char**>(GetMemoryManager().Allocate((sizeof(char*) * (max_argc + 1)) JDWP_FILE_LINE));
+    AgentAutoFree afva(argv JDWP_FILE_LINE);
+
+    // parse command line
+    int argc = 0;        
+    int cmd_len = strlen(command);
+    char* cmd = static_cast<char*>(GetMemoryManager().Allocate((cmd_len + 1) JDWP_FILE_LINE));
+    AgentAutoFree afv(cmd JDWP_FILE_LINE);
+
+    if (command != 0 && cmd_len > 0) {
+        JDWP_TRACE_PROG("StartDebugger: parse: cmd=" << JDWP_CHECK_NULL(command));
+
+        const char *arg = command, *p;
+        char *arg1 = cmd, *s;
+
+        for (; *arg != 0;) {
+
+            // skip initial spaces
+            while (isspace(*arg)) arg++;
+
+            // parse non-spaced or quoted argument 
+            for (p = arg, s = arg1; ; p++) {
+                // check for quote
+                if (*p == '\"' || *p == '\'') {
+                     char quote = *(p++);
+                     // skip all chars until terminating quote or null
+                     for (; *p != '\0'; p++) {
+                         // check for terminating quote
+                         if (*p == quote) {
+                             p++;
+                             break;
+                         }
+                         // preserve escaped quote
+                         if (*p == '\\' && *(p + 1) == quote) 
+                             p++;
+                         // store current char
+                         *(s++) = *p;
+                     }
+                }
+                // check for ending separator
+                if (*p == '\0' || isspace(*p)) {
+                     *(s++) = '\0';
+                     if (argc >= max_argc) {
+                        JDWP_ERROR("Too many arguments for launching debugger proccess: " << argc);
+                        throw AgentException(JDWP_ERROR_INTERNAL);
+                     }
+                     argv[argc++] = arg1;
+                     JDWP_TRACE_PROG("StartDebugger: launch: arg[" << argc << "]=" << JDWP_CHECK_NULL(arg1));
+                     arg = p;
+                     arg1 = s;
+                     break;
+                }
+                // skip escaped quote
+                if (*p == '\\' && (*(p + 1) == '\"' || *(p + 1) == '\'')) 
+                    p++;
+                // store current char
+                *(s++) = *p;
+            }
+        }
+    }
+
+    // add extra arguments
+
+    int i;
+    for (i = 0; i < extra_argc; i++) {
+         if (extra_argv[i] != 0) {
+             JDWP_TRACE_PROG("StartDebugger: launch: arg[" << argc << "]=" << JDWP_CHECK_NULL(extra_argv[i]));
+             argv[argc++] = const_cast<char*>(extra_argv[i]);
+         }
+    }
+    argv[argc] = 0;
+    
+    // launch debugger process
+
+    int pid = fork();
+    if (pid == -1) {
+        JDWP_ERROR("Failed to fork debugger process: error=" << errno);
+        throw AgentException(JDWP_ERROR_INTERNAL);
+    } else if (pid == 0) {
+        // execute debugger in child process
+        execv(argv[0], argv);
+        // returned here only in case of error, terminate child process
+        JDWP_DIE("Failed to execute debugger process: error=" << errno);
+    } else {
+        JDWP_TRACE_PROG("StartDebugger: launched: pid=" << pid);
+    }
 }
 
 ProcPtr jdwp::GetProcAddress(LoadedLibraryHandler libHandler, const char* procName)
 {
+    JDWP_TRACE_ENTRY("GetProcAddress(" << libHandler << ',' << JDWP_CHECK_NULL(procName) << ')');
+
     dlerror();
     ProcPtr res = (ProcPtr)dlsym(libHandler, procName);
-    char* errorMessage = 0;
-    if (errorMessage = dlerror()) {
-        JDWP_TRACE_PROG("free library failed (error: " << errorMessage << ")");
+    char* errorMessage = dlerror();
+    if (errorMessage) {
+        JDWP_TRACE_PROG("FreeLibrary: getting library entry failed (error: " << errorMessage << ")");
     }
     return res;
 }
 
 bool jdwp::FreeLibrary(LoadedLibraryHandler libHandler)
 {
+    JDWP_TRACE_ENTRY("FreeLibrary(" << libHandler << ')');
+
     dlerror();
     if (dlclose(libHandler) != 0) {
-        JDWP_TRACE_PROG("free library failed (error: " << dlerror() << ")");
+        JDWP_TRACE_PROG("FreeLibrary: closing library failed (error: " << dlerror() << ")");
         return false;
     }
     return true;
@@ -65,6 +161,8 @@
 
 LoadedLibraryHandler TransportManager::LoadTransport(const char* dirName, const char* transportName)
 {
+    JDWP_TRACE_ENTRY("LoadTransport(" << JDWP_CHECK_NULL(dirName) << ',' << JDWP_CHECK_NULL(transportName) << ')');
+
     JDWP_ASSERT(transportName != 0);
     dlerror();
     char* transportFullName = 0;
@@ -80,9 +178,9 @@
     AgentAutoFree afv(transportFullName JDWP_FILE_LINE);
     LoadedLibraryHandler res = dlopen(transportFullName, RTLD_LAZY);
     if (res == 0) {
-        JDWP_TRACE_PROG("loading of " << transportFullName << " failed (error: " << dlerror() << ")");
+        JDWP_TRACE_PROG("LoadTransport: loading library " << transportFullName << " failed (error: " << dlerror() << ")");
     } else {
-        JDWP_TRACE_PROG("transport " << transportFullName << " loaded");
+        JDWP_TRACE_PROG("LoadTransport: transport library " << transportFullName << " loaded");
     }
     return res;
 }

Modified: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/unix/agent/makefile
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/unix/agent/makefile?view=diff&rev=558788&r1=558787&r2=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/unix/agent/makefile (original)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/unix/agent/makefile Mon Jul 23 09:18:27 2007
@@ -28,7 +28,7 @@
 INCLUDES += -I$(CMNAGENT)commands -I$(CMNAGENT)core \
             -I$(COMMON)generic -Icore
 
-HYLDFLAGS += -lstdc++ -lgcc_s
+LDFLAGS += -lstdc++ -lgcc_s
 
 BUILDFILES = \
     $(CMNAGENT)commands/ArrayReference.o \
@@ -50,7 +50,7 @@
     $(CMNAGENT)core/EventDispatcher.o $(CMNAGENT)core/LogManager.o $(CMNAGENT)core/MemoryManager.o \
     $(CMNAGENT)core/ObjectManager.o $(CMNAGENT)core/OptionParser.o $(CMNAGENT)core/PacketDispatcher.o \
     $(CMNAGENT)core/PacketParser.o $(CMNAGENT)core/RequestManager.o $(CMNAGENT)core/RequestModifier.o \
-    $(CMNAGENT)core/ThreadManager.o $(CMNAGENT)core/TransportManager.o \
+    $(CMNAGENT)core/ThreadManager.o $(CMNAGENT)core/TransportManager.o $(CMNAGENT)core/AgentManager.o \
     core/TransportManager_pd.o
 
 MDLLIBFILES = 

Modified: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/unix/transport/makefile
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/unix/transport/makefile?view=diff&rev=558788&r1=558787&r2=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/unix/transport/makefile (original)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/unix/transport/makefile Mon Jul 23 09:18:27 2007
@@ -32,7 +32,7 @@
 INCLUDES += -I$(CMNTRANS)common -I$(CMNTRANS)dt_socket \
             -I$(COMMON)generic -Idt_socket
 
-HYLDFLAGS += -lstdc++ -lgcc_s
+LDFLAGS += -lstdc++ -lgcc_s
 
 BUILDFILES = \
     $(CMNTRANS)common/LastTransportError.o \

Modified: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/windows/agent/core/TransportManager_pd.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/windows/agent/core/TransportManager_pd.cpp?view=diff&rev=558788&r1=558787&r2=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/windows/agent/core/TransportManager_pd.cpp (original)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/windows/agent/core/TransportManager_pd.cpp Mon Jul 23 09:18:27 2007
@@ -45,13 +45,63 @@
 
 const char TransportManager::pathSeparator = ';';
 
-void TransportManager::StartDebugger(const char* command) throw(AgentException)
+void TransportManager::StartDebugger(const char* command, int extra_argc, const char* extra_argv[]) throw(AgentException)
 {
-    throw NotImplementedException();
+    JDWP_TRACE_ENTRY("StartDebugger(" << JDWP_CHECK_NULL(command) << ',' << extra_argc << ',' << extra_argv << ')');
+
+JDWP_TRACE_PROG("StartDebugger: transport=" << JDWP_CHECK_NULL(extra_argv[0]));
+JDWP_TRACE_PROG("StartDebugger: address=" << JDWP_CHECK_NULL(extra_argv[1]));
+
+    // append extra arguments to command line
+
+    int cmd_len = strlen(command);
+    int extra_len = 0;
+    int i;
+
+    for (i = 0; i < extra_argc; i++) {
+         if (extra_argv[i] != 0) {
+             extra_len += strlen(extra_argv[i]) + 1;
+         }
+    }
+
+    char* cmd = static_cast<char*>(GetMemoryManager().Allocate((cmd_len + extra_len + 1) JDWP_FILE_LINE));
+    AgentAutoFree afv(cmd JDWP_FILE_LINE);
+    strcpy(cmd, command);
+
+    for (i = 0; i < extra_argc; i++) {
+         if (extra_argv[i] != 0) {
+             strcat(cmd, " ");
+             strcat(cmd, extra_argv[i]);
+         }
+    }
+
+    // launch debugger process
+
+    STARTUPINFO si;
+    PROCESS_INFORMATION pi;
+
+    ZeroMemory(&si, sizeof(si));
+    si.cb = sizeof(si);
+    ZeroMemory(&pi, sizeof(pi));
+
+    JDWP_TRACE_PROG("StartDebugger: launch: cmd=" << JDWP_CHECK_NULL(cmd));
+
+    if(!CreateProcess(NULL, const_cast<LPSTR>(cmd), NULL, NULL, 
+            TRUE, NULL, NULL, NULL, &si, &pi)) {
+        JDWP_ERROR("Failed to launch debugger process: error=" << GetLastError());
+        throw AgentException(JDWP_ERROR_INTERNAL);
+    }
+
+    JDWP_TRACE_PROG("StartDebugger: launched: pid=" << pi.dwProcessId);
+
+    CloseHandle(pi.hProcess);
+    CloseHandle(pi.hThread);
 }
 
 LoadedLibraryHandler TransportManager::LoadTransport(const char* dirName, const char* transportName)
 {
+    JDWP_TRACE_ENTRY("LoadTransport(" << JDWP_CHECK_NULL(dirName) << ',' << JDWP_CHECK_NULL(transportName) << ')');
+
     JDWP_ASSERT(transportName != 0);
     char* transportFullName = 0;
     if (dirName == 0) {
@@ -66,9 +116,9 @@
     AgentAutoFree afv(transportFullName JDWP_FILE_LINE);
     LoadedLibraryHandler res = LoadLibrary(transportFullName);
     if (res == 0) {
-        JDWP_TRACE_PROG("loading of " << transportFullName << " failed (error code: " << GetLastError() << ")");
+        JDWP_TRACE_PROG("LoadTransport: loading library " << transportFullName << " failed (error code: " << GetLastError() << ")");
     } else {
-        JDWP_TRACE_PROG("transport " << transportFullName << " loaded");
+        JDWP_TRACE_PROG("LoadTransport: transport library " << transportFullName << " loaded");
     }
     return res;
 }

Modified: harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/windows/agent/makefile
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/windows/agent/makefile?view=diff&rev=558788&r1=558787&r2=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/windows/agent/makefile (original)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/main/native/jdwp/windows/agent/makefile Mon Jul 23 09:18:27 2007
@@ -54,7 +54,7 @@
     $(CMNAGENT)core\EventDispatcher.obj $(CMNAGENT)core\LogManager.obj $(CMNAGENT)core\MemoryManager.obj \
     $(CMNAGENT)core\ObjectManager.obj $(CMNAGENT)core\OptionParser.obj $(CMNAGENT)core\PacketDispatcher.obj \
     $(CMNAGENT)core\PacketParser.obj $(CMNAGENT)core\RequestManager.obj $(CMNAGENT)core\RequestModifier.obj \
-    $(CMNAGENT)core\ThreadManager.obj $(CMNAGENT)core\TransportManager.obj \
+    $(CMNAGENT)core\ThreadManager.obj $(CMNAGENT)core\TransportManager.obj $(CMNAGENT)core\AgentManager.obj \
     core\TransportManager_pd.obj
 
 VIRTFILES = 

Modified: harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/TestOptions.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/TestOptions.java?view=diff&rev=558788&r1=558787&r2=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/TestOptions.java (original)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/framework/TestOptions.java Mon Jul 23 09:18:27 2007
@@ -25,7 +25,6 @@
  */
 package org.apache.harmony.jpda.tests.framework;
 
-import java.io.File;
 import java.util.HashMap;
 
 /**
@@ -52,6 +51,8 @@
  *   - full name of class to run debuggee with
  * <li><code>jpda.settings.debuggeeVMExtraOptions</code>
  *   - extra options to run debuggee with
+ * <li><code>jpda.settings.debuggeeSuspend</code>
+ *   - debuggee suspend mode ("y"|"n")
  * <li><code>jpda.settings.transportWrapperClass</code>
  *   - class name of TransportWrapper implementation
  * <li><code>jpda.settings.transportAddress</code>
@@ -83,6 +84,9 @@
     public static final String DEFAULT_ATTACHING_ADDRESS = "127.0.0.1:9898";
 
     /** Default port number for sync connection. */
+    public static final String DEFAULT_STATIC_SYNC_PORT = "9797";
+
+    /** Default port number for sync connection. */
     public static final int DEFAULT_SYNC_PORT = 0;
 
     /** Default class name for transport wrapper. */
@@ -211,7 +215,7 @@
 
         return getProperty("jpda.settings.debuggeeAgentOptions",
                 "transport=dt_socket,address=" + address + ",server=" + serv
-                        + agentExtraOptions);
+                + ",suspend=" + getDebuggeeSuspend() + agentExtraOptions);
     }
 
     /**
@@ -269,6 +273,34 @@
         String extOpts = getProperty("jpda.settings.debuggeeVMExtraOptions", "");
         extOpts = extOpts + " -Djpda.settings.verbose=" + isVerbose();
         return extOpts;
+    }
+
+    /**
+     * Returns debuggee suspend mode ("y"|"n").
+     * 
+     * @return option "jpda.settings.debuggeeSuspend" or "y" by default
+     */
+    public String getDebuggeeSuspend() {
+        return getProperty("jpda.settings.debuggeeSuspend", "y");
+    }
+
+    /**
+     * Returns debuggee suspend mode ("y"|"n").
+     * 
+     * @param mode
+     *            suspend mode
+     */
+    public void setDebuggeeSuspend(String mode) {
+        setProperty("jpda.settings.debuggeeSuspend", mode);
+    }
+
+    /**
+     * Checks if debuggee is launched in suspend mode.
+     * 
+     * @return true if debuggee is launched in suspend mode
+     */
+    public boolean isDebuggeeSuspend() {
+        return getDebuggeeSuspend().equals("y");
     }
 
     /**

Added: harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/jdwp/DebuggerOnDemand/LaunchedDebugger.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/jdwp/DebuggerOnDemand/LaunchedDebugger.java?view=auto&rev=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/jdwp/DebuggerOnDemand/LaunchedDebugger.java (added)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/jdwp/DebuggerOnDemand/LaunchedDebugger.java Mon Jul 23 09:18:27 2007
@@ -0,0 +1,333 @@
+/*
+ * 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.
+ */
+package org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand;
+
+import org.apache.harmony.jpda.tests.framework.LogWriter;
+import org.apache.harmony.jpda.tests.framework.TestErrorException;
+import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket;
+import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands;
+import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
+import org.apache.harmony.jpda.tests.framework.jdwp.Location;
+import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
+import org.apache.harmony.jpda.tests.jdwp.share.JDWPTestCase;
+import org.apache.harmony.jpda.tests.jdwp.share.JDWPUnitDebuggeeWrapper;
+import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
+import org.apache.harmony.jpda.tests.share.JPDATestOptions;
+
+/**
+ * Base class for debuggers that are used in tests for DebuggerOnDemand functionality.
+ */
+public abstract class LaunchedDebugger extends JDWPTestCase {
+    
+    // synchronization channel between debugger and debuggee
+    protected JPDADebuggeeSynchronizer synchronizer;
+
+    // synchronization channel between debugger and test
+    protected JPDADebuggeeSynchronizer testSynchronizer;
+    
+    // name of tested debuggee class
+    public static final String DEBUGGEE_CLASS_NAME = 
+    	"org/apache/harmony/jpda/tests/jdwp/DebuggerOnDemand/OnthowDebuggerLaunchDebuggee";
+
+    // signature of the tested debuggee class
+    public static final String DEBUGGEE_CLASS_SIGNATURE = "L" + DEBUGGEE_CLASS_NAME + ";";
+    
+    /**
+     * This method is invoked right before attaching to debuggee VM.
+     * It forces to use attaching connector and fixed transport address.
+     */
+/*
+    protected void beforeDebuggeeStart(JDWPOnDemandDebuggeeWrapper debugeeWrapper) {
+    	settings.setAttachConnectorKind();
+        if (settings.getTransportAddress() == null) {
+            settings.setTransportAddress(JPDADebuggerOnDemandOptions.DEFAULT_ATTACHING_ADDRESS);
+        }
+        logWriter.println("DEBUGGER: Use ATTACH connector kind");
+       
+        super.beforeDebuggeeStart(debuggeeWrapper);
+    }
+ */
+    	
+    /**
+     * Overrides inherited method to resume debuggee VM and then to establish
+     * sync connection with debuggee and server.
+     */
+    protected void internalSetUp() throws Exception {
+
+        // estabslish synch connection with test
+        logWriter.println("Establish synch connection between debugger and test");
+        JPDADebuggerOnDemandOptions debuggerSettings = new JPDADebuggerOnDemandOptions();
+        testSynchronizer = new JPDADebuggerOnDemandSynchronizer(logWriter, debuggerSettings);
+        testSynchronizer.startClient();
+        logWriter.println("Established synch connection between debugger and test");
+
+        // handle JDWP connection with debuggee
+        super.internalSetUp();
+
+    	// establish synch connection with debuggee
+        logWriter.println("Establish synch connection between debugger and debuggee");
+    	synchronizer = new JPDADebuggeeSynchronizer(logWriter, settings);;
+        synchronizer.startClient();
+        logWriter.println("Established synch connection between debugger and debuggee");
+    }
+    
+    /**
+     * Creates wrapper for debuggee process.
+     */
+    protected JDWPUnitDebuggeeWrapper createDebuggeeWrapper() {
+        return new JPDADebuggerOnDemandDebuggeeWrapper(settings, logWriter);
+    }
+    
+    /**
+     * Receives initial EXCEPTION event if debuggee is suspended on event.
+     */
+    protected void receiveInitialEvent() {
+        if (settings.isDebuggeeSuspend()) {
+            initialEvent = 
+                debuggeeWrapper.vmMirror.receiveCertainEvent(JDWPConstants.EventKind.EXCEPTION);
+            logWriter.println("Received inital EXCEPTION event");
+            debuggeeWrapper.resume();
+            logWriter.println("Resumed debuggee VM");
+        }
+    }
+
+    /**
+     * Overrides inherited method to close sync connection upon exit.
+     */
+    protected void internalTearDown() {
+        // close synch connection with debuggee
+        if (synchronizer != null) {
+            synchronizer.stop();
+            logWriter.println("Closed synch connection between debugger and debuggee");
+        }
+
+        // close synch connection with test
+        if (testSynchronizer != null) {
+            testSynchronizer.stop();
+            logWriter.println("Closed synch connection between debugger and test");
+        }
+
+        // close connections with debuggee
+        super.internalTearDown();
+    }
+
+	protected String getDebuggeeClassName() {
+        return null;
+    }
+    
+	///////////////////////////////////////////////////////////////////
+
+	/**
+     * This class contains information about frame of a java thread. 
+     */
+    public class FrameInfo {
+        long frameID;
+        Location location;
+        
+        public FrameInfo(long frameID, Location location) {
+            super();
+            this.frameID = frameID;
+            this.location = location;
+        }
+        
+        /**
+         * @return Returns the frameID.
+         */
+        public long getFrameID() {
+            return frameID;
+        }
+        /**
+         * @return Returns the location.
+         */
+        public Location getLocation() {
+            return location;
+        }
+    }
+    
+    protected FrameInfo[] jdwpGetFrames(long threadID, int startFrame, int length) {
+        CommandPacket packet = new CommandPacket(
+                JDWPCommands.ThreadReferenceCommandSet.CommandSetID,
+                JDWPCommands.ThreadReferenceCommandSet.FramesCommand);
+        packet.setNextValueAsThreadID(threadID);
+        packet.setNextValueAsInt(startFrame);
+        packet.setNextValueAsInt(length);
+        
+        ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
+        if (!checkReplyPacketWithoutFail(reply, "ThreadReference::FramesCommand command")) {
+            throw new TestErrorException("Error during performing ThreadReference::Frames command");
+        }
+               
+        int frames = reply.getNextValueAsInt();
+        FrameInfo[] frameInfos = new FrameInfo[frames];
+        for (int i = 0; i < frames; i++) {
+            long frameID = reply.getNextValueAsLong();
+            Location location = reply.getNextValueAsLocation();
+            frameInfos[i] = new FrameInfo(frameID, location);
+        }
+        return frameInfos;
+    }
+    
+    protected long getClassIDBySignature(String signature) {
+        logWriter.println("=> Getting reference type ID for class: " + signature);
+        CommandPacket packet = new CommandPacket(
+                JDWPCommands.VirtualMachineCommandSet.CommandSetID,
+                JDWPCommands.VirtualMachineCommandSet.ClassesBySignatureCommand);
+        packet.setNextValueAsString(signature);
+        ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
+        if (!checkReplyPacketWithoutFail(reply, "VirtualMachine::ClassesBySignature command")) {
+            throw new TestErrorException("Error during performing VirtualMachine::ClassesBySignature command");
+        }
+        int classes = reply.getNextValueAsInt();
+        logWriter.println("=> Returned number of classes: " + classes);
+        long classID = 0;
+        for (int i = 0; i < classes; i++) {
+            reply.getNextValueAsByte();
+            classID = reply.getNextValueAsReferenceTypeID();
+            reply.getNextValueAsInt();
+            // we need the only class, even if there were multiply ones
+            break;
+        }
+        assertTrue("VirtualMachine::ClassesBySignature command returned invalid classID:<" +
+                classID + "> for signature " + signature, classID > 0);
+        return classID;
+    }
+    
+    protected void printStackFrame(int NumberOfFrames, FrameInfo[] frameInfos) {
+        for (int i = 0; i < NumberOfFrames; i++) {
+            logWriter.println(" ");
+            logWriter
+                    .println("=> #" + i + " frameID=" + frameInfos[i].frameID);
+            String methodName = "";
+            try {
+                methodName = getMethodName(frameInfos[i].location.classID,
+                           frameInfos[i].location.methodID);
+            } catch (TestErrorException e) {
+                throw new TestErrorException(e);
+            }
+            logWriter.println("=> method name=" + methodName);
+        }
+        logWriter.println(" ");
+    }
+    
+    protected String getMethodName(long classID, long methodID) {
+        CommandPacket packet = new CommandPacket(
+                JDWPCommands.ReferenceTypeCommandSet.CommandSetID,
+                JDWPCommands.ReferenceTypeCommandSet.MethodsCommand);
+        packet.setNextValueAsClassID(classID);
+        ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet);
+        if (!checkReplyPacketWithoutFail(reply, "ReferenceType::Methods command")) {
+            throw new TestErrorException("Error during performing ReferenceType::Method command");
+        }
+        int methods = reply.getNextValueAsInt();
+        for (int i = 0; i < methods; i++) {
+            long mid = reply.getNextValueAsMethodID();
+            String name = reply.getNextValueAsString();
+            reply.getNextValueAsString();
+            reply.getNextValueAsInt();
+            if (mid == methodID) {
+                return name;
+            }
+        }
+        return "unknown";
+    }
+
+    //////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * This class provides functionality to establish synch connection between debugger and test.  
+     */
+    protected static class JPDADebuggerOnDemandSynchronizer extends JPDADebuggeeSynchronizer {
+
+        public JPDADebuggerOnDemandSynchronizer(LogWriter logWriter, JPDADebuggerOnDemandOptions settings) {
+            super(logWriter, settings);
+            this.settings = settings;
+        }
+
+        public int getSyncPortNumber() {
+            return ((JPDADebuggerOnDemandOptions)settings).getSyncDebuggerPortNumber();
+        }
+    }
+
+    /**
+     * This class provides customization of DebuggeeWrapper that attaches to already launched debuggee.
+     */
+    protected static class JPDADebuggerOnDemandDebuggeeWrapper extends JDWPUnitDebuggeeWrapper {
+
+        public JPDADebuggerOnDemandDebuggeeWrapper(JPDATestOptions settings, LogWriter logWriter) {
+            super(settings, logWriter);
+        }
+    	
+    	/**
+         * Attaches to already launched debuggee process and
+         * establishes JDWP connection.
+         */
+        public void start() {
+            try {
+                transport = createTransportWrapper();
+                openConnection();
+                logWriter.println("Established connection");
+            } catch (Exception e) {
+                throw new TestErrorException(e);
+            }
+        }
+
+        /**
+         * Closes all connections but does not wait for debuggee process to exit.
+         */
+        public void stop() {
+            disposeConnection();
+            closeConnection();
+        }
+    }
+
+    /**
+     * This class provides additional options to debuggers, that are used in DebuggerOnDemand tests.
+     * Currently the following additional options are supported:
+     * <ul>
+     * <li><i>jpda.settings.syncDebuggerPort</i> 
+     *  - port number for sync connection between debugger and test
+     * </ul>
+     *
+     */
+    protected static class JPDADebuggerOnDemandOptions extends JPDATestOptions {
+
+        public static final String DEFAULT_SYNC_DEBUGGER_PORT = "9899";
+    	
+        /**
+         * Returns port number string for sync connection between debugger and test.
+         */
+        public String getSyncDebuggerPortString() {
+            return getProperty("jpda.settings.syncDebuggerPort", null);
+        }
+        
+        /**
+         * Returns port number for sync connection between debugger and test.
+         */
+        public int getSyncDebuggerPortNumber() {
+            String buf = getSyncDebuggerPortString();
+            if (buf == null) {
+                buf = DEFAULT_SYNC_DEBUGGER_PORT;
+            }
+
+            try {
+                return Integer.parseInt(buf);
+            } catch (NumberFormatException e) {
+                throw new TestErrorException(e);
+            }
+        }
+    }
+}

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

Added: harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/jdwp/DebuggerOnDemand/OnthowDebuggerLaunchDebuggee.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/jdwp/DebuggerOnDemand/OnthowDebuggerLaunchDebuggee.java?view=auto&rev=558788
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/jdwp/DebuggerOnDemand/OnthowDebuggerLaunchDebuggee.java (added)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/test/common/unit/org/apache/harmony/jpda/tests/jdwp/DebuggerOnDemand/OnthowDebuggerLaunchDebuggee.java Mon Jul 23 09:18:27 2007
@@ -0,0 +1,94 @@
+/*
+ * 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 Aleksander V. Budniy
+ * @version $Revision: $
+ */
+
+/**
+ * Created on 5.06.2006
+ */
+package org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand;
+
+import org.apache.harmony.jpda.tests.share.Debuggee;
+import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
+
+/**
+ * This class provides simple debuggee class with deferred synch establishing.
+ * 
+ * When debuggee throws exception, agent launches debugger, that connects to debuggee. 
+ * Then debuggee establishes synch connection with debugger and invokes tested method.
+ */
+public class OnthowDebuggerLaunchDebuggee extends Debuggee {
+
+    public void onStart() {
+        super.onStart();
+
+        logWriter.println("DEBUGGEE: started");
+        
+        // prepare for connection with debugger
+        logWriter.println("DEBUGGEE: bind for synch connection with debugger");
+        synchronizer = createSynchronizer();
+        synchronizer.bindServer();
+
+        // throw tested exception to launch debugger
+        try {
+            logWriter.println("DEBUGGEE: throw ExceptionForDebugger");
+            throw new ExceptionForDebugger();
+        } catch (ExceptionForDebugger e) {
+            logWriter.println("DEBUGGEE: cought ExceptionForDebugger: " + e);
+        }
+
+        // listen for connection with debugger
+        synchronizer.startServer();
+        logWriter.println("DEBUGGEE: established synch connection with debugger");
+    }
+
+    public void run() {
+        synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_READY);
+        synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
+        testMethod();
+    }
+
+    void testMethod() {
+        logWriter.println("DEBUGGEE: testMethod invoked");
+    }
+
+    protected JPDADebuggeeSynchronizer createSynchronizer() {
+        return new JPDADebuggeeSynchronizer(logWriter, settings);
+    }
+
+    public void onFinish() {
+        logWriter.println("DEBUGGEE: finished");
+
+        if (synchronizer != null) {
+            synchronizer.stop();
+            logWriter.println("DEBUGGEE: closed synch connection with debugger");
+        }
+        super.onFinish();
+    }
+
+    public static void main(String[] args) {
+        runDebuggee(OnthowDebuggerLaunchDebuggee.class);
+    }
+
+    protected JPDADebuggeeSynchronizer synchronizer;
+}
+
+class ExceptionForDebugger extends Exception {
+}

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