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 [11/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/src/common/other/jpda/jdwp/agent/core/OptionParser.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/OptionParser.cpp?view=auto&rev=480141
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/OptionParser.cpp (added)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/OptionParser.cpp Tue Nov 28 09:49:08 2006
@@ -0,0 +1,166 @@
+/*
+ * 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 Pavel N. Vyssotski
+ * @version $Revision: 1.7 $
+ */
+// OptionParser.cpp
+
+#include <cstring>
+
+#include "AgentBase.h"
+#include "MemoryManager.h"
+#include "AgentException.h"
+#include "Log.h"
+
+#include "OptionParser.h"
+
+using namespace jdwp;
+using namespace std;
+
+OptionParser::OptionParser() throw()
+{
+ m_optionCount = 0;
+ m_optionString = 0;
+ m_options = 0;
+ m_help = false;
+ m_suspend = true;
+ m_server = false;
+ m_timeout = 0;
+ m_transport = 0;
+ m_address = 0;
+ m_log = 0;
+ m_kindFilter = 0;
+ m_srcFilter = 0;
+}
+
+bool OptionParser::AsciiToBool(const char *str) throw(IllegalArgumentException)
+{
+ if (strcmp("y", str) == 0) {
+ return true;
+ } else if (strcmp("n", str) == 0) {
+ return false;
+ } else {
+ throw IllegalArgumentException();
+ }
+}
+
+void OptionParser::Parse(const char* str) throw(AgentException)
+{
+ size_t i;
+ int k;
+
+ if (str == 0)
+ return;
+
+ const size_t len = strlen(str);
+ if (len == 0)
+ return;
+
+ for (i = 0; i < len; i++) {
+ if (str[i] == ',') {
+ m_optionCount++;
+ } else if (str[i] == '"') {
+ if (i > 0 && str[i-1] != '=') {
+ throw IllegalArgumentException();
+ }
+ i++;
+ while (i < len && str[i] != '"') {
+ i++;
+ }
+ if (i+1 < len && str[i+1] != ',') {
+ throw IllegalArgumentException();
+ }
+ }
+ }
+ m_optionCount++;
+
+ m_optionString = reinterpret_cast<char*>(AgentBase::GetMemoryManager().
+ Allocate(len + 1 JDWP_FILE_LINE));
+ strcpy(m_optionString, str);
+
+ m_options = reinterpret_cast<Option*>(AgentBase::GetMemoryManager().
+ Allocate(m_optionCount * sizeof(Option) JDWP_FILE_LINE));
+
+ m_options[0].name = m_optionString;
+ m_options[0].value = "";
+ k = 0;
+ for (i = 0; i < len && k < m_optionCount; i++) {
+ if (m_optionString[i] == '=') {
+ m_optionString[i] = '\0';
+ m_options[k].value = &m_optionString[i+1];
+ } else if (m_optionString[i] == ',') {
+ m_optionString[i] = '\0';
+ k++;
+ m_options[k].name = &m_optionString[i+1];
+ m_options[k].value = "";
+ } else if (m_optionString[i] == '"') {
+ m_optionString[i] = '\0';
+ m_options[k].value = &m_optionString[i+1];
+ i++;
+ while (i < len && m_optionString[i] != '"') {
+ i++;
+ }
+ if (i < len) {
+ m_optionString[i] = '\0';
+ }
+ }
+ }
+
+ for (k = 0; k < m_optionCount; k++) {
+ if (strcmp("transport", m_options[k].name) == 0) {
+ m_transport = m_options[k].value;
+ } else if (strcmp("address", m_options[k].name) == 0) {
+ m_address = m_options[k].value;
+ } else if (strcmp("timeout", m_options[k].name) == 0) {
+ m_timeout = atol(m_options[k].value);
+ } else if (strcmp("suspend", m_options[k].name) == 0) {
+ 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("help", m_options[k].name) == 0) {
+ m_help = true;
+#ifndef NDEBUG
+ } else if (strcmp("log", m_options[k].name) == 0) {
+ m_log = m_options[k].value;
+ } else if (strcmp("trace", m_options[k].name) == 0) {
+ m_kindFilter = m_options[k].value;
+ } else if (strcmp("src", m_options[k].name) == 0) {
+ m_srcFilter = m_options[k].value;
+#endif // NDEBUG
+ }
+ }
+}
+
+OptionParser::~OptionParser() throw()
+{
+ if (m_optionString != 0)
+ AgentBase::GetMemoryManager().Free(m_optionString JDWP_FILE_LINE);
+ if (m_options != 0)
+ AgentBase::GetMemoryManager().Free(m_options JDWP_FILE_LINE);
+}
+
+const char *OptionParser::FindOptionValue(const char *name) const throw()
+{
+ for (int i = 0; i < m_optionCount; i++) {
+ if (strcmp(name, m_options[i].name) == 0) {
+ return m_options[i].value;
+ }
+ }
+ return 0;
+}
Propchange: harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/OptionParser.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Added: harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/OptionParser.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/OptionParser.h?view=auto&rev=480141
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/OptionParser.h (added)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/OptionParser.h Tue Nov 28 09:49:08 2006
@@ -0,0 +1,212 @@
+/*
+ * 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 Pavel N. Vyssotski
+ * @version $Revision: 1.8.2.1 $
+ */
+
+/**
+ * @file
+ * OptionParser.h
+ *
+ * Provides access to startup options and actual capabilities of the agent.
+ * Parses command-line options of the agent.
+ */
+
+#ifndef _OPTION_PARSER_H_
+#define _OPTION_PARSER_H_
+
+#include "AgentBase.h"
+
+namespace jdwp {
+
+ /**
+ * The class provides certain means for parsing and manipulating agent options
+ * that are passed to the command line of the target VM.
+ */
+ class OptionParser : public AgentBase {
+
+ public:
+
+ /**
+ * A constructor.
+ */
+ OptionParser() throw();
+
+ /**
+ * A destructor.
+ */
+ ~OptionParser() throw();
+
+ /**
+ * Parses the input string containing the arguments passed to the agent.
+ *
+ * @param str - the string containing agent arguments
+ */
+ void Parse(const char* str) throw(AgentException);
+
+ /**
+ * Returns a number of parsed options.
+ */
+ int GetOptionCount() const throw() {
+ return m_optionCount;
+ }
+
+ /**
+ * Gets an option name and value by the index.
+ *
+ * @param i - the option index
+ * @param name - the option name
+ * @param value - the option value
+ */
+ void GetOptionByIndex(int i, const char *&name, const char *&value)
+ const throw(InvalidIndexException) {
+ if (i < m_optionCount) {
+ name = m_options[i].name;
+ value = m_options[i].value;
+ } else {
+ throw InvalidIndexException();
+ }
+ }
+
+ /**
+ * Looks for an option with the given name.
+ *
+ * @param name - the option name
+ */
+ const char *FindOptionValue(const char *name) const throw();
+
+ /**
+ * Returns a value for the agent's <code>help</code> option.
+ *
+ * @return Boolean.
+ */
+ bool GetHelp() const throw() {
+ return m_help;
+ }
+
+ /**
+ * Returns a value for the agent's <code>suspend</code> option.
+ *
+ * @return Boolean.
+ */
+ bool GetSuspend() const throw() {
+ return m_suspend;
+ }
+
+ /**
+ * Returns a value for the agent's <code>server</code> option.
+ *
+ * @return Boolean.
+ */
+ bool GetServer() const throw() {
+ return m_server;
+ }
+
+ /**
+ * Returns a time-out value for transport operations.
+ *
+ * @return Java long value.
+ */
+ jlong GetTimeout() const throw() {
+ return m_timeout;
+ }
+
+ /**
+ * Returns the name of the JDWP transport.
+ *
+ * @return Zero-terminated string.
+ */
+ const char *GetTransport() const throw() {
+ return m_transport;
+ }
+
+ /**
+ * Returns the address for the socket transport to connect to.
+ *
+ * @return Zero-terminated string.
+ */
+ const char *GetAddress() const throw() {
+ return m_address;
+ }
+
+ /**
+ * Returns the name for log file.
+ *
+ * @return Zero-terminated string.
+ */
+ const char *GetLog() const throw() {
+ return m_log;
+ }
+
+ /**
+ * Returns the log kind filter.
+ *
+ * @return Zero-terminated string.
+ */
+ const char *GetTraceKindFilter() const throw() {
+ return m_kindFilter;
+ }
+
+ /**
+ * Returns the source-files filter.
+ *
+ * @return Zero-terminated string.
+ */
+ const char *GetTraceSrcFilter() const throw() {
+ return m_srcFilter;
+ }
+
+ private:
+
+ /**
+ * The helper structure containing the option pair: name and value.
+ */
+ struct Option {
+ const char *name;
+ const char *value;
+ };
+
+ /**
+ * The helper converting string to boolean.
+ *
+ * @param str - the input null-terminated string
+ *
+ * @exception IllegalArgumentException.
+ */
+ bool AsciiToBool(const char *str) throw(IllegalArgumentException);
+
+ int m_optionCount;
+ char *m_optionString;
+ Option *m_options;
+
+ bool m_help;
+ bool m_suspend;
+ bool m_server;
+ jlong m_timeout;
+ const char *m_transport;
+ const char *m_address;
+ const char *m_log;
+ const char *m_kindFilter;
+ const char *m_srcFilter;
+ };
+
+} // namespace jdwp
+
+#endif // _OPTION_PARSER_H_
Propchange: harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/OptionParser.h
------------------------------------------------------------------------------
svn:eol-style = native
Added: harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/PacketDispatcher.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/PacketDispatcher.cpp?view=auto&rev=480141
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/PacketDispatcher.cpp (added)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/PacketDispatcher.cpp Tue Nov 28 09:49:08 2006
@@ -0,0 +1,324 @@
+/*
+ * 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 Vitaly A. Provodin
+ * @version $Revision: 1.22 $
+ */
+#include "PacketDispatcher.h"
+#include "TransportManager.h"
+#include "AgentException.h"
+#include "ThreadManager.h"
+#include "EventDispatcher.h"
+#include "ObjectManager.h"
+#include "ClassManager.h"
+#include "RequestManager.h"
+#include "OptionParser.h"
+
+using namespace jdwp;
+
+//-----------------------------------------------------------------------------
+
+PacketDispatcher::PacketDispatcher() throw()
+ :AgentBase()
+{
+ m_isProcessed = false;
+ m_isRunning = false;
+ m_completionMonitor = 0;
+ m_executionMonitor = 0;
+}
+
+//-----------------------------------------------------------------------------
+
+void
+PacketDispatcher::Init(JNIEnv *jni) throw(AgentException)
+{
+ JDWP_TRACE_ENTRY("Init(" << jni << ")");
+
+ m_completionMonitor = new AgentMonitor("_agent_Packet_Dispatcher_completion");
+ m_executionMonitor = new AgentMonitor("_agent_Packet_Dispatcher_execution");
+}
+
+void
+PacketDispatcher::Start(JNIEnv *jni) throw(AgentException)
+{
+ JDWP_TRACE_ENTRY("Start(" << jni << ")");
+
+ JDWP_ASSERT(!m_isProcessed);
+
+ try
+ {
+ GetThreadManager().RunAgentThread(jni, StartFunction, this,
+ JVMTI_THREAD_MAX_PRIORITY, "_jdwp_PacketDispatcher");
+ }
+ catch (const AgentException& e)
+ {
+ JDWP_ASSERT(e.ErrCode() != JDWP_ERROR_NULL_POINTER);
+ JDWP_ASSERT(e.ErrCode() != JDWP_ERROR_INVALID_PRIORITY);
+
+ throw e;
+ }
+
+}
+
+//-----------------------------------------------------------------------------
+
+void
+PacketDispatcher::Run(JNIEnv *jni)
+{
+ JDWP_TRACE_ENTRY("Run(" << jni << ")");
+
+ m_isRunning = true;
+
+ MonitorAutoLock lock(m_completionMonitor JDWP_FILE_LINE);
+ TransportManager &transport = GetTransportManager();
+
+ try
+ {
+ // run multiplle sessions in a loop
+ for (; ;)
+ {
+ // connect for new session
+ JDWP_TRACE_PROG("Run: start new session");
+ try
+ {
+ transport.Connect();
+ }
+ catch (const TransportException& e)
+ {
+ JDWP_TRACE_PROG("Run: Exception in connection: "
+ << e.what() << " [" << e.ErrCode()
+ << "/" << e.TransportErrorCode() << "]");
+ if (!IsDead()) {
+ JDWP_DIE(e.what() << " [" << e.ErrCode() << "/"
+ << e.TransportErrorCode() << "]: "
+ << GetTransportManager().GetLastTransportError());
+ }
+ break;
+ }
+
+ // start session and execute commands
+ try
+ {
+ // add internal request for automatic VMDeath event with no modifiers
+ GetRequestManager().AddInternalRequest(jni,
+ new AgentEventRequest(JDWP_EVENT_VM_DEATH, JDWP_SUSPEND_NONE));
+
+ // release events
+ GetEventDispatcher().ReleaseEvents();
+
+ // read and execute commands
+ m_isProcessed = true;
+ while (m_isProcessed)
+ {
+ // read command
+ try {
+ JDWP_TRACE_PROG("Run: handle next command");
+ m_cmdParser.ReadCommand();
+ if (m_cmdParser.command.GetLength() == 0)
+ break;
+ }
+ catch (const TransportException& e)
+ {
+ JDWP_TRACE_PROG("Run: Exception in reading command: "
+ << e.what() << " [" << e.ErrCode()
+ << "/" << e.TransportErrorCode() << "]");
+ if (m_isProcessed && !IsDead())
+ {
+ char* msg = GetTransportManager().GetLastTransportError();
+ AgentAutoFree af(msg JDWP_FILE_LINE);
+
+ if (e.TransportErrorCode() == JDWPTRANSPORT_ERROR_OUT_OF_MEMORY) {
+ JDWP_DIE(e.what() << " [" << e.ErrCode() << "/"
+ << e.TransportErrorCode() << "]: " << msg);
+ } else {
+ JDWP_ERROR(e.what() << " [" << e.ErrCode() << "/"
+ << e.TransportErrorCode() << "]: " << msg);
+ }
+ }
+ break;
+ }
+
+ // execute command and prevent from reset while execution
+ {
+ MonitorAutoLock lock(m_executionMonitor JDWP_FILE_LINE);
+ m_cmdDispatcher.ExecCommand(jni, &m_cmdParser);
+ }
+ }
+ }
+ catch (const AgentException& e)
+ {
+ JDWP_TRACE_PROG("Run: Exception in executing command: "
+ << e.what() << " [" << e.ErrCode() << "]");
+ if (!IsDead()) {
+ JDWP_ERROR(e.what() << " [" << e.ErrCode() << "]");
+ }
+ }
+
+ // reset all modules after session finished
+ JDWP_TRACE_PROG("Run: reset session");
+ ResetAll(jni);
+
+ // no more sessions if VMDeath event occured
+ if (IsDead()) {
+ JDWP_TRACE_PROG("Run: VM is dead -> shutdown");
+ break;
+ }
+
+ // no more sessions in attach mode
+ if (!GetOptionParser().GetServer()) {
+ JDWP_TRACE_PROG("Run: attach mode -> shutdown");
+ break;
+ }
+ }
+ }
+ catch (const AgentException& e)
+ {
+ JDWP_TRACE_PROG("Run: Exception in PacketDispatcher: "
+ << e.what() << " [" << e.ErrCode() << "]");
+ if (!IsDead()) {
+ JDWP_DIE(e.what() << " [" << e.ErrCode() << "]");
+ }
+ }
+
+ // stop also EventDispatcher thread
+ try
+ {
+ JDWP_TRACE_PROG("Run: stop EventDispatcher");
+ GetEventDispatcher().Stop(jni);
+ }
+ catch (const AgentException& e)
+ {
+ JDWP_TRACE_PROG("Run: Exception in stopping EventDispatcher: "
+ << e.what() << " [" << e.ErrCode() << "]");
+ }
+
+ m_isRunning = false;
+}
+
+//-----------------------------------------------------------------------------
+
+void
+PacketDispatcher::Stop() throw(AgentException)
+{
+ JDWP_TRACE_ENTRY("Stop()");
+
+ if (!m_isRunning) return;
+
+ // cause thread loop to break
+ m_isProcessed = false;
+
+ // wait for thread finished
+ {
+ MonitorAutoLock lock(m_completionMonitor JDWP_FILE_LINE);
+ }
+ JDWP_ASSERT(!m_isRunning);
+
+ // EventDispatcher is also stopped
+}
+
+void
+PacketDispatcher::Clean(JNIEnv *jni) throw(AgentException)
+{
+ JDWP_TRACE_ENTRY("Clean(" << jni << ')');
+
+ JDWP_TRACE_PROG("Clean: clean internal data");
+
+ if (m_completionMonitor != 0) {
+ delete m_completionMonitor;
+ m_completionMonitor = 0;
+ }
+
+ if (m_executionMonitor != 0) {
+ delete m_executionMonitor;
+ m_executionMonitor = 0;
+ }
+}
+
+void
+PacketDispatcher::Reset(JNIEnv *jni) throw(AgentException)
+{
+ JDWP_TRACE_ENTRY("Reset(" << jni << ')');
+
+ // cause thread loop to break
+ JDWP_TRACE_PROG("Reset: reset session");
+ m_isProcessed = false;
+}
+
+void
+PacketDispatcher::ResetAll(JNIEnv *jni) throw(AgentException)
+{
+ JDWP_TRACE_ENTRY("ResetAll(" << jni << ")");
+
+ // reset all modules, but not while executing current command
+ if (m_executionMonitor != 0) {
+ MonitorAutoLock lock(m_executionMonitor JDWP_FILE_LINE);
+
+ JDWP_TRACE_PROG("ResetAll: reset all modules");
+
+ GetThreadManager().Reset(jni);
+ GetRequestManager().Reset(jni);
+ GetEventDispatcher().Reset(jni);
+ GetTransportManager().Reset();
+ GetPacketDispatcher().Reset(jni);
+ GetClassManager().Reset(jni);
+ 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();
+
+ // 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();
+}
+
+
+//-----------------------------------------------------------------------------
+
+void JNICALL
+PacketDispatcher::StartFunction(jvmtiEnv* jvmti_env, JNIEnv* jni, void* arg)
+{
+ JDWP_TRACE_ENTRY("StartFunction(" << jvmti_env << "," << jni << "," << arg << ")");
+
+ (reinterpret_cast<PacketDispatcher *>(arg))->Run(jni);
+}
Propchange: harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/PacketDispatcher.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Added: harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/PacketDispatcher.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/PacketDispatcher.h?view=auto&rev=480141
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/PacketDispatcher.h (added)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/PacketDispatcher.h Tue Nov 28 09:49:08 2006
@@ -0,0 +1,173 @@
+/*
+ * 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 Vitaly A. Provodin
+ * @version $Revision: 1.8.2.1 $
+ */
+
+/**
+ * @file
+ * PacketDispatcher.h
+ *
+ * Reads command packets from the transport, wraps and passes them to
+ * CommandDispatcher.
+ * Operates in a separate agent thread.
+ */
+
+#ifndef _PACKET_DISPATCHER_H_
+#define _PACKET_DISPATCHER_H_
+
+#include "AgentBase.h"
+#include "AgentException.h"
+#include "PacketParser.h"
+#include "CommandDispatcher.h"
+
+
+namespace jdwp {
+
+ class AgentMonitor;
+
+ /**
+ * Unwraps JDWP commands and passes them to <code>CommandDispatcher</code>
+ * for executing.
+ * The JDWP agent has only one object of <code>PacketDispatcher</code> that
+ * is started at the startup routine in a separate thread.
+ * <code>PacketDispatcher</code> reads command packets from the active
+ * JDWP transport via <code>TransportManager</code>, unwraps them and passes
+ * to <code>CommandDispatcher</code>. In case <code>CommandDispatcher</code>
+ * can not execute the obtained JDWP command, <code>PacketDispatcher</code>
+ * composes the corresponding reply packet, according to the JDWP
+ * specification, and sends it back to the JDWP transport.
+ *
+ * @see CommandDispatcher
+ * @see TransportManager
+ */
+ class PacketDispatcher : public AgentBase
+ {
+ public:
+
+ /**
+ * Constructs a new <code>PacketDispatcher</code> object.
+ */
+ PacketDispatcher() throw();
+
+ /**
+ * Initializes the <code>PacketDispatcher</code>'s thread.
+ *
+ * @param jni - the JNI interface pointer
+ *
+ * @exception If any error occurs, <code>AgentException</code> is thrown.
+ */
+ void Init(JNIEnv *jni) throw(AgentException);
+
+ /**
+ * Starts the <code>PacketDispatcher</code>'s thread.
+ *
+ * @param jni - the JNI interface pointer
+ *
+ * @exception If any error occurs, <code>AgentException</code> is thrown.
+ */
+ void Start(JNIEnv *jni) throw(AgentException);
+
+ /**
+ * Stops the <code>PacketDispatcher</code>'s thread.
+ *
+ * @exception If any error occurs, <code>AgentException</code> is thrown.
+ */
+ void Stop() throw(AgentException);
+
+ /**
+ * Resets the <code>PacketDispatcher</code> object.
+ *
+ * @param jni - the JNI interface pointer
+ *
+ * @exception If any error occurs, <code>AgentException</code> is thrown.
+ */
+ void Reset(JNIEnv *jni) throw(AgentException);
+
+ /**
+ * Cleans the <code>PacketDispatcher</code> object.
+ *
+ * @param jni - the JNI interface pointer
+ *
+ * @exception If any error occurs, <code>AgentException</code> is thrown.
+ */
+ void Clean(JNIEnv *jni) throw(AgentException);
+
+ /**
+ * Resets all agent modules.
+ *
+ * @param jni - the JNI interface pointer
+ *
+ * @exception If any error occurs, <code>AgentException</code> is thrown.
+ */
+ void ResetAll(JNIEnv *jni) throw(AgentException);
+
+ /**
+ * Shutdowns all agent modules.
+ *
+ * @param jni - the JNI interface pointer
+ *
+ * @exception If any error occurs, <code>AgentException</code> is thrown.
+ */
+ void ShutdownAll(JNIEnv *jni) throw(AgentException);
+
+ /**
+ * Determines if the <code>PacketDispatcher</code> object is already
+ * started.
+ */
+ bool IsProcessed() const {return m_isProcessed;}
+
+ protected:
+
+ /**
+ * Main execution function of the dispatcher processing
+ * commands from the debugger.
+ *
+ * @param jni - the JNI interface pointer
+ */
+ void Run(JNIEnv *jni);
+
+ /**
+ * Starts <code>PacketDispatcher</code> thread.
+ * The given function is passed as the <code>proc</code> parameter of
+ * <code>ThreadManager::RunAgentThread</code>. The <code>arg</code>
+ * parameter must be a pointer to the agent's
+ * <code>PacketDisptacher</code> object.
+ *
+ * @param jvmti - the JVMTI interface pointer
+ * @param jni - the JNI interface pointer
+ * @param arg - the agent's <code>PacketDisptacher</code> object pointer
+ */
+ static void JNICALL
+ StartFunction(jvmtiEnv* jvmti, JNIEnv* jni, void* arg);
+
+ private:
+ volatile bool m_isProcessed;
+ volatile bool m_isRunning;
+ CommandParser m_cmdParser;
+ CommandDispatcher m_cmdDispatcher;
+ AgentMonitor* m_completionMonitor;
+ AgentMonitor* m_executionMonitor;
+
+ };//class PacketDispatcher
+
+}//jdwp
+
+#endif //_PACKET_DISPATCHER_H_
Propchange: harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/PacketDispatcher.h
------------------------------------------------------------------------------
svn:eol-style = native
Added: harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/PacketParser.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/PacketParser.cpp?view=auto&rev=480141
==============================================================================
--- harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/PacketParser.cpp (added)
+++ harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/PacketParser.cpp Tue Nov 28 09:49:08 2006
@@ -0,0 +1,845 @@
+/*
+ * 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.18 $
+ */
+// PacketParser.cpp: implementation of the PacketParser class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "PacketParser.h"
+#include "jdwpTypes.h"
+#include "MemoryManager.h"
+#include "ObjectManager.h"
+#include "TransportManager.h"
+#include "ClassManager.h"
+
+#include <cstring>
+
+using namespace jdwp;
+
+// Constant defining increment for m_registeredObjectIDTable
+const int REGISTERED_OBJECTID_TABLE_STEP = 0x10;
+
+const size_t ALLOCATION_STEP = 0x10;
+const jbyte PACKET_IS_UNINITIALIZED = 0x03;
+
+// GCList
+PacketWrapper::GCList::GCList() :
+ m_memoryRefAllocatedSize(0),
+ m_memoryRef(0),
+ m_memoryRefPosition(0),
+ m_globalRefAllocatedSize(0),
+ m_globalRef(0),
+ m_globalRefPosition(0)
+{
+}
+
+void PacketWrapper::GCList::Reset(JNIEnv *jni) {
+ if (m_memoryRef != 0) {
+ while (m_memoryRefPosition-- > 0) {
+ GetMemoryManager().Free(m_memoryRef[m_memoryRefPosition] JDWP_FILE_LINE);
+ }
+ GetMemoryManager().Free(m_memoryRef JDWP_FILE_LINE);
+ m_memoryRef = 0;
+ m_memoryRefAllocatedSize = 0;
+ m_memoryRefPosition = 0;
+ }
+
+ if (m_globalRef != 0) {
+ while (m_globalRefPosition-- > 0) {
+ jni->DeleteGlobalRef(m_globalRef[m_globalRefPosition]);
+ }
+ GetMemoryManager().Free(m_globalRef JDWP_FILE_LINE);
+ m_globalRef = 0;
+ m_globalRefAllocatedSize = 0;
+ m_globalRefPosition = 0;
+ }
+}
+
+void PacketWrapper::GCList::StoreStringRef(char* ref) throw (OutOfMemoryException) {
+ if (m_memoryRefPosition >= m_memoryRefAllocatedSize) {
+ // then reallocate buffer
+ size_t oldAllocatedSize = this->m_memoryRefAllocatedSize;
+ if (m_memoryRefAllocatedSize<ALLOCATION_STEP)
+ m_memoryRefAllocatedSize += ALLOCATION_STEP;
+ else
+ m_memoryRefAllocatedSize *= 2;
+
+ m_memoryRef = static_cast<char**>
+ (GetMemoryManager().Reallocate(m_memoryRef,
+ oldAllocatedSize * sizeof(char*),
+ m_memoryRefAllocatedSize * sizeof(char*) JDWP_FILE_LINE));
+ }
+ m_memoryRef[m_memoryRefPosition++] = ref;
+}
+
+void PacketWrapper::GCList::StoreGlobalRef(jobject globalRef) throw (OutOfMemoryException) {
+ if (m_globalRefPosition >= m_globalRefAllocatedSize) {
+ // then reallocate buffer
+ size_t oldAllocatedSize = m_globalRefAllocatedSize;
+ if (m_globalRefAllocatedSize < ALLOCATION_STEP) {
+ m_globalRefAllocatedSize += ALLOCATION_STEP;
+ } else {
+ m_globalRefAllocatedSize *= 2;
+ }
+
+ m_globalRef = static_cast<jobject*>
+ (GetMemoryManager().Reallocate(m_globalRef,
+ oldAllocatedSize * sizeof(jobject),
+ m_globalRefAllocatedSize * sizeof(jobject) JDWP_FILE_LINE));
+ }
+ m_globalRef[m_globalRefPosition++] = globalRef;
+}
+
+void PacketWrapper::GCList::MoveData(GCList* to) {
+ to->m_memoryRefAllocatedSize = m_memoryRefAllocatedSize;
+ to->m_memoryRef = m_memoryRef;
+ to->m_memoryRefPosition = m_memoryRefPosition;
+
+ m_memoryRefAllocatedSize = 0;
+ m_memoryRef = 0;
+ m_memoryRefPosition = 0;
+
+ to->m_globalRefAllocatedSize = m_globalRefAllocatedSize;
+ to->m_globalRef = m_globalRef;
+ to->m_globalRefPosition = m_globalRefPosition;
+
+ m_globalRefAllocatedSize = 0;
+ m_globalRef = 0;
+ m_globalRefPosition = 0;
+}
+
+//////////////////////////////////////////////////////////////////////
+// PacketWrapper
+//////////////////////////////////////////////////////////////////////
+
+PacketWrapper::PacketWrapper() :
+ m_packet(),
+ m_garbageList()
+{
+ this->m_packet.type.cmd.flags = PACKET_IS_UNINITIALIZED;
+}
+
+void PacketWrapper::Reset(JNIEnv *jni) {
+ // clear links
+ m_garbageList.Reset(jni);
+
+ // free packet's data
+ if (m_packet.type.cmd.data!=0) {
+ GetMemoryManager().Free(m_packet.type.cmd.data JDWP_FILE_LINE);
+ m_packet.type.cmd.data = 0;
+ }
+
+ m_packet.type.cmd.flags = PACKET_IS_UNINITIALIZED;
+}
+
+bool PacketWrapper::IsPacketInitialized() {
+ return ((m_packet.type.cmd.flags & PACKET_IS_UNINITIALIZED) == 0);
+}
+
+void PacketWrapper::MoveData(JNIEnv *jni, PacketWrapper* to) {
+ to->Reset(jni);
+
+ // move m_garbageList data to other PacketWrapper
+ to->m_garbageList.MoveData(&to->m_garbageList);
+
+ // move m_packet to packetWrapper
+ memcpy(&to->m_packet, &m_packet, sizeof(m_packet));
+ m_packet.type.cmd.data = 0;
+ m_packet.type.cmd.len = 0;
+ m_packet.type.cmd.flags = PACKET_IS_UNINITIALIZED;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+// InputPacketParser - sequential reading of m_packet data
+//////////////////////////////////////////////////////////////////////
+
+void InputPacketParser::ReadPacketFromTransport() throw (TransportException) {
+ JDWP_ASSERT(!IsPacketInitialized());
+ GetTransportManager().Read(&m_packet);
+}
+
+void InputPacketParser::ReadBigEndianData(void* data, int len) throw (InternalErrorException) {
+ JDWP_ASSERT(IsPacketInitialized());
+
+ if (m_position+len>m_packet.type.cmd.len-JDWP_MIN_PACKET_LENGTH) {
+ throw InternalErrorException();
+ }
+
+ #if IS_BIG_ENDIAN_PLATFORM
+ jbyte* from = static_cast<jbyte*>(&m_packet.type.cmd.data[m_position]);
+ jbyte* to = static_cast<jbyte*>(data);
+ for (int i=0; i<len; i++) {
+ to[i] = from[len-i-1];
+ }
+ #else
+ memcpy(data, &m_packet.type.cmd.data[m_position], length);
+ #endif
+ m_position += len;
+}
+
+void InputPacketParser::ReadRawData(void* data, int len) throw (InternalErrorException) {
+ JDWP_ASSERT(IsPacketInitialized());
+
+ if (m_position+len>m_packet.type.cmd.len-JDWP_MIN_PACKET_LENGTH) {
+ throw InternalErrorException();
+ }
+
+ memcpy(data, &m_packet.type.cmd.data[m_position], len);
+
+ m_position += len;
+}
+
+
+
+jbyte InputPacketParser::ReadByte() throw (InternalErrorException) {
+ jbyte data = 0;
+ ReadBigEndianData(&data, sizeof(jbyte));
+ return data;
+}
+
+jboolean InputPacketParser::ReadBoolean() throw (InternalErrorException) {
+ jboolean data = 0;
+ ReadBigEndianData(&data, sizeof(jboolean));
+ return data;
+}
+
+jint InputPacketParser::ReadInt() throw (InternalErrorException) {
+ jint res = 0;
+ ReadBigEndianData(&res, sizeof(jint));
+ return res;
+}
+
+jlong InputPacketParser::ReadLong() throw (InternalErrorException) {
+ jlong data = 0;
+ ReadBigEndianData(&data, sizeof(jlong));
+ return data;
+}
+
+ObjectID InputPacketParser::ReadRawObjectID() throw (InternalErrorException) {
+ ObjectID data = 0;
+ ReadBigEndianData(&data, OBJECT_ID_SIZE);
+ return data;
+}
+
+jobject InputPacketParser::ReadObjectIDOrNull(JNIEnv *jni) throw (AgentException) {
+ // read raw ObjectID and check for null
+ ObjectID oid = ReadRawObjectID();
+ if (oid == 0) {
+ return 0;
+ }
+
+ // convert to jobject (actually to WeakReference or GlobalReference)
+ jobject obj = GetObjectManager().MapFromObjectID(jni, oid);
+ JDWP_ASSERT(obj != NULL);
+
+ // make GlobalReference and check if WeakReference was freed
+ jobject ref = jni->NewGlobalRef(obj);
+ if (ref == 0) {
+ if (jni->IsSameObject(obj, 0)) {
+ throw AgentException(JDWP_ERROR_INVALID_OBJECT);
+ } else {
+ throw OutOfMemoryException();
+ }
+ }
+
+ // store GlobalReference for futher disposal
+ m_garbageList.StoreGlobalRef(ref);
+ return ref;
+}
+
+jobject InputPacketParser::ReadObjectID(JNIEnv *jni) throw (AgentException) {
+ jobject obj = ReadObjectIDOrNull(jni);
+ if (obj == 0) {
+ throw AgentException(JDWP_ERROR_INVALID_OBJECT);
+ }
+ return obj;
+}
+
+jclass InputPacketParser::ReadReferenceTypeIDOrNull(JNIEnv *jni) throw (AgentException) {
+ ReferenceTypeID rtid = 0;
+ ReadBigEndianData(&rtid, REFERENCE_TYPE_ID_SIZE);
+ if (rtid == 0) {
+ return 0;
+ }
+
+ // convert to jclass (actually to WeakReference or GlobalReference)
+ jclass cls = GetObjectManager().MapFromReferenceTypeID(jni, rtid);
+ JDWP_ASSERT(cls != 0);
+
+ // make GlobalReference and check if WeakReference was freed
+ jclass ref = static_cast<jclass>(jni->NewGlobalRef(cls));
+ if (ref == 0) {
+ if (jni->IsSameObject(cls, 0)) {
+ throw AgentException(JDWP_ERROR_INVALID_OBJECT);
+ } else {
+ throw OutOfMemoryException();
+ }
+ }
+
+ // store GlobalReference for futher disposal
+ m_garbageList.StoreGlobalRef(ref);
+ return ref;
+}
+
+jclass InputPacketParser::ReadReferenceTypeID(JNIEnv *jni) throw (AgentException) {
+ jclass cls = ReadReferenceTypeIDOrNull(jni);
+ if (cls == 0) {
+ throw AgentException(JDWP_ERROR_INVALID_OBJECT);
+ }
+ return cls;
+}
+
+jfieldID InputPacketParser::ReadFieldID(JNIEnv *jni) throw (AgentException) {
+ FieldID fid = 0;
+ ReadBigEndianData(&fid, FIELD_ID_SIZE);
+ jfieldID res = GetObjectManager().MapFromFieldID(jni, fid);
+ return res;
+}
+
+jmethodID InputPacketParser::ReadMethodID(JNIEnv *jni) throw (AgentException) {
+ MethodID mid = 0;
+ ReadBigEndianData(&mid, METHOD_ID_SIZE);
+ jmethodID res = GetObjectManager().MapFromMethodID(jni, mid);
+ return res;
+}
+
+jint InputPacketParser::ReadFrameID(JNIEnv *jni) throw (AgentException) {
+ FrameID fid;
+ ReadBigEndianData(&fid, FRAME_ID_SIZE);
+ jint res = GetObjectManager().MapFromFrameID(jni, fid);
+ return res;
+}
+
+jdwpLocation InputPacketParser::ReadLocation(JNIEnv *jni) throw (AgentException) {
+ jdwpLocation res;
+ res.typeTag = static_cast<jdwpTypeTag>(ReadByte());
+ res.classID = ReadReferenceTypeID(jni);
+ res.methodID = ReadMethodID(jni);
+ res.loc = ReadLong();
+ return res;
+}
+
+jthread InputPacketParser::ReadThreadID(JNIEnv *jni) throw (AgentException) {
+ return static_cast<jthread>(ReadObjectID(jni));
+}
+
+jthreadGroup InputPacketParser::ReadThreadGroupID(JNIEnv *jni) throw (AgentException) {
+ return static_cast<jthreadGroup>(ReadObjectID(jni));
+}
+
+jstring InputPacketParser::ReadStringID(JNIEnv *jni) throw (AgentException) {
+ return static_cast<jstring>(ReadObjectID(jni));
+}
+
+jarray InputPacketParser::ReadArrayID(JNIEnv *jni) throw (AgentException) {
+ return static_cast<jarray>(ReadObjectID(jni));
+}
+
+char* InputPacketParser::ReadStringNoFree() throw (InternalErrorException, OutOfMemoryException) {
+ jint len = ReadInt();
+ if (m_position+len>m_packet.type.cmd.len) {
+ throw InternalErrorException();
+ }
+ char* res = static_cast<char*>(GetMemoryManager().Allocate(len+1 JDWP_FILE_LINE));
+ strncpy(res, reinterpret_cast<char*>(&m_packet.type.cmd.data[m_position]), len);
+ res[len] = '\0';
+ m_position += len;
+ return res;
+}
+
+char* InputPacketParser::ReadString() throw (InternalErrorException, OutOfMemoryException) {
+ char* res = ReadStringNoFree();
+ m_garbageList.StoreStringRef(res);
+ return res;
+}
+
+jdwpTaggedValue InputPacketParser::ReadValue(JNIEnv *jni) throw (AgentException) {
+ //The first byte is a signature byte which is used to identify the type
+ jdwpTaggedValue tv;
+ tv.tag = static_cast<jdwpTag>(ReadByte());
+ tv.value = ReadUntaggedValue(jni, tv.tag);
+ return tv;
+}
+
+jvalue InputPacketParser::ReadUntaggedValue(JNIEnv *jni, jdwpTag tagPtr) throw (AgentException) {
+ jvalue value;
+
+ switch (tagPtr) {
+ case JDWP_TAG_ARRAY:
+ value.l = ReadObjectIDOrNull(jni);
+ break;
+ case JDWP_TAG_BYTE:
+ value.b = ReadByte();
+ break;
+ case JDWP_TAG_CHAR:
+ value.c = ReadChar();
+ break;
+ case JDWP_TAG_OBJECT:
+ value.l = ReadObjectIDOrNull(jni);
+ break;
+ case JDWP_TAG_FLOAT:
+ value.f = ReadFloat();
+ break;
+ case JDWP_TAG_DOUBLE:
+ value.d = ReadDouble();
+ break;
+ case JDWP_TAG_INT:
+ value.i = ReadInt();
+ break;
+ case JDWP_TAG_LONG:
+ value.j = ReadLong();
+ break;
+ case JDWP_TAG_SHORT:
+ value.s = ReadShort();
+ break;
+ case JDWP_TAG_VOID:
+ // read nothing
+ break;
+ case JDWP_TAG_BOOLEAN:
+ value.z = ReadBoolean();
+ break;
+ case JDWP_TAG_STRING:
+ value.l = ReadObjectIDOrNull(jni);
+ break;
+ case JDWP_TAG_THREAD:
+ value.l = ReadObjectIDOrNull(jni);
+ break;
+ case JDWP_TAG_THREAD_GROUP:
+ value.l = ReadObjectIDOrNull(jni);
+ break;
+ case JDWP_TAG_CLASS_LOADER:
+ value.l = ReadObjectIDOrNull(jni);
+ break;
+ case JDWP_TAG_CLASS_OBJECT:
+ value.l = ReadObjectIDOrNull(jni);
+ break;
+ default: JDWP_ERROR("Illegal jdwp-tag value: " << tagPtr);
+ }
+ return value;
+}
+
+// InputPacket's private methods
+
+jchar InputPacketParser::ReadChar() throw (InternalErrorException) {
+ jchar data = 0;
+ ReadBigEndianData(&data, sizeof(jchar));
+ return data;
+}
+jshort InputPacketParser::ReadShort() throw (InternalErrorException) {
+ jshort data = 0;
+ ReadBigEndianData(&data, sizeof(jshort));
+ return data;
+}
+
+jfloat InputPacketParser::ReadFloat() throw (InternalErrorException) {
+ jfloat data = 0;
+ ReadBigEndianData(&data, sizeof(jfloat));
+ return data;
+}
+jdouble InputPacketParser::ReadDouble() throw (InternalErrorException) {
+ jdouble data = 0;
+ ReadBigEndianData(&data, sizeof(jdouble));
+ return data;
+}
+
+void InputPacketParser::Reset(JNIEnv *jni) {
+ PacketWrapper::Reset(jni);
+ m_position = 0;
+}
+
+void InputPacketParser::MoveData(JNIEnv *jni, InputPacketParser* to) {
+ PacketWrapper::MoveData(jni, to);
+ m_position = 0;
+}
+
+//////////////////////////////////////////////////////////////////////
+// OutputPacketComposer - sequential writing of m_packet data
+//////////////////////////////////////////////////////////////////////
+void OutputPacketComposer::WritePacketToTransport() throw (TransportException) {
+ JDWP_ASSERT(IsPacketInitialized());
+ GetTransportManager().Write(&m_packet);
+ if ( GetError() == JDWP_ERROR_NONE ) {
+ IncreaseObjectIDRefCounts();
+ }
+}
+
+void OutputPacketComposer::AllocateMemoryForData(int length) throw (OutOfMemoryException) {
+ size_t newPosition = m_position + static_cast<size_t>(length);
+ if (newPosition >= m_allocatedSize) {
+ // then reallocate buffer
+ size_t newAllocatedSize = m_allocatedSize + ALLOCATION_STEP;
+ while (newPosition >= newAllocatedSize) {
+ if (newAllocatedSize < ALLOCATION_STEP)
+ newAllocatedSize += ALLOCATION_STEP;
+ else
+ newAllocatedSize *= 2;
+ }
+ m_packet.type.cmd.data = static_cast<jbyte*>
+ (GetMemoryManager().Reallocate(m_packet.type.cmd.data,
+ m_allocatedSize, newAllocatedSize JDWP_FILE_LINE));
+ m_allocatedSize = newAllocatedSize;
+ }
+}
+
+
+void OutputPacketComposer::WriteRawData(const void* data, int length) throw (OutOfMemoryException) {
+ AllocateMemoryForData(length);
+
+ memcpy(&m_packet.type.cmd.data[m_position], data, length);
+
+ m_position += length;
+ m_packet.type.cmd.len += length;
+}
+
+
+void OutputPacketComposer::WriteBigEndianData(void* data, int length) throw (OutOfMemoryException) {
+ JDWP_ASSERT(length <= sizeof(jlong));
+ AllocateMemoryForData(length);
+
+ #if IS_BIG_ENDIAN_PLATFORM
+ const jbyte* from = static_cast<jbyte*>(const_cast<void*>(data));
+ jbyte* to = static_cast<jbyte*>(&m_packet.type.cmd.data[m_position]);
+ for (int i=0; i<length; i++) {
+ to[i] = from[length-i-1];
+ }
+
+ #else
+ memcpy(&m_packet.type.cmd.data[m_position], data, length);
+ #endif
+ m_position += length;
+ m_packet.type.cmd.len += length;
+
+}
+
+void OutputPacketComposer::WriteByte(jbyte value) throw (OutOfMemoryException) {
+ WriteBigEndianData(&value, sizeof(value));
+}
+void OutputPacketComposer::WriteBoolean(jboolean value) throw (OutOfMemoryException) {
+ WriteBigEndianData(&value, sizeof(value));
+}
+void OutputPacketComposer::WriteInt(jint value) throw (OutOfMemoryException) {
+ WriteBigEndianData(&value, sizeof(value));
+}
+void OutputPacketComposer::WriteLong(jlong value) throw (OutOfMemoryException) {
+ WriteBigEndianData(&value, sizeof(value));
+}
+
+void OutputPacketComposer::WriteObjectID(JNIEnv *jni, jobject value) throw (AgentException) {
+ ObjectID id = GetObjectManager().MapToObjectID(jni, value);
+ WriteBigEndianData(&id, OBJECT_ID_SIZE);
+ RegisterObjectID(id);
+}
+
+void OutputPacketComposer::WriteReferenceTypeID(JNIEnv *jni, jclass value) throw (OutOfMemoryException) {
+ ReferenceTypeID id = GetObjectManager().MapToReferenceTypeID(jni, value);
+ WriteBigEndianData(&id, REFERENCE_TYPE_ID_SIZE);
+}
+
+void OutputPacketComposer::WriteFieldID(JNIEnv *jni, jfieldID value) throw (OutOfMemoryException) {
+ FieldID id = GetObjectManager().MapToFieldID(jni, value);
+ WriteBigEndianData(&id, FIELD_ID_SIZE);
+}
+
+void OutputPacketComposer::WriteMethodID(JNIEnv *jni, jmethodID value) throw (OutOfMemoryException) {
+ MethodID id = GetObjectManager().MapToMethodID(jni, value);
+ WriteBigEndianData(&id, METHOD_ID_SIZE);
+}
+
+void OutputPacketComposer::WriteFrameID(JNIEnv *jni, jthread jvmThread, jint frameDepth, jint framesCount)
+throw (OutOfMemoryException) {
+ FrameID id = GetObjectManager().MapToFrameID(jni, jvmThread, frameDepth, framesCount);
+ WriteBigEndianData(&id, FRAME_ID_SIZE);
+}
+
+void OutputPacketComposer::WriteLocation(JNIEnv *jni, jdwpTypeTag typeTag, jclass clazz,
+ jmethodID method, jlocation location)
+throw (OutOfMemoryException) {
+ WriteByte(static_cast<jbyte>(typeTag));
+ WriteReferenceTypeID(jni, clazz);
+ WriteMethodID(jni, method);
+ WriteLong(static_cast<jlong>(location));
+}
+
+void OutputPacketComposer::WriteLocation(JNIEnv *jni, jdwpLocation *location) throw (OutOfMemoryException) {
+ WriteLocation(jni, location->typeTag, location->classID, location->methodID, location->loc);
+}
+
+void OutputPacketComposer::WriteThreadID(JNIEnv *jni, jthread value) throw (OutOfMemoryException) {
+ WriteObjectID(jni, value);
+}
+
+void OutputPacketComposer::WriteThreadGroupID(JNIEnv *jni, jthreadGroup value) throw (OutOfMemoryException) {
+ WriteObjectID(jni, value);
+}
+
+void OutputPacketComposer::WriteStringID(JNIEnv *jni, jstring value) throw (OutOfMemoryException) {
+ WriteObjectID(jni, value);
+}
+
+void OutputPacketComposer::WriteArrayID(JNIEnv *jni, jarray value) throw (OutOfMemoryException) {
+ WriteObjectID(jni, value);
+}
+
+void OutputPacketComposer::WriteString(const char* value) throw (OutOfMemoryException) {
+ jint len = static_cast<jint>((value == 0) ? 0 : std::strlen(value));
+ WriteString(value, len);
+}
+
+void OutputPacketComposer::WriteString(const char* value, jint length) throw (OutOfMemoryException) {
+ WriteBigEndianData(&length, sizeof(jint));
+ if (length > 0) {
+ WriteRawData(value, length);
+ }
+}
+
+void OutputPacketComposer::WriteUntaggedValue(JNIEnv *jni, jdwpTag tag, jvalue value)
+throw (OutOfMemoryException) {
+ //The first byte is a signature byte which is used to identify the type
+ switch (tag) {
+ case JDWP_TAG_ARRAY:
+ WriteObjectID(jni, value.l);
+ break;
+ case JDWP_TAG_BYTE:
+ WriteByte(value.b);
+ break;
+ case JDWP_TAG_CHAR:
+ WriteChar(value.c);
+ break;
+ case JDWP_TAG_OBJECT:
+ WriteObjectID(jni, value.l);
+ break;
+ case JDWP_TAG_FLOAT:
+ WriteFloat(value.f);
+ break;
+ case JDWP_TAG_DOUBLE:
+ WriteDouble(value.d);
+ break;
+ case JDWP_TAG_INT:
+ WriteInt(value.i);
+ break;
+ case JDWP_TAG_LONG:
+ WriteLong(value.j);
+ break;
+ case JDWP_TAG_SHORT:
+ WriteShort(value.s);
+ break;
+ case JDWP_TAG_VOID:
+ // read nothing
+ break;
+ case JDWP_TAG_BOOLEAN:
+ WriteBoolean(value.z);
+ break;
+ case JDWP_TAG_STRING:
+ WriteObjectID(jni, value.l);
+ break;
+ case JDWP_TAG_THREAD:
+ WriteObjectID(jni, value.l);
+ break;
+ case JDWP_TAG_THREAD_GROUP:
+ WriteObjectID(jni, value.l);
+ break;
+ case JDWP_TAG_CLASS_LOADER:
+ WriteObjectID(jni, value.l);
+ break;
+ case JDWP_TAG_CLASS_OBJECT:
+ WriteObjectID(jni, value.l);
+ break;
+ default: JDWP_ERROR("Illegal jdwp-tag value: " << tag);
+ }
+}
+
+void OutputPacketComposer::WriteValue(JNIEnv *jni, jdwpTag tag, jvalue value) throw (OutOfMemoryException) {
+ WriteByte(static_cast<jbyte>(tag));
+ WriteUntaggedValue(jni, tag, value);
+}
+
+void OutputPacketComposer::WriteTaggedObjectID(JNIEnv *jni, jobject object) throw (OutOfMemoryException) {
+ jdwpTag tag = GetClassManager().GetJdwpTag(jni, object);
+ WriteByte(static_cast<jbyte>(tag));
+ WriteObjectID(jni, object);
+}
+
+void OutputPacketComposer::WriteValues(JNIEnv *jni, jdwpTag tag,
+ jint length, jvalue* value) throw (OutOfMemoryException) {
+ WriteByte(static_cast<jbyte>(tag));
+ WriteInt(length);
+ for (int i=0; i<length; i++)
+ WriteUntaggedValue(jni, tag, value[i]);
+}
+
+void OutputPacketComposer::WriteByteArray(jbyte* byte, jint length) throw (OutOfMemoryException) {
+ WriteInt(length);
+ WriteRawData(byte, length);
+}
+
+void OutputPacketComposer::Reset(JNIEnv *jni) {
+ PacketWrapper::Reset(jni);
+ m_position = 0;
+ m_allocatedSize = 0;
+ if (m_registeredObjectIDCount != 0) {
+ GetMemoryManager().Free(m_registeredObjectIDTable JDWP_FILE_LINE);
+ m_registeredObjectIDTable = 0;
+ m_registeredObjectIDCount = 0;
+ m_registeredObjectIDTableSise = 0;
+ }
+}
+
+void OutputPacketComposer::MoveData(JNIEnv *jni, OutputPacketComposer* to) {
+ PacketWrapper::MoveData(jni, to);
+ m_position = 0;
+ m_allocatedSize = 0;
+}
+
+// OutputPacketComposer's private methods
+void OutputPacketComposer::WriteChar(jchar value) throw (OutOfMemoryException) {
+ WriteBigEndianData(&value, sizeof(value));
+}
+void OutputPacketComposer::WriteShort(jshort value) throw (OutOfMemoryException) {
+ WriteBigEndianData(&value, sizeof(value));
+}
+void OutputPacketComposer::WriteFloat(jfloat value) throw (OutOfMemoryException) {
+ WriteBigEndianData(&value, sizeof(value));
+}
+void OutputPacketComposer::WriteDouble(jdouble value) throw (OutOfMemoryException) {
+ WriteBigEndianData(&value, sizeof(value));
+}
+
+void OutputPacketComposer::RegisterObjectID(ObjectID objectID)
+ throw (AgentException) {
+
+ if ( objectID == JDWP_OBJECT_ID_NULL ) {
+ return;
+ }
+
+ if ( m_registeredObjectIDCount == m_registeredObjectIDTableSise ) {
+
+ if ( m_registeredObjectIDCount == 0 ) {
+ m_registeredObjectIDTable = reinterpret_cast<ObjectID*>
+ (AgentBase::GetMemoryManager().Allocate(sizeof(ObjectID)
+ * REGISTERED_OBJECTID_TABLE_STEP JDWP_FILE_LINE));
+ // can be: OutOfMemoryException, InternalErrorException
+ m_registeredObjectIDTableSise = REGISTERED_OBJECTID_TABLE_STEP;
+ } else {
+ m_registeredObjectIDTableSise
+ = m_registeredObjectIDTableSise + REGISTERED_OBJECTID_TABLE_STEP;
+ m_registeredObjectIDTable = reinterpret_cast<ObjectID*>
+ (AgentBase::GetMemoryManager().Reallocate(m_registeredObjectIDTable,
+ static_cast<size_t>(sizeof(ObjectID) * (m_registeredObjectIDTableSise-REGISTERED_OBJECTID_TABLE_STEP)),
+ static_cast<size_t>(sizeof(ObjectID) * m_registeredObjectIDTableSise) JDWP_FILE_LINE));
+ // can be: OutOfMemoryException, InternalErrorException
+ }
+ }
+ m_registeredObjectIDTable[m_registeredObjectIDCount++] = objectID;
+}
+
+void OutputPacketComposer::IncreaseObjectIDRefCounts() {
+ for ( int i=0; i < m_registeredObjectIDCount; i++) {
+ GetObjectManager().IncreaseIDRefCount(m_registeredObjectIDTable[i]);
+ }
+}
+
+// new reply
+void OutputPacketComposer::CreateJDWPReply(jint id, jdwpError errorCode) throw (InternalErrorException) {
+ JDWP_ASSERT(!IsPacketInitialized());
+ m_packet.type.reply.id = id;
+ m_packet.type.reply.len = JDWP_MIN_PACKET_LENGTH;
+ m_packet.type.reply.flags = JDWP_FLAG_REPLY_PACKET;
+ m_packet.type.reply.errorCode = errorCode;
+}
+
+// new event
+void OutputPacketComposer::CreateJDWPEvent(jint id, jdwpCommandSet commandSet, jdwpCommand command)
+throw (InternalErrorException) {
+ JDWP_ASSERT(!IsPacketInitialized());
+ m_packet.type.cmd.id = id;
+ m_packet.type.cmd.len = JDWP_MIN_PACKET_LENGTH;
+ m_packet.type.cmd.flags = 0;
+ m_packet.type.cmd.cmdSet = commandSet;
+ m_packet.type.cmd.cmd = command;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// CommandParser
+///////////////////////////////////////////////////////////////////////////////
+
+void CommandParser::ReadCommand() throw (TransportException) {
+ command.ReadPacketFromTransport();
+ reply.CreateJDWPReply(command.GetId(), JDWP_ERROR_NONE);
+}
+
+void CommandParser::WriteReply(JNIEnv *jni) throw (TransportException) {
+ reply.WritePacketToTransport();
+ Reset(jni);
+}
+
+void CommandParser::Reset(JNIEnv *jni) {
+ command.Reset(jni);
+ reply.Reset(jni);
+}
+
+void CommandParser::MoveData(JNIEnv *jni, CommandParser* to) {
+ command.MoveData(jni, &to->command);
+ reply.MoveData(jni, &to->reply);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// EventComposer
+///////////////////////////////////////////////////////////////////////////////
+
+EventComposer::EventComposer(jint id,
+ jdwpCommandSet commandSet, jdwpCommand command, jdwpSuspendPolicy sp)
+{
+ event.CreateJDWPEvent(id, commandSet, command);
+ m_suspendPolicy = sp;
+ m_thread = 0;
+ m_isSent = false;
+ m_isWaiting = false;
+ m_isReleased = false;
+ m_isAutoDeathEvent = false;
+ event.WriteByte(sp);
+}
+
+void EventComposer::WriteThread(JNIEnv *jni, jthread thread)
+ throw (OutOfMemoryException)
+{
+ event.WriteThreadID(jni, thread);
+ m_thread = jni->NewGlobalRef(thread);
+ if (m_thread == 0) {
+ throw OutOfMemoryException();
+ }
+}
+
+void EventComposer::Reset(JNIEnv *jni)
+{
+ if (m_thread != 0) {
+ jni->DeleteGlobalRef(m_thread);
+ m_thread = 0;
+ }
+ event.Reset(jni);
+}
+
+void EventComposer::WriteEvent(JNIEnv *jni) throw (TransportException)
+{
+ event.WritePacketToTransport();
+ m_isSent = true;
+ event.Reset(jni);
+}
Propchange: harmony/enhanced/jdktools/trunk/modules/jpda/src/common/other/jpda/jdwp/agent/core/PacketParser.cpp
------------------------------------------------------------------------------
svn:eol-style = native