blob: 037471ee4247363b11830d4bfeaf4825c7b75071 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
#include <activemq/commands/ActiveMQDestination.h>
#include <activemq/util/URISupport.h>
#include <activemq/util/CMSExceptionSupport.h>
#include <activemq/util/AdvisorySupport.h>
#include <activemq/commands/ActiveMQTopic.h>
#include <activemq/commands/ActiveMQQueue.h>
#include <activemq/commands/ActiveMQTempTopic.h>
#include <activemq/commands/ActiveMQTempQueue.h>
#include <decaf/util/StringTokenizer.h>
#include <decaf/util/StlSet.h>
#include <decaf/util/HashCode.h>
#include <decaf/lang/exceptions/NullPointerException.h>
#include <decaf/internal/util/StringUtils.h>
using namespace activemq;
using namespace activemq::util;
using namespace activemq::commands;
using namespace decaf::internal::util;
using namespace decaf::util;
using namespace decaf::lang;
using namespace decaf::lang::exceptions;
////////////////////////////////////////////////////////////////////////////////
const std::string ActiveMQDestination::DEFAULT_ORDERED_TARGET = "coordinator";
const std::string ActiveMQDestination::TEMP_PREFIX = "{TD{";
const std::string ActiveMQDestination::TEMP_POSTFIX = "}TD}";
const std::string ActiveMQDestination::COMPOSITE_SEPARATOR = ",";
const std::string ActiveMQDestination::DestinationFilter::ANY_CHILD = ">";
const std::string ActiveMQDestination::DestinationFilter::ANY_DESCENDENT = "*";
const std::string ActiveMQDestination::QUEUE_QUALIFIED_PREFIX = "queue://";
const std::string ActiveMQDestination::TOPIC_QUALIFIED_PREFIX = "topic://";
const std::string ActiveMQDestination::TEMP_QUEUE_QUALIFED_PREFIX = "temp-queue://";
const std::string ActiveMQDestination::TEMP_TOPIC_QUALIFED_PREFIX = "temp-topic://";
const std::string ActiveMQDestination::TEMP_DESTINATION_NAME_PREFIX = "ID:";
////////////////////////////////////////////////////////////////////////////////
namespace {
const std::string trim(const std::string& input, const std::string& ws = " \t")
{
const size_t beginStr = input.find_first_not_of(ws);
if (beginStr == std::string::npos)
{
// no content
return "";
}
const size_t endStr = input.find_last_not_of(ws);
const size_t range = endStr - beginStr + 1;
return input.substr(beginStr, range);
}
}
////////////////////////////////////////////////////////////////////////////////
ActiveMQDestination::ActiveMQDestination() :
BaseDataStructure(), exclusive(false), ordered(false), advisory(false), compositeDestinations(),
orderedTarget(DEFAULT_ORDERED_TARGET), physicalName(), options(), hashCode() {
}
////////////////////////////////////////////////////////////////////////////////
ActiveMQDestination::ActiveMQDestination(const std::string& physicalName) :
BaseDataStructure(), exclusive(false), ordered(false), advisory(false), compositeDestinations(),
orderedTarget(DEFAULT_ORDERED_TARGET), physicalName(), options(), hashCode() {
this->setPhysicalName(physicalName);
}
////////////////////////////////////////////////////////////////////////////////
ActiveMQDestination::~ActiveMQDestination() throw() {
}
////////////////////////////////////////////////////////////////////////////////
void ActiveMQDestination::setPhysicalName(const std::string& physicalName) {
this->physicalName = physicalName;
size_t pos = physicalName.find_first_of('?');
if (pos != std::string::npos) {
std::string optstring = physicalName.substr(pos + 1);
this->physicalName = physicalName.substr(0, pos);
URISupport::parseQuery(optstring, &options.getProperties());
}
this->advisory = physicalName.find_first_of(AdvisorySupport::ADVISORY_TOPIC_PREFIX) == 0;
this->compositeDestinations.clear();
this->hashCode = HashCode<std::string>()(this->physicalName);
}
////////////////////////////////////////////////////////////////////////////////
void ActiveMQDestination::copyDataStructure(const DataStructure* src) {
// Copy the data of the base class or classes
BaseDataStructure::copyDataStructure( src );
const ActiveMQDestination* srcPtr = dynamic_cast<const ActiveMQDestination*> (src);
if (srcPtr == NULL || src == NULL) {
throw decaf::lang::exceptions::NullPointerException(
__FILE__, __LINE__, "BrokerId::copyDataStructure - src is NULL or invalid");
}
this->setPhysicalName(srcPtr->getPhysicalName());
this->setAdvisory(srcPtr->isAdvisory());
this->setOrdered(srcPtr->isOrdered());
this->setExclusive(srcPtr->isExclusive());
this->setOrderedTarget(srcPtr->getOrderedTarget());
this->options.copy(&srcPtr->getOptions());
}
////////////////////////////////////////////////////////////////////////////////
std::string ActiveMQDestination::toString() const {
switch (this->getDestinationType()) {
case cms::Destination::TOPIC:
return std::string("topic://") + this->getPhysicalName();
case cms::Destination::TEMPORARY_TOPIC:
return std::string("temp-topic://") + this->getPhysicalName();
case cms::Destination::TEMPORARY_QUEUE:
return std::string("temp-queue://") + this->getPhysicalName();
default:
return std::string("queue://") + this->getPhysicalName();
}
}
////////////////////////////////////////////////////////////////////////////////
bool ActiveMQDestination::equals(const DataStructure* value) const {
if (this == value) {
return true;
}
const ActiveMQDestination* valuePtr = dynamic_cast<const ActiveMQDestination*> (value);
if (valuePtr == NULL || value == NULL) {
return false;
}
return this->getPhysicalName() == valuePtr->getPhysicalName();
}
////////////////////////////////////////////////////////////////////////////////
unsigned char ActiveMQDestination::getDataStructureType() const {
return ActiveMQDestination::ID_ACTIVEMQDESTINATION;
}
////////////////////////////////////////////////////////////////////////////////
std::string ActiveMQDestination::getClientId(const ActiveMQDestination* destination) {
std::string answer = "";
if (destination != NULL && destination->isTemporary()) {
std::string name = destination->getPhysicalName();
size_t start = name.find(TEMP_PREFIX);
if (start != std::string::npos) {
start += TEMP_PREFIX.length();
size_t stop = name.rfind(TEMP_POSTFIX);
if (stop > start && stop < name.length()) {
answer = name.substr(start, stop - start);
}
}
}
return answer;
}
////////////////////////////////////////////////////////////////////////////////
Pointer<ActiveMQDestination> ActiveMQDestination::createDestination(int type, const std::string& name) {
Pointer<ActiveMQDestination> result;
if (name.find(QUEUE_QUALIFIED_PREFIX) == 0) {
result.reset(new ActiveMQQueue(name.substr(QUEUE_QUALIFIED_PREFIX.length())));
return result;
} else if (name.find(TOPIC_QUALIFIED_PREFIX) == 0) {
result.reset(new ActiveMQTopic(name.substr(TOPIC_QUALIFIED_PREFIX.length())));
return result;
} else if (name.find(TEMP_QUEUE_QUALIFED_PREFIX) == 0) {
result.reset(new ActiveMQTempQueue(name.substr(TEMP_QUEUE_QUALIFED_PREFIX.length())));
return result;
} else if (name.find(TEMP_TOPIC_QUALIFED_PREFIX) == 0) {
result.reset(new ActiveMQTempTopic(name.substr(TEMP_TOPIC_QUALIFED_PREFIX.length())));
return result;
}
switch (type) {
case cms::Destination::QUEUE:
result.reset(new ActiveMQQueue(name));
return result;
case cms::Destination::TOPIC:
result.reset(new ActiveMQTopic(name));
return result;
case cms::Destination::TEMPORARY_QUEUE:
result.reset(new ActiveMQTempQueue(name));
return result;
case cms::Destination::TEMPORARY_TOPIC:
result.reset(new ActiveMQTempTopic(name));
return result;
default:
throw IllegalArgumentException(
__FILE__, __LINE__, "Invalid default destination type: %d", type);
}
}
////////////////////////////////////////////////////////////////////////////////
std::string ActiveMQDestination::getDestinationTypeAsString() const {
switch (getDestinationType()) {
case cms::Destination::QUEUE:
return "Queue";
case cms::Destination::TOPIC:
return "Topic";
case cms::Destination::TEMPORARY_QUEUE:
return "TempQueue";
case cms::Destination::TEMPORARY_TOPIC:
return "TempTopic";
default:
throw new IllegalArgumentException(
__FILE__, __LINE__, "Invalid destination type: %d", (int) getDestinationType());
}
}
////////////////////////////////////////////////////////////////////////////////
decaf::util::ArrayList< Pointer<ActiveMQDestination> > ActiveMQDestination::getCompositeDestinations() const {
if (!this->compositeDestinations.isEmpty()) {
return this->compositeDestinations;
}
if (this->isComposite()) {
StlSet<std::string> components;
StringTokenizer iter(this->physicalName, ActiveMQDestination::COMPOSITE_SEPARATOR);
while (iter.hasMoreTokens()) {
std::string name = trim(iter.nextToken());
if (name.length() == 0) {
continue;
}
components.add(name);
}
Pointer< Iterator<std::string> > iterator(components.iterator());
while (iterator->hasNext()) {
compositeDestinations.add(createDestination(iterator->next()));
}
}
return this->compositeDestinations;
}
////////////////////////////////////////////////////////////////////////////////
int ActiveMQDestination::compareTo(const ActiveMQDestination& value) const {
if (this == &value) {
return 0;
}
int valueComp = StringUtils::compare(this->getPhysicalName().c_str(), value.getPhysicalName().c_str());
if (valueComp != 0) {
return valueComp;
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
bool ActiveMQDestination::equals(const ActiveMQDestination& value) const {
return this->getPhysicalName() == value.getPhysicalName();
}
////////////////////////////////////////////////////////////////////////////////
bool ActiveMQDestination::operator==(const ActiveMQDestination& value) const {
return this->getPhysicalName() == value.getPhysicalName();
}
////////////////////////////////////////////////////////////////////////////////
bool ActiveMQDestination::operator<(const ActiveMQDestination& value) const {
return this->compareTo(value) < 0;
}