/**
*
* Copyright 2004 Protique Ltd
*
* 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.activemq.message;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.StringTokenizer;
import org.activemq.util.BitArray;
import EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArraySet;
/**
* Abstract class for a transportable Packet
*
* @version $Revision: 1.1.1.1 $
*/
public abstract class AbstractPacket implements Packet {
/**
* Message flag indexes (used for writing/reading to/from a Stream
*/
public static final int RECEIPT_REQUIRED_INDEX = 0;
public static final int BROKERS_VISITED_INDEX =1;
private short id = 0;
protected BitArray bitArray;
protected transient int cachedHashCode = -1;
private boolean receiptRequired;
private transient int memoryUsage = 2048;
private transient int memoryUsageReferenceCount;
private CopyOnWriteArraySet brokersVisited;
protected AbstractPacket(){
this.bitArray = new BitArray();
}
/**
* @return the unique id for this Packet
*/
public short getId() {
return this.id;
}
/**
* Set the unique id for this Packet
*
* @param newId
*/
public void setId(short newId) {
this.id = newId;
}
/**
* @return true if a Recipt is required
*/
public boolean isReceiptRequired() {
return this.receiptRequired;
}
/**
* @return false since most packets are not receipt packets
*/
public boolean isReceipt() {
return false;
}
/**
* Set if a Recipt if required on receiving this Packet
*
* @param value
*/
public void setReceiptRequired(boolean value) {
this.receiptRequired = value;
}
/**
* Retrieve if a JMS Message type or not
*
* @return true if it is a JMS Message
*/
public boolean isJMSMessage() {
return false;
}
/**
* Tests equality with another instance
*
* @param obj - the other instance to test equality with
* @return Returns true if the objects are equilvant
*/
public boolean equals(Object obj) {
boolean result = this == obj;
if (!result && obj != null && obj instanceof AbstractPacket) {
AbstractPacket other = (AbstractPacket) obj;
result = other.id == this.id;
}
return result;
}
/**
* @return Returns hash code for this instance
*/
public int hashCode() {
return this.id;
}
/**
* Get a hint about how much memory this Packet is consuming
*
* @return an aproximation of the current memory used by this instance
*/
public int getMemoryUsage() {
return memoryUsage;
}
/**
* Set a hint about how mujch memory this packet is consuming
*
* @param newMemoryUsage
*/
public void setMemoryUsage(int newMemoryUsage) {
this.memoryUsage = newMemoryUsage;
}
/**
* Increment reference count for bounded memory collections
*
* @return the incremented reference value
* @see org.activemq.io.util.MemoryBoundedQueue
*/
public synchronized int incrementMemoryReferenceCount() {
return ++memoryUsageReferenceCount;
}
/**
* Decrement reference count for bounded memory collections
*
* @return the decremented reference value
* @see org.activemq.io.util.MemoryBoundedQueue
*/
public synchronized int decrementMemoryReferenceCount() {
return --memoryUsageReferenceCount;
}
/**
* @return the current reference count for bounded memory collections
* @see org.activemq.io.util.MemoryBoundedQueue
*/
public synchronized int getMemoryUsageReferenceCount() {
return memoryUsageReferenceCount;
}
/**
* As the packet passes through the broker add the broker to the visited list
*
* @param brokerName the name of the broker
*/
public void addBrokerVisited(String brokerName) {
if (brokerName == null || brokerName.trim().equals("")) {
throw new IllegalArgumentException("Broker name cannot be empty or null");
}
initializeBrokersVisited();
brokersVisited.add(brokerName);
}
/**
* clear list of brokers visited
*/
public void clearBrokersVisited(){
brokersVisited = null;
}
/**
* test to see if the named broker has already seen this packet
*
* @param brokerName the name of the broker
* @return true if the packet has visited the broker
*/
public boolean hasVisited(String brokerName) {
if (brokersVisited == null){
return false;
}
return brokersVisited.contains(brokerName);
}
/**
* @return Returns the brokersVisited.
*/
public String getBrokersVisitedAsString() {
String result = "";
if (brokersVisited != null && !brokersVisited.isEmpty()){
for (Iterator i = brokersVisited.iterator(); i.hasNext();){
result += i.next().toString() + ",";
}
}
return result;
}
public void setBrokersVisitedAsString(String value) {
initializeBrokersVisited();
StringTokenizer enm = new StringTokenizer(value, ",");
while (enm.hasMoreElements()) {
brokersVisited.add(enm.nextToken());
}
}
/**
* @return pretty print of this Packet
*/
public String toString() {
return getPacketTypeAsString(getPacketType()) + ": id = " + getId();
}
public static String getPacketTypeAsString(int type) {
String packetTypeStr = "";
switch (type) {
case ACTIVEMQ_MESSAGE:
packetTypeStr = "ACTIVEMQ_MESSAGE";
break;
case ACTIVEMQ_TEXT_MESSAGE:
packetTypeStr = "ACTIVEMQ_TEXT_MESSAGE";
break;
case ACTIVEMQ_OBJECT_MESSAGE:
packetTypeStr = "ACTIVEMQ_OBJECT_MESSAGE";
break;
case ACTIVEMQ_BYTES_MESSAGE:
packetTypeStr = "ACTIVEMQ_BYTES_MESSAGE";
break;
case ACTIVEMQ_STREAM_MESSAGE:
packetTypeStr = "ACTIVEMQ_STREAM_MESSAGE";
break;
case ACTIVEMQ_MAP_MESSAGE:
packetTypeStr = "ACTIVEMQ_MAP_MESSAGE";
break;
case ACTIVEMQ_MSG_ACK:
packetTypeStr = "ACTIVEMQ_MSG_ACK";
break;
case RECEIPT_INFO:
packetTypeStr = "RECEIPT_INFO";
break;
case CONSUMER_INFO:
packetTypeStr = "CONSUMER_INFO";
break;
case PRODUCER_INFO:
packetTypeStr = "PRODUCER_INFO";
break;
case TRANSACTION_INFO:
packetTypeStr = "TRANSACTION_INFO";
break;
case XA_TRANSACTION_INFO:
packetTypeStr = "XA_TRANSACTION_INFO";
break;
case ACTIVEMQ_BROKER_INFO:
packetTypeStr = "ACTIVEMQ_BROKER_INFO";
break;
case ACTIVEMQ_CONNECTION_INFO:
packetTypeStr = "ACTIVEMQ_CONNECTION_INFO";
break;
case SESSION_INFO:
packetTypeStr = "SESSION_INFO";
break;
case DURABLE_UNSUBSCRIBE:
packetTypeStr = "DURABLE_UNSUBSCRIBE";
break;
case RESPONSE_RECEIPT_INFO:
packetTypeStr = "RESPONSE_RECEIPT_INFO";
break;
case INT_RESPONSE_RECEIPT_INFO:
packetTypeStr = "INT_RESPONSE_RECEIPT_INFO";
break;
case CAPACITY_INFO:
packetTypeStr = "CAPACITY_INFO";
break;
case CAPACITY_INFO_REQUEST:
packetTypeStr = "CAPACITY_INFO_REQUEST";
break;
case WIRE_FORMAT_INFO:
packetTypeStr = "WIRE_FORMAT_INFO";
break;
case KEEP_ALIVE:
packetTypeStr = "KEEP_ALIVE";
break;
case CACHED_VALUE_COMMAND:
packetTypeStr = "CachedValue";
break;
default :
packetTypeStr = "UNKNOWN PACKET TYPE: " + type;
}
return packetTypeStr;
}
/**
* A helper method used when implementing equals() which returns true if the objects are identical or equal handling
* nulls properly
* @param left
* @param right
*
* @return true if the objects are the same or equal or both null
*/
protected boolean equals(Object left, Object right) {
return left == right || (left != null && left.equals(right));
}
/**
* Initializes another message with current values from this instance
*
* @param other the other ActiveMQMessage to initialize
*/
protected void initializeOther(AbstractPacket other) {
initializeBrokersVisited();
other.id = this.id;
other.receiptRequired = this.receiptRequired;
other.memoryUsage = this.memoryUsage;
CopyOnWriteArraySet set = this.brokersVisited;
if (set != null && !set.isEmpty()){
other.brokersVisited = new CopyOnWriteArraySet(set);
}
}
synchronized void initializeBrokersVisited(){
if (this.brokersVisited == null){
this.brokersVisited = new CopyOnWriteArraySet();
}
}
/**
* @return Returns the brokersVisited.
*/
public Object[] getBrokersVisited() {
if (brokersVisited == null || brokersVisited.isEmpty()){
return null;
}
return brokersVisited.toArray();
}
/**
* @return Returns the bitArray.
*/
public BitArray getBitArray() {
return bitArray;
}
/**
* @param bitArray The bitArray to set.
*/
public void setBitArray(BitArray bitArray) {
this.bitArray = bitArray;
}
}