protected virtual void WriteTransactionInfo(TransactionInfo command, StompFrameStream ss)
        {
            TransactionId id = command.TransactionId;

            if (id is LocalTransactionId)
            {
                string          type            = "BEGIN";
                TransactionType transactionType = (TransactionType)command.Type;
                switch (transactionType)
                {
                case TransactionType.CommitOnePhase:
                    command.ResponseRequired = true;
                    type = "COMMIT";
                    break;

                case TransactionType.Rollback:
                    command.ResponseRequired = true;
                    type = "ABORT";
                    break;
                }
                Console.WriteLine(">>> For transaction type: " + transactionType + " we are using command type: " + type);

                ss.WriteCommand(command, type);

                ss.WriteHeader("transaction", StompHelper.ToStomp(id));

                ss.Flush();
            }
        }
        protected virtual void WriteConsumerInfo(ConsumerInfo command, StompFrameStream ss)
        {
            ss.WriteCommand(command, "SUBSCRIBE");
            ss.WriteHeader("destination", StompHelper.ToStomp(command.Destination));
            ss.WriteHeader("id", StompHelper.ToStomp(command.ConsumerId));
            ss.WriteHeader("durable-subscriber-name", command.SubscriptionName);
            ss.WriteHeader("selector", command.Selector);
            if (command.NoLocal)
            {
                ss.WriteHeader("no-local", command.NoLocal);
            }
            ss.WriteHeader("ack", "client");

            // ActiveMQ extensions to STOMP
            ss.WriteHeader("activemq.dispatchAsync", command.DispatchAsync);
            if (command.Exclusive)
            {
                ss.WriteHeader("activemq.exclusive", command.Exclusive);
            }

            ss.WriteHeader("activemq.maximumPendingMessageLimit", command.MaximumPendingMessageLimit);
            ss.WriteHeader("activemq.prefetchSize", command.PrefetchSize);
            ss.WriteHeader("activemq.priority ", command.Priority);
            if (command.Retroactive)
            {
                ss.WriteHeader("activemq.retroactive", command.Retroactive);
            }

            consumers[command.ConsumerId] = command.ConsumerId;
            ss.Flush();
        }
        protected virtual void WriteMessage(ActiveMQMessage command, StompFrameStream ss)
        {
            ss.WriteCommand(command, "SEND");
            ss.WriteHeader("destination", StompHelper.ToStomp(command.Destination));
            if (command.ReplyTo != null)
            {
                ss.WriteHeader("reply-to", StompHelper.ToStomp(command.ReplyTo));
            }
            if (command.CorrelationId != null)
            {
                ss.WriteHeader("correlation-id", command.CorrelationId);
            }
            if (command.Expiration != 0)
            {
                ss.WriteHeader("expires", command.Expiration);
            }
            if (command.Priority != 4)
            {
                ss.WriteHeader("priority", command.Priority);
            }
            if (command.Type != null)
            {
                ss.WriteHeader("type", command.Type);
            }
            if (command.TransactionId != null)
            {
                ss.WriteHeader("transaction", StompHelper.ToStomp(command.TransactionId));
            }

            ss.WriteHeader("persistent", command.Persistent);

            // lets force the content to be marshalled

            command.BeforeMarshall(null);
            if (command is ActiveMQTextMessage)
            {
                ActiveMQTextMessage textMessage = command as ActiveMQTextMessage;
                ss.Content = encoding.GetBytes(textMessage.Text);
            }
            else
            {
                ss.Content       = command.Content;
                ss.ContentLength = command.Content.Length;
            }

            IPrimitiveMap map = command.Properties;

            foreach (string key in map.Keys)
            {
                ss.WriteHeader(key, map[key]);
            }
            ss.Flush();
        }
        protected virtual void WriteMessageAck(MessageAck command, StompFrameStream ss)
        {
            ss.WriteCommand(command, "ACK");

            // TODO handle bulk ACKs?
            ss.WriteHeader("message-id", StompHelper.ToStomp(command.FirstMessageId));
            if (command.TransactionId != null)
            {
                ss.WriteHeader("transaction", StompHelper.ToStomp(command.TransactionId));
            }

            ss.Flush();
        }
        protected virtual void WriteRemoveInfo(RemoveInfo command, StompFrameStream ss)
        {
            object id = command.ObjectId;

            if (id is ConsumerId)
            {
                ConsumerId consumerId = id as ConsumerId;
                ss.WriteCommand(command, "UNSUBSCRIBE");
                ss.WriteHeader("id", StompHelper.ToStomp(consumerId));
                ss.Flush();
                consumers.Remove(consumerId);
            }
            // When a session is removed, it needs to remove it's consumers too.
            if (id is SessionId)
            {
                // Find all the consumer that were part of the session.
                SessionId sessionId = (SessionId)id;
                ArrayList matches   = new ArrayList();
                foreach (DictionaryEntry entry in consumers)
                {
                    ConsumerId t = (ConsumerId)entry.Key;
                    if (sessionId.ConnectionId == t.ConnectionId && sessionId.Value == t.SessionId)
                    {
                        matches.Add(t);
                    }
                }

                // Un-subscribe them.
                foreach (ConsumerId consumerId in matches)
                {
                    ss.WriteCommand(command, "UNSUBSCRIBE");
                    ss.WriteHeader("id", StompHelper.ToStomp(consumerId));
                    ss.Flush();
                    consumers.Remove(consumerId);
                }
            }
        }
        protected virtual Command ReadMessage(string command, IDictionary headers, byte[] content)
        {
            ActiveMQMessage message = null;

            if (headers.Contains("content-length"))
            {
                message         = new ActiveMQBytesMessage();
                message.Content = content;
            }
            else
            {
                message = new ActiveMQTextMessage(encoding.GetString(content, 0, content.Length));
            }

            if (message is ActiveMQTextMessage)
            {
                ActiveMQTextMessage textMessage = message as ActiveMQTextMessage;
            }

            // TODO now lets set the various headers

            message.Type             = RemoveHeader(headers, "type");
            message.Destination      = StompHelper.ToDestination(RemoveHeader(headers, "destination"));
            message.ReplyTo          = StompHelper.ToDestination(RemoveHeader(headers, "reply-to"));
            message.TargetConsumerId = StompHelper.ToConsumerId(RemoveHeader(headers, "subscription"));
            message.CorrelationId    = ToString(headers["correlation-id"]);
            message.MessageId        = StompHelper.ToMessageId(RemoveHeader(headers, "message-id"));
            message.Persistent       = StompHelper.ToBool(RemoveHeader(headers, "persistent"), true);

            string header = RemoveHeader(headers, "priority");

            if (header != null)
            {
                message.Priority = Byte.Parse(header);
            }

            header = RemoveHeader(headers, "timestamp");
            if (header != null)
            {
                message.Timestamp = Int64.Parse(header);
            }

            header = RemoveHeader(headers, "expires");
            if (header != null)
            {
                message.Expiration = Int64.Parse(header);
            }

            header = RemoveHeader(headers, "timestamp");
            if (header != null)
            {
                message.Timestamp = Int64.Parse(header);
            }


            // now lets add the generic headers
            foreach (string key in headers.Keys)
            {
                Object value = headers[key];
                if (value != null)
                {
                    // lets coerce some standard header extensions
                    if (key == "NMSXGroupSeq")
                    {
                        value = Int32.Parse(value.ToString());
                    }
                }
                message.Properties[key] = value;
            }
            MessageDispatch dispatch = new MessageDispatch();

            dispatch.Message     = message;
            dispatch.ConsumerId  = message.TargetConsumerId;
            dispatch.Destination = message.Destination;
            return(dispatch);
        }