mirror of https://github.com/apache/activemq.git
AMQ-517 - adding activemq-cpp project to support integration of c++ stomp and openwire projects.
git-svn-id: https://svn.apache.org/repos/asf/incubator/activemq/trunk@418749 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
7a853a45bf
commit
be47d4066c
|
@ -0,0 +1,142 @@
|
|||
SRCDIR = src
|
||||
MAKESUPPORT_HOME = $(PWD)
|
||||
|
||||
OFILES = \
|
||||
$(OUTDIR)/main/activemq/exceptions/ActiveMQException.o \
|
||||
\
|
||||
$(OUTDIR)/main/activemq/support/InitDirector.o \
|
||||
\
|
||||
$(OUTDIR)/main/activemq/transport/IOTransport.o \
|
||||
$(OUTDIR)/main/activemq/transport/TcpTransport.o \
|
||||
$(OUTDIR)/main/activemq/transport/ResponseCorrelator.o \
|
||||
$(OUTDIR)/main/activemq/transport/TransportFactoryMap.o \
|
||||
$(OUTDIR)/main/activemq/transport/IOTransportFactory.o \
|
||||
$(OUTDIR)/main/activemq/transport/TcpTransportFactory.o \
|
||||
\
|
||||
$(OUTDIR)/main/activemq/connector/ConnectorFactoryMap.o \
|
||||
\
|
||||
$(OUTDIR)/main/activemq/connector/stomp/StompConnector.o \
|
||||
$(OUTDIR)/main/activemq/connector/stomp/StompConnectorFactory.o \
|
||||
$(OUTDIR)/main/activemq/connector/stomp/StompCommandReader.o \
|
||||
$(OUTDIR)/main/activemq/connector/stomp/StompCommandWriter.o \
|
||||
$(OUTDIR)/main/activemq/connector/stomp/StompSessionManager.o \
|
||||
\
|
||||
$(OUTDIR)/main/activemq/connector/stomp/commands/CommandConstants.o \
|
||||
\
|
||||
$(OUTDIR)/main/activemq/connector/stomp/marshal/Marshaler.o \
|
||||
\
|
||||
$(OUTDIR)/main/activemq/core/ActiveMQConnectionFactory.o \
|
||||
$(OUTDIR)/main/activemq/core/ActiveMQConnection.o \
|
||||
$(OUTDIR)/main/activemq/core/ActiveMQSession.o \
|
||||
$(OUTDIR)/main/activemq/core/ActiveMQProducer.o \
|
||||
$(OUTDIR)/main/activemq/core/ActiveMQConsumer.o \
|
||||
$(OUTDIR)/main/activemq/core/ActiveMQTransaction.o \
|
||||
\
|
||||
$(OUTDIR)/main/activemq/io/EndianReader.o \
|
||||
$(OUTDIR)/main/activemq/io/EndianWriter.o \
|
||||
$(OUTDIR)/main/activemq/io/BufferedInputStream.o \
|
||||
$(OUTDIR)/main/activemq/io/BufferedOutputStream.o \
|
||||
$(OUTDIR)/main/activemq/io/ByteArrayInputStream.o \
|
||||
$(OUTDIR)/main/activemq/io/ByteArrayOutputStream.o \
|
||||
\
|
||||
$(OUTDIR)/main/activemq/logger/SimpleLogger.o \
|
||||
$(OUTDIR)/main/activemq/logger/LogWriter.o \
|
||||
$(OUTDIR)/main/activemq/logger/LogManager.o \
|
||||
$(OUTDIR)/main/activemq/logger/LoggerHierarchy.o \
|
||||
\
|
||||
$(OUTDIR)/main/activemq/network/ServerSocket.o \
|
||||
$(OUTDIR)/main/activemq/network/TcpSocket.o \
|
||||
$(OUTDIR)/main/activemq/network/BufferedSocket.o \
|
||||
$(OUTDIR)/main/activemq/network/SocketFactory.o \
|
||||
$(OUTDIR)/main/activemq/network/SocketInputStream.o \
|
||||
$(OUTDIR)/main/activemq/network/SocketOutputStream.o\
|
||||
\
|
||||
$(OUTDIR)/main/activemq/util/Guid.o \
|
||||
$(OUTDIR)/main/activemq/util/StringTokenizer.o \
|
||||
\
|
||||
$(OUTDIR)/main/activemq/concurrent/Thread.o \
|
||||
$(OUTDIR)/main/activemq/concurrent/Mutex.o \
|
||||
$(OUTDIR)/main/activemq/concurrent/ThreadPool.o \
|
||||
$(OUTDIR)/main/activemq/concurrent/PooledThread.o
|
||||
|
||||
OTESTFILES = \
|
||||
$(OUTDIR)/test/main.o \
|
||||
\
|
||||
$(OUTDIR)/test/activemq/core/ActiveMQConnectionFactoryTest.o \
|
||||
$(OUTDIR)/test/activemq/core/ActiveMQConnectionTest.o \
|
||||
$(OUTDIR)/test/activemq/core/ActiveMQSessionTest.o \
|
||||
\
|
||||
$(OUTDIR)/test/activemq/concurrent/MutexTest.o \
|
||||
$(OUTDIR)/test/activemq/concurrent/ThreadPoolTest.o \
|
||||
$(OUTDIR)/test/activemq/concurrent/ThreadTest.o \
|
||||
\
|
||||
$(OUTDIR)/test/activemq/connector/stomp/StompConnectorTest.o \
|
||||
$(OUTDIR)/test/activemq/connector/stomp/StompFrameTest.o \
|
||||
$(OUTDIR)/test/activemq/connector/stomp/StompCommandReaderTest.o \
|
||||
$(OUTDIR)/test/activemq/connector/stomp/StompCommandWriterTest.o \
|
||||
$(OUTDIR)/test/activemq/connector/stomp/StompSessionManagerTest.o \
|
||||
\
|
||||
$(OUTDIR)/test/activemq/connector/stomp/commands/CommandConstantsTest.o \
|
||||
$(OUTDIR)/test/activemq/connector/stomp/commands/AbortCommandTest.o \
|
||||
$(OUTDIR)/test/activemq/connector/stomp/commands/AckCommandTest.o \
|
||||
$(OUTDIR)/test/activemq/connector/stomp/commands/BeginCommandTest.o \
|
||||
$(OUTDIR)/test/activemq/connector/stomp/commands/CommitCommandTest.o \
|
||||
$(OUTDIR)/test/activemq/connector/stomp/commands/ConnectCommandTest.o \
|
||||
$(OUTDIR)/test/activemq/connector/stomp/commands/ConnectedCommandTest.o \
|
||||
$(OUTDIR)/test/activemq/connector/stomp/commands/DisconnectCommandTest.o \
|
||||
$(OUTDIR)/test/activemq/connector/stomp/commands/ErrorCommandTest.o \
|
||||
$(OUTDIR)/test/activemq/connector/stomp/commands/ReceiptCommandTest.o \
|
||||
$(OUTDIR)/test/activemq/connector/stomp/commands/SubscribeCommandTest.o \
|
||||
$(OUTDIR)/test/activemq/connector/stomp/commands/UnsubscribeCommandTest.o \
|
||||
$(OUTDIR)/test/activemq/connector/stomp/commands/MessageCommandTest.o \
|
||||
$(OUTDIR)/test/activemq/connector/stomp/commands/BytesMessageCommandTest.o \
|
||||
$(OUTDIR)/test/activemq/connector/stomp/commands/TextMessageCommandTest.o \
|
||||
\
|
||||
$(OUTDIR)/test/activemq/connector/stomp/marshal/MarshalerTest.o \
|
||||
\
|
||||
$(OUTDIR)/test/activemq/connector/ConnectorFactoryMapRegistrarTest.o \
|
||||
$(OUTDIR)/test/activemq/connector/ConnectorFactoryMapTest.o \
|
||||
\
|
||||
$(OUTDIR)/test/activemq/exceptions/ActiveMQExceptionTest.o \
|
||||
\
|
||||
$(OUTDIR)/test/activemq/io/BufferedInputStreamTest.o \
|
||||
$(OUTDIR)/test/activemq/io/BufferedOutputStreamTest.o \
|
||||
$(OUTDIR)/test/activemq/io/ByteArrayInputStreamTest.o \
|
||||
$(OUTDIR)/test/activemq/io/ByteArrayOutputStreamTest.o \
|
||||
$(OUTDIR)/test/activemq/io/EndianReaderTest.o \
|
||||
$(OUTDIR)/test/activemq/io/EndianWriterTest.o \
|
||||
\
|
||||
$(OUTDIR)/test/activemq/logger/LoggerTest.o \
|
||||
\
|
||||
$(OUTDIR)/test/activemq/network/SocketFactoryTest.o \
|
||||
$(OUTDIR)/test/activemq/network/SocketTest.o \
|
||||
\
|
||||
$(OUTDIR)/test/activemq/transport/DummyTransportFactory.o \
|
||||
$(OUTDIR)/test/activemq/transport/IOTransportTest.o \
|
||||
$(OUTDIR)/test/activemq/transport/ResponseCorrelatorTest.o \
|
||||
$(OUTDIR)/test/activemq/transport/TransportFactoryMapTest.o \
|
||||
$(OUTDIR)/test/activemq/transport/TransportFactoryMapRegistrarTest.o \
|
||||
\
|
||||
$(OUTDIR)/test/activemq/util/GuidTest.o \
|
||||
$(OUTDIR)/test/activemq/util/IntegerTest.o \
|
||||
$(OUTDIR)/test/activemq/util/LongTest.o \
|
||||
$(OUTDIR)/test/activemq/util/BooleanTest.o \
|
||||
$(OUTDIR)/test/activemq/util/QueueTest.o \
|
||||
$(OUTDIR)/test/activemq/util/StringTokenizerTest.o
|
||||
|
||||
OINTEGRATIONFILES = \
|
||||
$(OUTDIR)/test-integration/main.o \
|
||||
\
|
||||
$(OUTDIR)/test-integration/integration/simple/SimpleTester.o \
|
||||
$(OUTDIR)/test-integration/integration/transactional/TransactionTester.o \
|
||||
$(OUTDIR)/test-integration/integration/common/AbstractTester.o \
|
||||
$(OUTDIR)/test-integration/integration/common/IntegrationCommon.o
|
||||
|
||||
LIBFILE = $(OUTDIR)/activemq.a
|
||||
TESTEXE = $(OUTDIR)/activemqTest
|
||||
INTEGRATIONEXE = $(OUTDIR)/activemqIntegrationTests
|
||||
|
||||
DEFINES =
|
||||
|
||||
include $(MAKESUPPORT_HOME)/makefile.cfg
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#
|
||||
# Compiler specific configuration
|
||||
#
|
||||
|
||||
OUTDIR = out
|
||||
LIBRARY_NAME = activemq-cpp
|
||||
LIBFILE = $(OUTDIR)/lib$(LIBRARY_NAME).a
|
||||
|
||||
#
|
||||
# GCC/G++ debug for Linux
|
||||
#
|
||||
CC = g++ -frtti -g -pthread -DDEBUG -D_DEBUG -D_REENTRANT
|
||||
LD = g++ -g -frtti -pthread
|
||||
CCFLAGS = -Wall
|
||||
LDFLAGS = -L$(OUTDIR) -l$(LIBRARY_NAME) -lcppunit -ldl -luuid
|
||||
ARFLAGS =
|
||||
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# Compiler specific configuration
|
||||
#
|
||||
|
||||
OUTDIR = out
|
||||
LIBRARY_NAME = activemq-cpp
|
||||
LIBFILE = $(OUTDIR)/lib$(LIBRARY_NAME).a
|
||||
|
||||
#
|
||||
# GCC/G++ release for Linux
|
||||
#
|
||||
CC = g++ -frtti -pthread -O3 -DNDEBUG -D_REENTRANT
|
||||
LD = g++ -frtti -pthread
|
||||
CCFLAGS = -Wall
|
||||
LDFLAGS = -L$(OUTDIR) -l$(LIBRARY_NAME) -lcppunit -ldl -luuid
|
||||
OUTDIR = out
|
||||
ARFLAGS =
|
||||
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#
|
||||
# Compiler specific configuration
|
||||
#
|
||||
|
||||
LIBFILE = $(OUTDIR)/libactivemq-cpp.a
|
||||
|
||||
#
|
||||
# GCC/G++ debug for Linux
|
||||
#
|
||||
CC = g++ -fexceptions -frtti -O0 -g3 -DDEBUG -D_DEBUG -D_REENTRANT -D_WIN32 -DWINVER=0x0502 -DWIN32_LEAN_AND_MEAN
|
||||
LD = g++ -g3 -frtti
|
||||
CCFLAGS = -Wall
|
||||
LDFLAGS = -L$(OUTDIR) -lactivemq -lcppunit -lws2_32 -lrpcrt4
|
||||
OUTDIR = out
|
||||
ARFLAGS =
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
#
|
||||
# Compiler specific configuration
|
||||
#
|
||||
|
||||
LIBFILE = $(OUTDIR)/libactivemq-cpp.a
|
||||
|
||||
#
|
||||
# GCC/G++ release for Linux
|
||||
#
|
||||
CC = g++ -fexceptions -frtti -O3 -DNDEBUG -D_REENTRANT -D__WIN32 -DWIN32_LEAN_AND_MEAN
|
||||
LD = g++ -frtti
|
||||
CCFLAGS = -Wall
|
||||
LDFLAGS = -L$(OUTDIR) -lactivemq -lcppunit -lws2_32 -lrpcrt4
|
||||
OUTDIR = out
|
||||
ARFLAGS =
|
||||
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
CURRENT = $(PWD)
|
||||
|
||||
# --- select compiler for structure
|
||||
# ----------------------------------------------------------
|
||||
|
||||
include $(MAKESUPPORT_HOME)/makefile-$(OSTYPE)-$(CONFIG).cfg
|
||||
|
||||
# --- set generic commmands
|
||||
# ----------------------------------------------------------
|
||||
|
||||
MV = mv
|
||||
RM = rm -f
|
||||
RMR = rm -rf
|
||||
CP = cp -p
|
||||
LN = ln -s
|
||||
LS = ls
|
||||
CAT = cat
|
||||
MD = mkdir
|
||||
AR = ar -r
|
||||
PURIFY = purify
|
||||
ECHO = echo
|
||||
TOUCH = touch
|
||||
CD = cd
|
||||
STRIP = strip
|
||||
|
||||
# --- set default targets and their handling procedures
|
||||
# ----------------------------------------------------------
|
||||
|
||||
.SILENT:
|
||||
.KEEP_STATE:
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .cpp .CC
|
||||
|
||||
.INIT:
|
||||
$(ECHO) " -<>- Compiling "$(CURRENT)
|
||||
|
||||
.DONE:
|
||||
$(ECHO) " -<>- Done"
|
||||
|
||||
.FAILED:
|
||||
$(ECHO) " *** Compilation of $(CURRENT) Failed"
|
||||
|
||||
$(OUTDIR)/main/%.o: $(SRCDIR)/main/%.cpp
|
||||
$(ECHO) " - "$(CC) "'"$<"'"
|
||||
$(CC) -o $@ $(DEFINES) $(CCFLAGS) -I$(SRCDIR)/main \
|
||||
$(LOCAL_INCLUDE) -c $<
|
||||
|
||||
$(OUTDIR)/test/%.o: $(SRCDIR)/test/%.cpp
|
||||
$(ECHO) " - "$(CC) "'"$<"'"
|
||||
$(CC) -o $@ $(DEFINES) $(CCFLAGS) -I$(SRCDIR)/main -I$(SRCDIR)/test \
|
||||
$(LOCAL_INCLUDE) -c $<
|
||||
|
||||
$(OUTDIR)/test-integration/%.o: $(SRCDIR)/test-integration/%.cpp
|
||||
$(ECHO) " - "$(CC) "'"$<"'"
|
||||
$(CC) -o $@ $(DEFINES) $(CCFLAGS) -I$(SRCDIR)/main -I$(SRCDIR)/test-integration \
|
||||
$(LOCAL_INCLUDE) -c $<
|
||||
|
||||
# --- set generic targets and their handling procedures
|
||||
# ----------------------------------------------------------
|
||||
|
||||
lib: \
|
||||
prepare \
|
||||
$(OFILES) \
|
||||
$(LIBFILE) \
|
||||
done
|
||||
|
||||
test: \
|
||||
prepare_test \
|
||||
$(OTESTFILES) \
|
||||
$(TESTEXE) \
|
||||
done
|
||||
|
||||
integration: \
|
||||
prepare_integration \
|
||||
$(OINTEGRATIONFILES) \
|
||||
$(INTEGRATIONEXE) \
|
||||
done
|
||||
|
||||
all: lib test integration
|
||||
|
||||
default: all
|
||||
|
||||
|
||||
$(LIBFILE): $(OFILES) $(DEPLIBS)
|
||||
$(ECHO) " - Creating static library file "$@
|
||||
$(AR) $(ARFLAGS) $@ $(OFILES)
|
||||
|
||||
$(TESTEXE): $(OTESTFILES)
|
||||
$(LD) -o $@ $(OTESTFILES) $(LDFLAGS)
|
||||
$(ECHO) 'Finished building target: $@'
|
||||
|
||||
$(INTEGRATIONEXE): $(OINTEGRATIONFILES)
|
||||
$(LD) -o $@ $(OINTEGRATIONFILES) $(LDFLAGS)
|
||||
$(ECHO) 'Finished building target: $@'
|
||||
|
||||
clean:
|
||||
$(ECHO) " - Cleaning up local directory "$(CURRENT)
|
||||
$(ECHO) " - Removing object files"
|
||||
$(RM) $(OFILES)
|
||||
$(ECHO) " - Removing file "$(LIBFILE)
|
||||
$(RM) -rf $(OUTDIR)
|
||||
$(RM) $(LIBFILE)
|
||||
$(RM) *~ *%
|
||||
$(RM) #*
|
||||
$(RM) core
|
||||
$(RM) a.out
|
||||
|
||||
prepare:
|
||||
if test ! -d $(OUTDIR) ; \
|
||||
then \
|
||||
$(MD) $(OUTDIR); \
|
||||
$(MD) $(OUTDIR)/main; \
|
||||
$(MD) $(OUTDIR)/main/activemq; \
|
||||
$(MD) $(OUTDIR)/main/activemq/exceptions; \
|
||||
$(MD) $(OUTDIR)/main/activemq/commands; \
|
||||
$(MD) $(OUTDIR)/main/activemq/connector; \
|
||||
$(MD) $(OUTDIR)/main/activemq/connector/stomp; \
|
||||
$(MD) $(OUTDIR)/main/activemq/connector/stomp/commands; \
|
||||
$(MD) $(OUTDIR)/main/activemq/connector/stomp/marshal; \
|
||||
$(MD) $(OUTDIR)/main/activemq/core; \
|
||||
$(MD) $(OUTDIR)/main/activemq/io; \
|
||||
$(MD) $(OUTDIR)/main/activemq/logger; \
|
||||
$(MD) $(OUTDIR)/main/activemq/network; \
|
||||
$(MD) $(OUTDIR)/main/activemq/util; \
|
||||
$(MD) $(OUTDIR)/main/activemq/support; \
|
||||
$(MD) $(OUTDIR)/main/activemq/concurrent; \
|
||||
$(MD) $(OUTDIR)/main/activemq/transport; \
|
||||
fi
|
||||
|
||||
prepare_test:
|
||||
if test ! -d $(OUTDIR) ; \
|
||||
then \
|
||||
$(MD) $(OUTDIR); \
|
||||
fi
|
||||
if test ! -d $(OUTDIR)/test ; \
|
||||
then \
|
||||
$(MD) $(OUTDIR)/test; \
|
||||
$(MD) $(OUTDIR)/test/activemq; \
|
||||
$(MD) $(OUTDIR)/test/activemq/exceptions; \
|
||||
$(MD) $(OUTDIR)/test/activemq/commands; \
|
||||
$(MD) $(OUTDIR)/test/activemq/connector; \
|
||||
$(MD) $(OUTDIR)/test/activemq/connector/stomp; \
|
||||
$(MD) $(OUTDIR)/test/activemq/connector/stomp/commands; \
|
||||
$(MD) $(OUTDIR)/test/activemq/connector/stomp/marshal; \
|
||||
$(MD) $(OUTDIR)/test/activemq/core; \
|
||||
$(MD) $(OUTDIR)/test/activemq/io; \
|
||||
$(MD) $(OUTDIR)/test/activemq/logger; \
|
||||
$(MD) $(OUTDIR)/test/activemq/network; \
|
||||
$(MD) $(OUTDIR)/test/activemq/util; \
|
||||
$(MD) $(OUTDIR)/test/activemq/concurrent; \
|
||||
$(MD) $(OUTDIR)/test/activemq/transport; \
|
||||
fi
|
||||
|
||||
prepare_integration:
|
||||
if test ! -d $(OUTDIR) ; \
|
||||
then \
|
||||
$(MD) $(OUTDIR); \
|
||||
fi
|
||||
if test ! -d $(OUTDIR)/test-integration ; \
|
||||
then \
|
||||
$(MD) $(OUTDIR)/test-integration; \
|
||||
$(MD) $(OUTDIR)/test-integration/integration; \
|
||||
$(MD) $(OUTDIR)/test-integration/integration/common; \
|
||||
$(MD) $(OUTDIR)/test-integration/integration/simple; \
|
||||
$(MD) $(OUTDIR)/test-integration/integration/transactional; \
|
||||
$(MD) $(OUTDIR)/test-integration/integration/durable; \
|
||||
fi
|
||||
|
||||
done:
|
||||
$(ECHO) "Done."
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,228 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>activemq</groupId>
|
||||
<name>ActiveMQ :: CPP :: Parent</name>
|
||||
<artifactId>activemq-cpp-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<!-- these should be deleted when using a parent pom-->
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
||||
<!-- configure the Mojo native plugin -->
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>native-maven-plugin</artifactId>
|
||||
<version>1.0-alpha-1-SNAPSHOT</version>
|
||||
<extensions>true</extensions>
|
||||
|
||||
<!-- Make child POMs inherit this configuration -->
|
||||
<inherited>true</inherited>
|
||||
|
||||
<configuration>
|
||||
|
||||
<!-- All compiler flags are determined by the profile -->
|
||||
<compilerProvider>${compiler.provider}</compilerProvider>
|
||||
<envFactoryName>${env.factory.name}</envFactoryName>
|
||||
<compilerStartOptions>
|
||||
<compilerStartOption>${compiler.options}</compilerStartOption>
|
||||
</compilerStartOptions>
|
||||
<linkerExecutable>${linker.executable}</linkerExecutable>
|
||||
<linkerStartOptions>
|
||||
<linkerStartOption>${linker.options}</linkerStartOption>
|
||||
</linkerStartOptions>
|
||||
|
||||
<!-- Define the sources for the library build -->
|
||||
<sources>
|
||||
|
||||
<!-- Standard include directories -->
|
||||
<source><directory>../src/main</directory></source>
|
||||
<source><directory>../src/test</directory></source>
|
||||
|
||||
<source>
|
||||
<directory>../src/main/activemq/concurrent</directory>
|
||||
<fileNames>
|
||||
<fileName>Mutex.cpp</fileName>
|
||||
<fileName>PooledThread.cpp</fileName>
|
||||
<fileName>Thread.cpp</fileName>
|
||||
<fileName>ThreadPool.cpp</fileName>
|
||||
</fileNames>
|
||||
</source>
|
||||
<source>
|
||||
<directory>../src/main/activemq/connector</directory>
|
||||
<fileNames>
|
||||
<fileName>ConnectorFactoryMap.cpp</fileName>
|
||||
</fileNames>
|
||||
</source>
|
||||
<source>
|
||||
<directory>../src/main/activemq/connector/stomp</directory>
|
||||
<fileNames>
|
||||
<fileName>StompCommandReader.cpp</fileName>
|
||||
<fileName>StompCommandWriter.cpp</fileName>
|
||||
<fileName>StompConnector.cpp</fileName>
|
||||
<fileName>StompConnectorFactory.cpp</fileName>
|
||||
<fileName>StompSessionManager.cpp</fileName>
|
||||
</fileNames>
|
||||
</source>
|
||||
<source>
|
||||
<directory>../src/main/activemq/connector/stomp/commands</directory>
|
||||
<fileNames>
|
||||
<fileName>CommandConstants.cpp</fileName>
|
||||
</fileNames>
|
||||
</source>
|
||||
<source>
|
||||
<directory>../src/main/activemq/connector/stomp/marshal</directory>
|
||||
<fileNames>
|
||||
<fileName>Marshaler.cpp</fileName>
|
||||
</fileNames>
|
||||
</source>
|
||||
<source>
|
||||
<directory>../src/main/activemq/core</directory>
|
||||
<fileNames>
|
||||
<fileName>ActiveMQConnection.cpp</fileName>
|
||||
<fileName>ActiveMQConnectionFactory.cpp</fileName>
|
||||
<fileName>ActiveMQConsumer.cpp</fileName>
|
||||
<fileName>ActiveMQProducer.cpp</fileName>
|
||||
<fileName>ActiveMQSession.cpp</fileName>
|
||||
<fileName>ActiveMQTransaction.cpp</fileName>
|
||||
</fileNames>
|
||||
</source>
|
||||
<source>
|
||||
<directory>../src/main/activemq/exceptions</directory>
|
||||
<fileNames>
|
||||
<fileName>ActiveMQException.cpp</fileName>
|
||||
</fileNames>
|
||||
</source>
|
||||
<source>
|
||||
<directory>../src/main/activemq/io</directory>
|
||||
<fileNames>
|
||||
<fileName>BufferedInputStream.cpp</fileName>
|
||||
<fileName>BufferedOutputStream.cpp</fileName>
|
||||
<fileName>ByteArrayInputStream.cpp</fileName>
|
||||
<fileName>ByteArrayOutputStream.cpp</fileName>
|
||||
<fileName>EndianReader.cpp</fileName>
|
||||
<fileName>EndianWriter.cpp</fileName>
|
||||
</fileNames>
|
||||
</source>
|
||||
<source>
|
||||
<directory>../src/main/activemq/logger</directory>
|
||||
<fileNames>
|
||||
<fileName>Logger.cpp</fileName>
|
||||
<fileName>LoggerHierarchy.cpp</fileName>
|
||||
<fileName>LogManager.cpp</fileName>
|
||||
<fileName>LogWriter.cpp</fileName>
|
||||
<fileName>SimpleLogger.cpp</fileName>
|
||||
</fileNames>
|
||||
</source>
|
||||
<source>
|
||||
<directory>../src/main/activemq/network</directory>
|
||||
<fileNames>
|
||||
<fileName>BufferedSocket.cpp</fileName>
|
||||
<fileName>ServerSocket.cpp</fileName>
|
||||
<fileName>SocketFactory.cpp</fileName>
|
||||
<fileName>SocketInputStream.cpp</fileName>
|
||||
<fileName>SocketOutputStream.cpp</fileName>
|
||||
<fileName>TcpSocket.cpp</fileName>
|
||||
</fileNames>
|
||||
</source>
|
||||
<source>
|
||||
<directory>../src/main/activemq/support</directory>
|
||||
<fileNames>
|
||||
<fileName>InitDirector.cpp</fileName>
|
||||
</fileNames>
|
||||
</source>
|
||||
<source>
|
||||
<directory>../src/main/activemq/transport</directory>
|
||||
<fileNames>
|
||||
<fileName>IOTransport.cpp</fileName>
|
||||
<fileName>IOTransportFactory.cpp</fileName>
|
||||
<fileName>ResponseCorrelator.cpp</fileName>
|
||||
<fileName>TcpTransport.cpp</fileName>
|
||||
<fileName>TcpTransportFactory.cpp</fileName>
|
||||
<fileName>TransportFactoryMap.cpp</fileName>
|
||||
</fileNames>
|
||||
</source>
|
||||
<source>
|
||||
<directory>../src/main/activemq/util</directory>
|
||||
<fileNames>
|
||||
<fileName>Guid.cpp</fileName>
|
||||
<fileName>StringTokenizer.cpp</fileName>
|
||||
</fileNames>
|
||||
</source>
|
||||
</sources>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
|
||||
<!-- Default profile for Windows: MSVC compiler -->
|
||||
<profile>
|
||||
<id>win32-msvc</id>
|
||||
<activation>
|
||||
<os>
|
||||
<family>windows</family>
|
||||
</os>
|
||||
</activation>
|
||||
<modules>
|
||||
<module>win32-msvc</module>
|
||||
</modules>
|
||||
</profile>
|
||||
|
||||
<!-- Profile for building on windows (cygwin) with gcc -->
|
||||
<profile>
|
||||
<id>win32-gcc</id>
|
||||
<modules>
|
||||
<module>win32-gcc</module>
|
||||
</modules>
|
||||
</profile>
|
||||
|
||||
<!-- Profile for building on *nix with the default compiler -->
|
||||
<profile>
|
||||
<id>unix</id>
|
||||
<activation>
|
||||
<os>
|
||||
<family>unix</family>
|
||||
</os>
|
||||
</activation>
|
||||
<modules>
|
||||
<module>unix</module>
|
||||
</modules>
|
||||
</profile>
|
||||
|
||||
</profiles>
|
||||
|
||||
<!-- Repos for using the mojo native plugin -->
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>Maven Snapshots</id>
|
||||
<url>http://snapshots.maven.codehaus.org/maven2/</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>Maven Snapshots</id>
|
||||
<url>http://snapshots.maven.codehaus.org/maven2/</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
</project>
|
|
@ -0,0 +1,109 @@
|
|||
--------------------------------------------------------------------------
|
||||
ActiveMQ CPP Library - Version 0.0.1
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
This library provides a JMS like interface to an ActiveMQ broker in c++.
|
||||
|
||||
Currently the Library only supports the Stomp protocol, future versions
|
||||
will contain support for openwire.
|
||||
|
||||
UNIT Tests
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
The package contains a complete set of cppunit tests. In order for you
|
||||
to build an run the tests, you will need to download and install the
|
||||
cppunit suite.
|
||||
|
||||
http://cppunit.sourceforge.net/cppunit-wiki
|
||||
|
||||
or on Fedora type
|
||||
|
||||
yum install cppunit*
|
||||
|
||||
Make sure that the path to the installed cpp unit library and includes is
|
||||
visible in your current shell before you try building the tets.
|
||||
|
||||
Integration Tests
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
The library also contains a set of tests that are run against a real AMQ
|
||||
broker. Running these without a broker will result in failed tests.
|
||||
The tests currently hardcode the broker url to be tcp://127.0.0.1:61613,
|
||||
you can change this by changing the declaration in IntegrationCommon.cpp
|
||||
in the test-integration src tree.
|
||||
|
||||
Notes for Windows users
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
The builds support using the GNU compiler on Windows, we used the MinGW
|
||||
package. There is an issues still outstanding with this in that the sockets
|
||||
break for no reason when built this way. We therefore suggest that you
|
||||
stick with using the MSVC compiler when on windows.
|
||||
|
||||
There are a couple or things that you will need to setup to ensure that the
|
||||
MSVC compile succeeds.
|
||||
|
||||
* You need to download and install the Platform SDK if you don't have it
|
||||
installed already.
|
||||
* Ensure that the path to you MSVC install is set in the PATH env variable.
|
||||
you can tests this buy typing cl.exe at the command line, if you get an
|
||||
error complaining that its not found, then setup you PATH correctly.
|
||||
* Set the INCLUDE env variable to include the path to your MSVC includes,
|
||||
and the platform SDK includes.
|
||||
|
||||
i.e. INCLUDE = D:\Program Files\Microsoft Visual Studio 8\VC\include;D:\Program Files\Microsoft Platform SDK\Include
|
||||
|
||||
* Set the LIB env variable to include the path to your MSVC libs, and the
|
||||
Platform SDK libs.
|
||||
|
||||
i.e. LIB = D:\Program Files\Microsoft Visual Studio 8\VC\lib;D:\Program Files\Microsoft Platform SDK\Lib
|
||||
|
||||
Maven Builds
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
The pacakge currently supports building the library only using maven.
|
||||
|
||||
The Mojo Native plugin (from the MOJO maven plugins site) is required.
|
||||
|
||||
http://mojo.codehaus.org/maven-native/native-maven-plugin/introduction.html
|
||||
|
||||
On the windows platform is was necessay to download the source for this
|
||||
plugin and build it locally, this shouldn't be necessary on non-windows
|
||||
platforms, but if you have problems, try that first.
|
||||
|
||||
You can get the latest source via subversion:
|
||||
|
||||
svn co https://svn.codehaus.org/mojo/trunk/mojo/maven-native
|
||||
|
||||
Once you have downloaded the source, install the plugin into your local
|
||||
repository via: mvn install
|
||||
|
||||
Using Maven with activemq-cpp
|
||||
|
||||
* type mvn package
|
||||
|
||||
This will build the library using the default target for the platform
|
||||
you are on, which is release, and the gnu compiler for unix platforms, or
|
||||
the MSVC compiler on windows platforms.
|
||||
|
||||
Makefile Builds
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
The Makefile provided requires some env variable to be set
|
||||
|
||||
OSTYPE: This is the OS you are on and is reflected in the names of the
|
||||
makefiles. Currently your choices are Linux or Windows, both use
|
||||
the GNU compiler.
|
||||
|
||||
CONFIG: This is the build Mode you want to execute, i.e. debug or release.
|
||||
|
||||
MAKESUPPORT_HOME: Path to the folder where the Makefiles are stored.
|
||||
|
||||
There are three targets available in the Makefile, lib, test, and integration
|
||||
whose output is fairly obvious.
|
||||
|
||||
Using the Makefile:
|
||||
|
||||
* type make to build all targets: lib, tests and integration
|
||||
* type make < Target Name > to build only the target you need.
|
||||
* type make clean to remove all of the object, library, and executable files.
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef _ACTIVEMQ_CONCURRENT_CONCURRENT_H_
|
||||
#define _ACTIVEMQ_CONCURRENT_CONCURRENT_H_
|
||||
|
||||
#include <activemq/concurrent/Lock.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace concurrent{
|
||||
|
||||
/**
|
||||
* The synchronized macro defines a mechanism for snycronizing
|
||||
* a scetion of code. The macro must be passed an object that
|
||||
* implements the Syncronizable interface.
|
||||
*
|
||||
* The macro works by creating a for loop that will loop exactly
|
||||
* once, creating a Lock object that is scoped to the loop. Once
|
||||
* the loop conpletes and exits the Lock object goes out of scope
|
||||
* releasing the lock on object W. For added safety the if else
|
||||
* is used because not all compiles restrict the lifetime of
|
||||
* loop variables to the loop, they will however restrict them
|
||||
* to the scope of the else.
|
||||
*
|
||||
* The macro would be used as follows.
|
||||
*
|
||||
* <Syncronizable> X;
|
||||
*
|
||||
* somefunction()
|
||||
* {
|
||||
* syncronized(X)
|
||||
* {
|
||||
* // Do something that needs syncronizing.
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
|
||||
#define WAIT_INFINITE 0xFFFFFFFF
|
||||
|
||||
#define synchronized(W) \
|
||||
if(false){} \
|
||||
else \
|
||||
for(activemq::concurrent::Lock lock_W(W); \
|
||||
lock_W.isLocked(); lock_W.unlock())
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONCURRENT_CONCURRENT_H_*/
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef ACTIVEMQ_CONCURRENT_LOCK_H
|
||||
#define ACTIVEMQ_CONCURRENT_LOCK_H
|
||||
|
||||
// Includes.
|
||||
#include <activemq/concurrent/Synchronizable.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace concurrent{
|
||||
|
||||
/**
|
||||
* A wrapper class around a given synchronization mechanism that
|
||||
* provides automatic release upon destruction.
|
||||
* @author Nathan Mittler
|
||||
*/
|
||||
class Lock
|
||||
{
|
||||
private: // Data
|
||||
|
||||
/**
|
||||
* Flag to indicate whether or not this object has locked the
|
||||
* sync object.
|
||||
*/
|
||||
bool locked;
|
||||
|
||||
/**
|
||||
* The synchronizable object to lock/unlock.
|
||||
*/
|
||||
Synchronizable* syncObject;
|
||||
|
||||
public: // Interface
|
||||
|
||||
/**
|
||||
* Constructor - initializes the object member and locks
|
||||
* the object if desired.
|
||||
* @param object The sync object to control
|
||||
* @param intiallyLocked If true, the object will automatically
|
||||
* be locked.
|
||||
*/
|
||||
Lock( Synchronizable* object, const bool intiallyLocked = true )
|
||||
{
|
||||
try{
|
||||
syncObject = object;
|
||||
locked = false;
|
||||
|
||||
if( intiallyLocked )
|
||||
{
|
||||
lock();
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( exceptions::ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( exceptions::ActiveMQException )
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor - Unlocks the object if it is locked.
|
||||
*/
|
||||
virtual ~Lock()
|
||||
{
|
||||
try{
|
||||
if( locked )
|
||||
{
|
||||
syncObject->unlock();
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( exceptions::ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( exceptions::ActiveMQException )
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks the object.
|
||||
*/
|
||||
void lock()
|
||||
{
|
||||
try{
|
||||
syncObject->lock();
|
||||
locked = true;
|
||||
}
|
||||
AMQ_CATCH_RETHROW( exceptions::ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( exceptions::ActiveMQException )
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks the object.
|
||||
*/
|
||||
void unlock()
|
||||
{
|
||||
try{
|
||||
if(locked)
|
||||
{
|
||||
syncObject->unlock();
|
||||
locked = false;
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( exceptions::ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( exceptions::ActiveMQException )
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether or not the object is locked.
|
||||
* @return true if the object is locked, otherwise false.
|
||||
*/
|
||||
bool isLocked() const{ return locked; }
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif // ACTIVEMQ_CONCURRENT_LOCK_H
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#include <activemq/concurrent/Mutex.h>
|
||||
|
||||
using namespace activemq::concurrent;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,358 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef ACTIVEMQ_CONCURRENT_MUTEX_H
|
||||
#define ACTIVEMQ_CONCURRENT_MUTEX_H
|
||||
|
||||
// Includes.
|
||||
#include <activemq/concurrent/Synchronizable.h>
|
||||
#include <activemq/concurrent/Concurrent.h>
|
||||
#include <activemq/concurrent/Thread.h>
|
||||
#include <list>
|
||||
|
||||
#if (defined(__unix__) || defined(unix) || defined(MACOSX)) && !defined(USG)
|
||||
#ifndef unix
|
||||
#define unix
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) || defined(__CYGWIN__) && !defined unix
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#if ( !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0400)
|
||||
#if ( !defined(WINVER) || WINVER < 0x0400)
|
||||
#pragma message ("Unsupported platform, Windows NT 4.0 or later required")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace concurrent{
|
||||
|
||||
/**
|
||||
* Creates a pthread_mutex_t object. The object is created
|
||||
* such that successive locks from the same thread is allowed
|
||||
* and will be successful.
|
||||
* @see pthread_mutex_t
|
||||
*/
|
||||
class Mutex : public Synchronizable
|
||||
{
|
||||
private: // Data
|
||||
|
||||
/**
|
||||
* The mutex object.
|
||||
*/
|
||||
#ifdef unix
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
std::list<pthread_cond_t*> eventQ;
|
||||
#else
|
||||
CRITICAL_SECTION mutex;
|
||||
|
||||
std::list<HANDLE> eventQ;
|
||||
#endif
|
||||
|
||||
// Lock Status Members
|
||||
int lock_count;
|
||||
unsigned long lock_owner;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor - creates and initializes the mutex.
|
||||
*/
|
||||
Mutex()
|
||||
{
|
||||
#ifdef unix
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutex_init(&mutex, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
#else
|
||||
InitializeCriticalSection(&mutex);
|
||||
#endif
|
||||
|
||||
lock_owner = 0;
|
||||
lock_count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor - destroys the mutex object.
|
||||
*/
|
||||
virtual ~Mutex()
|
||||
{
|
||||
// Unlock the mutex.
|
||||
unlock();
|
||||
|
||||
#ifdef unix
|
||||
pthread_mutex_destroy(&mutex);
|
||||
#else
|
||||
DeleteCriticalSection(&mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks the object.
|
||||
*/
|
||||
virtual void lock() throw( exceptions::ActiveMQException )
|
||||
{
|
||||
if(isLockOwner())
|
||||
{
|
||||
lock_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef unix
|
||||
pthread_mutex_lock(&mutex);
|
||||
#else
|
||||
EnterCriticalSection(&mutex);
|
||||
#endif
|
||||
|
||||
lock_count = 1;
|
||||
lock_owner = Thread::getId();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks the object.
|
||||
*/
|
||||
virtual void unlock() throw( exceptions::ActiveMQException )
|
||||
{
|
||||
if(lock_owner == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(!isLockOwner())
|
||||
{
|
||||
throw exceptions::ActiveMQException(
|
||||
__FILE__, __LINE__,
|
||||
"Mutex::unlock - Failed, not Lock Owner!" );
|
||||
}
|
||||
|
||||
lock_count--;
|
||||
|
||||
if(lock_count == 0)
|
||||
{
|
||||
lock_owner = 0;
|
||||
|
||||
#ifdef unix
|
||||
pthread_mutex_unlock(&mutex);
|
||||
#else
|
||||
LeaveCriticalSection(&mutex);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits on a signal from this object, which is generated
|
||||
* by a call to Notify.
|
||||
*/
|
||||
virtual void wait() throw( exceptions::ActiveMQException )
|
||||
{
|
||||
// Delegate to the timed version
|
||||
wait( WAIT_INFINITE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits on a signal from this object, which is generated
|
||||
* by a call to Notify. Must have this object locked before
|
||||
* calling. This wait will timeout after the specified time
|
||||
* interval.
|
||||
*/
|
||||
virtual void wait( unsigned long millisecs )
|
||||
throw( exceptions::ActiveMQException )
|
||||
{
|
||||
if(!isLockOwner())
|
||||
{
|
||||
throw exceptions::ActiveMQException(
|
||||
__FILE__, __LINE__,
|
||||
"Mutex::wait - Failed, not Lock Owner!");
|
||||
}
|
||||
|
||||
// Save the current owner and Lock count as we are going to
|
||||
// unlock and release for someone else to lock on potentially.
|
||||
// When we come back and re-lock we want to restore to the
|
||||
// state we were in before.
|
||||
unsigned long lock_owner = this->lock_owner;
|
||||
int lock_count = this->lock_count;
|
||||
|
||||
this->lock_count = 0;
|
||||
this->lock_owner = 0;
|
||||
|
||||
#ifdef unix
|
||||
|
||||
// Create this threads wait event
|
||||
pthread_cond_t waitEvent;
|
||||
pthread_cond_init(&waitEvent, NULL);
|
||||
|
||||
// Store the event in the queue so that a notify can
|
||||
// call it and wake up the thread.
|
||||
eventQ.push_back(&waitEvent);
|
||||
|
||||
int returnValue = 0;
|
||||
if(millisecs != WAIT_INFINITE)
|
||||
{
|
||||
timeval now = {};
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
timespec wait = {};
|
||||
wait.tv_sec = now.tv_sec + (millisecs / 1000);
|
||||
wait.tv_nsec = (now.tv_usec * 1000) + ((millisecs % 1000) * 1000000);
|
||||
|
||||
if(wait.tv_nsec > 1000000000)
|
||||
{
|
||||
wait.tv_sec++;
|
||||
wait.tv_nsec -= 1000000000;
|
||||
}
|
||||
|
||||
returnValue = pthread_cond_timedwait(&waitEvent, &mutex, &wait);
|
||||
}
|
||||
else
|
||||
{
|
||||
returnValue = pthread_cond_wait(&waitEvent, &mutex);
|
||||
}
|
||||
|
||||
// If the wait did not succeed for any reason, remove it
|
||||
// from the queue.
|
||||
if( returnValue != 0 ){
|
||||
std::list<pthread_cond_t*>::iterator iter = eventQ.begin();
|
||||
for( ; iter != eventQ.end(); ++iter ){
|
||||
if( *iter == &waitEvent ){
|
||||
eventQ.erase(iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy our wait event now, the notify method will have removed it
|
||||
// from the event queue.
|
||||
pthread_cond_destroy(&waitEvent);
|
||||
|
||||
#else
|
||||
|
||||
// Create the event to wait on
|
||||
HANDLE waitEvent = CreateEvent( NULL, false, false, NULL );
|
||||
|
||||
if(waitEvent == NULL)
|
||||
{
|
||||
throw exceptions::ActiveMQException(
|
||||
__FILE__, __LINE__,
|
||||
"Mutex::Mutex - Failed Creating Event." );
|
||||
}
|
||||
|
||||
eventQ.push_back( waitEvent );
|
||||
|
||||
// Release the Lock
|
||||
LeaveCriticalSection( &mutex );
|
||||
|
||||
// Wait for a signal
|
||||
WaitForSingleObject( waitEvent, millisecs );
|
||||
|
||||
// Reaquire the Lock
|
||||
EnterCriticalSection( &mutex );
|
||||
|
||||
// Clean up the event, the notif methods will have
|
||||
// already poped it from the queue.
|
||||
CloseHandle( waitEvent );
|
||||
|
||||
#endif
|
||||
|
||||
// restore the owner
|
||||
this->lock_owner = lock_owner;
|
||||
this->lock_count = lock_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals a waiter on this object that it can now wake
|
||||
* up and continue.
|
||||
*/
|
||||
virtual void notify() throw( exceptions::ActiveMQException )
|
||||
{
|
||||
if( !isLockOwner() )
|
||||
{
|
||||
throw exceptions::ActiveMQException(
|
||||
__FILE__, __LINE__,
|
||||
"Mutex::Notify - Failed, not Lock Owner!" );
|
||||
}
|
||||
|
||||
if( !eventQ.empty() )
|
||||
{
|
||||
#ifdef unix
|
||||
pthread_cond_signal( eventQ.front() );
|
||||
eventQ.pop_front();
|
||||
#else
|
||||
SetEvent( eventQ.front() );
|
||||
eventQ.pop_front();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals the waiters on this object that it can now wake
|
||||
* up and continue.
|
||||
*/
|
||||
virtual void notifyAll() throw( exceptions::ActiveMQException )
|
||||
{
|
||||
if(!isLockOwner())
|
||||
{
|
||||
throw exceptions::ActiveMQException(
|
||||
__FILE__, __LINE__,
|
||||
"Mutex::NotifyAll - Failed, not Lock Owner!" );
|
||||
}
|
||||
|
||||
#ifdef unix
|
||||
|
||||
while(!eventQ.empty())
|
||||
{
|
||||
pthread_cond_signal( eventQ.front() );
|
||||
eventQ.pop_front();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
while(!eventQ.empty())
|
||||
{
|
||||
SetEvent( eventQ.front() );
|
||||
eventQ.pop_front();
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Check if the calling thread is the Lock Owner
|
||||
*/
|
||||
bool isLockOwner()
|
||||
{
|
||||
return lock_owner == Thread::getId();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif // ACTIVEMQ_CONCURRENT_MUTEX_H
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#include <activemq/concurrent/PooledThread.h>
|
||||
#include <activemq/concurrent/ThreadPool.h>
|
||||
#include <activemq/concurrent/TaskListener.h>
|
||||
#include <activemq/exceptions/IllegalArgumentException.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace activemq;
|
||||
using namespace activemq::concurrent;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
LOGCMS_INITIALIZE(logger, PooledThread, "com.activemq.concurrent.PooledThread");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
PooledThread::PooledThread(ThreadPool* pool)
|
||||
{
|
||||
if(pool == NULL)
|
||||
{
|
||||
throw exceptions::IllegalArgumentException( __FILE__, __LINE__,
|
||||
"PooledThread::PooledThread");
|
||||
}
|
||||
|
||||
busy = false;
|
||||
done = false;
|
||||
|
||||
listener = NULL;
|
||||
|
||||
// Store our Pool.
|
||||
this->pool = pool;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
PooledThread::~PooledThread()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void PooledThread::run(void)
|
||||
{
|
||||
ThreadPool::Task task;
|
||||
|
||||
try
|
||||
{
|
||||
while(!done)
|
||||
{
|
||||
//LOGCMS_DEBUG(logger, "PooledThread::run - Entering deQ");
|
||||
|
||||
// Blocks until there something to be done
|
||||
task = pool->deQueueTask();
|
||||
|
||||
//LOGCMS_DEBUG(logger, "PooledThread::run - Exited deQ");
|
||||
|
||||
// Check if the Done Flag is set, in case it happened while we
|
||||
// were waiting for a task
|
||||
if(done)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// If we got here and the runnable was null then something
|
||||
// bad must have happened. Throw an Exception and bail.
|
||||
if(!task.first)
|
||||
{
|
||||
throw exceptions::ActiveMQException( __FILE__, __LINE__,
|
||||
"PooledThread::run - Retrieive NULL task from Pool.");
|
||||
}
|
||||
|
||||
// Got some work to do, so set flag to busy
|
||||
busy = true;
|
||||
|
||||
// Inform a listener that we are going to start
|
||||
if(listener)
|
||||
{
|
||||
/*LOGCMS_DEBUG(logger,
|
||||
"PooledThread::run - Inform Listener we are starting");*/
|
||||
listener->onTaskStarted(this);
|
||||
}
|
||||
|
||||
// Perform the work
|
||||
task.first->run();
|
||||
|
||||
/*LOGCMS_DEBUG(logger,
|
||||
"PooledThread::run - Inform Task Listener we are done");*/
|
||||
|
||||
// Notify the Task listener that we are done
|
||||
task.second->onTaskComplete(task.first);
|
||||
|
||||
// Inform a listener that we are going to stop and wait
|
||||
// for a new task
|
||||
if(listener)
|
||||
{
|
||||
/*LOGCMS_DEBUG(logger,
|
||||
"PooledThread::run - Inform Listener we are done");*/
|
||||
listener->onTaskCompleted(this);
|
||||
}
|
||||
|
||||
// Set flag to inactive, we will wait for work
|
||||
busy = false;
|
||||
}
|
||||
}
|
||||
catch(exceptions::ActiveMQException& ex)
|
||||
{
|
||||
ex.setMark( __FILE__, __LINE__ );
|
||||
|
||||
// Notify the Task owner
|
||||
if(task.first && task.second)
|
||||
{
|
||||
task.second->onTaskException(task.first, ex);
|
||||
}
|
||||
|
||||
busy = false;
|
||||
|
||||
// Notify the PooledThreadListener
|
||||
if(listener)
|
||||
{
|
||||
listener->onTaskException(this, ex);
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
exceptions::ActiveMQException ex(
|
||||
__FILE__, __LINE__,
|
||||
"PooledThread::run - Caught Unknown Exception");
|
||||
|
||||
// Notify the Task owner
|
||||
if(task.first && task.second)
|
||||
{
|
||||
task.second->onTaskException(task.first, ex);
|
||||
}
|
||||
|
||||
busy = false;
|
||||
|
||||
// Notify the PooledThreadListener
|
||||
if(listener)
|
||||
{
|
||||
listener->onTaskException(this, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void PooledThread::stop(void) throw ( cms::CMSException )
|
||||
{
|
||||
done = true;
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CONCURRENT_POOLEDTHREAD_H_
|
||||
#define _ACTIVEMQ_CONCURRENT_POOLEDTHREAD_H_
|
||||
|
||||
#include <activemq/concurrent/Thread.h>
|
||||
#include <activemq/concurrent/Runnable.h>
|
||||
#include <activemq/concurrent/PooledThreadListener.h>
|
||||
#include <activemq/logger/LoggerDefines.h>
|
||||
|
||||
#include <cms/Stoppable.h>
|
||||
#include <cms/CMSException.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace concurrent{
|
||||
|
||||
class ThreadPool;
|
||||
|
||||
class PooledThread : public Thread, public cms::Stoppable
|
||||
{
|
||||
private:
|
||||
|
||||
// Is this thread currently processing something
|
||||
bool busy;
|
||||
|
||||
// Boolean flag indicating thread should stop
|
||||
bool done;
|
||||
|
||||
// Listener for Task related events
|
||||
PooledThreadListener* listener;
|
||||
|
||||
// The thread pool this Pooled Thread is Servicing
|
||||
ThreadPool* pool;
|
||||
|
||||
// Logger Init
|
||||
LOGCMS_DECLARE(logger);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
PooledThread(ThreadPool* pool);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~PooledThread(void);
|
||||
|
||||
/**
|
||||
* Run Method for this object waits for something to be
|
||||
* enqueued on the ThreadPool and then grabs it and calls
|
||||
* its run method.
|
||||
*/
|
||||
virtual void run(void);
|
||||
|
||||
/**
|
||||
* Stops the Thread, thread will complete its task if currently
|
||||
* running one, and then die. Does not block.
|
||||
*/
|
||||
virtual void stop(void) throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Checks to see if the thread is busy, if busy it means
|
||||
* that this thread has taken a task from the ThreadPool's
|
||||
* queue and is processing it.
|
||||
*/
|
||||
virtual bool isBusy(void) { return busy; }
|
||||
|
||||
/**
|
||||
* Adds a listener to this <code>PooledThread</code> to be
|
||||
* notified when this thread starts and completes a task.
|
||||
*/
|
||||
virtual void setPooledThreadListener(PooledThreadListener* listener)
|
||||
{
|
||||
this->listener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener for this <code>PooledThread</code> to be
|
||||
* notified when this thread starts and completes a task.
|
||||
*/
|
||||
virtual PooledThreadListener* getPooledThreadListener(void)
|
||||
{
|
||||
return this->listener;
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONCURRENT_POOLEDTHREAD_H_*/
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CONCURRENT_POOLEDTHREADLISTENER_H_
|
||||
#define _ACTIVEMQ_CONCURRENT_POOLEDTHREADLISTENER_H_
|
||||
|
||||
#include <activemq/exceptions/ActiveMQException.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace concurrent{
|
||||
|
||||
//forward declare
|
||||
class PooledThread;
|
||||
|
||||
class PooledThreadListener
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~PooledThreadListener(void) {}
|
||||
|
||||
/**
|
||||
* Called by a pooled thread when it is about to begin
|
||||
* executing a new task.
|
||||
* @param Pointer to the Pooled Thread that is making this call
|
||||
*/
|
||||
virtual void onTaskStarted(PooledThread* thread) = 0;
|
||||
|
||||
/**
|
||||
* Called by a pooled thread when it has completed a task
|
||||
* and is going back to waiting for another task to run
|
||||
* @param Pointer the the Pooled Thread that is making this call.
|
||||
*/
|
||||
virtual void onTaskCompleted(PooledThread* thread) = 0;
|
||||
|
||||
/**
|
||||
* Called by a pooled thread when it has encountered an exception
|
||||
* while running a user task, after receiving this notification
|
||||
* the callee should assume that the PooledThread is now no longer
|
||||
* running.
|
||||
* @param Pointer to the Pooled Thread that is making this call
|
||||
* @param The Exception that occured.
|
||||
*/
|
||||
virtual void onTaskException(PooledThread* thread,
|
||||
exceptions::ActiveMQException& ex) = 0;
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONCURRENT_POOLEDTHREADLISTENER_H_*/
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef ACTIVEMQ_CONCURRENT_RUNNABLE_H_
|
||||
#define ACTIVEMQ_CONCURRENT_RUNNABLE_H_
|
||||
|
||||
namespace activemq{
|
||||
namespace concurrent{
|
||||
|
||||
/**
|
||||
* Interface for a runnable object - defines a task
|
||||
* that can be run by a thread.
|
||||
*/
|
||||
class Runnable{
|
||||
public:
|
||||
|
||||
virtual ~Runnable(){}
|
||||
|
||||
/**
|
||||
* Run method - called by the Thread class in the context
|
||||
* of the thread.
|
||||
*/
|
||||
virtual void run() = 0;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*ACTIVEMQ_CONCURRENT_RUNNABLE_H_*/
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef ACTIVEMQ_CONCURRENT_SYNCHRONIZABLE_H
|
||||
#define ACTIVEMQ_CONCURRENT_SYNCHRONIZABLE_H
|
||||
|
||||
#include <activemq/exceptions/ActiveMQException.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace concurrent{
|
||||
|
||||
/**
|
||||
* The interface for all synchronizable objects (that is, objects
|
||||
* that can be locked and unlocked).
|
||||
*/
|
||||
class Synchronizable
|
||||
{
|
||||
public: // Abstract Interface
|
||||
|
||||
virtual ~Synchronizable(){}
|
||||
|
||||
/**
|
||||
* Locks the object.
|
||||
* @throws ActiveMQException
|
||||
*/
|
||||
virtual void lock() throw(exceptions::ActiveMQException) = 0;
|
||||
|
||||
/**
|
||||
* Unlocks the object.
|
||||
* @throws ActiveMQException
|
||||
*/
|
||||
virtual void unlock() throw(exceptions::ActiveMQException) = 0;
|
||||
|
||||
/**
|
||||
* Waits on a signal from this object, which is generated
|
||||
* by a call to Notify. Must have this object locked before
|
||||
* calling.
|
||||
* @throws ActiveMQException
|
||||
*/
|
||||
virtual void wait() throw(exceptions::ActiveMQException) = 0;
|
||||
|
||||
/**
|
||||
* Waits on a signal from this object, which is generated
|
||||
* by a call to Notify. Must have this object locked before
|
||||
* calling. This wait will timeout after the specified time
|
||||
* interval.
|
||||
* @param time in millisecsonds to wait, or WAIT_INIFINITE
|
||||
* @throws ActiveMQException
|
||||
*/
|
||||
virtual void wait(unsigned long millisecs)
|
||||
throw(exceptions::ActiveMQException) = 0;
|
||||
|
||||
/**
|
||||
* Signals a waiter on this object that it can now wake
|
||||
* up and continue. Must have this object locked before
|
||||
* calling.
|
||||
* @throws ActiveMQException
|
||||
*/
|
||||
virtual void notify() throw(exceptions::ActiveMQException) = 0;
|
||||
|
||||
/**
|
||||
* Signals the waiters on this object that it can now wake
|
||||
* up and continue. Must have this object locked before
|
||||
* calling.
|
||||
* @throws ActiveMQException
|
||||
*/
|
||||
virtual void notifyAll() throw(exceptions::ActiveMQException) = 0;
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*ACTIVEMQ_CONCURRENT_SYNCHRONIZABLE_H*/
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CONCURRENT_TASKLISTENER_H_
|
||||
#define _ACTIVEMQ_CONCURRENT_TASKLISTENER_H_
|
||||
|
||||
#include <activemq/concurrent/Runnable.h>
|
||||
#include <activemq/exceptions/ActiveMQException.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace concurrent{
|
||||
|
||||
class TaskListener
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~TaskListener() {}
|
||||
|
||||
/**
|
||||
* Called when a queued task has completed, the task that
|
||||
* finished is passed along for user consumption
|
||||
* @param Runnable Pointer to the task that finished
|
||||
*/
|
||||
virtual void onTaskComplete(Runnable* task) = 0;
|
||||
|
||||
/**
|
||||
* Called when a queued task has thrown an exception while
|
||||
* being run. The Callee should assume that this was an
|
||||
* unrecoverable exeption and that this task is now defunct.
|
||||
* @param Runnable Pointer to the task
|
||||
* @param The ActiveMQException that was thrown.
|
||||
*/
|
||||
virtual void onTaskException(Runnable* task,
|
||||
exceptions::ActiveMQException& ex) = 0;
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONCURRENT_TASKLISTENER_H_*/
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#include "Thread.h"
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef unix
|
||||
#include <errno.h> // EINTR
|
||||
extern int errno;
|
||||
#else
|
||||
#include <process.h> // _endthreadex
|
||||
#endif
|
||||
|
||||
#include <activemq/exceptions/ActiveMQException.h>
|
||||
|
||||
using namespace activemq;
|
||||
using namespace activemq::concurrent;
|
||||
|
||||
#ifdef unix
|
||||
static struct ThreadStaticInitializer {
|
||||
// Thread Attribute member
|
||||
pthread_attr_t threadAttribute;
|
||||
// Static Initializer:
|
||||
ThreadStaticInitializer() {
|
||||
pthread_attr_init (&threadAttribute);
|
||||
pthread_attr_setdetachstate (&threadAttribute, PTHREAD_CREATE_JOINABLE);
|
||||
}
|
||||
} threadStaticInitializer;
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Thread::Thread()
|
||||
{
|
||||
task = this;
|
||||
started = false;
|
||||
joined = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Thread::Thread( Runnable* task )
|
||||
{
|
||||
this->task = task;
|
||||
started = false;
|
||||
joined = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Thread::~Thread()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Thread::start() throw ( exceptions::ActiveMQException )
|
||||
{
|
||||
if (this->started) {
|
||||
throw exceptions::ActiveMQException( __FILE__, __LINE__,
|
||||
"Thread already started");
|
||||
}
|
||||
|
||||
#ifdef unix
|
||||
|
||||
pthread_attr_init (&attributes);
|
||||
pthread_attr_setdetachstate (&attributes, PTHREAD_CREATE_JOINABLE);
|
||||
int err = pthread_create (
|
||||
&this->threadHandle,
|
||||
&attributes,
|
||||
runCallback,
|
||||
this);
|
||||
if (err != 0) {
|
||||
throw exceptions::ActiveMQException( __FILE__, __LINE__,
|
||||
"Coud not start thread");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
unsigned int threadId = 0;
|
||||
this->threadHandle =
|
||||
(HANDLE)_beginthreadex(NULL, 0, runCallback, this, 0, &threadId);
|
||||
if (this->threadHandle == NULL) {
|
||||
throw exceptions::ActiveMQException( __FILE__, __LINE__,
|
||||
"Coud not start thread");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Mark the thread as started.
|
||||
started = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Thread::join() throw( exceptions::ActiveMQException )
|
||||
{
|
||||
if (!this->started) {
|
||||
throw exceptions::ActiveMQException( __FILE__, __LINE__,
|
||||
"Thread::join() called without having called Thread::start()");
|
||||
}
|
||||
if (!this->joined) {
|
||||
|
||||
#ifdef unix
|
||||
pthread_join(this->threadHandle, NULL);
|
||||
#else
|
||||
WaitForSingleObject (this->threadHandle, INFINITE);
|
||||
#endif
|
||||
|
||||
}
|
||||
this->joined = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Thread::sleep(int millisecs)
|
||||
{
|
||||
#ifdef unix
|
||||
struct timespec rec, rem;
|
||||
rec.tv_sec = millisecs / 1000;
|
||||
rec.tv_nsec = (millisecs % 1000) * 1000000;
|
||||
while( nanosleep( &rec, &rem ) == -1 ){
|
||||
if( errno != EINTR ){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
Sleep (millisecs);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
unsigned long Thread::getId(void)
|
||||
{
|
||||
#ifdef unix
|
||||
return (long)(pthread_self());
|
||||
#else
|
||||
return GetCurrentThreadId();
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef unix
|
||||
void*
|
||||
#else
|
||||
unsigned int WINAPI
|
||||
#endif
|
||||
Thread::runCallback (void* param)
|
||||
{
|
||||
// Get the instance.
|
||||
Thread* thread = (Thread*)param;
|
||||
|
||||
// Invoke run on the task.
|
||||
thread->task->run();
|
||||
|
||||
#ifdef unix
|
||||
return NULL;
|
||||
#else
|
||||
// Return 0 if no exception was threwn. Otherwise -1.
|
||||
_endthreadex(0); // Needed when using threads and CRT in Windows. Otherwise memleak can appear.
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef ACTIVEMQ_CONCURRENT_THREAD_H
|
||||
#define ACTIVEMQ_CONCURRENT_THREAD_H
|
||||
|
||||
#include <activemq/exceptions/ActiveMQException.h>
|
||||
#include <activemq/concurrent/Runnable.h>
|
||||
#include <stdexcept>
|
||||
#include <assert.h>
|
||||
|
||||
#if (defined(__unix__) || defined(unix) || defined(MACOSX)) && !defined(USG)
|
||||
|
||||
#ifndef unix
|
||||
#define unix
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace activemq{
|
||||
namespace concurrent{
|
||||
|
||||
/**
|
||||
* Basic thread class - mimics the Java Thread. Derived classes may
|
||||
* implement the run method, or this class can be used as is with
|
||||
* a provided Runnable delegate.
|
||||
*/
|
||||
class Thread : public Runnable
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* The task to be run by this thread, defaults to
|
||||
* this thread object.
|
||||
*/
|
||||
Runnable* task;
|
||||
|
||||
#ifdef unix
|
||||
pthread_attr_t attributes;
|
||||
pthread_t threadHandle ;
|
||||
#else
|
||||
HANDLE threadHandle ;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Started state of this thread.
|
||||
*/
|
||||
bool started;
|
||||
|
||||
/**
|
||||
* Indicates whether the thread has already been
|
||||
* joined.
|
||||
*/
|
||||
bool joined;
|
||||
|
||||
public:
|
||||
|
||||
Thread();
|
||||
Thread( Runnable* task );
|
||||
virtual ~Thread();
|
||||
|
||||
/**
|
||||
* Creates a system thread and starts it in a joinable mode.
|
||||
* Upon creation, the
|
||||
* run() method of either this object or the provided Runnable
|
||||
* object will be invoked in the context of this thread.
|
||||
* @exception runtime_error is thrown if the system could
|
||||
* not start the thread.
|
||||
*/
|
||||
virtual void start() throw (exceptions::ActiveMQException);
|
||||
|
||||
/**
|
||||
* Wait til the thread exits. This is when the run()
|
||||
* method has returned or has thrown an exception.
|
||||
* If an exception was thrown in the run() method,
|
||||
* join() will return the thrown exception. Otherwise
|
||||
* (if run() returned normally), join() will
|
||||
* return NULL.
|
||||
*/
|
||||
virtual void join() throw (exceptions::ActiveMQException);
|
||||
|
||||
/**
|
||||
* Default implementation of the run method - does nothing.
|
||||
*/
|
||||
virtual void run(){};
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Halts execution of the calling thread for a specified no of millisec.
|
||||
*
|
||||
* Note that this method is a static method that applies to the
|
||||
* calling thread and not to the thread object.
|
||||
*/
|
||||
static void sleep(int millisecs);
|
||||
|
||||
/**
|
||||
* Obtains the Thread Id of the current thread
|
||||
* @return Thread Id
|
||||
*/
|
||||
static unsigned long getId(void);
|
||||
|
||||
private:
|
||||
|
||||
// Internal thread handling
|
||||
#ifdef unix
|
||||
static void* runCallback (void* param);
|
||||
#else
|
||||
static unsigned int WINAPI runCallback (void* param);
|
||||
#endif
|
||||
} ;
|
||||
|
||||
}}
|
||||
|
||||
#endif /*ACTIVEMQ_CONCURRENT_THREAD_H*/
|
|
@ -0,0 +1,344 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#include <activemq/concurrent/ThreadPool.h>
|
||||
#include <activemq/concurrent/Concurrent.h>
|
||||
#include <activemq/exceptions/IllegalArgumentException.h>
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
using namespace activemq;
|
||||
using namespace activemq::concurrent;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
LOGCMS_INITIALIZE(logger, ThreadPool, "com.activemq.concurrent.ThreadPool");
|
||||
LOGCMS_INITIALIZE(marker, ThreadPool, "com.activemq.concurrent.ThreadPool.Marker");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ThreadPool ThreadPool::instance;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ThreadPool::ThreadPool(void)
|
||||
{
|
||||
maxThreads = DEFAULT_MAX_POOL_SIZE;
|
||||
blockSize = DEFAULT_MAX_BLOCK_SIZE;
|
||||
freeThreads = 0;
|
||||
|
||||
shutdown = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ThreadPool::~ThreadPool(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::vector<PooledThread*>::iterator itr = pool.begin();
|
||||
|
||||
// Stop all the threads
|
||||
for(; itr != pool.end(); ++itr)
|
||||
{
|
||||
(*itr)->stop();
|
||||
}
|
||||
|
||||
// Set the shutdown flag so that the DeQueue methods all quit
|
||||
// when we interrupt them.
|
||||
shutdown = true;
|
||||
|
||||
synchronized(&queue)
|
||||
{
|
||||
// Signal the Queue so that all waiters are notified
|
||||
queue.notifyAll();
|
||||
}
|
||||
|
||||
// Wait for everyone to die
|
||||
for(itr = pool.begin(); itr != pool.end(); ++itr)
|
||||
{
|
||||
(*itr)->join();
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( exceptions::ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( exceptions::ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ThreadPool::queueTask(ThreadPool::Task task)
|
||||
throw ( exceptions::ActiveMQException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if(!task.first || !task.second)
|
||||
{
|
||||
throw exceptions::IllegalArgumentException( __FILE__, __LINE__,
|
||||
"ThreadPool::QueueTask - Invalid args for Task");
|
||||
}
|
||||
|
||||
//LOGCMS_DEBUG(logger, "ThreadPool::QueueTask - syncing on queue");
|
||||
|
||||
synchronized(&queue)
|
||||
{
|
||||
//LOGCMS_DEBUG(logger, "ThreadPool::QueueTask - sync'd, synching pool");
|
||||
|
||||
// If there's nobody open to do work, then create some more
|
||||
// threads to handle the work.
|
||||
if(freeThreads == 0)
|
||||
{
|
||||
AllocateThreads(blockSize);
|
||||
}
|
||||
|
||||
//LOGCMS_DEBUG(logger, "ThreadPool::QueueTask - pushing task");
|
||||
|
||||
// queue the new work.
|
||||
queue.push(task);
|
||||
|
||||
//LOGCMS_DEBUG(logger, "ThreadPool::QueueTask - calling notify");
|
||||
|
||||
// Inform waiters that we put some work on the queue.
|
||||
queue.notify();
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( exceptions::ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( exceptions::ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ThreadPool::Task ThreadPool::deQueueTask(void)
|
||||
throw ( exceptions::ActiveMQException )
|
||||
{
|
||||
try
|
||||
{
|
||||
//LOGCMS_DEBUG(logger, "ThreadPool::DeQueueTask - syncing on queue");
|
||||
|
||||
synchronized(&queue)
|
||||
{
|
||||
/*LOGCMS_DEBUG(logger,
|
||||
"ThreadPool::DeQueueTask - sync'd checking queue empty");*/
|
||||
|
||||
// Wait for work, wait in a while loop since another thread could
|
||||
// be waiting for a lock and get the work before we get woken up
|
||||
// from our wait.
|
||||
while(queue.empty() && !shutdown)
|
||||
{
|
||||
//LOGCMS_DEBUG(logger, "ThreadPool::DeQueueTask - Q empty, waiting");
|
||||
|
||||
queue.wait();
|
||||
|
||||
//LOGCMS_DEBUG(logger, "ThreadPool::DeQueueTask - done waiting");
|
||||
}
|
||||
|
||||
// Don't give more work if we are closing down
|
||||
if(shutdown)
|
||||
{
|
||||
return Task();
|
||||
}
|
||||
|
||||
// check size again.
|
||||
if(queue.empty())
|
||||
{
|
||||
throw exceptions::ActiveMQException( __FILE__, __LINE__,
|
||||
"ThreadPool::DeQueueUserWorkItem - Empty Taskn, not in shutdown.");
|
||||
}
|
||||
|
||||
//LOGCMS_DEBUG(logger, "ThreadPool::DeQueueTask - popping task");
|
||||
|
||||
// not empty so get the new work to do
|
||||
return queue.pop();
|
||||
}
|
||||
|
||||
return Task();
|
||||
}
|
||||
AMQ_CATCH_RETHROW( exceptions::ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( exceptions::ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ThreadPool::reserve(unsigned long size)
|
||||
{
|
||||
try{
|
||||
synchronized(&poolLock)
|
||||
{
|
||||
if(size < pool.size() || pool.size() == maxThreads)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// How many do we reserve
|
||||
unsigned long allocCount = size - pool.size();
|
||||
|
||||
// Allocate the new Threads
|
||||
AllocateThreads(allocCount);
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( exceptions::ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( exceptions::ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ThreadPool::setMaxThreads(unsigned long maxThreads)
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized(&poolLock)
|
||||
{
|
||||
if(maxThreads == 0)
|
||||
{
|
||||
// Caller tried to do something stupid, ignore them.
|
||||
return;
|
||||
}
|
||||
|
||||
this->maxThreads = maxThreads;
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( exceptions::ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( exceptions::ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ThreadPool::setBlockSize(unsigned long blockSize)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(blockSize <= 0)
|
||||
{
|
||||
// User tried something dumb, protect them from themselves
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized(&poolLock)
|
||||
{
|
||||
this->blockSize = blockSize;
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( exceptions::ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( exceptions::ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ThreadPool::AllocateThreads(unsigned long count)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(pool.size() >= maxThreads)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized(&poolLock)
|
||||
{
|
||||
// Take the min of alloc size of maxThreads since we don't
|
||||
// want anybody sneaking eaxtra threads in, greedy bastards.
|
||||
count = std::min(count, maxThreads - pool.size());
|
||||
|
||||
// Each time we create a thread we increment the free Threads
|
||||
// counter, but before we call start so that the Thread doesn't
|
||||
// get ahead of us.
|
||||
for(unsigned long i = 0; i < count; ++i)
|
||||
{
|
||||
pool.push_back(new PooledThread(this));
|
||||
pool.back()->setPooledThreadListener(this);
|
||||
freeThreads++;
|
||||
pool.back()->start();
|
||||
}
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( exceptions::ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( exceptions::ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ThreadPool::onTaskStarted(PooledThread* thread)
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized(&poolLock)
|
||||
{
|
||||
freeThreads--;
|
||||
|
||||
// Now that this callback has decremented the free threads coutner
|
||||
// let check if there is any outstanding work to be done and no
|
||||
// threads to handle it. This could happen if the QueueTask
|
||||
// method was called successively without any of the PooledThreads
|
||||
// having a chance to wake up and service the queue. This would
|
||||
// cause the number of Task to exceed the number of free threads
|
||||
// once the Threads got a chance to wake up and service the queue
|
||||
if(freeThreads == 0 && !queue.empty())
|
||||
{
|
||||
// Allocate a new block of threads
|
||||
AllocateThreads(blockSize);
|
||||
}
|
||||
}
|
||||
|
||||
//LOGCMS_DEBUG(logger, "ThreadPool::onTaskStarted:");
|
||||
}
|
||||
AMQ_CATCH_RETHROW( exceptions::ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( exceptions::ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ThreadPool::onTaskCompleted(PooledThread* thread)
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized(&poolLock)
|
||||
{
|
||||
freeThreads++;
|
||||
}
|
||||
|
||||
//LOGCMS_DEBUG(logger, "ThreadPool::onTaskCompleted: ");
|
||||
}
|
||||
AMQ_CATCH_RETHROW( exceptions::ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( exceptions::ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ThreadPool::onTaskException(
|
||||
PooledThread* thread,
|
||||
exceptions::ActiveMQException& ex)
|
||||
{
|
||||
//LOGCMS_DEBUG(logger, "ThreadPool::onTaskException: ");
|
||||
|
||||
try
|
||||
{
|
||||
synchronized(&poolLock)
|
||||
{
|
||||
// Delete the thread that had the exception and start a new
|
||||
// one to take its place.
|
||||
freeThreads--;
|
||||
|
||||
std::vector<PooledThread*>::iterator itr =
|
||||
std::find(pool.begin(), pool.end(), thread);
|
||||
|
||||
if(itr != pool.end())
|
||||
{
|
||||
pool.erase(itr);
|
||||
}
|
||||
|
||||
// Bye-Bye Thread Object
|
||||
delete thread;
|
||||
|
||||
// Now allocate a replacement
|
||||
AllocateThreads(1);
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( exceptions::ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( exceptions::ActiveMQException )
|
||||
}
|
||||
|
|
@ -0,0 +1,239 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CONCURRENT_THREADPOOL_H_
|
||||
#define _ACTIVEMQ_CONCURRENT_THREADPOOL_H_
|
||||
|
||||
#include <activemq/concurrent/Runnable.h>
|
||||
#include <activemq/concurrent/PooledThread.h>
|
||||
#include <activemq/concurrent/PooledThreadListener.h>
|
||||
#include <activemq/concurrent/TaskListener.h>
|
||||
#include <activemq/concurrent/Mutex.h>
|
||||
#include <activemq/util/Queue.h>
|
||||
#include <activemq/logger/LoggerDefines.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace activemq{
|
||||
namespace concurrent{
|
||||
|
||||
/**
|
||||
* Defines a Thread Pool object that implements the functionality
|
||||
* of pooling threads to perform user tasks. The Thread Poll has
|
||||
* max size that it will grow to. The thread pool allocates threads
|
||||
* in blocks. When there are no waiting worker threads and a task
|
||||
* is queued then a new batch is allocated. The user can specify
|
||||
* the size of the blocks, otherwise a default value is used.
|
||||
* <P>
|
||||
* When the user queues a task they must also queue a listner to
|
||||
* be notified when the task has completed, this provides the user
|
||||
* with a mechanism to know when a task object can be freed.
|
||||
* <P>
|
||||
* To have the Thread Pool perform a task, the user enqueue's an
|
||||
* object that implements the <code>Runnable</code> insterface and
|
||||
* one of the worker threads will executing it in its thread context.
|
||||
*/
|
||||
class ThreadPool : public PooledThreadListener
|
||||
{
|
||||
public:
|
||||
|
||||
// Constants
|
||||
static const size_t DEFAULT_MAX_POOL_SIZE = 10;
|
||||
static const size_t DEFAULT_MAX_BLOCK_SIZE = 3;
|
||||
|
||||
// Types
|
||||
typedef std::pair<Runnable*, TaskListener*> Task;
|
||||
|
||||
private:
|
||||
|
||||
// Vector of threads that this object has created for its pool.
|
||||
std::vector< PooledThread* > pool;
|
||||
|
||||
// Queue of Task that are in need of completion
|
||||
util::Queue<Task> queue;
|
||||
|
||||
// Max number of Threads this Pool can contian
|
||||
unsigned long maxThreads;
|
||||
|
||||
// Max number of tasks that can be allocated at a time
|
||||
unsigned long blockSize;
|
||||
|
||||
// boolean flag use to indocate that this object is shutting down.
|
||||
bool shutdown;
|
||||
|
||||
// Count of threads that are currently free to perfom some work.
|
||||
unsigned long freeThreads;
|
||||
|
||||
// Mutex for locking operations that affect the pool.
|
||||
Mutex poolLock;
|
||||
|
||||
// Logger Init
|
||||
LOGCMS_DECLARE(logger);
|
||||
LOGCMS_DECLARE(marker);
|
||||
|
||||
private: // Statics
|
||||
|
||||
// The singleton instance of this class
|
||||
static ThreadPool instance;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ThreadPool(void);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ThreadPool(void);
|
||||
|
||||
/**
|
||||
* Queue a task to be completed by one of the Pooled Threads.
|
||||
* tasks are serviced as soon as a <code>PooledThread</code>
|
||||
* is available to run it.
|
||||
* @param object that derives from Runnable
|
||||
* @throws ActiveMQException
|
||||
*/
|
||||
virtual void queueTask(Task task)
|
||||
throw ( exceptions::ActiveMQException );
|
||||
|
||||
/**
|
||||
* DeQueue a task to be completed by one of the Pooled Threads.
|
||||
* A caller of this method will block until there is something
|
||||
* in the tasks queue, therefore care must be taken when calling
|
||||
* this function. Normally clients of ThreadPool don't use
|
||||
* this, only the <code>PooledThread</code> objects owned by
|
||||
* this ThreadPool.
|
||||
* @return object that derives from Runnable
|
||||
* @throws ActiveMQException
|
||||
*/
|
||||
virtual Task deQueueTask(void)
|
||||
throw ( exceptions::ActiveMQException );
|
||||
|
||||
/**
|
||||
* Returns the current number of Threads in the Pool, this is
|
||||
* how many there are now, not how many are active or the max
|
||||
* number that might exist.
|
||||
* @return integer number of threads in existance.
|
||||
*/
|
||||
virtual unsigned long getPoolSize(void) const { return pool.size(); }
|
||||
|
||||
/**
|
||||
* Returns the current backlog of items in the tasks queue, this
|
||||
* is how much work is still waiting to get done.
|
||||
* @return number of outstanding tasks.
|
||||
*/
|
||||
virtual unsigned long getBacklog(void) const { return queue.size(); }
|
||||
|
||||
/**
|
||||
* Ensures that there is at least the specified number of Threads
|
||||
* allocated to the pool. If the size is greater than the MAX
|
||||
* number of threads in the pool, then only MAX threads are
|
||||
* reservved. If the size is smaller than the number of threads
|
||||
* currently in the pool, than nothing is done.
|
||||
* @param number of threads to reserve.
|
||||
*/
|
||||
virtual void reserve(unsigned long size);
|
||||
|
||||
/**
|
||||
* Get the Max Number of Threads this Pool can contain
|
||||
* @return max size
|
||||
*/
|
||||
virtual unsigned long getMaxThreads(void) const { return maxThreads; }
|
||||
|
||||
/**
|
||||
* Sets the Max number of threads this pool can contian.
|
||||
* if this value is smaller than the current size of the
|
||||
* pool nothing is done.
|
||||
*/
|
||||
virtual void setMaxThreads(unsigned long maxThreads);
|
||||
|
||||
/**
|
||||
* Gets the Max number of threads that can be allocated at a time
|
||||
* when new threads are needed.
|
||||
* @return max Thread Block Size
|
||||
*/
|
||||
virtual unsigned long getBlockSize(void) const { return blockSize; }
|
||||
|
||||
/**
|
||||
* Sets the Max number of Threads that can be allocated at a time
|
||||
* when the Thread Pool determines that more Threads are needed.
|
||||
* @param Max Thread Block Size
|
||||
*/
|
||||
virtual void setBlockSize(unsigned long blockSize);
|
||||
|
||||
/**
|
||||
* Returns the current number of available threads in the pool, threads
|
||||
* that are performing a user task are considered unavailable. This value
|
||||
* could change immeadiately after calling as Threads could finish right
|
||||
* after and be available again. This is informational only.
|
||||
* @return totoal free threads
|
||||
*/
|
||||
virtual unsigned long getFreeThreadCount(void) const { return freeThreads; }
|
||||
|
||||
public: // PooledThreadListener Callbacks
|
||||
|
||||
/**
|
||||
* Called by a pooled thread when it is about to begin
|
||||
* executing a new task. This will decrement the available
|
||||
* threads counter so that this object knows when there are
|
||||
* no more free threads and must create new ones.
|
||||
* @param Pointer to the Pooled Thread that is making this call
|
||||
*/
|
||||
virtual void onTaskStarted(PooledThread* thread);
|
||||
|
||||
/**
|
||||
* Called by a pooled thread when it has completed a task
|
||||
* and is going back to waiting for another task to run,
|
||||
* this will increment the free threads counter.
|
||||
* @param Pointer the the Pooled Thread that is making this call.
|
||||
*/
|
||||
virtual void onTaskCompleted(PooledThread* thread);
|
||||
|
||||
/**
|
||||
* Called by a pooled thread when it has encountered an exception
|
||||
* while running a user task, after receiving this notification
|
||||
* the callee should assume that the PooledThread is now no longer
|
||||
* running.
|
||||
* @param Pointer to the Pooled Thread that is making this call
|
||||
* @param The Exception that occured.
|
||||
*/
|
||||
virtual void onTaskException(PooledThread* thread,
|
||||
exceptions::ActiveMQException& ex);
|
||||
|
||||
public: // Statics
|
||||
|
||||
/**
|
||||
* Return the one and only Thread Pool instance.
|
||||
* @return The Thread Pool Pointer
|
||||
*/
|
||||
static ThreadPool* getInstance(void) { return &instance; }
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Allocates the requested ammount of Threads, won't exceed
|
||||
* <code>maxThreads</code>.
|
||||
* @param the number of threads to create
|
||||
*/
|
||||
void AllocateThreads(unsigned long count);
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONCURRENT_THREADPOOL_H_*/
|
|
@ -0,0 +1,317 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_CONNECTOR_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_CONNECTOR_H_
|
||||
|
||||
#include <list>
|
||||
|
||||
#include <cms/Startable.h>
|
||||
#include <cms/Closeable.h>
|
||||
#include <cms/MessageListener.h>
|
||||
#include <cms/ExceptionListener.h>
|
||||
#include <cms/Topic.h>
|
||||
#include <cms/Queue.h>
|
||||
#include <cms/TemporaryTopic.h>
|
||||
#include <cms/TemporaryQueue.h>
|
||||
#include <cms/Session.h>
|
||||
#include <cms/BytesMessage.h>
|
||||
#include <cms/TextMessage.h>
|
||||
#include <cms/MapMessage.h>
|
||||
|
||||
#include <activemq/exceptions/InvalidStateException.h>
|
||||
|
||||
#include <activemq/transport/Transport.h>
|
||||
#include <activemq/connector/SessionInfo.h>
|
||||
#include <activemq/connector/ConsumerInfo.h>
|
||||
#include <activemq/connector/ProducerInfo.h>
|
||||
#include <activemq/connector/TransactionInfo.h>
|
||||
#include <activemq/connector/ConsumerMessageListener.h>
|
||||
#include <activemq/connector/ConnectorException.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
|
||||
// Forward declarations.
|
||||
class Connector
|
||||
:
|
||||
public cms::Startable,
|
||||
public cms::Closeable
|
||||
{
|
||||
public: // Connector Types
|
||||
|
||||
enum AckType
|
||||
{
|
||||
DeliveredAck = 0, // Message delivered but not consumed
|
||||
PoisonAck = 1, // Message could not be processed due to
|
||||
// poison pill but discard anyway
|
||||
ConsumedAck = 2 // Message consumed, discard
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
virtual ~Connector(void) {};
|
||||
|
||||
/**
|
||||
* Gets the Client Id for this connection, if this
|
||||
* connection has been closed, then this method returns ""
|
||||
* @return Client Id String
|
||||
*/
|
||||
virtual std::string getClientId(void) const = 0;
|
||||
|
||||
/**
|
||||
* Gets a reference to the Transport that this connection
|
||||
* is using.
|
||||
* @param reference to a transport
|
||||
* @throws InvalidStateException if the Transport is not set
|
||||
*/
|
||||
virtual transport::Transport& getTransport(void) const
|
||||
throw (exceptions::InvalidStateException ) = 0;
|
||||
|
||||
/**
|
||||
* Creates a Session Info object for this connector
|
||||
* @param Acknowledgement Mode of the Session
|
||||
* @returns Session Info Object
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual SessionInfo* createSession(
|
||||
cms::Session::AcknowledgeMode ackMode)
|
||||
throw( ConnectorException ) = 0;
|
||||
|
||||
/**
|
||||
* Create a Consumer for the given Session
|
||||
* @param Destination to Subscribe to.
|
||||
* @param Session Information.
|
||||
* @return Consumer Information
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual ConsumerInfo* createConsumer(
|
||||
cms::Destination* destination,
|
||||
SessionInfo* session,
|
||||
const std::string& selector = "")
|
||||
throw ( ConnectorException ) = 0;
|
||||
|
||||
/**
|
||||
* Create a Durable Consumer for the given Session
|
||||
* @param Topic to Subscribe to.
|
||||
* @param Session Information.
|
||||
* @param name of the Durable Topic
|
||||
* @param Selector
|
||||
* @param if set, inhibits the delivery of messages
|
||||
* published by its own connection
|
||||
* @return Consumer Information
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual ConsumerInfo* createDurableConsumer(
|
||||
cms::Topic* topic,
|
||||
SessionInfo* session,
|
||||
const std::string& name,
|
||||
const std::string& selector = "",
|
||||
bool noLocal = false)
|
||||
throw ( ConnectorException ) = 0;
|
||||
|
||||
/**
|
||||
* Create a Consumer for the given Session
|
||||
* @param Destination to Subscribe to.
|
||||
* @param Session Information.
|
||||
* @return Producer Information
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual ProducerInfo* createProducer(
|
||||
cms::Destination* destination,
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException ) = 0;
|
||||
|
||||
/**
|
||||
* Creates a Topic given a name and session info
|
||||
* @param Topic Name
|
||||
* @param Session Information
|
||||
* @return a newly created Topic Object
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual cms::Topic* createTopic(const std::string& name,
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException ) = 0;
|
||||
|
||||
/**
|
||||
* Creates a Queue given a name and session info
|
||||
* @param Queue Name
|
||||
* @param Session Information
|
||||
* @return a newly created Queue Object
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual cms::Queue* createQueue(const std::string& name,
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException ) = 0;
|
||||
|
||||
/**
|
||||
* Creates a Temporary Topic given a name and session info
|
||||
* @param Temporary Topic Name
|
||||
* @param Session Information
|
||||
* @return a newly created Temporary Topic Object
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual cms::TemporaryTopic* createTemporaryTopic(
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException ) = 0;
|
||||
|
||||
/**
|
||||
* Creates a Temporary Queue given a name and session info
|
||||
* @param Temporary Queue Name
|
||||
* @param Session Information
|
||||
* @return a newly created Temporary Queue Object
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual cms::TemporaryQueue* createTemporaryQueue(
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException ) = 0;
|
||||
|
||||
/**
|
||||
* Sends a Message
|
||||
* @param The Message to send.
|
||||
* @param Producer Info for the sender of this message
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual void send(cms::Message* message, ProducerInfo* producerInfo)
|
||||
throw ( ConnectorException ) = 0;
|
||||
|
||||
/**
|
||||
* Sends a set of Messages
|
||||
* @param List of Messages to send.
|
||||
* @param Producer Info for the sender of this message
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual void send(std::list<cms::Message*>& messages,
|
||||
ProducerInfo* producerInfo)
|
||||
throw ( ConnectorException ) = 0;
|
||||
|
||||
/**
|
||||
* Acknowledges a Message
|
||||
* @param An ActiveMQMessage to Ack.
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual void acknowledge(const SessionInfo* session,
|
||||
const cms::Message* message,
|
||||
AckType ackType = ConsumedAck)
|
||||
throw ( ConnectorException ) = 0;
|
||||
|
||||
/**
|
||||
* Starts a new Transaction.
|
||||
* @param Session Information
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual TransactionInfo* startTransaction(
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException ) = 0;
|
||||
|
||||
/**
|
||||
* Commits a Transaction.
|
||||
* @param The Transaction information
|
||||
* @param Session Information
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual void commit(TransactionInfo* transaction,
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException ) = 0;
|
||||
|
||||
/**
|
||||
* Rolls back a Transaction.
|
||||
* @param The Transaction information
|
||||
* @param Session Information
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual void rollback(TransactionInfo* transaction,
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException ) = 0;
|
||||
|
||||
/**
|
||||
* Creates a new Message.
|
||||
* @param Session Information
|
||||
* @param Transaction Info for this Message
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual cms::Message* createMessage(
|
||||
SessionInfo* session,
|
||||
TransactionInfo* transaction)
|
||||
throw ( ConnectorException ) = 0;
|
||||
|
||||
/**
|
||||
* Creates a new BytesMessage.
|
||||
* @param Session Information
|
||||
* @param Transaction Info for this Message
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual cms::BytesMessage* createBytesMessage(
|
||||
SessionInfo* session,
|
||||
TransactionInfo* transaction)
|
||||
throw ( ConnectorException ) = 0;
|
||||
|
||||
/**
|
||||
* Creates a new TextMessage.
|
||||
* @param Session Information
|
||||
* @param Transaction Info for this Message
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual cms::TextMessage* createTextMessage(
|
||||
SessionInfo* session,
|
||||
TransactionInfo* transaction)
|
||||
throw ( ConnectorException ) = 0;
|
||||
|
||||
/**
|
||||
* Creates a new MapMessage.
|
||||
* @param Session Information
|
||||
* @param Transaction Info for this Message
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual cms::MapMessage* createMapMessage(
|
||||
SessionInfo* session,
|
||||
TransactionInfo* transaction)
|
||||
throw ( ConnectorException ) = 0;
|
||||
|
||||
/**
|
||||
* Unsubscribe from a givenDurable Subscription
|
||||
* @param name of the Subscription
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual void unsubscribe(const std::string& name)
|
||||
throw ( ConnectorException ) = 0;
|
||||
|
||||
/**
|
||||
* Destroys the given connector resource.
|
||||
* @param resource the resource to be destroyed.
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual void destroyResource( ConnectorResource* resource )
|
||||
throw ( ConnectorException ) = 0;
|
||||
|
||||
/**
|
||||
* Sets the listener of consumer messages.
|
||||
* @param listener the observer.
|
||||
*/
|
||||
virtual void setConsumerMessageListener(
|
||||
ConsumerMessageListener* listener) = 0;
|
||||
|
||||
/**
|
||||
* Sets the Listner of exceptions for this connector
|
||||
* @param ExceptionListener the observer.
|
||||
*/
|
||||
virtual void setExceptionListener(
|
||||
cms::ExceptionListener* listener) = 0;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_CONNECTOR_H_*/
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef CONNECTOREXCEPTION_H_
|
||||
#define CONNECTOREXCEPTION_H_
|
||||
|
||||
#include <activemq/exceptions/ActiveMQException.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
|
||||
/*
|
||||
* Signals that an Connector exception of some sort has occurred.
|
||||
*/
|
||||
class ConnectorException : public exceptions::ActiveMQException
|
||||
{
|
||||
public:
|
||||
|
||||
ConnectorException() {}
|
||||
ConnectorException( const exceptions::ActiveMQException& ex ){
|
||||
*(ActiveMQException*)this = ex;
|
||||
}
|
||||
ConnectorException( const ConnectorException& ex ){
|
||||
*(exceptions::ActiveMQException*)this = ex;
|
||||
}
|
||||
ConnectorException(const char* file, const int lineNumber,
|
||||
const char* msg, ...)
|
||||
{
|
||||
va_list vargs ;
|
||||
va_start(vargs, msg) ;
|
||||
buildMessage(msg, vargs) ;
|
||||
|
||||
// Set the first mark for this exception.
|
||||
setMark( file, lineNumber );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones this exception. This is useful for cases where you need
|
||||
* to preserve the type of the original exception as well as the message.
|
||||
* All subclasses should override.
|
||||
*/
|
||||
virtual exceptions::ActiveMQException* clone() const{
|
||||
return new ConnectorException( *this );
|
||||
}
|
||||
virtual ~ConnectorException() {}
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*CONNECTOREXCEPTION_H_*/
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef CONNECTORFACTORY_H_
|
||||
#define CONNECTORFACTORY_H_
|
||||
|
||||
#include <activemq/util/Properties.h>
|
||||
#include <activemq/transport/Transport.h>
|
||||
#include <activemq/connector/Connector.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
|
||||
/**
|
||||
* Interface class for all Connector Factory Classes
|
||||
*/
|
||||
class ConnectorFactory
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~ConnectorFactory(void) {};
|
||||
|
||||
/**
|
||||
* Creates a connector
|
||||
* @param The Properties that the new connector is configured with
|
||||
*/
|
||||
virtual Connector* createConnector(
|
||||
const activemq::util::Properties& properties,
|
||||
activemq::transport::Transport* transport) = 0;
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*CONNECTORFACTORY_H_*/
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#include <activemq/connector/ConnectorFactoryMap.h>
|
||||
|
||||
using namespace activemq;
|
||||
using namespace activemq::connector;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ConnectorFactoryMap* ConnectorFactoryMap::getInstance(void)
|
||||
{
|
||||
// Static instance of this Map, create here so that one will
|
||||
// always exist, the one and only Connector Map.
|
||||
static ConnectorFactoryMap instance;
|
||||
|
||||
return &instance;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ConnectorFactoryMap::registerConnectorFactory(const std::string& name,
|
||||
ConnectorFactory* factory)
|
||||
{
|
||||
factoryMap[name] = factory;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ConnectorFactoryMap::unregisterConnectorFactory(const std::string& name)
|
||||
{
|
||||
factoryMap.erase(name);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ConnectorFactory* ConnectorFactoryMap::lookup(const std::string& name)
|
||||
{
|
||||
std::map<std::string, ConnectorFactory*>::const_iterator itr =
|
||||
factoryMap.find(name);
|
||||
|
||||
if(itr != factoryMap.end())
|
||||
{
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
// Didn't find it, return nothing, not a single thing.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::size_t ConnectorFactoryMap::getFactoryNames(
|
||||
std::vector<std::string>& factoryList)
|
||||
{
|
||||
std::map<std::string, ConnectorFactory*>::const_iterator itr =
|
||||
factoryMap.begin();
|
||||
|
||||
for(; itr != factoryMap.end(); ++itr)
|
||||
{
|
||||
factoryList.insert(factoryList.end(), itr->first);
|
||||
}
|
||||
|
||||
return factoryMap.size();
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef CONNECTORFACTORYMAP_H_
|
||||
#define CONNECTORFACTORYMAP_H_
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <activemq/exceptions/ActiveMQException.h>
|
||||
#include <activemq/connector/ConnectorFactory.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
|
||||
/**
|
||||
* Lookup Map for Connector Factories. Use the Connector name to
|
||||
* find the associated factory. This class does not take ownership
|
||||
* of the stored factories, they must be deallocated somewhere.
|
||||
*/
|
||||
class ConnectorFactoryMap
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Gets a singleton instance of this class.
|
||||
*/
|
||||
static ConnectorFactoryMap* getInstance(void);
|
||||
|
||||
/**
|
||||
* Registers a new Connector Factory with this map
|
||||
* @param name to associate the factory with
|
||||
* @param factory to store.
|
||||
*/
|
||||
void registerConnectorFactory(const std::string& name,
|
||||
ConnectorFactory* factory);
|
||||
|
||||
/**
|
||||
* Unregisters a Connector Factory with this map
|
||||
* @param name of the factory to remove
|
||||
*/
|
||||
void unregisterConnectorFactory(const std::string& name);
|
||||
|
||||
/**
|
||||
* Lookup the named factory in the Map
|
||||
* @param the factory name to lookup
|
||||
* @return the factory assciated with the name, or NULL
|
||||
*/
|
||||
ConnectorFactory* lookup(const std::string& name);
|
||||
|
||||
/**
|
||||
* Fetch a list of factory names that this Map contains
|
||||
* @param vector object to receive the list
|
||||
* @returns count of factories.
|
||||
*/
|
||||
std::size_t getFactoryNames(std::vector<std::string>& factoryList);
|
||||
|
||||
private:
|
||||
|
||||
// Hidden Contrustor, prevents instantiation
|
||||
ConnectorFactoryMap() {};
|
||||
|
||||
// Hidden Destructor.
|
||||
virtual ~ConnectorFactoryMap() {};
|
||||
|
||||
// Hidden Copy Constructore
|
||||
ConnectorFactoryMap(const ConnectorFactoryMap& factoryMap);
|
||||
|
||||
// Hidden Assignment operator
|
||||
ConnectorFactoryMap operator=(const ConnectorFactoryMap& factoryMap);
|
||||
|
||||
// Map of Factories
|
||||
std::map<std::string, ConnectorFactory*> factoryMap;
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*CONNECTORFACTORYMAP_H_*/
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef CONNECTORFACTORYMAPREGISTRAR_H_
|
||||
#define CONNECTORFACTORYMAPREGISTRAR_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <activemq/connector/ConnectorFactoryMap.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
|
||||
/**
|
||||
* Registers the passed in factory into the factory map, this class
|
||||
* can manage the lifetime of the registered factory (default behaviour).
|
||||
*/
|
||||
class ConnectorFactoryMapRegistrar
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor for this class
|
||||
* @param name of the factory to register
|
||||
* @param the factory
|
||||
* @param boolean indicating if this object manages the lifetime of
|
||||
* the factory that is being registered.
|
||||
*/
|
||||
ConnectorFactoryMapRegistrar( const std::string& name,
|
||||
ConnectorFactory* factory,
|
||||
bool manageLifetime = true )
|
||||
{
|
||||
// Register it in the map.
|
||||
ConnectorFactoryMap::getInstance()->
|
||||
registerConnectorFactory(name, factory);
|
||||
|
||||
// Store for later deletion
|
||||
this->factory = factory;
|
||||
this->manageLifetime = manageLifetime;
|
||||
this->name = name;
|
||||
}
|
||||
|
||||
virtual ~ConnectorFactoryMapRegistrar(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
// UnRegister it in the map.
|
||||
ConnectorFactoryMap::getInstance()->
|
||||
unregisterConnectorFactory(name);
|
||||
|
||||
if(manageLifetime)
|
||||
{
|
||||
delete factory;
|
||||
}
|
||||
}
|
||||
catch(...) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* get a reference to the factory that this class is holding
|
||||
* @return reference to a factory class
|
||||
*/
|
||||
virtual ConnectorFactory& getFactory(void) {
|
||||
return *factory;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::string name;
|
||||
ConnectorFactory* factory;
|
||||
bool manageLifetime;
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*CONNECTORFACTORYMAPREGISTRAR_H_*/
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef ACTIVEMQ_CONNECTOR_CONNECTORRESOURCE_H_
|
||||
#define ACTIVEMQ_CONNECTOR_CONNECTORRESOURCE_H_
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
|
||||
/**
|
||||
* An object who's lifetime is determined by
|
||||
* the connector that created it. All ConnectorResources
|
||||
* should be given back to the connector rather than
|
||||
* deleting explicitly.
|
||||
*/
|
||||
class ConnectorResource
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ConnectorResource() {}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*ACTIVEMQ_CONNECTOR_CONNECTORRESOURCE_H_*/
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_CONSUMERINFO_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_CONSUMERINFO_H_
|
||||
|
||||
#include <activemq/connector/ConnectorResource.h>
|
||||
#include <activemq/connector/SessionInfo.h>
|
||||
#include <cms/Destination.h>
|
||||
#include <string>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
|
||||
class ConsumerInfo : public ConnectorResource
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ConsumerInfo(void) {}
|
||||
|
||||
/**
|
||||
* Gets this message consumer's message selector expression.
|
||||
* @return This Consumer's selector expression or "".
|
||||
*/
|
||||
virtual const std::string& getMessageSelector(void) const = 0;
|
||||
|
||||
/**
|
||||
* Sets this message consumer's message selector expression.
|
||||
* @param This Consumer's selector expression or "".
|
||||
*/
|
||||
virtual void setMessageSelector( const std::string& selector ) = 0;
|
||||
|
||||
/**
|
||||
* Gets the ID that is assigned to this consumer
|
||||
* @return value of the Consumer Id.
|
||||
*/
|
||||
virtual unsigned int getConsumerId(void) const = 0;
|
||||
|
||||
/**
|
||||
* Sets the ID that is assigned to this consumer
|
||||
* @return string value of the Consumer Id.
|
||||
*/
|
||||
virtual void setConsumerId( const unsigned int id ) = 0;
|
||||
|
||||
/**
|
||||
* Gets the Destination that this Consumer is subscribed on
|
||||
* @return Destination
|
||||
*/
|
||||
virtual const cms::Destination& getDestination(void) const = 0;
|
||||
|
||||
/**
|
||||
* Sets the destination that this Consumer is listening on
|
||||
* @param Destination
|
||||
*/
|
||||
virtual void setDestination( const cms::Destination& destination ) = 0;
|
||||
|
||||
/**
|
||||
* Gets the Session Info that this consumer is attached too
|
||||
* @return SessionnInfo pointer
|
||||
*/
|
||||
virtual const SessionInfo* getSessionInfo(void) const = 0;
|
||||
|
||||
/**
|
||||
* Gets the Session Info that this consumer is attached too
|
||||
* @return SessionnInfo pointer
|
||||
*/
|
||||
virtual void setSessionInfo( const SessionInfo* session ) = 0;
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_CONSUMERINFO_H_*/
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_CONSUMERMESSAGELISTENER_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_CONSUMERMESSAGELISTENER_H_
|
||||
|
||||
#include <activemq/connector/ConsumerInfo.h>
|
||||
#include <activemq/core/ActiveMQMessage.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
|
||||
/**
|
||||
* An observer of messages that are targeted at a
|
||||
* particular consumer.
|
||||
*/
|
||||
class ConsumerMessageListener{
|
||||
public:
|
||||
|
||||
virtual ~ConsumerMessageListener(){}
|
||||
|
||||
/**
|
||||
* Called to dispatch a message to a particular consumer.
|
||||
* @param consumer the target consumer of the dispatch.
|
||||
* @param msg the message to be dispatched.
|
||||
*/
|
||||
virtual void onConsumerMessage( ConsumerInfo* consumer,
|
||||
core::ActiveMQMessage* msg ) = 0;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_CONSUMERMESSAGELISTENER_H_*/
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_PRODUCERINFO_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_PRODUCERINFO_H_
|
||||
|
||||
#include <cms/Destination.h>
|
||||
|
||||
#include <activemq/connector/ConnectorResource.h>
|
||||
#include <activemq/connector/SessionInfo.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
|
||||
class ProducerInfo : public ConnectorResource
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~ProducerInfo(void) {}
|
||||
|
||||
/**
|
||||
* Retrieves the default destination that this producer
|
||||
* sends its messages to.
|
||||
* @return Destionation, owned by this object
|
||||
*/
|
||||
virtual const cms::Destination& getDestination(void) const = 0;
|
||||
|
||||
/**
|
||||
* Sets the Default Destination for this Producer
|
||||
* @param reference to a destination, copied internally
|
||||
*/
|
||||
virtual void setDestination( const cms::Destination& dest ) = 0;
|
||||
|
||||
/**
|
||||
* Gets the ID that is assigned to this Producer
|
||||
* @return value of the Producer Id.
|
||||
*/
|
||||
virtual unsigned int getProducerId(void) const = 0;
|
||||
|
||||
/**
|
||||
* Sets the ID that is assigned to this Producer
|
||||
* @return string value of the Producer Id.
|
||||
*/
|
||||
virtual void setProducerId( const unsigned int id ) = 0;
|
||||
|
||||
/**
|
||||
* Gets the Session Info that this consumer is attached too
|
||||
* @return SessionnInfo pointer
|
||||
*/
|
||||
virtual const SessionInfo* getSessionInfo(void) const = 0;
|
||||
|
||||
/**
|
||||
* Gets the Session Info that this consumer is attached too
|
||||
* @return SessionnInfo pointer
|
||||
*/
|
||||
virtual void setSessionInfo( const SessionInfo* session ) = 0;
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_PRODUCERINFO_H_*/
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_SESSIONINFO_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_SESSIONINFO_H_
|
||||
|
||||
#include <activemq/connector/ConnectorResource.h>
|
||||
#include <activemq/connector/TransactionInfo.h>
|
||||
#include <cms/Session.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
|
||||
class SessionInfo : public ConnectorResource
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~SessionInfo(void) {}
|
||||
|
||||
/**
|
||||
* Gets the Connection Id of the Connection that this consumer is
|
||||
* using to receive its messages.
|
||||
* @return string value of the connection id
|
||||
*/
|
||||
virtual const std::string& getConnectionId(void) const = 0;
|
||||
|
||||
/**
|
||||
* Sets the Connection Id of the Connection that this consumer is
|
||||
* using to receive its messages.
|
||||
* @param string value of the connection id
|
||||
*/
|
||||
virtual void setConnectionId( const std::string& id ) = 0;
|
||||
|
||||
/**
|
||||
* Gets the Sessions Id value
|
||||
* @return id for this session
|
||||
*/
|
||||
virtual unsigned int getSessionId(void) const = 0;
|
||||
|
||||
/**
|
||||
* Sets the Session Id for this Session
|
||||
* @param integral id value for this session
|
||||
*/
|
||||
virtual void setSessionId( const unsigned int id ) = 0;
|
||||
|
||||
/**
|
||||
* Sets the Ack Mode of this Session Info object
|
||||
* @param Ack Mode
|
||||
*/
|
||||
virtual void setAckMode(cms::Session::AcknowledgeMode ackMode) = 0;
|
||||
|
||||
/**
|
||||
* Gets the Ack Mode of this Session
|
||||
* @return Ack Mode
|
||||
*/
|
||||
virtual cms::Session::AcknowledgeMode getAckMode(void) const = 0;
|
||||
|
||||
/**
|
||||
* Gets the currently active transaction info, if this session is
|
||||
* transacted, returns NULL when not transacted. You must call
|
||||
* getAckMode and see if the session is transacted.
|
||||
* @return Transaction Id of current Transaction
|
||||
*/
|
||||
virtual const TransactionInfo* getTransactionInfo(void) const = 0;
|
||||
|
||||
/**
|
||||
* Sets the current transaction info for this session, this is nit
|
||||
* used when the session is not transacted.
|
||||
* @param Transaction Id
|
||||
*/
|
||||
virtual void setTransactionInfo( const TransactionInfo* transaction ) = 0;
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_SESSIONINFO_H_*/
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_TRANSACTIONINFO_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_TRANSACTIONINFO_H_
|
||||
|
||||
#include <activemq/connector/ConnectorResource.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
|
||||
class SessionInfo;
|
||||
|
||||
class TransactionInfo : public ConnectorResource
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~TransactionInfo(void) {}
|
||||
|
||||
/**
|
||||
* Gets the Transction Id
|
||||
* @return unsigned int Id
|
||||
*/
|
||||
virtual unsigned int getTransactionId(void) const = 0;
|
||||
|
||||
/**
|
||||
* Sets the Transction Id
|
||||
* @param unsigned int Id
|
||||
*/
|
||||
virtual void setTransactionId( const unsigned int id ) = 0;
|
||||
|
||||
/**
|
||||
* Gets the Session Info that this transaction is attached too
|
||||
* @return SessionnInfo pointer
|
||||
*/
|
||||
virtual const SessionInfo* getSessionInfo(void) const = 0;
|
||||
|
||||
/**
|
||||
* Gets the Session Info that this transaction is attached too
|
||||
* @return SessionnInfo pointer
|
||||
*/
|
||||
virtual void setSessionInfo( const SessionInfo* session ) = 0;
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_TRANSACTIONINFO_H_*/
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_STOMP_STOMPCOMMANDLISTENER_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_STOMP_STOMPCOMMANDLISTENER_H_
|
||||
|
||||
#include <activemq/connector/stomp/commands/StompCommand.h>
|
||||
#include <activemq/connector/stomp/StompConnectorException.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
|
||||
/**
|
||||
* Interface class for object that with to register with the Stomp
|
||||
* Connector in order to process a Command that was received.
|
||||
*/
|
||||
class StompCommandListener
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~StompCommandListener(void) {}
|
||||
|
||||
/**
|
||||
* Process the Stomp Command
|
||||
* @param command to process
|
||||
* @throw ConnterException
|
||||
*/
|
||||
virtual void onStompCommand( commands::StompCommand* command )
|
||||
throw ( StompConnectorException ) = 0;
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_STOMP_STOMPCOMMANDLISTENER_H_*/
|
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#include "StompCommandReader.h"
|
||||
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
#include <activemq/concurrent/Thread.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace activemq;
|
||||
using namespace activemq::concurrent;
|
||||
using namespace activemq::connector;
|
||||
using namespace activemq::connector::stomp;
|
||||
using namespace activemq::transport;
|
||||
using namespace activemq::io;
|
||||
using namespace activemq::exceptions;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
StompCommandReader::StompCommandReader(void)
|
||||
{
|
||||
inputStream = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
StompCommandReader::StompCommandReader(InputStream* is)
|
||||
{
|
||||
inputStream = is;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Command* StompCommandReader::readCommand(void)
|
||||
throw (CommandIOException)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create a new Frame for reading to.
|
||||
StompFrame* frame = new StompFrame();
|
||||
|
||||
// Read the command into the frame.
|
||||
readStompCommand( *frame );
|
||||
|
||||
// Read the headers.
|
||||
readStompHeaders( *frame );
|
||||
|
||||
// Read the body.
|
||||
readStompBody( *frame );
|
||||
|
||||
// Return the Command, caller must delete it.
|
||||
return marshaler.marshal( frame );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( CommandIOException )
|
||||
AMQ_CATCH_EXCEPTION_CONVERT( ActiveMQException, CommandIOException )
|
||||
AMQ_CATCHALL_THROW( CommandIOException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompCommandReader::readStompCommand( StompFrame& frame )
|
||||
throw ( StompConnectorException )
|
||||
{
|
||||
// Read the command;
|
||||
int numChars = readStompHeaderLine();
|
||||
|
||||
if( numChars <= 0 )
|
||||
{
|
||||
throw StompConnectorException(
|
||||
__FILE__, __LINE__,
|
||||
"StompCommandReader::readStompCommand: "
|
||||
"Error on Read of Command Header" );
|
||||
}
|
||||
|
||||
// Set the command in the frame - copy the memory.
|
||||
frame.setCommand( reinterpret_cast<char*>(&buffer[0]) );
|
||||
|
||||
// Clean up the mess.
|
||||
buffer.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompCommandReader::readStompHeaders( StompFrame& frame )
|
||||
throw (StompConnectorException)
|
||||
{
|
||||
// Read the command;
|
||||
bool endOfHeaders = false;
|
||||
|
||||
while( !endOfHeaders )
|
||||
{
|
||||
// Clean up the mess.
|
||||
buffer.clear();
|
||||
|
||||
// Read in the next header line.
|
||||
int numChars = readStompHeaderLine();
|
||||
|
||||
if( numChars == 0 )
|
||||
{
|
||||
// should never get here
|
||||
throw StompConnectorException(
|
||||
__FILE__, __LINE__,
|
||||
"StompCommandReader::readStompHeaders: no characters read" );
|
||||
}
|
||||
|
||||
// Check for an empty line to demark the end of the header section.
|
||||
// if its not the end then we have a header to process, so parse it.
|
||||
if( numChars == 1 && buffer[0] == '\0' )
|
||||
{
|
||||
endOfHeaders = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Search through this line to separate the key/value pair.
|
||||
for( size_t ix = 0; ix < buffer.size(); ++ix )
|
||||
{
|
||||
// If found the key/value separator...
|
||||
if( buffer[ix] == ':' )
|
||||
{
|
||||
// Null-terminate the key.
|
||||
buffer[ix] = '\0';
|
||||
|
||||
const char* key = reinterpret_cast<char*>(&buffer[0]);
|
||||
const char* value = reinterpret_cast<char*>(&buffer[ix+1]);
|
||||
|
||||
// Assign the header key/value pair.
|
||||
frame.getProperties().setProperty(key, value);
|
||||
|
||||
// Break out of the for loop.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up the mess.
|
||||
buffer.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int StompCommandReader::readStompHeaderLine(void)
|
||||
throw (StompConnectorException)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
while( true )
|
||||
{
|
||||
// Read the next char from the stream.
|
||||
buffer.push_back( inputStream->read() );
|
||||
|
||||
// Increment the position pointer.
|
||||
count++;
|
||||
|
||||
// If we reached the line terminator, return the total number
|
||||
// of characters read.
|
||||
if( buffer[count-1] == '\n' )
|
||||
{
|
||||
// Overwrite the line feed with a null character.
|
||||
buffer[count-1] = '\0';
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here something bad must have happened.
|
||||
throw StompConnectorException(
|
||||
__FILE__, __LINE__,
|
||||
"StompCommandReader::readStompHeaderLine: "
|
||||
"Unrecoverable, error condition");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompCommandReader::readStompBody( StompFrame& frame )
|
||||
throw ( StompConnectorException )
|
||||
{
|
||||
unsigned long content_length = 0;
|
||||
|
||||
if(frame.getProperties().hasProperty(
|
||||
commands::CommandConstants::toString(
|
||||
commands::CommandConstants::HEADER_CONTENTLENGTH)))
|
||||
{
|
||||
char* stopped_string = NULL;
|
||||
|
||||
string length =
|
||||
frame.getProperties().getProperty(
|
||||
commands::CommandConstants::toString(
|
||||
commands::CommandConstants::HEADER_CONTENTLENGTH));
|
||||
|
||||
content_length = strtoul(
|
||||
length.c_str(),
|
||||
&stopped_string,
|
||||
10);
|
||||
}
|
||||
|
||||
if(content_length != 0)
|
||||
{
|
||||
// For this case its assumed that content length indicates how
|
||||
// much to read. We reserve space in the buffer for it to
|
||||
// minimize the number of reallocs that might occur. We are
|
||||
// assuming that content length doesn't count the trailing null
|
||||
// that indicates the end of frame. The reserve won't do anything
|
||||
// if the buffer already has that much capacity. The resize call
|
||||
// basically sets the end iterator to the correct location since
|
||||
// this is a char vector and we already reserve enough space.
|
||||
// Resize doesn't realloc the vector smaller if content_length
|
||||
// is less than capacity of the buffer, it just move the end
|
||||
// iterator. Reserve adds the benefit that the mem is set to
|
||||
// zero. Over time as larger messages come in thsi will cause
|
||||
// us to adapt to that size so that future messages that are
|
||||
// around that size won't alloc any new memory.
|
||||
|
||||
buffer.reserve( content_length );
|
||||
buffer.resize( content_length );
|
||||
|
||||
// Read the Content Length now
|
||||
read( &buffer[0], content_length );
|
||||
|
||||
// Content Length read, now pop the end terminator off (\0\n).
|
||||
if(inputStream->read() != '\0' ||
|
||||
inputStream->read() != '\n')
|
||||
{
|
||||
throw StompConnectorException(
|
||||
__FILE__, __LINE__,
|
||||
"StompCommandReader::readStompBody: "
|
||||
"Read Content Length, and no trailing null");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Content length was either zero, or not set, so we read until the
|
||||
// first null is encounted.
|
||||
|
||||
while( true )
|
||||
{
|
||||
char byte = inputStream->read();
|
||||
|
||||
buffer.push_back(byte);
|
||||
|
||||
content_length++;
|
||||
|
||||
if(byte != '\0')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// We read up to the first NULL, now lets pop off the required
|
||||
// newline to complete the packet.
|
||||
if(inputStream->read() != '\n')
|
||||
{
|
||||
throw StompConnectorException(
|
||||
__FILE__, __LINE__,
|
||||
"StompCommandReader::readStompBody: "
|
||||
"Read Body, and no trailing newline");
|
||||
}
|
||||
|
||||
break; // Read null and newline we are done.
|
||||
}
|
||||
}
|
||||
|
||||
if( content_length != 0 )
|
||||
{
|
||||
char* cpyBody = new char[content_length];
|
||||
memcpy(cpyBody, &buffer[0], content_length);
|
||||
|
||||
// Set the body contents in the frame - copy the memory
|
||||
frame.setBody( cpyBody, content_length );
|
||||
}
|
||||
|
||||
// Clean up the mess.
|
||||
buffer.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int StompCommandReader::read(unsigned char* buffer, int count)
|
||||
throw(io::IOException)
|
||||
{
|
||||
if( inputStream == NULL )
|
||||
{
|
||||
throw IOException(
|
||||
__FILE__, __LINE__,
|
||||
"StompCommandReader::read(char*,int) - input stream is NULL" );
|
||||
}
|
||||
|
||||
int head = 0;
|
||||
|
||||
// We call the read(buffer, size) version asking for one
|
||||
// byte, if this returns zero, then there wasn't anything
|
||||
// on the stream to read, so we try again after a short
|
||||
// pause in hopes that some more data will show up.
|
||||
while( true )
|
||||
{
|
||||
head += inputStream->read(&buffer[head], count - head);
|
||||
|
||||
if(head == count)
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
// Got here, so we wait a bit and try again.
|
||||
Thread::sleep( 10 );
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
unsigned char StompCommandReader::readByte(void) throw(io::IOException)
|
||||
{
|
||||
if( inputStream == NULL )
|
||||
{
|
||||
throw IOException(
|
||||
__FILE__, __LINE__,
|
||||
"StompCommandReader::read(char*,int) - input stream is NULL" );
|
||||
}
|
||||
|
||||
unsigned char c = 0;
|
||||
inputStream->read(&c, 1);
|
||||
return c;
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_STOMP_STOMPCOMMANDREADER_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_STOMP_STOMPCOMMANDREADER_H_
|
||||
|
||||
#include <activemq/transport/CommandReader.h>
|
||||
#include <activemq/io/InputStream.h>
|
||||
#include <activemq/transport/CommandIOException.h>
|
||||
#include <activemq/transport/Command.h>
|
||||
#include <activemq/connector/stomp/StompFrame.h>
|
||||
#include <activemq/connector/stomp/StompConnectorException.h>
|
||||
#include <activemq/connector/stomp/marshal/Marshaler.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
|
||||
class StompCommandReader : public transport::CommandReader
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* The target input stream.
|
||||
*/
|
||||
io::InputStream* inputStream;
|
||||
|
||||
/**
|
||||
* Vector Object used to buffer data
|
||||
*/
|
||||
std::vector<unsigned char> buffer;
|
||||
|
||||
/**
|
||||
* Marshaler of Stomp Commands
|
||||
*/
|
||||
marshal::Marshaler marshaler;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Deafult Constructor
|
||||
*/
|
||||
StompCommandReader( void );
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param is the target input stream.
|
||||
*/
|
||||
StompCommandReader( io::InputStream* is );
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~StompCommandReader(void) {}
|
||||
|
||||
/**
|
||||
* Reads a command from the given input stream.
|
||||
* @return The next command available on the stream.
|
||||
* @throws CommandIOException if a problem occurs during the read.
|
||||
*/
|
||||
virtual transport::Command* readCommand( void )
|
||||
throw ( transport::CommandIOException );
|
||||
|
||||
/**
|
||||
* Sets the target input stream.
|
||||
* @param Target Input Stream
|
||||
*/
|
||||
virtual void setInputStream(io::InputStream* is){
|
||||
inputStream = is;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the target input stream.
|
||||
* @return Target Input Stream
|
||||
*/
|
||||
virtual io::InputStream* getInputStream( void ){
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to read an array of bytes from the stream.
|
||||
* @param buffer The target byte buffer.
|
||||
* @param count The number of bytes to read.
|
||||
* @return The number of bytes read.
|
||||
* @throws IOException thrown if an error occurs.
|
||||
*/
|
||||
virtual int read(unsigned char* buffer, int count)
|
||||
throw( io::IOException );
|
||||
|
||||
/**
|
||||
* Attempts to read a byte from the input stream
|
||||
* @return The byte.
|
||||
* @throws IOException thrown if an error occurs.
|
||||
*/
|
||||
virtual unsigned char readByte(void) throw( io::IOException );
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Read the Stomp Command from the Frame
|
||||
* @param reference to a Stomp Frame
|
||||
* @throws StompConnectorException
|
||||
*/
|
||||
void readStompCommand( StompFrame& frame )
|
||||
throw ( StompConnectorException );
|
||||
|
||||
/**
|
||||
* Read all the Stomp Headers for the incoming Frame
|
||||
* @param Frame to place data into
|
||||
* @throws StompConnectorException
|
||||
*/
|
||||
void readStompHeaders( StompFrame& frame )
|
||||
throw ( StompConnectorException );
|
||||
|
||||
/**
|
||||
* Reads a Stomp Header line and stores it in the buffer object
|
||||
* @return number of bytes read, zero if there was a problem.
|
||||
* @throws StompConnectorException
|
||||
*/
|
||||
int readStompHeaderLine( void ) throw ( StompConnectorException );
|
||||
|
||||
/**
|
||||
* Reads the Stomp Body from the Wire and store it in the frame.
|
||||
* @param Stomp Frame to place data in
|
||||
*/
|
||||
void readStompBody( StompFrame& frame )
|
||||
throw ( StompConnectorException );
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_STOMP_STOMPCOMMANDREADER_H_*/
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#include "StompCommandWriter.h"
|
||||
|
||||
#include <activemq/connector/stomp/StompFrame.h>
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace activemq;
|
||||
using namespace activemq::connector;
|
||||
using namespace activemq::connector::stomp;
|
||||
using namespace activemq::connector::stomp::commands;
|
||||
using namespace activemq::transport;
|
||||
using namespace activemq::io;
|
||||
using namespace activemq::exceptions;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
StompCommandWriter::StompCommandWriter(void)
|
||||
{
|
||||
outputStream = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
StompCommandWriter::StompCommandWriter(OutputStream* os)
|
||||
{
|
||||
outputStream = os;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompCommandWriter::writeCommand( const Command* command )
|
||||
throw ( transport::CommandIOException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if( outputStream == NULL )
|
||||
{
|
||||
throw CommandIOException(
|
||||
__FILE__, __LINE__,
|
||||
"StompCommandWriter::writeCommand - "
|
||||
"output stream is NULL" );
|
||||
}
|
||||
|
||||
const StompFrame& frame = marshaler.marshal( command );
|
||||
|
||||
// Write the command.
|
||||
const string& cmdString = frame.getCommand();
|
||||
write( cmdString.c_str(), cmdString.length() );
|
||||
writeByte( '\n' );
|
||||
|
||||
// Write all the headers.
|
||||
vector< pair<string,string> > headers = frame.getProperties().toArray();
|
||||
for( unsigned int ix=0; ix < headers.size(); ++ix )
|
||||
{
|
||||
string& name = headers[ix].first;
|
||||
string& value = headers[ix].second;
|
||||
|
||||
write( name.c_str(), name.length() );
|
||||
writeByte( ':' );
|
||||
write( value.c_str(), value.length() );
|
||||
writeByte( '\n' );
|
||||
}
|
||||
|
||||
// Finish the header section with a form feed.
|
||||
writeByte( '\n' );
|
||||
|
||||
// Write the body.
|
||||
const char* body = frame.getBody();
|
||||
if( body != NULL )
|
||||
{
|
||||
write( body, frame.getBodyLength() );
|
||||
}
|
||||
|
||||
if( ( frame.getBodyLength() == 0 ) ||
|
||||
( frame.getProperties().getProperty(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_CONTENTLENGTH ), "" ) != "" ) )
|
||||
{
|
||||
writeByte( '\0' );
|
||||
}
|
||||
|
||||
writeByte( '\n' );
|
||||
|
||||
// Flush the stream.
|
||||
outputStream->flush();
|
||||
}
|
||||
AMQ_CATCH_RETHROW( CommandIOException )
|
||||
AMQ_CATCH_EXCEPTION_CONVERT( ActiveMQException, CommandIOException )
|
||||
AMQ_CATCHALL_THROW( CommandIOException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompCommandWriter::write(const unsigned char* buffer, int count)
|
||||
throw(IOException)
|
||||
{
|
||||
if( outputStream == NULL )
|
||||
{
|
||||
throw IOException(
|
||||
__FILE__, __LINE__,
|
||||
"StompCommandWriter::write(char*,int) - input stream is NULL" );
|
||||
}
|
||||
|
||||
outputStream->write( buffer, count );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompCommandWriter::writeByte(unsigned char v) throw(IOException)
|
||||
{
|
||||
if( outputStream == NULL )
|
||||
{
|
||||
throw IOException(
|
||||
__FILE__, __LINE__,
|
||||
"StompCommandWriter::write(char) - input stream is NULL" );
|
||||
}
|
||||
|
||||
outputStream->write( v );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompCommandWriter::write(const char* buffer, int count)
|
||||
throw(io::IOException)
|
||||
{
|
||||
write(reinterpret_cast<const unsigned char*>(buffer), count);
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_STOMP_STOMPCOMMANDWRITER_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_STOMP_STOMPCOMMANDWRITER_H_
|
||||
|
||||
#include <activemq/transport/CommandWriter.h>
|
||||
#include <activemq/io/InputStream.h>
|
||||
#include <activemq/transport/CommandIOException.h>
|
||||
#include <activemq/connector/stomp/StompConnectorException.h>
|
||||
#include <activemq/transport/Command.h>
|
||||
#include <activemq/io/OutputStream.h>
|
||||
#include <activemq/connector/stomp/marshal/Marshaler.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
|
||||
class StompCommandWriter : public transport::CommandWriter
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* Target output stream.
|
||||
*/
|
||||
io::OutputStream* outputStream;
|
||||
|
||||
/**
|
||||
* Marshaler of Stomp Commands
|
||||
*/
|
||||
marshal::Marshaler marshaler;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Default Constructor
|
||||
*/
|
||||
StompCommandWriter(void);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param os the target output stream.
|
||||
*/
|
||||
StompCommandWriter( io::OutputStream* os );
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~StompCommandWriter(void) {}
|
||||
|
||||
/**
|
||||
* Sets the target output stream.
|
||||
*/
|
||||
virtual void setOutputStream(io::OutputStream* os){
|
||||
outputStream = os;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the target output stream.
|
||||
*/
|
||||
virtual io::OutputStream* getOutputStream(void){
|
||||
return outputStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a command to the given output stream.
|
||||
* @param command the command to write.
|
||||
* @param os the target stream for the write.
|
||||
* @throws CommandIOException if a problem occurs during the write.
|
||||
*/
|
||||
virtual void writeCommand( const transport::Command* command )
|
||||
throw ( transport::CommandIOException );
|
||||
|
||||
/**
|
||||
* Writes a byte array to the output stream.
|
||||
* @param buffer a byte array
|
||||
* @param count the number of bytes in the array to write.
|
||||
* @throws IOException thrown if an error occurs.
|
||||
*/
|
||||
virtual void write(const unsigned char* buffer, int count)
|
||||
throw( io::IOException );
|
||||
|
||||
/**
|
||||
* Writes a byte to the output stream.
|
||||
* @param v The value to be written.
|
||||
* @throws IOException thrown if an error occurs.
|
||||
*/
|
||||
virtual void writeByte(unsigned char v) throw( io::IOException );
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Writes a char array to the output stream.
|
||||
* @param buffer a char array
|
||||
* @param count the number of bytes in the array to write.
|
||||
* @throws IOException thrown if an error occurs.
|
||||
*/
|
||||
virtual void write(const char* buffer, int count)
|
||||
throw( io::IOException );
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_STOMP_STOMPCOMMANDWRITER_H_*/
|
|
@ -0,0 +1,795 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#include <activemq/connector/stomp/StompConnector.h>
|
||||
#include <activemq/concurrent/Concurrent.h>
|
||||
#include <activemq/transport/BrokerError.h>
|
||||
#include <activemq/transport/Transport.h>
|
||||
#include <activemq/transport/ExceptionResponse.h>
|
||||
#include <activemq/connector/stomp/StompTopic.h>
|
||||
#include <activemq/connector/stomp/StompQueue.h>
|
||||
#include <activemq/connector/stomp/commands/ConnectCommand.h>
|
||||
#include <activemq/connector/stomp/commands/ErrorCommand.h>
|
||||
#include <activemq/connector/stomp/commands/BeginCommand.h>
|
||||
#include <activemq/connector/stomp/commands/AbortCommand.h>
|
||||
#include <activemq/connector/stomp/commands/AckCommand.h>
|
||||
#include <activemq/connector/stomp/commands/CommitCommand.h>
|
||||
#include <activemq/connector/stomp/commands/MessageCommand.h>
|
||||
#include <activemq/connector/stomp/commands/BytesMessageCommand.h>
|
||||
#include <activemq/connector/stomp/commands/TextMessageCommand.h>
|
||||
#include <activemq/connector/stomp/commands/ConnectedCommand.h>
|
||||
#include <activemq/connector/stomp/commands/DisconnectCommand.h>
|
||||
#include <activemq/exceptions/UnsupportedOperationException.h>
|
||||
#include <activemq/connector/stomp/StompProducerInfo.h>
|
||||
#include <activemq/connector/stomp/StompTransactionInfo.h>
|
||||
#include <activemq/util/Integer.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace activemq;
|
||||
using namespace activemq::connector;
|
||||
using namespace activemq::util;
|
||||
using namespace activemq::transport;
|
||||
using namespace activemq::exceptions;
|
||||
using namespace activemq::connector::stomp;
|
||||
using namespace activemq::connector::stomp::commands;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
StompConnector::StompConnector( Transport* transport,
|
||||
const util::Properties& properties )
|
||||
throw ( IllegalArgumentException )
|
||||
{
|
||||
if(transport == NULL)
|
||||
{
|
||||
throw IllegalArgumentException(
|
||||
__FILE__, __LINE__,
|
||||
"StompConnector::StompConnector - Transport cannot be NULL");
|
||||
}
|
||||
|
||||
this->transport = transport;
|
||||
this->state = DISCONNECTED;
|
||||
this->exceptionListener = NULL;
|
||||
this->messageListener = NULL;
|
||||
this->sessionManager = NULL;
|
||||
this->nextProducerId = 0;
|
||||
this->nextTransactionId = 0;
|
||||
this->properties.copy( &properties );
|
||||
|
||||
// Observe the transport for events.
|
||||
this->transport->setCommandListener( this );
|
||||
this->transport->setTransportExceptionListener( this );
|
||||
|
||||
// Setup the reader and writer in the transport.
|
||||
this->transport->setCommandReader( &reader );
|
||||
this->transport->setCommandWriter( &writer );
|
||||
|
||||
// Register ourself for those commands that we process
|
||||
addCmdListener( CommandConstants::ERROR_CMD, this );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
StompConnector::~StompConnector(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
close();
|
||||
|
||||
delete sessionManager;
|
||||
}
|
||||
AMQ_CATCH_NOTHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_NOTHROW( )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
unsigned int StompConnector::getNextProducerId(void)
|
||||
{
|
||||
synchronized(&mutex)
|
||||
{
|
||||
return nextProducerId++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
unsigned int StompConnector::getNextTransactionId(void)
|
||||
{
|
||||
synchronized(&mutex)
|
||||
{
|
||||
return nextTransactionId++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompConnector::enforceConnected( void ) throw ( ConnectorException )
|
||||
{
|
||||
if( state != CONNECTED )
|
||||
{
|
||||
throw StompConnectorException(
|
||||
__FILE__, __LINE__,
|
||||
"StompConnector::enforceConnected - Not Connected!" );
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompConnector::addCmdListener(
|
||||
commands::CommandConstants::CommandId commandId,
|
||||
StompCommandListener* listener )
|
||||
{
|
||||
cmdListenerMap.insert( make_pair( commandId, listener ) );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompConnector::removeCmdListener(
|
||||
commands::CommandConstants::CommandId commandId )
|
||||
{
|
||||
cmdListenerMap.erase(commandId);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompConnector::start(void) throw( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized( &mutex )
|
||||
{
|
||||
if( state == CONNECTED )
|
||||
{
|
||||
throw ActiveMQException(
|
||||
__FILE__, __LINE__,
|
||||
"StompConnector::start - already started" );
|
||||
}
|
||||
|
||||
// Start the transport - this establishes the socket.
|
||||
transport->start();
|
||||
|
||||
// Send the connect message to the broker.
|
||||
connect();
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompConnector::close(void) throw( cms::CMSException ){
|
||||
|
||||
try
|
||||
{
|
||||
synchronized( &mutex )
|
||||
{
|
||||
if( state == this->CONNECTED )
|
||||
{
|
||||
// Send the disconnect message to the broker.
|
||||
disconnect();
|
||||
|
||||
// Close the transport.
|
||||
transport->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompConnector::connect(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Mark this connector as started.
|
||||
state = this->CONNECTING;
|
||||
|
||||
// Send the connect command to the broker
|
||||
ConnectCommand cmd;
|
||||
|
||||
// Encode User Name and Password and Client ID
|
||||
string login = getLogin();
|
||||
if( login.length() > 0 ){
|
||||
cmd.setLogin( login );
|
||||
}
|
||||
string password = getPassword();
|
||||
if( password.length() > 0 ){
|
||||
cmd.setPassword( password );
|
||||
}
|
||||
string clientId = getClientId();
|
||||
if( clientId.length() > 0 ){
|
||||
cmd.setClientId( clientId );
|
||||
}
|
||||
|
||||
Response* response = transport->request( &cmd );
|
||||
|
||||
if( dynamic_cast< ExceptionResponse* >( response ) != NULL )
|
||||
{
|
||||
throw StompConnectorException(
|
||||
__FILE__, __LINE__,
|
||||
"StompConnector::connect - Failed on Connect Request" );
|
||||
}
|
||||
|
||||
ConnectedCommand* connected =
|
||||
dynamic_cast< ConnectedCommand* >( response );
|
||||
|
||||
if( connected == NULL )
|
||||
{
|
||||
throw StompConnectorException(
|
||||
__FILE__, __LINE__,
|
||||
"StompConnector::connect - "
|
||||
"Response not a connected response" );
|
||||
}
|
||||
|
||||
// Connected so we now create the SessionManager
|
||||
sessionManager = new StompSessionManager(
|
||||
connected->getSessionId(), transport );
|
||||
|
||||
// Give our message listener to the session manager it will
|
||||
// notify all the interested clients
|
||||
sessionManager->setConsumerMessageListener( messageListener );
|
||||
|
||||
// Add the Session Manager as the Command Listener for
|
||||
// Message commands so that it can route them to the
|
||||
// correct consumers.
|
||||
addCmdListener( CommandConstants::MESSAGE, sessionManager );
|
||||
|
||||
// In Stomp, the client Id is the same as the session id that is
|
||||
// returned in the Connected response
|
||||
properties.setProperty(
|
||||
commands::CommandConstants::toString(
|
||||
commands::CommandConstants::HEADER_CLIENT_ID ),
|
||||
connected->getSessionId() );
|
||||
|
||||
// Tag us in the Connected State now.
|
||||
state = CONNECTED;
|
||||
|
||||
// Clean up
|
||||
delete response;
|
||||
}
|
||||
AMQ_CATCH_RETHROW( BrokerError )
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompConnector::disconnect(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Mark state as no longer connected.
|
||||
state = this->DISCONNECTED;
|
||||
|
||||
// Send the disconnect command to the broker.
|
||||
DisconnectCommand cmd;
|
||||
transport->oneway( &cmd );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
SessionInfo* StompConnector::createSession(
|
||||
cms::Session::AcknowledgeMode ackMode)
|
||||
throw( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
enforceConnected();
|
||||
|
||||
return sessionManager->createSession( ackMode );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ConsumerInfo* StompConnector::createConsumer(
|
||||
cms::Destination* destination,
|
||||
SessionInfo* session,
|
||||
const std::string& selector)
|
||||
throw ( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
enforceConnected();
|
||||
|
||||
return sessionManager->createConsumer(
|
||||
destination, session, selector );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ConsumerInfo* StompConnector::createDurableConsumer(
|
||||
cms::Topic* topic,
|
||||
SessionInfo* session,
|
||||
const std::string& name,
|
||||
const std::string& selector,
|
||||
bool noLocal)
|
||||
throw ( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
enforceConnected();
|
||||
|
||||
return sessionManager->createDurableConsumer(
|
||||
topic, session, name, selector, noLocal );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ProducerInfo* StompConnector::createProducer(
|
||||
cms::Destination* destination,
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
enforceConnected();
|
||||
|
||||
ProducerInfo* producer = new StompProducerInfo();
|
||||
|
||||
producer->setDestination( *destination );
|
||||
producer->setProducerId( getNextProducerId() );
|
||||
producer->setSessionInfo( session );
|
||||
|
||||
return producer;
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::Topic* StompConnector::createTopic(const std::string& name,
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
enforceConnected();
|
||||
|
||||
return new StompTopic(name);
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::Queue* StompConnector::createQueue(const std::string& name,
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
enforceConnected();
|
||||
|
||||
return new StompQueue(name);
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::TemporaryTopic* StompConnector::createTemporaryTopic(
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
throw UnsupportedOperationException(
|
||||
__FILE__, __LINE__,
|
||||
"StompConnector::createTemporaryTopic - No Stomp Support");
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::TemporaryQueue* StompConnector::createTemporaryQueue(
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
throw UnsupportedOperationException(
|
||||
__FILE__, __LINE__,
|
||||
"StompConnector::createTemporaryQueue - No Stomp Support");
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompConnector::send(cms::Message* message,
|
||||
ProducerInfo* producerInfo)
|
||||
throw ( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
enforceConnected();
|
||||
|
||||
const SessionInfo* session = producerInfo->getSessionInfo();
|
||||
Command* command = dynamic_cast< transport::Command* >( message );
|
||||
|
||||
if( command == NULL )
|
||||
{
|
||||
throw StompConnectorException(
|
||||
__FILE__, __LINE__,
|
||||
"StompConnector::send - "
|
||||
"Message is not a valid stomp type.");
|
||||
}
|
||||
|
||||
if( session->getAckMode() == cms::Session::Transactional )
|
||||
{
|
||||
StompCommand* stompCommand =
|
||||
dynamic_cast< StompCommand* >( message );
|
||||
|
||||
if( stompCommand == NULL )
|
||||
{
|
||||
throw StompConnectorException(
|
||||
__FILE__, __LINE__,
|
||||
"StompConnector::send - "
|
||||
"Message is not a valid stomp type.");
|
||||
}
|
||||
|
||||
stompCommand->setTransactionId(
|
||||
Integer::toString(
|
||||
session->getTransactionInfo()->getTransactionId() ) );
|
||||
}
|
||||
|
||||
// Send it
|
||||
transport->oneway( command );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompConnector::send(std::list<cms::Message*>& messages,
|
||||
ProducerInfo* producerInfo)
|
||||
throw ( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
enforceConnected();
|
||||
|
||||
list<cms::Message*>::const_iterator itr = messages.begin();
|
||||
|
||||
for(; itr != messages.end(); ++itr)
|
||||
{
|
||||
this->send(*itr, producerInfo);
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompConnector::acknowledge( const SessionInfo* session,
|
||||
const cms::Message* message,
|
||||
AckType ackType = ConsumedAck )
|
||||
throw ( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
enforceConnected();
|
||||
|
||||
// Auto to Stomp means don't do anything, so we drop it here
|
||||
// for client acknowledge we have to send and ack.
|
||||
if( session->getAckMode() == cms::Session::ClientAcknowledge )
|
||||
{
|
||||
AckCommand cmd;
|
||||
|
||||
if( message->getCMSMessageId() == NULL )
|
||||
{
|
||||
throw StompConnectorException(
|
||||
__FILE__, __LINE__,
|
||||
"StompConnector::send - "
|
||||
"Message has no Message Id, cannot ack.");
|
||||
}
|
||||
|
||||
cmd.setMessageId( message->getCMSMessageId() );
|
||||
|
||||
if( session->getAckMode() == cms::Session::Transactional )
|
||||
{
|
||||
cmd.setTransactionId(
|
||||
Integer::toString(
|
||||
session->getTransactionInfo()->getTransactionId() ) );
|
||||
}
|
||||
|
||||
transport->oneway( &cmd );
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
TransactionInfo* StompConnector::startTransaction(
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
enforceConnected();
|
||||
|
||||
TransactionInfo* transaction = new StompTransactionInfo();
|
||||
|
||||
transaction->setTransactionId( getNextTransactionId() );
|
||||
|
||||
session->setTransactionInfo( transaction );
|
||||
|
||||
BeginCommand cmd;
|
||||
|
||||
cmd.setTransactionId(
|
||||
Integer::toString( transaction->getTransactionId() ) );
|
||||
|
||||
transport->oneway( &cmd );
|
||||
|
||||
return transaction;
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompConnector::commit(TransactionInfo* transaction,
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
enforceConnected();
|
||||
|
||||
CommitCommand cmd;
|
||||
|
||||
cmd.setTransactionId(
|
||||
Integer::toString( transaction->getTransactionId() ) );
|
||||
|
||||
transport->oneway( &cmd );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompConnector::rollback(TransactionInfo* transaction,
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
enforceConnected();
|
||||
|
||||
AbortCommand cmd;
|
||||
|
||||
cmd.setTransactionId(
|
||||
Integer::toString( transaction->getTransactionId() ) );
|
||||
|
||||
transport->oneway( &cmd );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::Message* StompConnector::createMessage(
|
||||
SessionInfo* session,
|
||||
TransactionInfo* transaction)
|
||||
throw ( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
enforceConnected();
|
||||
|
||||
MessageCommand* cmd = new MessageCommand();
|
||||
|
||||
if( transaction != NULL )
|
||||
{
|
||||
cmd->setTransactionId(
|
||||
Integer::toString( transaction->getTransactionId() ) );
|
||||
}
|
||||
|
||||
return cmd;
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::BytesMessage* StompConnector::createBytesMessage(
|
||||
SessionInfo* session,
|
||||
TransactionInfo* transaction)
|
||||
throw ( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
enforceConnected();
|
||||
|
||||
BytesMessageCommand* cmd = new BytesMessageCommand();
|
||||
|
||||
if( transaction != NULL )
|
||||
{
|
||||
cmd->setTransactionId(
|
||||
Integer::toString( transaction->getTransactionId() ) );
|
||||
}
|
||||
|
||||
return cmd;
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::TextMessage* StompConnector::createTextMessage(
|
||||
SessionInfo* session,
|
||||
TransactionInfo* transaction)
|
||||
throw ( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
enforceConnected();
|
||||
|
||||
TextMessageCommand* cmd = new TextMessageCommand;
|
||||
|
||||
if( transaction != NULL )
|
||||
{
|
||||
cmd->setTransactionId(
|
||||
Integer::toString( transaction->getTransactionId() ) );
|
||||
}
|
||||
|
||||
return cmd;
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::MapMessage* StompConnector::createMapMessage(
|
||||
SessionInfo* session,
|
||||
TransactionInfo* transaction)
|
||||
throw ( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
throw UnsupportedOperationException(
|
||||
__FILE__, __LINE__,
|
||||
"StompConnector::createTemporaryQueue - No Stomp Support");
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompConnector::unsubscribe(const std::string& name)
|
||||
throw ( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
throw UnsupportedOperationException(
|
||||
__FILE__, __LINE__,
|
||||
"StompConnector::createTemporaryQueue - No Stomp Support");
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompConnector::destroyResource( ConnectorResource* resource )
|
||||
throw ( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
ConsumerInfo* consumer =
|
||||
dynamic_cast<ConsumerInfo*>(resource);
|
||||
SessionInfo* session =
|
||||
dynamic_cast<SessionInfo*>(resource);
|
||||
|
||||
if( consumer != NULL)
|
||||
{
|
||||
sessionManager->removeConsumer( consumer );
|
||||
}
|
||||
else if( session != NULL)
|
||||
{
|
||||
sessionManager->removeSession( session );
|
||||
}
|
||||
|
||||
// No matter what we end it here.
|
||||
delete resource;
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompConnector::onCommand( transport::Command* command )
|
||||
{
|
||||
try
|
||||
{
|
||||
StompCommand* stompCommand = dynamic_cast< StompCommand* >(command);
|
||||
|
||||
if(stompCommand == NULL)
|
||||
{
|
||||
fire( ConnectorException(
|
||||
__FILE__, __LINE__,
|
||||
"StompConnector::onCommand - Recieved an unknown Command") );
|
||||
}
|
||||
|
||||
CmdListenerMap::iterator itr =
|
||||
cmdListenerMap.find( stompCommand->getStompCommandId() );
|
||||
|
||||
if( itr == cmdListenerMap.end() )
|
||||
{
|
||||
fire( ConnectorException(
|
||||
__FILE__, __LINE__,
|
||||
"StompConnector::onCommand - "
|
||||
"Recieved command with no listener") );
|
||||
|
||||
// This isn't going an farther, so delete it.
|
||||
delete command;
|
||||
|
||||
return; // we are done
|
||||
}
|
||||
|
||||
// Hand off
|
||||
itr->second->onStompCommand( stompCommand );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompConnector::onTransportException(
|
||||
transport::Transport* source,
|
||||
const exceptions::ActiveMQException& ex )
|
||||
{
|
||||
try
|
||||
{
|
||||
// Inform the user.
|
||||
fire( ex );
|
||||
|
||||
// Close down.
|
||||
close();
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompConnector::onStompCommand( commands::StompCommand* command )
|
||||
throw ( StompConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
ErrorCommand* error =
|
||||
dynamic_cast<ErrorCommand*>(command);
|
||||
|
||||
if(error != NULL)
|
||||
{
|
||||
fire( StompConnectorException(
|
||||
__FILE__, __LINE__,
|
||||
(string( "StompConnector::onStompCommand - " ) +
|
||||
error->getErrorMessage() ).c_str() ) );
|
||||
|
||||
// Shutdown
|
||||
close();
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( StompConnectorException )
|
||||
AMQ_CATCHALL_THROW( StompConnectorException );
|
||||
}
|
|
@ -0,0 +1,533 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef ACTIVEMQ_CONNECTOR_STOMP_STOMPCONNECTOR_H_
|
||||
#define ACTIVEMQ_CONNECTOR_STOMP_STOMPCONNECTOR_H_
|
||||
|
||||
#include <activemq/connector/Connector.h>
|
||||
#include <activemq/transport/Transport.h>
|
||||
#include <activemq/transport/CommandListener.h>
|
||||
#include <activemq/transport/TransportExceptionListener.h>
|
||||
#include <activemq/concurrent/Mutex.h>
|
||||
#include <activemq/util/Properties.h>
|
||||
#include <activemq/connector/stomp/StompCommandReader.h>
|
||||
#include <activemq/connector/stomp/StompCommandWriter.h>
|
||||
#include <activemq/connector/stomp/StompCommandListener.h>
|
||||
#include <activemq/connector/stomp/StompSessionManager.h>
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
#include <activemq/exceptions/IllegalArgumentException.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
|
||||
/**
|
||||
* The connector implementation for the STOMP protocol.
|
||||
*/
|
||||
class StompConnector
|
||||
:
|
||||
public Connector,
|
||||
public transport::CommandListener,
|
||||
public transport::TransportExceptionListener,
|
||||
public StompCommandListener
|
||||
{
|
||||
private:
|
||||
|
||||
// Flags the state we are in for connection to broker.
|
||||
enum connectionState
|
||||
{
|
||||
DISCONNECTED,
|
||||
CONNECTING,
|
||||
CONNECTED
|
||||
};
|
||||
|
||||
// Maps Command Ids to listener that are interested
|
||||
typedef std::map< commands::CommandConstants::CommandId,
|
||||
StompCommandListener*> CmdListenerMap;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* The transport for sending/receiving commands on the wire.
|
||||
*/
|
||||
transport::Transport* transport;
|
||||
|
||||
/**
|
||||
* Flag to indicate the start state of the connector.
|
||||
*/
|
||||
connectionState state;
|
||||
|
||||
/**
|
||||
* Sync object.
|
||||
*/
|
||||
concurrent::Mutex mutex;
|
||||
|
||||
/**
|
||||
* Observer of messages directed at a particular
|
||||
* consumer.
|
||||
*/
|
||||
ConsumerMessageListener* messageListener;
|
||||
|
||||
/**
|
||||
* Observer of connector exceptions.
|
||||
*/
|
||||
cms::ExceptionListener* exceptionListener;
|
||||
|
||||
/**
|
||||
* This Connector's Command Reader
|
||||
*/
|
||||
StompCommandReader reader;
|
||||
|
||||
/**
|
||||
* This Connector's Command Writer
|
||||
*/
|
||||
StompCommandWriter writer;
|
||||
|
||||
/**
|
||||
* Map to hold StompCommandListeners
|
||||
*/
|
||||
CmdListenerMap cmdListenerMap;
|
||||
|
||||
/**
|
||||
* Session Manager object that will be allocated when we connect
|
||||
*/
|
||||
StompSessionManager* sessionManager;
|
||||
|
||||
/**
|
||||
* Next avaliable Producer Id
|
||||
*/
|
||||
unsigned int nextProducerId;
|
||||
|
||||
/**
|
||||
* Next avaliable Transaction Id
|
||||
*/
|
||||
unsigned int nextTransactionId;
|
||||
|
||||
/**
|
||||
* Properties for the connector.
|
||||
*/
|
||||
util::SimpleProperties properties;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Sends the connect message to the broker and
|
||||
* waits for the response.
|
||||
*/
|
||||
void connect(void);
|
||||
|
||||
/**
|
||||
* Sends a oneway disconnect message to the broker.
|
||||
*/
|
||||
void disconnect(void);
|
||||
|
||||
/**
|
||||
* Fires a consumer message to the observer.
|
||||
*/
|
||||
void fire( ConsumerInfo* consumer, core::ActiveMQMessage* msg ){
|
||||
try{
|
||||
if( messageListener != NULL ){
|
||||
messageListener->onConsumerMessage(
|
||||
consumer,
|
||||
msg );
|
||||
}
|
||||
}catch( ... ){/* do nothing*/}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires an exception event to the observing object.
|
||||
*/
|
||||
void fire( const exceptions::ActiveMQException& ex ){
|
||||
try{
|
||||
if( exceptionListener != NULL ){
|
||||
exceptionListener->onException( ex );
|
||||
}
|
||||
}catch( ... ){/* do nothing*/}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor for the stomp connector.
|
||||
* @param transport the transport object for sending/receiving
|
||||
* commands on the wire.
|
||||
* @param props properties for configuring the connector.
|
||||
*/
|
||||
StompConnector( transport::Transport* transport,
|
||||
const util::Properties& properties )
|
||||
throw ( exceptions::IllegalArgumentException );
|
||||
|
||||
virtual ~StompConnector(void);
|
||||
|
||||
/**
|
||||
* Starts the service.
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual void start(void) throw( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Closes this object and deallocates the appropriate resources.
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual void close(void) throw( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Gets the Client Id for this connection, if this
|
||||
* connection has been closed, then this method returns ""
|
||||
* @return Client Id String
|
||||
*/
|
||||
virtual std::string getClientId(void) const {
|
||||
return properties.getProperty(
|
||||
commands::CommandConstants::toString(
|
||||
commands::CommandConstants::HEADER_CLIENT_ID ), "" );
|
||||
}
|
||||
|
||||
virtual std::string getLogin(void) const {
|
||||
return properties.getProperty(
|
||||
commands::CommandConstants::toString(
|
||||
commands::CommandConstants::HEADER_LOGIN ), "" );
|
||||
}
|
||||
|
||||
virtual std::string getPassword(void) const {
|
||||
return properties.getProperty(
|
||||
commands::CommandConstants::toString(
|
||||
commands::CommandConstants::HEADER_PASSWORD ), "" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to the Transport that this connection
|
||||
* is using.
|
||||
* @param reference to a transport
|
||||
* @throws InvalidStateException if the Transport is not set
|
||||
*/
|
||||
virtual transport::Transport& getTransport(void) const
|
||||
throw (exceptions::InvalidStateException ) {
|
||||
|
||||
if( transport == NULL ) {
|
||||
throw exceptions::InvalidStateException(
|
||||
__FILE__, __LINE__,
|
||||
"StompConnector::getTransport - "
|
||||
"Invalid State, No Transport.");
|
||||
}
|
||||
|
||||
return *transport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Session Info object for this connector
|
||||
* @param Acknowledgement Mode of the Session
|
||||
* @returns Session Info Object
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual SessionInfo* createSession(
|
||||
cms::Session::AcknowledgeMode ackMode)
|
||||
throw( ConnectorException );
|
||||
|
||||
/**
|
||||
* Create a Consumer for the given Session
|
||||
* @param Destination to Subscribe to.
|
||||
* @param Session Information.
|
||||
* @return Consumer Information
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual ConsumerInfo* createConsumer(
|
||||
cms::Destination* destination,
|
||||
SessionInfo* session,
|
||||
const std::string& selector = "")
|
||||
throw ( ConnectorException );
|
||||
|
||||
/**
|
||||
* Create a Durable Consumer for the given Session
|
||||
* @param Topic to Subscribe to.
|
||||
* @param Session Information.
|
||||
* @param name of the Durable Topic
|
||||
* @param Selector
|
||||
* @param if set, inhibits the delivery of messages
|
||||
* published by its own connection
|
||||
* @return Consumer Information
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual ConsumerInfo* createDurableConsumer(
|
||||
cms::Topic* topic,
|
||||
SessionInfo* session,
|
||||
const std::string& name,
|
||||
const std::string& selector = "",
|
||||
bool noLocal = false)
|
||||
throw ( ConnectorException );
|
||||
|
||||
/**
|
||||
* Create a Consumer for the given Session
|
||||
* @param Destination to Subscribe to.
|
||||
* @param Session Information.
|
||||
* @return Producer Information
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual ProducerInfo* createProducer(
|
||||
cms::Destination* destination,
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException );
|
||||
|
||||
/**
|
||||
* Creates a Topic given a name and session info
|
||||
* @param Topic Name
|
||||
* @param Session Information
|
||||
* @return a newly created Topic Object
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual cms::Topic* createTopic( const std::string& name,
|
||||
SessionInfo* session )
|
||||
throw ( ConnectorException );
|
||||
|
||||
/**
|
||||
* Creates a Queue given a name and session info
|
||||
* @param Queue Name
|
||||
* @param Session Information
|
||||
* @return a newly created Queue Object
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual cms::Queue* createQueue( const std::string& name,
|
||||
SessionInfo* session )
|
||||
throw ( ConnectorException );
|
||||
|
||||
/**
|
||||
* Creates a Temporary Topic given a name and session info
|
||||
* @param Temporary Topic Name
|
||||
* @param Session Information
|
||||
* @return a newly created Temporary Topic Object
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual cms::TemporaryTopic* createTemporaryTopic(
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException );
|
||||
|
||||
/**
|
||||
* Creates a Temporary Queue given a name and session info
|
||||
* @param Temporary Queue Name
|
||||
* @param Session Information
|
||||
* @return a newly created Temporary Queue Object
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual cms::TemporaryQueue* createTemporaryQueue(
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException );
|
||||
|
||||
/**
|
||||
* Sends a Message
|
||||
* @param The Message to send.
|
||||
* @param Producer Info for the sender of this message
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual void send( cms::Message* message, ProducerInfo* producerInfo )
|
||||
throw ( ConnectorException );
|
||||
|
||||
/**
|
||||
* Sends a set of Messages
|
||||
* @param List of Messages to send.
|
||||
* @param Producer Info for the sender of this message
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual void send( std::list<cms::Message*>& messages,
|
||||
ProducerInfo* producerInfo )
|
||||
throw ( ConnectorException );
|
||||
|
||||
/**
|
||||
* Acknowledges a Message
|
||||
* @param An ActiveMQMessage to Ack.
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual void acknowledge( const SessionInfo* session,
|
||||
const cms::Message* message,
|
||||
AckType ackType)
|
||||
throw ( ConnectorException );
|
||||
|
||||
/**
|
||||
* Starts a new Transaction.
|
||||
* @param Session Information
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual TransactionInfo* startTransaction(
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException );
|
||||
|
||||
/**
|
||||
* Commits a Transaction.
|
||||
* @param The Transaction information
|
||||
* @param Session Information
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual void commit(TransactionInfo* transaction,
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException );
|
||||
|
||||
/**
|
||||
* Rolls back a Transaction.
|
||||
* @param The Transaction information
|
||||
* @param Session Information
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual void rollback(TransactionInfo* transaction,
|
||||
SessionInfo* session)
|
||||
throw ( ConnectorException );
|
||||
|
||||
/**
|
||||
* Creates a new Message.
|
||||
* @param Session Information
|
||||
* @param Transaction Info for this Message
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual cms::Message* createMessage(
|
||||
SessionInfo* session,
|
||||
TransactionInfo* transaction)
|
||||
throw ( ConnectorException );
|
||||
|
||||
/**
|
||||
* Creates a new BytesMessage.
|
||||
* @param Session Information
|
||||
* @param Transaction Info for this Message
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual cms::BytesMessage* createBytesMessage(
|
||||
SessionInfo* session,
|
||||
TransactionInfo* transaction)
|
||||
throw ( ConnectorException );
|
||||
|
||||
/**
|
||||
* Creates a new TextMessage.
|
||||
* @param Session Information
|
||||
* @param Transaction Info for this Message
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual cms::TextMessage* createTextMessage(
|
||||
SessionInfo* session,
|
||||
TransactionInfo* transaction)
|
||||
throw ( ConnectorException );
|
||||
|
||||
/**
|
||||
* Creates a new MapMessage.
|
||||
* @param Session Information
|
||||
* @param Transaction Info for this Message
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual cms::MapMessage* createMapMessage(
|
||||
SessionInfo* session,
|
||||
TransactionInfo* transaction)
|
||||
throw ( ConnectorException );
|
||||
|
||||
/**
|
||||
* Unsubscribe from a givenDurable Subscription
|
||||
* @param name of the Subscription
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual void unsubscribe( const std::string& name )
|
||||
throw ( ConnectorException );
|
||||
|
||||
/**
|
||||
* Destroys the given connector resource.
|
||||
* @param resource the resource to be destroyed.
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual void destroyResource( ConnectorResource* resource )
|
||||
throw ( ConnectorException );
|
||||
|
||||
/**
|
||||
* Sets the listener of consumer messages.
|
||||
* @param listener the observer.
|
||||
*/
|
||||
virtual void setConsumerMessageListener(
|
||||
ConsumerMessageListener* listener)
|
||||
{
|
||||
this->messageListener = listener;
|
||||
|
||||
if(sessionManager != NULL)
|
||||
{
|
||||
sessionManager->setConsumerMessageListener( listener );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Listner of exceptions for this connector
|
||||
* @param ExceptionListener the observer.
|
||||
*/
|
||||
virtual void setExceptionListener(
|
||||
cms::ExceptionListener* listener)
|
||||
{
|
||||
this->exceptionListener = listener;
|
||||
}
|
||||
|
||||
public: // transport::CommandListener
|
||||
|
||||
/**
|
||||
* Event handler for the receipt of a non-response command from the
|
||||
* transport.
|
||||
* @param command the received command object.
|
||||
*/
|
||||
virtual void onCommand( transport::Command* command );
|
||||
|
||||
public: // TransportExceptionListener
|
||||
|
||||
/**
|
||||
* Event handler for an exception from a command transport.
|
||||
* @param source The source of the exception
|
||||
* @param ex The exception.
|
||||
*/
|
||||
virtual void onTransportException(
|
||||
transport::Transport* source,
|
||||
const exceptions::ActiveMQException& ex );
|
||||
|
||||
public: // StompCommandListener
|
||||
|
||||
/**
|
||||
* Process the Stomp Command
|
||||
* @param command to process
|
||||
* @throw ConnterException
|
||||
*/
|
||||
virtual void onStompCommand( commands::StompCommand* command )
|
||||
throw ( StompConnectorException );
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Registers a Command Listener using the CommandId specified
|
||||
* if there is already a listener for that command it will be
|
||||
* removed.
|
||||
* @param CommandId to process
|
||||
* @param pointer to the listener to call
|
||||
*/
|
||||
virtual void addCmdListener(
|
||||
commands::CommandConstants::CommandId commandId,
|
||||
StompCommandListener* listener );
|
||||
|
||||
/**
|
||||
* UnRegisters a Command Listener using the CommandId specified
|
||||
* @param CommandId of the listener to remove.
|
||||
*/
|
||||
virtual void removeCmdListener(
|
||||
commands::CommandConstants::CommandId commandId );
|
||||
|
||||
private:
|
||||
|
||||
unsigned int getNextProducerId( void );
|
||||
unsigned int getNextTransactionId( void );
|
||||
|
||||
// Check for Connected State and Throw an exception if not.
|
||||
void enforceConnected( void ) throw ( ConnectorException );
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif /*ACTIVEMQ_CONNECTOR_STOMP_STOMPCONNECTOR_H_*/
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef ACTIVEMQ_CONNECTOR_STOMP_STOMPCONNECTOREXCEPTION_H_
|
||||
#define ACTIVEMQ_CONNECTOR_STOMP_STOMPCONNECTOREXCEPTION_H_
|
||||
|
||||
#include <activemq/connector/ConnectorException.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
|
||||
/*
|
||||
* Signals that an Connector exception of some sort has occurred.
|
||||
*/
|
||||
class StompConnectorException : public connector::ConnectorException
|
||||
{
|
||||
public:
|
||||
|
||||
StompConnectorException() {}
|
||||
StompConnectorException( const exceptions::ActiveMQException& ex ){
|
||||
*(ActiveMQException*)this = ex;
|
||||
}
|
||||
StompConnectorException( const StompConnectorException& ex ){
|
||||
*(exceptions::ActiveMQException*)this = ex;
|
||||
}
|
||||
StompConnectorException(const char* file, const int lineNumber,
|
||||
const char* msg, ...)
|
||||
{
|
||||
va_list vargs ;
|
||||
va_start(vargs, msg) ;
|
||||
buildMessage(msg, vargs) ;
|
||||
|
||||
// Set the first mark for this exception.
|
||||
setMark( file, lineNumber );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones this exception. This is useful for cases where you need
|
||||
* to preserve the type of the original exception as well as the message.
|
||||
* All subclasses should override.
|
||||
*/
|
||||
virtual exceptions::ActiveMQException* clone() const{
|
||||
return new StompConnectorException( *this );
|
||||
}
|
||||
virtual ~StompConnectorException() {}
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif /*ACTIVEMQ_CONNECTOR_STOMP_STOMPCONNECTOREXCEPTION_H_*/
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#include <activemq/connector/stomp/StompConnectorFactory.h>
|
||||
#include <activemq/connector/stomp/StompConnector.h>
|
||||
#include <activemq/connector/Connector.h>
|
||||
#include <activemq/transport/Transport.h>
|
||||
|
||||
using namespace activemq;
|
||||
using namespace activemq::util;
|
||||
using namespace activemq::transport;
|
||||
using namespace activemq::connector;
|
||||
using namespace activemq::connector::stomp;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Connector* StompConnectorFactory::createConnector(
|
||||
const activemq::util::Properties& properties,
|
||||
activemq::transport::Transport* transport)
|
||||
{
|
||||
return dynamic_cast<Connector*>(
|
||||
new StompConnector(transport, properties));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ConnectorFactory& StompConnectorFactory::getInstance(void)
|
||||
{
|
||||
// Create a static instance of the registrar and return a reference to
|
||||
// its internal instance of this class.
|
||||
static ConnectorFactoryMapRegistrar registrar(
|
||||
"stomp", new StompConnectorFactory());
|
||||
|
||||
return registrar.getFactory();
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef ACTIVEMQ_CONNECTOR_STOMP_STOMPCONNECTORFACTORY_H_
|
||||
#define ACTIVEMQ_CONNECTOR_STOMP_STOMPCONNECTORFACTORY_H_
|
||||
|
||||
#include <activemq/connector/ConnectorFactory.h>
|
||||
#include <activemq/connector/ConnectorFactoryMapRegistrar.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
|
||||
class StompConnectorFactory : public connector::ConnectorFactory
|
||||
{
|
||||
private:
|
||||
|
||||
|
||||
public:
|
||||
|
||||
virtual ~StompConnectorFactory(void) {}
|
||||
|
||||
/**
|
||||
* Creates a StompConnector
|
||||
* @param The Properties that the new connector is configured with
|
||||
*/
|
||||
virtual Connector* createConnector(
|
||||
const activemq::util::Properties& properties,
|
||||
activemq::transport::Transport* transport);
|
||||
|
||||
/**
|
||||
* Returns an instance of this Factory by reference
|
||||
* @return StompConnectorFactory reference
|
||||
*/
|
||||
static ConnectorFactory& getInstance(void);
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif /*ACTIVEMQ_CONNECTOR_STOMP_STOMPCONNECTORFACTORY_H_*/
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_STOMP_STOMPCONSUMERINFO_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_STOMP_STOMPCONSUMERINFO_H_
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
|
||||
class StompConsumerInfo : public ConsumerInfo
|
||||
{
|
||||
private:
|
||||
|
||||
// Message Selector for this Consumer
|
||||
std::string selector;
|
||||
|
||||
// Consumer Id
|
||||
unsigned int consumerId;
|
||||
|
||||
// Destination
|
||||
cms::Destination* destination;
|
||||
|
||||
// Session Info - We do not own this
|
||||
const SessionInfo* session;
|
||||
|
||||
public:
|
||||
|
||||
StompConsumerInfo(void) {
|
||||
selector = "";
|
||||
consumerId = 0;
|
||||
destination = NULL;
|
||||
}
|
||||
virtual ~StompConsumerInfo(void) { delete destination; }
|
||||
|
||||
/**
|
||||
* Gets this message consumer's message selector expression.
|
||||
* @return This Consumer's selector expression or "".
|
||||
*/
|
||||
virtual const std::string& getMessageSelector(void) const {
|
||||
return selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this message consumer's message selector expression.
|
||||
* @param This Consumer's selector expression or "".
|
||||
*/
|
||||
virtual void setMessageSelector( const std::string& selector ) {
|
||||
this->selector = selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ID that is assigned to this consumer
|
||||
* @return value of the Consumer Id.
|
||||
*/
|
||||
virtual unsigned int getConsumerId(void) const {
|
||||
return consumerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ID that is assigned to this consumer
|
||||
* @return string value of the Consumer Id.
|
||||
*/
|
||||
virtual void setConsumerId( const unsigned int id ) {
|
||||
this->consumerId = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Destination that this Consumer is subscribed on
|
||||
* @return Destination
|
||||
*/
|
||||
virtual const cms::Destination& getDestination(void) const {
|
||||
return *destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the destination that this Consumer is listening on
|
||||
* @param Destination
|
||||
*/
|
||||
virtual void setDestination( const cms::Destination& destination ) {
|
||||
this->destination = destination.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Session Info that this consumer is attached too
|
||||
* @return SessionnInfo pointer
|
||||
*/
|
||||
virtual const SessionInfo* getSessionInfo(void) const {
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Session Info that this consumer is attached too
|
||||
* @return SessionnInfo pointer
|
||||
*/
|
||||
virtual void setSessionInfo( const SessionInfo* session ) {
|
||||
this->session = session;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_STOMP_STOMPCONSUMERINFO_H_*/
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_STOMP_STOMPDESTINATION_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_STOMP_STOMPDESTINATION_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <cms/Destination.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
|
||||
/**
|
||||
* Templatized Destination Class that bundles all the common aspects
|
||||
* of a Stomp Destination into one class. The template arguement is
|
||||
* one of Topic, Queue, TemporaryTopic, or TemporaryQueue.
|
||||
*/
|
||||
template <typename T>
|
||||
class StompDestination : public T
|
||||
{
|
||||
private:
|
||||
|
||||
// Destination type
|
||||
cms::Destination::DestinationType destType;
|
||||
|
||||
// Name of the Destination
|
||||
std::string name;
|
||||
|
||||
public:
|
||||
|
||||
StompDestination(void) {}
|
||||
|
||||
StompDestination( const std::string& name,
|
||||
cms::Destination::DestinationType type )
|
||||
{
|
||||
this->name = name;
|
||||
this->destType = type;
|
||||
}
|
||||
|
||||
virtual ~StompDestination(void) {}
|
||||
|
||||
/**
|
||||
* Retrieves the name of this destination, plus the stomp
|
||||
* destination decorator
|
||||
* @return name
|
||||
*/
|
||||
virtual std::string toProviderString(void) const {
|
||||
return getPrefix() + name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Destination Type for this Destination
|
||||
* @return The Destination Type
|
||||
*/
|
||||
virtual cms::Destination::DestinationType getDestinationType(void) const {
|
||||
return destType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the Destination Name into a String minus the
|
||||
* stomp decorator
|
||||
* @return string name
|
||||
*/
|
||||
virtual std::string toString(void) const {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the contents of the given Destinastion object to this one.
|
||||
* @param source The source Destination object.
|
||||
*/
|
||||
virtual void copy( const cms::Destination& source ) {
|
||||
this->destType = source.getDestinationType();
|
||||
this->name = source.toString();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Retrieves the proper Stomp Prefix for the specified type
|
||||
* of Destination
|
||||
* @return string prefix
|
||||
*/
|
||||
virtual std::string getPrefix(void) const = 0;
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_STOMP_STOMPDESTINATION_H_*/
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef ACTIVEMQ_CONNECTOR_STOMP_STOMPFRAMEWRAPPER_H_
|
||||
#define ACTIVEMQ_CONNECTOR_STOMP_STOMPFRAMEWRAPPER_H_
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <activemq/util/SimpleProperties.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
|
||||
/**
|
||||
* A Stomp-level message frame that encloses all messages
|
||||
* to and from the broker.
|
||||
*/
|
||||
class StompFrame{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
StompFrame(void){
|
||||
body = NULL;
|
||||
bodyLength = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destruction - frees the memory pool.
|
||||
*/
|
||||
virtual ~StompFrame(void) { delete body; }
|
||||
|
||||
/**
|
||||
* Clonse this message exactly, returns a new instance that the
|
||||
* caller is required to delete.
|
||||
* @return new copy of this message
|
||||
*/
|
||||
virtual StompFrame* clone(void) const {
|
||||
StompFrame* frame = new StompFrame();
|
||||
frame->command = command;
|
||||
frame->properties = properties;
|
||||
char* cpyBody = new char[bodyLength];
|
||||
memcpy(cpyBody, body, bodyLength);
|
||||
frame->setBody(cpyBody, bodyLength);
|
||||
return frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the command for this stomp frame.
|
||||
* @param command The command to be set.
|
||||
*/
|
||||
void setCommand( const std::string& cmd ){
|
||||
this->command = cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for this frame's command field.
|
||||
*/
|
||||
const std::string& getCommand(void) const{
|
||||
return command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets access to the header properties for this frame.
|
||||
*/
|
||||
util::Properties& getProperties(void){ return properties; }
|
||||
const util::Properties& getProperties(void) const {
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for the body data of this frame.
|
||||
* @return char pointer to body data
|
||||
*/
|
||||
const char* getBody(void) const{
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of bytes contained in this frames body
|
||||
* @return Body bytes length.
|
||||
*/
|
||||
int getBodyLength(void) const{ return bodyLength; }
|
||||
|
||||
/**
|
||||
* Sets the body data of this frame as a byte sequence.
|
||||
* @param bytes The byte buffer to be set in the body.
|
||||
* @param numBytes The number of bytes in the buffer.
|
||||
*/
|
||||
void setBody( const char* bytes, const int numBytes ){
|
||||
body = bytes;
|
||||
bodyLength = numBytes;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// String Name of this command.
|
||||
std::string command;
|
||||
|
||||
// Properties of the Stomp Message
|
||||
util::SimpleProperties properties;
|
||||
|
||||
// Byte data of Body.
|
||||
const char* body;
|
||||
int bodyLength;
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif /*ACTIVEMQ_CONNECTOR_STOMP_STOMPFRAMEWRAPPER_H_*/
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_STOMP_STOMPPRODUCERINFO_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_STOMP_STOMPPRODUCERINFO_H_
|
||||
|
||||
#include <activemq/connector/ProducerInfo.h>
|
||||
#include <cms/Destination.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
|
||||
class StompProducerInfo : public ProducerInfo
|
||||
{
|
||||
private:
|
||||
|
||||
// Producer Id
|
||||
unsigned int producerId;
|
||||
|
||||
// Default Destination
|
||||
cms::Destination* dest;
|
||||
|
||||
// Session that this producer is attached to - we do not own this
|
||||
const SessionInfo* session;
|
||||
|
||||
public:
|
||||
|
||||
StompProducerInfo(void) { dest = NULL; }
|
||||
virtual ~StompProducerInfo(void) { delete dest; }
|
||||
|
||||
/**
|
||||
* Retrieves the default destination that this producer
|
||||
* sends its messages to.
|
||||
* @return Destionation, owned by this object
|
||||
*/
|
||||
virtual const cms::Destination& getDestination(void) const {
|
||||
return *dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Default Destination for this Producer
|
||||
* @param reference to a destination, copied internally
|
||||
*/
|
||||
virtual void setDestination( const cms::Destination& dest ) {
|
||||
this->dest = dest.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ID that is assigned to this Producer
|
||||
* @return value of the Producer Id.
|
||||
*/
|
||||
virtual unsigned int getProducerId(void) const {
|
||||
return producerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ID that is assigned to this Producer
|
||||
* @return string value of the Producer Id.
|
||||
*/
|
||||
virtual void setProducerId( const unsigned int id ) {
|
||||
this->producerId = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Session Info that this consumer is attached too
|
||||
* @return SessionnInfo pointer
|
||||
*/
|
||||
virtual const SessionInfo* getSessionInfo(void) const {
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Session Info that this consumer is attached too
|
||||
* @return SessionnInfo pointer
|
||||
*/
|
||||
virtual void setSessionInfo( const SessionInfo* session ) {
|
||||
this->session = session;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_STOMP_STOMPPRODUCERINFO_H_*/
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_STOMP_STOMPQUEUE_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_STOMP_STOMPQUEUE_H_
|
||||
|
||||
#include <activemq/connector/stomp/StompDestination.h>
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
#include <cms/Queue.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
|
||||
class StompQueue : public StompDestination<cms::Queue>
|
||||
{
|
||||
public:
|
||||
|
||||
StompQueue(void) : StompDestination< cms::Queue >() {}
|
||||
|
||||
StompQueue(const std::string& name) :
|
||||
StompDestination< cms::Queue >( name, cms::Destination::QUEUE )
|
||||
{}
|
||||
|
||||
virtual ~StompQueue(void) {}
|
||||
|
||||
/**
|
||||
* Gets the name of this queue.
|
||||
* @return The queue name.
|
||||
*/
|
||||
virtual std::string getQueueName(void) const
|
||||
throw( cms::CMSException ) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of this destination type that is a
|
||||
* copy of this one, and returns it.
|
||||
* @returns cloned copy of this object
|
||||
*/
|
||||
virtual cms::Destination* clone(void) const {
|
||||
return new StompQueue( toString() );
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Retrieves the proper Stomp Prefix for the specified type
|
||||
* of Destination
|
||||
* @return string prefix
|
||||
*/
|
||||
virtual std::string getPrefix(void) const {
|
||||
return commands::CommandConstants::queuePrefix;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_STOMP_STOMPQUEUE_H_*/
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef ACTIVEMQ_CONNECTOR_STOMP_STOMPSELECTOR_H_
|
||||
#define ACTIVEMQ_CONNECTOR_STOMP_STOMPSELECTOR_H_
|
||||
|
||||
#include <cms/Message.h>
|
||||
#include <string>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
|
||||
/**
|
||||
* Since the stomp protocol doesn't have a consumer-based selector
|
||||
* mechanism, we have to do the selector logic on the client
|
||||
* side. This class provides the selector algorithm that is
|
||||
* needed to determine if a given message is to be selected for
|
||||
* a given consumer's selector string.
|
||||
*/
|
||||
class StompSelector{
|
||||
public:
|
||||
|
||||
static bool isSelected( const std::string& selector,
|
||||
cms::Message* msg )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif /*ACTIVEMQ_CONNECTOR_STOMP_STOMPSELECTOR_H_*/
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_STOMP_STOMPSESSIONINFO_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_STOMP_STOMPSESSIONINFO_H_
|
||||
|
||||
#include <activemq/connector/SessionInfo.h>
|
||||
#include <cms/Session.h>
|
||||
#include <string>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
|
||||
class StompSessionInfo : public connector::SessionInfo
|
||||
{
|
||||
private:
|
||||
|
||||
// Acknowledge Mode of this Session
|
||||
cms::Session::AcknowledgeMode ackMode;
|
||||
|
||||
// The id of the connection to the broker
|
||||
// (given to us by the broker)
|
||||
std::string connectionId;
|
||||
|
||||
// The unique session id
|
||||
unsigned int sessionId;
|
||||
|
||||
// Info for this sessions current transaction
|
||||
const TransactionInfo* transaction;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
StompSessionInfo(void)
|
||||
{
|
||||
sessionId = 0;
|
||||
ackMode = cms::Session::AutoAcknowledge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~StompSessionInfo(void) {}
|
||||
|
||||
/**
|
||||
* Gets the Connection Id of the Connection that this consumer is
|
||||
* using to receive its messages.
|
||||
* @return string value of the connection id
|
||||
*/
|
||||
virtual const std::string& getConnectionId(void) const{
|
||||
return connectionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Connection Id of the Connection that this consumer is
|
||||
* using to receive its messages.
|
||||
* @param string value of the connection id
|
||||
*/
|
||||
virtual void setConnectionId( const std::string& id ){
|
||||
connectionId = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Sessions Id value
|
||||
* @return id for this session
|
||||
*/
|
||||
virtual unsigned int getSessionId(void) const {
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Session Id for this Session
|
||||
* @param integral id value for this session
|
||||
*/
|
||||
virtual void setSessionId( const unsigned int id ) {
|
||||
this->sessionId = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Ack Mode of this Session Info object
|
||||
* @param Ack Mode
|
||||
*/
|
||||
virtual void setAckMode(cms::Session::AcknowledgeMode ackMode) {
|
||||
this->ackMode = ackMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Ack Mode of this Session
|
||||
* @return Ack Mode
|
||||
*/
|
||||
virtual cms::Session::AcknowledgeMode getAckMode(void) const {
|
||||
return ackMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the currently active transaction info, if this session is
|
||||
* transacted, returns NULL when not transacted. You must call
|
||||
* getAckMode and see if the session is transacted.
|
||||
* @return Transaction Id of current Transaction
|
||||
*/
|
||||
virtual const TransactionInfo* getTransactionInfo(void) const {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current transaction info for this session, this is nit
|
||||
* used when the session is not transacted.
|
||||
* @param Transaction Id
|
||||
*/
|
||||
virtual void setTransactionInfo( const TransactionInfo* transaction ) {
|
||||
this->transaction = transaction;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_STOMP_STOMPSESSIONINFO_H_*/
|
|
@ -0,0 +1,326 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#include "StompSessionManager.h"
|
||||
|
||||
#include <activemq/core/ActiveMQMessage.h>
|
||||
#include <activemq/concurrent/Concurrent.h>
|
||||
#include <activemq/connector/stomp/StompSessionInfo.h>
|
||||
#include <activemq/connector/stomp/StompConsumerInfo.h>
|
||||
#include <activemq/connector/stomp/commands/SubscribeCommand.h>
|
||||
#include <activemq/connector/stomp/commands/UnsubscribeCommand.h>
|
||||
#include <activemq/connector/stomp/StompSelector.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace activemq;
|
||||
using namespace activemq::core;
|
||||
using namespace activemq::exceptions;
|
||||
using namespace activemq::transport;
|
||||
using namespace activemq::connector;
|
||||
using namespace activemq::connector::stomp;
|
||||
using namespace activemq::connector::stomp::commands;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
StompSessionManager::StompSessionManager( const std::string& connectionId,
|
||||
Transport* transport )
|
||||
{
|
||||
if( transport == NULL )
|
||||
{
|
||||
throw NullPointerException(
|
||||
__FILE__, __LINE__,
|
||||
"StompSessionManager::StompSessionManager" );
|
||||
}
|
||||
|
||||
this->transport = transport;
|
||||
this->connectionId = connectionId;
|
||||
this->nextSessionId = 0;
|
||||
this->nextConsumerId = 0;
|
||||
this->messageListener = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
StompSessionManager::~StompSessionManager(void)
|
||||
{
|
||||
// NOTE - I am not cleaning out the ConsumerInfo objects in the
|
||||
// map becaise it is really the job of the consumer ot remove itself
|
||||
// when it is destructed. If it doesn't then we would have problems,
|
||||
// but if it does, but it's deleted after this object then we would
|
||||
// still have problems.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
unsigned int StompSessionManager::getNextSessionId(void)
|
||||
{
|
||||
synchronized(&mutex)
|
||||
{
|
||||
return nextSessionId++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
unsigned int StompSessionManager::getNextConsumerId(void)
|
||||
{
|
||||
synchronized(&mutex)
|
||||
{
|
||||
return nextConsumerId++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
connector::SessionInfo* StompSessionManager::createSession(
|
||||
cms::Session::AcknowledgeMode ackMode)
|
||||
throw ( exceptions::ActiveMQException )
|
||||
{
|
||||
try
|
||||
{
|
||||
SessionInfo* session = new StompSessionInfo();
|
||||
|
||||
// Init data
|
||||
session->setAckMode(ackMode);
|
||||
session->setConnectionId( connectionId );
|
||||
session->setSessionId( getNextSessionId() );
|
||||
|
||||
return session;
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompSessionManager::removeSession(
|
||||
connector::SessionInfo* session )
|
||||
throw ( exceptions::ActiveMQException )
|
||||
{
|
||||
// NO-op
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
connector::ConsumerInfo* StompSessionManager::createConsumer(
|
||||
cms::Destination* destination,
|
||||
SessionInfo* session,
|
||||
const std::string& selector)
|
||||
throw( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
// Delegate to the createDurableConsumer method, just pas the
|
||||
// appropriate params so that a regular consumer is created on
|
||||
// the broker side.
|
||||
return createDurableConsumer(
|
||||
destination, session, "", selector, false );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
connector::ConsumerInfo* StompSessionManager::createDurableConsumer(
|
||||
cms::Destination* destination,
|
||||
SessionInfo* session,
|
||||
const std::string& name,
|
||||
const std::string& selector,
|
||||
bool noLocal )
|
||||
throw ( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized(&mutex)
|
||||
{
|
||||
// Find the right mapping to consumers
|
||||
ConsumerMap& consumerMap =
|
||||
destinationMap[ destination->toString() ];
|
||||
|
||||
// We only need to send a sub request if there are no active
|
||||
// consumers on this destination.
|
||||
if( consumerMap.empty() )
|
||||
{
|
||||
// Send the request to the Broker
|
||||
SubscribeCommand cmd;
|
||||
|
||||
if( session->getAckMode() == cms::Session::ClientAcknowledge )
|
||||
{
|
||||
cmd.setAckMode( CommandConstants::ACK_CLIENT );
|
||||
}
|
||||
cmd.setDestination( destination->toProviderString() );
|
||||
cmd.setNoLocal( noLocal );
|
||||
|
||||
if( name != "" )
|
||||
{
|
||||
cmd.setSubscriptionName( name );
|
||||
}
|
||||
|
||||
// The Selector is set on the first subscribe on this dest,
|
||||
// and if another consumer is created on this destination
|
||||
// that specifies a selector it will be ignored. While
|
||||
// this is not ideal, is the only way to handle the fact
|
||||
// that activemq stomp doesn't support multiple sessions.
|
||||
if( selector != "" )
|
||||
{
|
||||
cmd.setMessageSelector( selector );
|
||||
}
|
||||
|
||||
// Fire the message
|
||||
transport->oneway( &cmd );
|
||||
}
|
||||
|
||||
// Initialize a new Consumer info Message
|
||||
ConsumerInfo* consumer = new StompConsumerInfo();
|
||||
|
||||
consumer->setConsumerId( getNextConsumerId() );
|
||||
consumer->setDestination( *destination );
|
||||
consumer->setMessageSelector( selector );
|
||||
consumer->setSessionInfo( session );
|
||||
|
||||
// Store this consumer for later message dispatching.
|
||||
consumerMap.insert(
|
||||
make_pair( consumer->getConsumerId(), consumer ) );
|
||||
|
||||
return consumer;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompSessionManager::removeConsumer(
|
||||
connector::ConsumerInfo* consumer)
|
||||
throw( ConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized(&mutex)
|
||||
{
|
||||
DestinationMap::iterator itr =
|
||||
destinationMap.find( consumer->getDestination().toString() );
|
||||
|
||||
if( itr == destinationMap.end() )
|
||||
{
|
||||
// Already removed from the map
|
||||
return;
|
||||
}
|
||||
|
||||
ConsumerMap& consumers = itr->second;
|
||||
|
||||
// Remove from the map.
|
||||
consumers.erase( consumer->getConsumerId() );
|
||||
|
||||
// If there are no more on this destination then we unsubscribe
|
||||
if( consumers.empty() )
|
||||
{
|
||||
UnsubscribeCommand cmd;
|
||||
|
||||
cmd.setDestination(
|
||||
consumer->getDestination().toProviderString() );
|
||||
|
||||
// Send the message
|
||||
transport->oneway( &cmd );
|
||||
}
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ConnectorException )
|
||||
AMQ_CATCHALL_THROW( ConnectorException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void StompSessionManager::onStompCommand( commands::StompCommand* command )
|
||||
throw ( StompConnectorException )
|
||||
{
|
||||
try
|
||||
{
|
||||
cms::Message* message = dynamic_cast< cms::Message*>( command );
|
||||
|
||||
if( message == NULL )
|
||||
{
|
||||
throw StompConnectorException(
|
||||
__FILE__, __LINE__,
|
||||
"StompSessionManager::onStompCommand - Invalid Command" );
|
||||
}
|
||||
|
||||
if( messageListener == NULL )
|
||||
{
|
||||
throw StompConnectorException(
|
||||
__FILE__, __LINE__,
|
||||
"StompSessionManager::onStompCommand - "
|
||||
"No Message Listener Registered." );
|
||||
}
|
||||
|
||||
synchronized(&mutex)
|
||||
{
|
||||
DestinationMap::iterator itr =
|
||||
destinationMap.find( message->getCMSDestination().toString() );
|
||||
|
||||
if( itr == destinationMap.end() )
|
||||
{
|
||||
throw StompConnectorException(
|
||||
__FILE__, __LINE__,
|
||||
"StompSessionManager::onStompCommand - "
|
||||
"Received a Message that doesn't have a listener" );
|
||||
}
|
||||
|
||||
// If we only have 1 consumer, we don't need to clone the original
|
||||
// message.
|
||||
if(itr->second.size() == 1)
|
||||
{
|
||||
ConsumerInfo* consumerInfo = itr->second.begin()->second;
|
||||
|
||||
if( StompSelector::isSelected(
|
||||
consumerInfo->getMessageSelector(),
|
||||
message ) )
|
||||
{
|
||||
ActiveMQMessage* msg =
|
||||
dynamic_cast< ActiveMQMessage* >( message );
|
||||
messageListener->onConsumerMessage( consumerInfo, msg );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// We have more than one consumer of this message - we have to
|
||||
// clone the message for each consumer so they don't destroy each other's
|
||||
// message.
|
||||
ConsumerMap::iterator c_itr = itr->second.begin();
|
||||
|
||||
for(; c_itr != itr->second.end(); ++c_itr )
|
||||
{
|
||||
ConsumerInfo* consumerInfo = c_itr->second;
|
||||
|
||||
if( StompSelector::isSelected(
|
||||
consumerInfo->getMessageSelector(),
|
||||
message ) )
|
||||
{
|
||||
ActiveMQMessage* msg =
|
||||
dynamic_cast< ActiveMQMessage* >( message->clone() );
|
||||
messageListener->onConsumerMessage( consumerInfo, msg );
|
||||
}
|
||||
}
|
||||
|
||||
// We got here which means that we sent copies, so remove
|
||||
// the original.
|
||||
delete command;
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( StompConnectorException )
|
||||
AMQ_CATCH_EXCEPTION_CONVERT( ActiveMQException, StompConnectorException )
|
||||
AMQ_CATCHALL_THROW( StompConnectorException )
|
||||
}
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_STOMP_STOMPSESSIONMANAGER_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_STOMP_STOMPSESSIONMANAGER_H_
|
||||
|
||||
#include <activemq/connector/SessionInfo.h>
|
||||
#include <activemq/connector/ConsumerInfo.h>
|
||||
#include <activemq/transport/Transport.h>
|
||||
#include <activemq/concurrent/Mutex.h>
|
||||
#include <activemq/connector/ConnectorException.h>
|
||||
#include <activemq/connector/stomp/StompCommandListener.h>
|
||||
#include <activemq/connector/ConsumerMessageListener.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
|
||||
/**
|
||||
* The Stomp Session Manager is responsible for managing multiple
|
||||
* Client Sessions. The management involves routing messages to
|
||||
* sessions. If more than one ActiveMQConsumer is created that is
|
||||
* listening to the same Topic or Queue, then the messages that are
|
||||
* received must be delivered to each of those sessions, and copied
|
||||
* so that a transactional session can manage the lifetime of the
|
||||
* message.
|
||||
*/
|
||||
class StompSessionManager : public StompCommandListener
|
||||
{
|
||||
private:
|
||||
|
||||
// Map Types
|
||||
typedef std::map<unsigned int, ConsumerInfo*> ConsumerMap;
|
||||
typedef std::map<std::string, ConsumerMap> DestinationMap;
|
||||
|
||||
private:
|
||||
|
||||
// Next id to be used for a Session Id
|
||||
unsigned int nextSessionId;
|
||||
|
||||
// Next id to be used for a Consumer Id
|
||||
unsigned int nextConsumerId;
|
||||
|
||||
// Mutex to protect ids.
|
||||
concurrent::Mutex mutex;
|
||||
|
||||
// Mapping of a Session to all the consumer's
|
||||
DestinationMap destinationMap;
|
||||
|
||||
// Transport that we use to find a transport for sending
|
||||
// commands
|
||||
transport::Transport* transport;
|
||||
|
||||
// Consumer Message listener, we notify this whenever we receive
|
||||
// a new StompMessage type command.
|
||||
ConsumerMessageListener* messageListener;
|
||||
|
||||
// The global connection id
|
||||
std::string connectionId;
|
||||
|
||||
public:
|
||||
|
||||
StompSessionManager( const std::string& connectionId,
|
||||
transport::Transport* transport );
|
||||
virtual ~StompSessionManager(void);
|
||||
|
||||
/**
|
||||
* Creates a new Session and returns a SessionInfo object whose
|
||||
* lifetime is the property of the caller.
|
||||
* @param the ackMode of the session.
|
||||
* @return new SessionInfo object
|
||||
*/
|
||||
virtual connector::SessionInfo* createSession(
|
||||
cms::Session::AcknowledgeMode ackMode)
|
||||
throw ( exceptions::ActiveMQException );
|
||||
|
||||
/**
|
||||
* removes the specified Session from the Manager, all data that
|
||||
* is associated with session consumers is now lost. The session
|
||||
* is not deleted here, it is the owner's responsibility.
|
||||
* @param the session info for the session to remove.
|
||||
*/
|
||||
virtual void removeSession( connector::SessionInfo* session )
|
||||
throw ( exceptions::ActiveMQException );
|
||||
|
||||
/**
|
||||
* Creates a new consumer to the specified session, will subscribe
|
||||
* to the destination if another consumer hasn't already been
|
||||
* subbed to that destination. The returned consumer is the
|
||||
* owned by the caller and not deleted by this class.
|
||||
* @param destination to subscribe to
|
||||
* @param session to associate with
|
||||
* @param selector string
|
||||
* @return new ConsumerInfo object.
|
||||
*/
|
||||
virtual connector::ConsumerInfo* createConsumer(
|
||||
cms::Destination* destination,
|
||||
SessionInfo* session,
|
||||
const std::string& selector)
|
||||
throw( ConnectorException );
|
||||
|
||||
/**
|
||||
* Creates a new durable consumer to the specified session, will
|
||||
* subscribe to the destination if another consumer hasn't already
|
||||
* been subbed to that destination. The returned consumer is the
|
||||
* owned by the caller and not deleted by this class.
|
||||
* @param Topic to subscribe to
|
||||
* @param session to associate with
|
||||
* @param Subscription Name
|
||||
* @param selector string
|
||||
* @param Should we be notified of messages we send.
|
||||
* @return new ConsumerInfo object.
|
||||
*/
|
||||
virtual connector::ConsumerInfo* createDurableConsumer(
|
||||
cms::Destination* destination,
|
||||
SessionInfo* session,
|
||||
const std::string& name,
|
||||
const std::string& selector,
|
||||
bool noLocal )
|
||||
throw ( ConnectorException );
|
||||
|
||||
/**
|
||||
* Removes the Consumer from the session, will unsubscrive if the
|
||||
* consumer is the only one listeneing on this destination. The
|
||||
* Consumer is not deleted, just unassociated from the Manager
|
||||
* caller is responsible for managing the lifetime.
|
||||
* @param the ConsumerInfo for the consumer to remove
|
||||
* @throws ConnectorException
|
||||
*/
|
||||
virtual void removeConsumer( connector::ConsumerInfo* consumer )
|
||||
throw( ConnectorException );
|
||||
|
||||
/**
|
||||
* Sets the listener of consumer messages.
|
||||
* @param listener the observer.
|
||||
*/
|
||||
virtual void setConsumerMessageListener(
|
||||
ConsumerMessageListener* listener )
|
||||
{
|
||||
this->messageListener = listener;
|
||||
}
|
||||
|
||||
public: // StompCommand Listener
|
||||
|
||||
/**
|
||||
* Process the Stomp Command
|
||||
* @param command to process
|
||||
* @throw ConnterException
|
||||
*/
|
||||
virtual void onStompCommand( commands::StompCommand* command )
|
||||
throw ( StompConnectorException );
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Gets the Next Session Id
|
||||
* @return unique session id
|
||||
*/
|
||||
virtual unsigned int getNextSessionId(void);
|
||||
|
||||
/**
|
||||
* Gets the Next Session Id
|
||||
* @return unique session id
|
||||
*/
|
||||
virtual unsigned int getNextConsumerId(void);
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_STOMP_STOMPSESSIONMANAGER_H_*/
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_STOMP_STOMPTOPIC_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_STOMP_STOMPTOPIC_H_
|
||||
|
||||
#include <activemq/connector/stomp/StompDestination.h>
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
#include <cms/Topic.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
|
||||
class StompTopic : public StompDestination<cms::Topic>
|
||||
{
|
||||
public:
|
||||
|
||||
StompTopic(void) : StompDestination<cms::Topic>() {}
|
||||
|
||||
StompTopic(const std::string& name) :
|
||||
StompDestination< cms::Topic >( name, cms::Destination::TOPIC )
|
||||
{}
|
||||
|
||||
virtual ~StompTopic(void) {}
|
||||
|
||||
/**
|
||||
* Gets the name of this queue.
|
||||
* @return The queue name.
|
||||
*/
|
||||
virtual std::string getTopicName(void) const
|
||||
throw( cms::CMSException ) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of this destination type that is a
|
||||
* copy of this one, and returns it.
|
||||
* @returns cloned copy of this object
|
||||
*/
|
||||
virtual cms::Destination* clone(void) const {
|
||||
return new StompTopic( toString() );
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Retrieves the proper Stomp Prefix for the specified type
|
||||
* of Destination
|
||||
* @return string prefix
|
||||
*/
|
||||
virtual std::string getPrefix(void) const {
|
||||
return commands::CommandConstants::topicPrefix;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_STOMP_STOMPTOPIC_H_*/
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef ACTIVEMQ_CONNECTOR_STOMPTRANSACTIONINFO_H_
|
||||
#define ACTIVEMQ_CONNECTOR_STOMPTRANSACTIONINFO_H_
|
||||
|
||||
#include <activemq/connector/TransactionInfo.h>
|
||||
#include <activemq/connector/SessionInfo.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
|
||||
class StompTransactionInfo : public connector::TransactionInfo
|
||||
{
|
||||
private:
|
||||
|
||||
// Transaction Id
|
||||
unsigned int transactionId;
|
||||
|
||||
// Session Info - We do not own this
|
||||
const SessionInfo* session;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* TransactionInfo Constructor
|
||||
*/
|
||||
StompTransactionInfo(void) {
|
||||
transactionId = 0;
|
||||
session = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~StompTransactionInfo(void) {}
|
||||
|
||||
/**
|
||||
* Gets the Transction Id
|
||||
* @return unsigned int Id
|
||||
*/
|
||||
virtual unsigned int getTransactionId(void) const {
|
||||
return transactionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Transction Id
|
||||
* @param unsigned int Id
|
||||
*/
|
||||
virtual void setTransactionId( const unsigned int id ) {
|
||||
this->transactionId = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Session Info that this Transction is attached too
|
||||
* @return SessionnInfo pointer
|
||||
*/
|
||||
virtual const SessionInfo* getSessionInfo(void) const {
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Session Info that this Transction is attached too
|
||||
* @return SessionnInfo pointer
|
||||
*/
|
||||
virtual void setSessionInfo( const SessionInfo* session ) {
|
||||
this->session = session;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif /*ACTIVEMQ_CONNECTOR_STOMPTRANSACTIONINFO_H_*/
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_ABORTCOMMAND_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_ABORTCOMMAND_H_
|
||||
|
||||
#include <activemq/connector/stomp/commands/AbstractCommand.h>
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
#include <activemq/transport/Command.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace commands{
|
||||
|
||||
/**
|
||||
* Represents the Stomp Abort Command which rolls back a
|
||||
* transaction in progress.
|
||||
*/
|
||||
class AbortCommand : public AbstractCommand< transport::Command >
|
||||
{
|
||||
public:
|
||||
|
||||
AbortCommand(void) :
|
||||
AbstractCommand<transport::Command>() {
|
||||
initialize( getFrame() );
|
||||
}
|
||||
AbortCommand( StompFrame* frame ) :
|
||||
AbstractCommand<transport::Command>(frame) {
|
||||
validate( getFrame() );
|
||||
}
|
||||
virtual ~AbortCommand(void) {}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to init the
|
||||
* frame with data appropriate for the command type.
|
||||
* @param Frame to init
|
||||
*/
|
||||
virtual void initialize( StompFrame& frame )
|
||||
{
|
||||
frame.setCommand( CommandConstants::toString(
|
||||
CommandConstants::ABORT ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to validate
|
||||
* the passed stomp frame before it is marshalled or unmarshaled
|
||||
* @param Frame to validate
|
||||
* @returns true if frame is valid
|
||||
*/
|
||||
virtual bool validate( const StompFrame& frame ) const
|
||||
{
|
||||
if((frame.getCommand() ==
|
||||
CommandConstants::toString( CommandConstants::ABORT ) ) &&
|
||||
(frame.getProperties().hasProperty(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_TRANSACTIONID ) ) ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_ABORTCOMMAND_H_*/
|
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_ABSTRACTCOMMAND_H_
|
||||
#define ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_ABSTRACTCOMMAND_H_
|
||||
|
||||
#include <activemq/connector/stomp/StompFrame.h>
|
||||
#include <activemq/connector/stomp/commands/StompCommand.h>
|
||||
#include <activemq/exceptions/NullPointerException.h>
|
||||
#include <activemq/util/Integer.h>
|
||||
#include <activemq/util/Long.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace commands{
|
||||
|
||||
/**
|
||||
* Interface for all Stomp commands. Commands wrap
|
||||
* around a stomp frame and provide their own marshalling
|
||||
* to and from frames. Stomp frame objects are dumb and have
|
||||
* a generic interface that becomes cumbersome to use directly.
|
||||
* Commands help to abstract the stomp frame by providing a
|
||||
* more user-friendly interface to the frame content.
|
||||
*/
|
||||
|
||||
template<typename T>
|
||||
class AbstractCommand
|
||||
:
|
||||
public StompCommand,
|
||||
public T
|
||||
{
|
||||
protected:
|
||||
|
||||
// Frame that contains the actual message
|
||||
StompFrame* frame;
|
||||
|
||||
protected:
|
||||
|
||||
StompFrame& getFrame(void) {
|
||||
if( frame == NULL ){
|
||||
throw exceptions::NullPointerException(
|
||||
__FILE__, __LINE__,
|
||||
"AbstractCommand::getFrame - Frame not initialized");
|
||||
}
|
||||
|
||||
return *frame;
|
||||
}
|
||||
|
||||
const StompFrame& getFrame(void) const {
|
||||
if( frame == NULL ){
|
||||
throw exceptions::NullPointerException(
|
||||
__FILE__, __LINE__,
|
||||
"AbstractCommand::getFrame - Frame not initialized");
|
||||
}
|
||||
|
||||
return *frame;
|
||||
}
|
||||
|
||||
void destroyFrame(void)
|
||||
{
|
||||
if( frame != NULL ){
|
||||
delete frame;
|
||||
frame = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const char* getPropertyValue( const std::string& name ) const{
|
||||
return getFrame().getProperties().getProperty( name );
|
||||
}
|
||||
|
||||
const std::string getPropertyValue(
|
||||
const std::string& name,
|
||||
const std::string& defReturn ) const {
|
||||
return getFrame().getProperties().getProperty(
|
||||
name, defReturn );
|
||||
}
|
||||
|
||||
void setPropertyValue( const std::string& name, const std::string& value ){
|
||||
getFrame().getProperties().setProperty( name, value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to init the
|
||||
* frame with data appropriate for the command type.
|
||||
* @param Frame to init
|
||||
*/
|
||||
virtual void initialize( StompFrame& frame ) = 0;
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to validate
|
||||
* the passed stomp frame before it is marshalled or unmarshaled
|
||||
* @param Frame to validate
|
||||
* @returns true if frame is valid
|
||||
*/
|
||||
virtual bool validate( const StompFrame& frame ) const = 0;
|
||||
|
||||
public:
|
||||
|
||||
AbstractCommand(void){
|
||||
frame = new StompFrame;
|
||||
}
|
||||
AbstractCommand(StompFrame* frame){
|
||||
this->frame = frame;
|
||||
}
|
||||
virtual ~AbstractCommand(void){
|
||||
destroyFrame();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Command Id of this Message
|
||||
* @param Command Id
|
||||
*/
|
||||
virtual void setCommandId( const unsigned int id ){
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_REQUESTID),
|
||||
util::Integer::toString( id ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Command Id of this Message
|
||||
* @return Command Id
|
||||
*/
|
||||
virtual unsigned int getCommandId(void) const {
|
||||
return util::Integer::parseInt(
|
||||
getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_REQUESTID ),
|
||||
"0" ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if this Message requires a Response
|
||||
* @param true if response is required
|
||||
*/
|
||||
virtual void setResponseRequired( const bool required ) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Is a Response required for this Command
|
||||
* @return true if a response is required.
|
||||
*/
|
||||
virtual bool isResponseRequired(void) const {
|
||||
return frame->getProperties().hasProperty(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_REQUESTID) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Correlation Id that is associated with this message
|
||||
* @return the Correlation Id
|
||||
*/
|
||||
virtual unsigned int getCorrelationId(void) const {
|
||||
return util::Integer::parseInt(
|
||||
getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_RESPONSEID ),
|
||||
"0" ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Correlation Id if this Command
|
||||
* @param Id
|
||||
*/
|
||||
virtual void setCorrelationId( const unsigned int corrId ) {
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_RESPONSEID),
|
||||
util::Integer::toString( corrId ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Transaction Id of this Command
|
||||
* @return the Id of the Transaction
|
||||
*/
|
||||
virtual const char* getTransactionId(void) const{
|
||||
return getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_TRANSACTIONID) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Transaction Id of this Command
|
||||
* @param the Id of the Transaction
|
||||
*/
|
||||
virtual void setTransactionId( const std::string& id ){
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_TRANSACTIONID),
|
||||
id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Stomp Command Id for this message.
|
||||
* @return Stomp CommandId enum
|
||||
*/
|
||||
virtual CommandConstants::CommandId getStompCommandId(void) const {
|
||||
return CommandConstants::toCommandId(
|
||||
getFrame().getCommand() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Marshals the command to a stomp frame.
|
||||
* @returns the stomp frame representation of this
|
||||
* command.
|
||||
* @throws MarshalException if the command is not
|
||||
* in a state that can be marshaled.
|
||||
*/
|
||||
virtual const StompFrame& marshal(void) const
|
||||
throw (marshal::MarshalException)
|
||||
{
|
||||
if( frame == NULL || !validate( *frame ) ){
|
||||
throw marshal::MarshalException(
|
||||
__FILE__, __LINE__,
|
||||
"AbstractCommand::marshal() - frame invalid" );
|
||||
}
|
||||
|
||||
return getFrame();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Fetch the number of bytes in the Stomp Frame Body
|
||||
* @return number of bytes
|
||||
*/
|
||||
virtual unsigned long getNumBytes(void) const{
|
||||
return getFrame().getBodyLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a char array of bytes that are contained in the message
|
||||
* @param pointer to array of bytes.
|
||||
*/
|
||||
virtual const char* getBytes(void) const{
|
||||
return getFrame().getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bytes that are to be sent in the body of this message
|
||||
* the content length flag indicates if the Content Length header
|
||||
* should be set.
|
||||
* @param bytes to store
|
||||
* @param number of bytes to pull from the bytes buffer
|
||||
* @param true if the content length header should be set
|
||||
*/
|
||||
virtual void setBytes( const char* bytes,
|
||||
const unsigned long numBytes,
|
||||
const bool setContentLength = true )
|
||||
{
|
||||
char* copy = new char[numBytes];
|
||||
memcpy( copy, bytes, numBytes );
|
||||
getFrame().setBody( copy, numBytes );
|
||||
if( setContentLength )
|
||||
{
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_CONTENTLENGTH),
|
||||
util::Long::toString( numBytes ) );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_ABSTRACTCOMMAND_H_*/
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef _ACTIVEMQ_CONNCETOR_STOMP_COMMANDS_ACKCOMMAND_H_
|
||||
#define _ACTIVEMQ_CONNCETOR_STOMP_COMMANDS_ACKCOMMAND_H_
|
||||
|
||||
#include <activemq/connector/stomp/commands/AbstractCommand.h>
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
#include <activemq/transport/Command.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace commands{
|
||||
|
||||
/**
|
||||
* Stomp Command that Represents Acknowledgement of a message
|
||||
* receive. The Ack Command has one required attribute, message
|
||||
* Id. For each message sent to the client from the broker, the
|
||||
* message will not be considered consumed until an Ack is sent.
|
||||
* Optionally a Transaction Id can be set that indicates that the
|
||||
* message acknowledgement should be part of a named transaction.
|
||||
*/
|
||||
class AckCommand : public AbstractCommand< transport::Command >
|
||||
{
|
||||
public:
|
||||
|
||||
AckCommand(void) :
|
||||
AbstractCommand<transport::Command>() {
|
||||
initialize( getFrame() );
|
||||
}
|
||||
AckCommand( StompFrame* frame ) :
|
||||
AbstractCommand<transport::Command>(frame) {
|
||||
validate( getFrame() );
|
||||
}
|
||||
virtual ~AckCommand(void) {}
|
||||
|
||||
/**
|
||||
* Get the Message Id of this Command
|
||||
* @return the Id of the Message
|
||||
*/
|
||||
virtual const char* getMessageId(void) const{
|
||||
return getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_MESSAGEID) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Message Id that this Ack is associated with
|
||||
* @param the Message Id
|
||||
*/
|
||||
virtual void setMessageId(const std::string& messageId){
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_MESSAGEID),
|
||||
messageId );
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to init the
|
||||
* frame with data appropriate for the command type.
|
||||
* @param Frame to init
|
||||
*/
|
||||
virtual void initialize( StompFrame& frame )
|
||||
{
|
||||
frame.setCommand( CommandConstants::toString(
|
||||
CommandConstants::ACK ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to validate
|
||||
* the passed stomp frame before it is marshalled or unmarshaled
|
||||
* @param Frame to validate
|
||||
* @returns true if frame is valid
|
||||
*/
|
||||
virtual bool validate( const StompFrame& frame ) const
|
||||
{
|
||||
if((frame.getCommand() ==
|
||||
CommandConstants::toString( CommandConstants::ACK )) &&
|
||||
(frame.getProperties().hasProperty(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_TRANSACTIONID ) ) &&
|
||||
(frame.getProperties().hasProperty(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_MESSAGEID ) ) ) ) );
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNCETOR_STOMP_COMMANDS_ACKCOMMAND_H_*/
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_BEGINCOMMAND_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_BEGINCOMMAND_H_
|
||||
|
||||
#include <activemq/connector/stomp/commands/AbstractCommand.h>
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
#include <activemq/transport/Command.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace commands{
|
||||
|
||||
/**
|
||||
* Begins a Transaction. Transactions in this case apply to
|
||||
* sending and acknowledging -- any messages sent or acknowledged
|
||||
* during a transaction will be handled atomically based on the
|
||||
* transaction.
|
||||
*
|
||||
* A transaction Identifier is required and this id will be used
|
||||
* for all sends, commits, aborts, or acks.
|
||||
*/
|
||||
class BeginCommand : public AbstractCommand< transport::Command >
|
||||
{
|
||||
public:
|
||||
|
||||
BeginCommand(void) :
|
||||
AbstractCommand<transport::Command>() {
|
||||
initialize( getFrame() );
|
||||
}
|
||||
BeginCommand( StompFrame* frame ) :
|
||||
AbstractCommand<transport::Command>(frame) {
|
||||
validate( getFrame() );
|
||||
}
|
||||
virtual ~BeginCommand(void) {}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to init the
|
||||
* frame with data appropriate for the command type.
|
||||
* @param Frame to init
|
||||
*/
|
||||
virtual void initialize( StompFrame& frame )
|
||||
{
|
||||
frame.setCommand( CommandConstants::toString(
|
||||
CommandConstants::BEGIN ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to validate
|
||||
* the passed stomp frame before it is marshalled or unmarshaled
|
||||
* @param Frame to validate
|
||||
* @returns true if frame is valid
|
||||
*/
|
||||
virtual bool validate( const StompFrame& frame ) const
|
||||
{
|
||||
if((frame.getCommand() ==
|
||||
CommandConstants::toString( CommandConstants::BEGIN )) &&
|
||||
(frame.getProperties().hasProperty(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_TRANSACTIONID ) ) ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_BEGINCOMMAND_H_*/
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_BYTESMESSAGECOMMAND_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_BYTESMESSAGECOMMAND_H_
|
||||
|
||||
#include <cms/BytesMessage.h>
|
||||
#include <activemq/connector/stomp/commands/StompMessage.h>
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace commands{
|
||||
|
||||
/**
|
||||
* Implements the interface for a cms::BytesMessage. Uses the template
|
||||
* class StompMessage to implement all cms::Message type functionality
|
||||
* and implements the BytesMessage interface here.
|
||||
*/
|
||||
class BytesMessageCommand : public StompMessage< cms::BytesMessage >
|
||||
{
|
||||
public:
|
||||
|
||||
BytesMessageCommand(void) :
|
||||
StompMessage< cms::BytesMessage >() {
|
||||
initialize( getFrame() );
|
||||
}
|
||||
BytesMessageCommand( StompFrame* frame ) :
|
||||
StompMessage< cms::BytesMessage >(frame) {
|
||||
validate( getFrame() );
|
||||
}
|
||||
virtual ~BytesMessageCommand(void) {}
|
||||
|
||||
/**
|
||||
* Clonse this message exactly, returns a new instance that the
|
||||
* caller is required to delete.
|
||||
* @return new copy of this message
|
||||
*/
|
||||
virtual cms::Message* clone(void) const {
|
||||
StompFrame* frame = getFrame().clone();
|
||||
|
||||
return new BytesMessageCommand( frame );
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the bytes given to the message body.
|
||||
* @param Byte Buffer to copy
|
||||
* @param Number of bytes in Buffer to copy
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual void setBodyBytes( const unsigned char* buffer,
|
||||
const unsigned long numBytes )
|
||||
throw( cms::CMSException ) {
|
||||
this->setBytes(
|
||||
reinterpret_cast<const char*>( buffer ), numBytes );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bytes that are contained in this message, user should
|
||||
* copy this data into a user allocated buffer. Call
|
||||
* <code>getBodyLength</code> to determine the number of bytes
|
||||
* to expect.
|
||||
* @return const pointer to a byte buffer
|
||||
*/
|
||||
virtual const unsigned char* getBodyBytes(void) const {
|
||||
return reinterpret_cast<const unsigned char*>( this->getBytes() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes contained in the body of this message.
|
||||
* @return number of bytes.
|
||||
*/
|
||||
virtual unsigned long getBodyLength(void) const {
|
||||
return this->getNumBytes();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_BYTESMESSAGECOMMAND_H_*/
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#include "CommandConstants.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include <activemq/connector/stomp/StompTopic.h>
|
||||
#include <activemq/connector/stomp/StompQueue.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace activemq;
|
||||
using namespace activemq::exceptions;
|
||||
using namespace activemq::connector::stomp;
|
||||
using namespace activemq::connector::stomp::commands;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const char* CommandConstants::queuePrefix = "/queue/";
|
||||
const char* CommandConstants::topicPrefix = "/topic/";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
string CommandConstants::StaticInitializer::stompHeaders[NUM_STOMP_HEADERS];
|
||||
string CommandConstants::StaticInitializer::commands[NUM_COMMANDS];
|
||||
string CommandConstants::StaticInitializer::ackModes[NUM_ACK_MODES];
|
||||
string CommandConstants::StaticInitializer::msgTypes[NUM_MSG_TYPES];
|
||||
map<std::string, CommandConstants::StompHeader> CommandConstants::StaticInitializer::stompHeaderMap;
|
||||
map<std::string, CommandConstants::CommandId> CommandConstants::StaticInitializer::commandMap;
|
||||
map<std::string, CommandConstants::AckMode> CommandConstants::StaticInitializer::ackModeMap;
|
||||
map<std::string, CommandConstants::MessageType> CommandConstants::StaticInitializer::msgTypeMap;
|
||||
CommandConstants::StaticInitializer CommandConstants::staticInits;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CommandConstants::StaticInitializer::StaticInitializer(){
|
||||
|
||||
stompHeaders[HEADER_DESTINATION] = "destination";
|
||||
stompHeaders[HEADER_TRANSACTIONID] = "transaction";
|
||||
stompHeaders[HEADER_CONTENTLENGTH] = "content-length";
|
||||
stompHeaders[HEADER_SESSIONID] = "session";
|
||||
stompHeaders[HEADER_RECEIPTID] = "receipt-id";
|
||||
stompHeaders[HEADER_RECEIPT_REQUIRED] = "receipt";
|
||||
stompHeaders[HEADER_MESSAGEID] = "message-id";
|
||||
stompHeaders[HEADER_ACK] = "ack";
|
||||
stompHeaders[HEADER_LOGIN] = "login";
|
||||
stompHeaders[HEADER_PASSWORD] = "passcode";
|
||||
stompHeaders[HEADER_CLIENT_ID] = "client-id";
|
||||
stompHeaders[HEADER_MESSAGE] = "message";
|
||||
stompHeaders[HEADER_CORRELATIONID] = "correlation-id";
|
||||
stompHeaders[HEADER_REQUESTID] = "request-id";
|
||||
stompHeaders[HEADER_RESPONSEID] = "response-id";
|
||||
stompHeaders[HEADER_EXPIRES] = "expires";
|
||||
stompHeaders[HEADER_PERSISTANT] = "persistent";
|
||||
stompHeaders[HEADER_PRIORITY] = "priority";
|
||||
stompHeaders[HEADER_REPLYTO] = "reply-to";
|
||||
stompHeaders[HEADER_TYPE] = "type";
|
||||
stompHeaders[HEADER_AMQMSGTYPE] = "amq-msg-type";
|
||||
stompHeaders[HEADER_JMSXGROUPID] = "JMSXGroupID";
|
||||
stompHeaders[HEADER_JMSXGROUPSEQNO] = "JMSXGroupSeq";
|
||||
stompHeaders[HEADER_SELECTOR] = "selector";
|
||||
stompHeaders[HEADER_DISPATCH_ASYNC] = "activemq.dispatchAsync";
|
||||
stompHeaders[HEADER_EXCLUSIVE] = "activemq.exclusive";
|
||||
stompHeaders[HEADER_MAXPENDINGMSGLIMIT] = "activemq.maximumPendingMessageLimit";
|
||||
stompHeaders[HEADER_NOLOCAL] = "activemq.noLocal";
|
||||
stompHeaders[HEADER_PREFETCHSIZE] = "activemq.prefetchSize";
|
||||
stompHeaders[HEADER_PRIORITY] = "activemq.priority";
|
||||
stompHeaders[HEADER_RETROACTIVE] = "activemq.retroactive";
|
||||
stompHeaders[HEADER_SUBSCRIPTIONNAME] = "activemq.subscriptionName";
|
||||
stompHeaders[HEADER_TIMESTAMP] = "timestamp";
|
||||
stompHeaders[HEADER_REDELIVERED] = "redelivered";
|
||||
stompHeaders[HEADER_REDELIVERYCOUNT] = "redelivery_count";
|
||||
stompHeaders[HEADER_SELECTOR] = "selector";
|
||||
stompHeaders[HEADER_ID] = "id";
|
||||
stompHeaders[HEADER_SUBSCRIPTION] = "subscription";
|
||||
commands[CONNECT] = "CONNECT";
|
||||
commands[CONNECTED] = "CONNECTED";
|
||||
commands[DISCONNECT] = "DISCONNECT";
|
||||
commands[SUBSCRIBE] = "SUBSCRIBE";
|
||||
commands[UNSUBSCRIBE] = "UNSUBSCRIBE";
|
||||
commands[MESSAGE] = "MESSAGE";
|
||||
commands[SEND] = "SEND";
|
||||
commands[BEGIN] = "BEGIN";
|
||||
commands[COMMIT] = "COMMIT";
|
||||
commands[ABORT] = "ABORT";
|
||||
commands[ACK] = "ACK";
|
||||
commands[ERROR_CMD] = "ERROR";
|
||||
commands[RECEIPT] = "RECEIPT";
|
||||
ackModes[ACK_CLIENT] = "client";
|
||||
ackModes[ACK_AUTO] = "auto";
|
||||
msgTypes[TEXT] = "text";
|
||||
msgTypes[BYTES] = "bytes";
|
||||
|
||||
for( int ix=0; ix<NUM_STOMP_HEADERS; ++ix ){
|
||||
stompHeaderMap[stompHeaders[ix]] = (StompHeader)ix;
|
||||
}
|
||||
|
||||
for( int ix=0; ix<NUM_COMMANDS; ++ix ){
|
||||
commandMap[commands[ix]] = (CommandId)ix;
|
||||
}
|
||||
|
||||
for( int ix=0; ix<NUM_ACK_MODES; ++ix ){
|
||||
ackModeMap[ackModes[ix]] = (AckMode)ix;
|
||||
}
|
||||
|
||||
for( int ix=0; ix<NUM_MSG_TYPES; ++ix ){
|
||||
msgTypeMap[msgTypes[ix]] = (MessageType)ix;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::Destination* CommandConstants::toDestination( const std::string& dest )
|
||||
throw ( exceptions::IllegalArgumentException )
|
||||
{
|
||||
int qpos = dest.find(queuePrefix);
|
||||
int tpos = dest.find(topicPrefix);
|
||||
|
||||
if(tpos == 0)
|
||||
{
|
||||
return new StompTopic(dest.substr(strlen(topicPrefix)));
|
||||
}
|
||||
else if(qpos == 0)
|
||||
{
|
||||
return new StompQueue(dest.substr(strlen(queuePrefix)));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw IllegalArgumentException(
|
||||
__FILE__, __LINE__,
|
||||
"CommandConstants::toDestionation - Not a valid Stomp Dest");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_COMMANDCONSTANTS_H_
|
||||
#define ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_COMMANDCONSTANTS_H_
|
||||
|
||||
#include <cms/Destination.h>
|
||||
#include <activemq/exceptions/IllegalArgumentException.h>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace commands{
|
||||
|
||||
class CommandConstants{
|
||||
public:
|
||||
|
||||
enum CommandId{
|
||||
CONNECT,
|
||||
CONNECTED,
|
||||
DISCONNECT,
|
||||
SUBSCRIBE,
|
||||
UNSUBSCRIBE,
|
||||
MESSAGE,
|
||||
SEND,
|
||||
BEGIN,
|
||||
COMMIT,
|
||||
ABORT,
|
||||
ACK,
|
||||
ERROR_CMD,
|
||||
RECEIPT,
|
||||
NUM_COMMANDS
|
||||
};
|
||||
|
||||
enum StompHeader{
|
||||
HEADER_DESTINATION,
|
||||
HEADER_TRANSACTIONID,
|
||||
HEADER_CONTENTLENGTH,
|
||||
HEADER_SESSIONID,
|
||||
HEADER_RECEIPT_REQUIRED,
|
||||
HEADER_RECEIPTID,
|
||||
HEADER_MESSAGEID,
|
||||
HEADER_ACK,
|
||||
HEADER_LOGIN,
|
||||
HEADER_PASSWORD,
|
||||
HEADER_CLIENT_ID,
|
||||
HEADER_MESSAGE,
|
||||
HEADER_CORRELATIONID,
|
||||
HEADER_REQUESTID,
|
||||
HEADER_RESPONSEID,
|
||||
HEADER_EXPIRES,
|
||||
HEADER_PERSISTANT,
|
||||
HEADER_REPLYTO,
|
||||
HEADER_TYPE,
|
||||
HEADER_AMQMSGTYPE,
|
||||
HEADER_JMSXGROUPID,
|
||||
HEADER_JMSXGROUPSEQNO,
|
||||
HEADER_DISPATCH_ASYNC,
|
||||
HEADER_EXCLUSIVE,
|
||||
HEADER_MAXPENDINGMSGLIMIT,
|
||||
HEADER_NOLOCAL,
|
||||
HEADER_PREFETCHSIZE,
|
||||
HEADER_PRIORITY,
|
||||
HEADER_RETROACTIVE,
|
||||
HEADER_SUBSCRIPTIONNAME,
|
||||
HEADER_TIMESTAMP,
|
||||
HEADER_REDELIVERED,
|
||||
HEADER_REDELIVERYCOUNT,
|
||||
HEADER_SELECTOR,
|
||||
HEADER_ID,
|
||||
HEADER_SUBSCRIPTION,
|
||||
NUM_STOMP_HEADERS
|
||||
};
|
||||
|
||||
enum AckMode{
|
||||
ACK_CLIENT,
|
||||
ACK_AUTO,
|
||||
NUM_ACK_MODES
|
||||
};
|
||||
|
||||
enum MessageType
|
||||
{
|
||||
TEXT,
|
||||
BYTES,
|
||||
NUM_MSG_TYPES
|
||||
};
|
||||
|
||||
static const char* queuePrefix;
|
||||
static const char* topicPrefix;
|
||||
|
||||
static const std::string& toString( const CommandId cmd ){
|
||||
return StaticInitializer::commands[cmd];
|
||||
}
|
||||
|
||||
static CommandId toCommandId( const std::string& cmd ){
|
||||
std::map<std::string, CommandId>::iterator iter =
|
||||
StaticInitializer::commandMap.find(cmd);
|
||||
|
||||
if( iter == StaticInitializer::commandMap.end() ){
|
||||
return NUM_COMMANDS;
|
||||
}
|
||||
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
static std::string toString( const StompHeader header ){
|
||||
return StaticInitializer::stompHeaders[header];
|
||||
}
|
||||
|
||||
static StompHeader toStompHeader( const std::string& header ){
|
||||
|
||||
std::map<std::string, StompHeader>::iterator iter =
|
||||
StaticInitializer::stompHeaderMap.find(header);
|
||||
|
||||
if( iter == StaticInitializer::stompHeaderMap.end() ){
|
||||
return NUM_STOMP_HEADERS;
|
||||
}
|
||||
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
static std::string toString( const AckMode mode ){
|
||||
return StaticInitializer::ackModes[mode];
|
||||
}
|
||||
|
||||
static AckMode toAckMode( const std::string& mode ){
|
||||
std::map<std::string, AckMode>::iterator iter =
|
||||
StaticInitializer::ackModeMap.find(mode);
|
||||
|
||||
if( iter == StaticInitializer::ackModeMap.end() ){
|
||||
return NUM_ACK_MODES;
|
||||
}
|
||||
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
static std::string toString( const MessageType type ){
|
||||
return StaticInitializer::msgTypes[type];
|
||||
}
|
||||
|
||||
static MessageType toMessageType( const std::string& type ){
|
||||
std::map<std::string, MessageType>::iterator iter =
|
||||
StaticInitializer::msgTypeMap.find(type);
|
||||
|
||||
if( iter == StaticInitializer::msgTypeMap.end() ){
|
||||
return NUM_MSG_TYPES;
|
||||
}
|
||||
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
static cms::Destination* toDestination( const std::string& dest )
|
||||
throw ( exceptions::IllegalArgumentException );
|
||||
|
||||
class StaticInitializer{
|
||||
public:
|
||||
StaticInitializer();
|
||||
virtual ~StaticInitializer(){}
|
||||
|
||||
static std::string stompHeaders[NUM_STOMP_HEADERS];
|
||||
static std::string commands[NUM_COMMANDS];
|
||||
static std::string ackModes[NUM_ACK_MODES];
|
||||
static std::string msgTypes[NUM_MSG_TYPES];
|
||||
static std::map<std::string, StompHeader> stompHeaderMap;
|
||||
static std::map<std::string, CommandId> commandMap;
|
||||
static std::map<std::string, AckMode> ackModeMap;
|
||||
static std::map<std::string, MessageType> msgTypeMap;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
static StaticInitializer staticInits;
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_COMMANDCONSTANTS_H_*/
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_COMMITCOMMAND_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_COMMITCOMMAND_H_
|
||||
|
||||
#include <activemq/connector/stomp/commands/AbstractCommand.h>
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
#include <activemq/transport/Command.h>
|
||||
#include <string>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace commands{
|
||||
|
||||
/**
|
||||
* Commits a Transaction.
|
||||
*/
|
||||
class CommitCommand : public AbstractCommand< transport::Command >
|
||||
{
|
||||
public:
|
||||
|
||||
CommitCommand(void) :
|
||||
AbstractCommand<transport::Command>() {
|
||||
initialize( getFrame() );
|
||||
}
|
||||
CommitCommand( StompFrame* frame ) :
|
||||
AbstractCommand<transport::Command>(frame) {
|
||||
validate( getFrame() );
|
||||
}
|
||||
virtual ~CommitCommand(void) {}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to init the
|
||||
* frame with data appropriate for the command type.
|
||||
* @param Frame to init
|
||||
*/
|
||||
virtual void initialize( StompFrame& frame )
|
||||
{
|
||||
frame.setCommand( CommandConstants::toString(
|
||||
CommandConstants::COMMIT ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to validate
|
||||
* the passed stomp frame before it is marshalled or unmarshaled
|
||||
* @param Frame to validate
|
||||
* @returns true if frame is valid
|
||||
*/
|
||||
virtual bool validate( const StompFrame& frame ) const
|
||||
{
|
||||
if((frame.getCommand() ==
|
||||
CommandConstants::toString( CommandConstants::COMMIT )) &&
|
||||
(frame.getProperties().hasProperty(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_TRANSACTIONID ) ) ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_COMMITCOMMAND_H_*/
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_CONNECTCOMMAND_H_
|
||||
#define ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_CONNECTCOMMAND_H_
|
||||
|
||||
#include <activemq/connector/stomp/commands/AbstractCommand.h>
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
#include <activemq/transport/Command.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace commands{
|
||||
|
||||
/**
|
||||
* Message sent to the broker to connect.
|
||||
*/
|
||||
class ConnectCommand : public AbstractCommand< transport::Command >
|
||||
{
|
||||
public:
|
||||
|
||||
ConnectCommand(void) :
|
||||
AbstractCommand<transport::Command>() {
|
||||
initialize( getFrame() );
|
||||
}
|
||||
ConnectCommand( StompFrame* frame ) :
|
||||
AbstractCommand<transport::Command>(frame) {
|
||||
validate( getFrame() );
|
||||
}
|
||||
virtual ~ConnectCommand(void) {};
|
||||
|
||||
/**
|
||||
* Get the login
|
||||
* @return char* to login, can be ""
|
||||
*/
|
||||
virtual const char* getLogin(void) const {
|
||||
return getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_LOGIN) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the login
|
||||
* @param password string value
|
||||
*/
|
||||
virtual void setLogin( const std::string& login ){
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_LOGIN) ,
|
||||
login );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the password
|
||||
* @return char* to password, can be ""
|
||||
*/
|
||||
virtual const char* getPassword(void) const{
|
||||
return getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_PASSWORD) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the password
|
||||
* @param passwrod string value
|
||||
*/
|
||||
virtual void setPassword( const std::string& password ){
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_PASSWORD) ,
|
||||
password );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Client Id
|
||||
* @return char* to client Id, can be ""
|
||||
*/
|
||||
virtual const char* getClientId(void) const{
|
||||
return getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_CLIENT_ID) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Client Id
|
||||
* @param client id string value
|
||||
*/
|
||||
virtual void setClientId( const std::string& clientId ){
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_CLIENT_ID) ,
|
||||
clientId );
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to init the
|
||||
* frame with data appropriate for the command type.
|
||||
* @param Frame to init
|
||||
*/
|
||||
virtual void initialize( StompFrame& frame )
|
||||
{
|
||||
frame.setCommand( CommandConstants::toString(
|
||||
CommandConstants::CONNECT ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to validate
|
||||
* the passed stomp frame before it is marshalled or unmarshaled
|
||||
* @param Frame to validate
|
||||
* @returns true if frame is valid
|
||||
*/
|
||||
virtual bool validate( const StompFrame& frame ) const
|
||||
{
|
||||
if(frame.getCommand() ==
|
||||
CommandConstants::toString( CommandConstants::CONNECT ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_CONNECTCOMMAND_H_*/
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef ACTIVEMQ_COMMAND_STOMP_COMMANDS_CONNECTEDCOMMAND_H_
|
||||
#define ACTIVEMQ_COMMAND_STOMP_COMMANDS_CONNECTEDCOMMAND_H_
|
||||
|
||||
#include <activemq/connector/stomp/commands/AbstractCommand.h>
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
#include <activemq/transport/Response.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace commands{
|
||||
|
||||
/**
|
||||
* The stomp command returned from the broker indicating
|
||||
* a connection has been established.
|
||||
*/
|
||||
class ConnectedCommand : public AbstractCommand< transport::Response >
|
||||
{
|
||||
public:
|
||||
|
||||
ConnectedCommand(void) :
|
||||
AbstractCommand< transport::Response >() {
|
||||
initialize( getFrame() );
|
||||
}
|
||||
ConnectedCommand( StompFrame* frame ) :
|
||||
AbstractCommand< transport::Response >( frame ) {
|
||||
validate( getFrame() );
|
||||
}
|
||||
virtual ~ConnectedCommand(void) {}
|
||||
|
||||
/**
|
||||
* Get the Session Id
|
||||
*/
|
||||
virtual const char* getSessionId() const {
|
||||
return getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_SESSIONID) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Session Id
|
||||
*/
|
||||
virtual void setSessionId( const std::string& session ) {
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_SESSIONID),
|
||||
session );
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to init the
|
||||
* frame with data appropriate for the command type.
|
||||
* @param Frame to init
|
||||
*/
|
||||
virtual void initialize( StompFrame& frame )
|
||||
{
|
||||
frame.setCommand( CommandConstants::toString(
|
||||
CommandConstants::CONNECTED ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to validate
|
||||
* the passed stomp frame before it is marshalled or unmarshaled
|
||||
* @param Frame to validate
|
||||
* @returns true if frame is valid
|
||||
*/
|
||||
virtual bool validate( const StompFrame& frame ) const
|
||||
{
|
||||
if(frame.getCommand() ==
|
||||
CommandConstants::toString( CommandConstants::CONNECTED ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*ACTIVEMQ_COMMAND_STOMP_COMMANDS_CONNECTEDCOMMAND_H_*/
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_DISCONNECTCOMMAND_H_
|
||||
#define ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_DISCONNECTCOMMAND_H_
|
||||
|
||||
#include <activemq/connector/stomp/commands/AbstractCommand.h>
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
#include <activemq/transport/Command.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace commands{
|
||||
|
||||
/**
|
||||
* Sent to the broker to disconnect gracefully before closing
|
||||
* the transport.
|
||||
*/
|
||||
class DisconnectCommand : public AbstractCommand< transport::Command >
|
||||
{
|
||||
public:
|
||||
|
||||
DisconnectCommand(void) :
|
||||
AbstractCommand<transport::Command>() {
|
||||
initialize( getFrame() );
|
||||
}
|
||||
DisconnectCommand( StompFrame* frame ) :
|
||||
AbstractCommand<transport::Command>(frame) {
|
||||
validate( getFrame() );
|
||||
}
|
||||
virtual ~DisconnectCommand(void){};
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to init the
|
||||
* frame with data appropriate for the command type.
|
||||
* @param Frame to init
|
||||
*/
|
||||
virtual void initialize( StompFrame& frame )
|
||||
{
|
||||
frame.setCommand( CommandConstants::toString(
|
||||
CommandConstants::DISCONNECT ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to validate
|
||||
* the passed stomp frame before it is marshalled or unmarshaled
|
||||
* @param Frame to validate
|
||||
* @returns true if frame is valid
|
||||
*/
|
||||
virtual bool validate( const StompFrame& frame ) const
|
||||
{
|
||||
if(frame.getCommand() ==
|
||||
CommandConstants::toString( CommandConstants::DISCONNECT ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_DISCONNECTCOMMAND_H_*/
|
||||
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_ERRORCOMMAND_H_
|
||||
#define ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_ERRORCOMMAND_H_
|
||||
|
||||
#include <activemq/connector/stomp/commands/AbstractCommand.h>
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
#include <activemq/transport/Command.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace commands{
|
||||
|
||||
/**
|
||||
* Message sent from the broker when an error
|
||||
* occurs.
|
||||
*/
|
||||
class ErrorCommand : public AbstractCommand< transport::Command >
|
||||
{
|
||||
public:
|
||||
|
||||
ErrorCommand(void) :
|
||||
AbstractCommand<transport::Command>() {
|
||||
initialize( getFrame() );
|
||||
}
|
||||
ErrorCommand( StompFrame* frame ) :
|
||||
AbstractCommand<transport::Command>(frame) {
|
||||
validate( getFrame() );
|
||||
}
|
||||
virtual ~ErrorCommand(void) {};
|
||||
|
||||
/**
|
||||
* Get the error message
|
||||
*/
|
||||
virtual const char* getErrorMessage(void) const {
|
||||
return getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_MESSAGE) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the error message
|
||||
*/
|
||||
virtual void setErrorMessage( const std::string& title ) {
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_MESSAGE),
|
||||
title );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Text associated with this Error
|
||||
* @param Error Message
|
||||
*/
|
||||
virtual void setErrorDetails( const std::string& text ) {
|
||||
setBytes( text.c_str(), text.length() + 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Text associated with this Error
|
||||
* @return Error Message
|
||||
*/
|
||||
virtual const char* getErrorDetails(void) const {
|
||||
return getBytes();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to init the
|
||||
* frame with data appropriate for the command type.
|
||||
* @param Frame to init
|
||||
*/
|
||||
virtual void initialize( StompFrame& frame )
|
||||
{
|
||||
frame.setCommand( CommandConstants::toString(
|
||||
CommandConstants::ERROR_CMD ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to validate
|
||||
* the passed stomp frame before it is marshalled or unmarshaled
|
||||
* @param Frame to validate
|
||||
* @returns true if frame is valid
|
||||
*/
|
||||
virtual bool validate( const StompFrame& frame ) const
|
||||
{
|
||||
if((frame.getCommand() ==
|
||||
CommandConstants::toString( CommandConstants::ERROR_CMD ) ) &&
|
||||
(frame.getProperties().hasProperty(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_MESSAGE ) ) ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_ERRORCOMMAND_H_*/
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_MESSAGECOMMAND_H_
|
||||
#define ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_MESSAGECOMMAND_H_
|
||||
|
||||
#include <cms/Message.h>
|
||||
#include <activemq/connector/stomp/commands/StompMessage.h>
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace commands{
|
||||
|
||||
/**
|
||||
* Message command which represents a ActiveMQMessage with no body
|
||||
* can be sent or recieved.
|
||||
*/
|
||||
class MessageCommand : public StompMessage< cms::Message >
|
||||
{
|
||||
public:
|
||||
|
||||
MessageCommand(void) :
|
||||
StompMessage< cms::Message >() {
|
||||
initialize( getFrame() );
|
||||
}
|
||||
MessageCommand( StompFrame* frame ) :
|
||||
StompMessage< cms::Message >( frame ) {
|
||||
validate( getFrame() );
|
||||
}
|
||||
virtual ~MessageCommand(void) {}
|
||||
|
||||
/**
|
||||
* Clonse this message exactly, returns a new instance that the
|
||||
* caller is required to delete.
|
||||
* @return new copy of this message
|
||||
*/
|
||||
virtual cms::Message* clone(void) const {
|
||||
StompFrame* frame = getFrame().clone();
|
||||
|
||||
return new MessageCommand( frame );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_MESSAGECOMMAND_H_*/
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_RECEIPTCOMMAND_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_RECEIPTCOMMAND_H_
|
||||
|
||||
#include <activemq/connector/stomp/commands/AbstractCommand.h>
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
#include <activemq/transport/Response.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace commands{
|
||||
|
||||
/**
|
||||
* Message sent from the Broker when a receipt is requested
|
||||
* for messages that are sent.
|
||||
*/
|
||||
class ReceiptCommand : public AbstractCommand< transport::Response >
|
||||
{
|
||||
public:
|
||||
|
||||
ReceiptCommand(void) :
|
||||
AbstractCommand<transport::Response>() {
|
||||
initialize( getFrame() );
|
||||
}
|
||||
ReceiptCommand( StompFrame* frame ) :
|
||||
AbstractCommand<transport::Response>(frame) {
|
||||
validate( getFrame() );
|
||||
}
|
||||
virtual ~ReceiptCommand(void) {}
|
||||
|
||||
/**
|
||||
* Get the receipt id
|
||||
*/
|
||||
virtual const char* getReceiptId(void) const{
|
||||
return getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_RECEIPTID) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the receipt id
|
||||
*/
|
||||
virtual void setReceiptId( const std::string& id ){
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_RECEIPTID),
|
||||
id );
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to init the
|
||||
* frame with data appropriate for the command type.
|
||||
* @param Frame to init
|
||||
*/
|
||||
virtual void initialize( StompFrame& frame )
|
||||
{
|
||||
frame.setCommand( CommandConstants::toString(
|
||||
CommandConstants::RECEIPT ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to validate
|
||||
* the passed stomp frame before it is marshalled or unmarshaled
|
||||
* @param Frame to validate
|
||||
* @returns true if frame is valid
|
||||
*/
|
||||
virtual bool validate( const StompFrame& frame ) const
|
||||
{
|
||||
if((frame.getCommand() ==
|
||||
CommandConstants::toString( CommandConstants::RECEIPT )) &&
|
||||
(frame.getProperties().hasProperty(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_RECEIPTID ) ) ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_RECEIPTCOMMAND_H_*/
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_STOMPCOMMAND_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_STOMPCOMMAND_H_
|
||||
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
#include <activemq/connector/stomp/marshal/Marshalable.h>
|
||||
#include <activemq/connector/stomp/marshal/MarshalException.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace commands{
|
||||
|
||||
class StompCommand : public marshal::Marshalable
|
||||
{
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to init the
|
||||
* frame with data appropriate for the command type.
|
||||
* @param Frame to init
|
||||
*/
|
||||
virtual void initialize( StompFrame& frame ) = 0;
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to validate
|
||||
* the passed stomp frame before it is marshalled or unmarshaled
|
||||
* @param Frame to validate
|
||||
* @returns true if frame is valid
|
||||
*/
|
||||
virtual bool validate( const StompFrame& frame ) const = 0;
|
||||
|
||||
public:
|
||||
|
||||
virtual ~StompCommand(void) {}
|
||||
|
||||
/**
|
||||
* Sets the Command Id of this Message
|
||||
* @param Command Id
|
||||
*/
|
||||
virtual void setCommandId( const unsigned int id ) = 0;
|
||||
|
||||
/**
|
||||
* Gets the Command Id of this Message
|
||||
* @return Command Id
|
||||
*/
|
||||
virtual unsigned int getCommandId(void) const = 0;
|
||||
|
||||
/**
|
||||
* Set if this Message requires a Response
|
||||
* @param true if response is required
|
||||
*/
|
||||
virtual void setResponseRequired( const bool required ) = 0;
|
||||
|
||||
/**
|
||||
* Is a Response required for this Command
|
||||
* @return true if a response is required.
|
||||
*/
|
||||
virtual bool isResponseRequired(void) const = 0;
|
||||
|
||||
/**
|
||||
* Gets the Correlation Id that is associated with this message
|
||||
* @return the Correlation Id
|
||||
*/
|
||||
virtual unsigned int getCorrelationId(void) const = 0;
|
||||
|
||||
/**
|
||||
* Sets the Correlation Id if this Command
|
||||
* @param Id
|
||||
*/
|
||||
virtual void setCorrelationId( const unsigned int corrId ) = 0;
|
||||
|
||||
/**
|
||||
* Get the Transaction Id of this Command
|
||||
* @return the Id of the Transaction
|
||||
*/
|
||||
virtual const char* getTransactionId(void) const = 0;
|
||||
|
||||
/**
|
||||
* Set the Transaction Id of this Command
|
||||
* @param the Id of the Transaction
|
||||
*/
|
||||
virtual void setTransactionId( const std::string& id ) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve the Stomp Command Id for this message.
|
||||
* @return Stomp CommandId enum
|
||||
*/
|
||||
virtual CommandConstants::CommandId getStompCommandId(void) const = 0;
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_STOMPCOMMAND_H_*/
|
|
@ -0,0 +1,400 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_STOMPMESSAGE_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_STOMPMESSAGE_H_
|
||||
|
||||
#include <activemq/core/ActiveMQMessage.h>
|
||||
#include <activemq/core/ActiveMQAckHandler.h>
|
||||
#include <activemq/connector/stomp/commands/AbstractCommand.h>
|
||||
#include <activemq/transport/Command.h>
|
||||
#include <activemq/connector/stomp/StompTopic.h>
|
||||
|
||||
#include <activemq/util/Long.h>
|
||||
#include <activemq/util/Integer.h>
|
||||
#include <activemq/util/Boolean.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace commands{
|
||||
|
||||
/**
|
||||
* Base class for Stomp Commands that represent the Active MQ message
|
||||
* types. This class is templated and expects the Template type to be
|
||||
* a cms::Message type, Message, TextMessage etc. This class will
|
||||
* implement all the general cms:Message methods
|
||||
*
|
||||
* This class implement AbsractCommand<StompCommnd> and the
|
||||
* ActiveMQMessage interface.
|
||||
*/
|
||||
template<typename T>
|
||||
class StompMessage :
|
||||
public AbstractCommand< transport::Command >,
|
||||
public T,
|
||||
public core::ActiveMQMessage
|
||||
{
|
||||
private:
|
||||
|
||||
// Core API defined Acknowedge Handler.
|
||||
core::ActiveMQAckHandler* ackHandler;
|
||||
|
||||
// Cached Destination
|
||||
cms::Destination* dest;
|
||||
|
||||
public:
|
||||
|
||||
StompMessage(void) :
|
||||
AbstractCommand< transport::Command >(),
|
||||
ackHandler( NULL ) { dest = new StompTopic(); }
|
||||
StompMessage( StompFrame* frame ) :
|
||||
AbstractCommand< transport::Command >( frame ),
|
||||
ackHandler( NULL )
|
||||
{
|
||||
dest = CommandConstants::toDestination(
|
||||
getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_DESTINATION ), "" ) );
|
||||
}
|
||||
|
||||
virtual ~StompMessage(void) { delete dest; }
|
||||
|
||||
/**
|
||||
* Gets the properties map for this command.
|
||||
* @return Reference to a Properties object
|
||||
*/
|
||||
virtual util::Properties& getProperties(void){
|
||||
return getFrame().getProperties();
|
||||
}
|
||||
virtual const util::Properties& getProperties(void) const{
|
||||
return getFrame().getProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Correlation Id for this message
|
||||
* @return string representation of the correlation Id
|
||||
*/
|
||||
virtual const char* getCMSCorrelationId(void) const {
|
||||
return getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_CORRELATIONID ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Correlation Id used by this message
|
||||
* @param String representing the correlation id.
|
||||
*/
|
||||
virtual void setCMSCorrelationId(const std::string& correlationId) {
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_CORRELATIONID ) ,
|
||||
correlationId );
|
||||
}
|
||||
|
||||
/**
|
||||
* Acknowledges all consumed messages of the session
|
||||
* of this consumed message.
|
||||
*/
|
||||
virtual void acknowledge(void) const throw( cms::CMSException ) {
|
||||
if(ackHandler != NULL) ackHandler->acknowledgeMessage(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the DeliveryMode for this message
|
||||
* @return DeliveryMode enumerated value.
|
||||
*/
|
||||
virtual cms::Message::DeliveryMode getCMSDeliveryMode(void) const {
|
||||
if(!getFrame().getProperties().hasProperty(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_PERSISTANT ) ) ) {
|
||||
return cms::Message::PERSISTANT;
|
||||
}
|
||||
|
||||
return (cms::Message::DeliveryMode)(
|
||||
util::Integer::parseInt( getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_PERSISTANT ) ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the DeliveryMode for this message
|
||||
* @param DeliveryMode enumerated value.
|
||||
*/
|
||||
virtual void setCMSDeliveryMode(cms::Message::DeliveryMode mode) {
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_PERSISTANT ) ,
|
||||
util::Integer::toString((int)mode) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Destination for this Message
|
||||
* @return Destination object
|
||||
*/
|
||||
virtual const cms::Destination& getCMSDestination(void) const{
|
||||
return *dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Destination for this message
|
||||
* @param Destination Object
|
||||
*/
|
||||
virtual void setCMSDestination(const cms::Destination& destination) {
|
||||
dest->copy( destination );
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_DESTINATION ),
|
||||
dest->toProviderString() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Expiration Time for this Message
|
||||
* @return time value
|
||||
*/
|
||||
virtual long getCMSExpiration(void) const {
|
||||
return util::Long::parseLong( getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_EXPIRES ), "0" ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Expiration Time for this message
|
||||
* @param time value
|
||||
*/
|
||||
virtual void setCMSExpiration(long expireTime) {
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_EXPIRES) ,
|
||||
util::Long::toString( expireTime ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CMS Message Id for this Message
|
||||
* @return time value
|
||||
*/
|
||||
virtual const char* getCMSMessageId(void) const {
|
||||
return getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_MESSAGEID ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the CMS Message Id for this message
|
||||
* @param time value
|
||||
*/
|
||||
virtual void setCMSMessageId(const std::string& id) {
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_MESSAGEID ),
|
||||
id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Priority Value for this Message
|
||||
* @return priority value
|
||||
*/
|
||||
virtual int getCMSPriority(void) const {
|
||||
return util::Integer::parseInt( getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_PRIORITY ), "0" ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Priority Value for this message
|
||||
* @param priority value
|
||||
*/
|
||||
virtual void setCMSPriority(int priority) {
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_PRIORITY),
|
||||
util::Integer::toString( priority ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Redelivered Flag for this Message
|
||||
* @return redelivered value
|
||||
*/
|
||||
virtual bool getCMSRedelivered(void) const {
|
||||
return util::Boolean::parseBoolean( getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_REDELIVERED ),
|
||||
"false" ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Redelivered Flag for this message
|
||||
* @param redelivered value
|
||||
*/
|
||||
virtual void setCMSRedelivered(bool redelivered) {
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_REDELIVERED ),
|
||||
util::Boolean::toString( redelivered ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CMS Reply To Address for this Message
|
||||
* @return Reply To Value
|
||||
*/
|
||||
virtual const char* getCMSReplyTo(void) const {
|
||||
return getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_REPLYTO ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the CMS Reply To Address for this message
|
||||
* @param Reply To value
|
||||
*/
|
||||
virtual void setCMSReplyTo(const std::string& id) {
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_REPLYTO ),
|
||||
id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Time Stamp for this Message
|
||||
* @return time stamp value
|
||||
*/
|
||||
virtual long getCMSTimeStamp(void) const {
|
||||
return util::Long::parseLong( getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_TIMESTAMP ), "0" ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Time Stamp for this message
|
||||
* @param time stamp value
|
||||
*/
|
||||
virtual void setCMSTimeStamp(long timeStamp) {
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_TIMESTAMP ),
|
||||
util::Long::toString( timeStamp ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CMS Message Type for this Message
|
||||
* @return type value
|
||||
*/
|
||||
virtual const char* getCMSMessageType(void) const {
|
||||
return getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_TYPE ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the CMS Message Type for this message
|
||||
* @param type value
|
||||
*/
|
||||
virtual void setCMSMessageType(const std::string& type) {
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_TYPE ),
|
||||
type );
|
||||
}
|
||||
|
||||
public: // ActiveMQMessage
|
||||
|
||||
/**
|
||||
* Sets the Acknowledgement Handler that this Message will use
|
||||
* when the Acknowledge method is called.
|
||||
* @param ActiveMQAckHandler
|
||||
*/
|
||||
virtual void setAckHandler(core::ActiveMQAckHandler* handler) {
|
||||
this->ackHandler = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of times this message has been redelivered.
|
||||
* @return redelivery count
|
||||
*/
|
||||
virtual int getRedeliveryCount(void) const {
|
||||
return util::Integer::parseInt( getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_REDELIVERYCOUNT ),
|
||||
"0" ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the count of the number of times this message has been
|
||||
* redelivered
|
||||
* @param redelivery count
|
||||
*/
|
||||
virtual void setRedeliveryCount(int count) {
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_REDELIVERYCOUNT ),
|
||||
util::Integer::toString( count ) );
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to init the
|
||||
* frame with data appropriate for the command type.
|
||||
* @param Frame to init
|
||||
*/
|
||||
virtual void initialize( StompFrame& frame )
|
||||
{
|
||||
frame.setCommand( CommandConstants::toString(
|
||||
CommandConstants::SEND ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to validate
|
||||
* the passed stomp frame before it is marshalled or unmarshaled
|
||||
* @param Frame to validate
|
||||
* @returns true if frame is valid
|
||||
*/
|
||||
virtual bool validate( const StompFrame& frame ) const
|
||||
{
|
||||
if(frame.getCommand() ==
|
||||
CommandConstants::toString( CommandConstants::SEND ) )
|
||||
{
|
||||
if(frame.getProperties().hasProperty(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_DESTINATION ) ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if( frame.getCommand() ==
|
||||
CommandConstants::toString( CommandConstants::MESSAGE ) )
|
||||
{
|
||||
if(frame.getProperties().hasProperty(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_DESTINATION ) ) &&
|
||||
frame.getProperties().hasProperty(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_MESSAGEID ) ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_STOMPMESSAGE_H_*/
|
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_SUBSCRIBECOMMAND_H_
|
||||
#define ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_SUBSCRIBECOMMAND_H_
|
||||
|
||||
#include <activemq/connector/stomp/commands/AbstractCommand.h>
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
#include <activemq/transport/Command.h>
|
||||
#include <activemq/util/Boolean.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace commands{
|
||||
|
||||
/**
|
||||
* Command sent to the broker to subscribe to a topic
|
||||
* or queue.
|
||||
*/
|
||||
class SubscribeCommand : public AbstractCommand< transport::Command >
|
||||
{
|
||||
public:
|
||||
|
||||
SubscribeCommand(void) :
|
||||
AbstractCommand<transport::Command>() {
|
||||
initialize( getFrame() );
|
||||
}
|
||||
SubscribeCommand( StompFrame* frame ) :
|
||||
AbstractCommand< transport::Command >( frame ) {
|
||||
validate( getFrame() );
|
||||
}
|
||||
virtual ~SubscribeCommand(void) {}
|
||||
|
||||
/**
|
||||
* Get the destination
|
||||
* @returns the destination Name String
|
||||
*/
|
||||
virtual const char* getDestination(void) const{
|
||||
return getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_DESTINATION) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the destination
|
||||
* @param the destination Name String
|
||||
*/
|
||||
virtual void setDestination( const std::string& dest ){
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_DESTINATION),
|
||||
dest );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Ack Mode of this Subscription
|
||||
* @param mode setting.
|
||||
*/
|
||||
virtual void setAckMode( const CommandConstants::AckMode mode ){
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_ACK),
|
||||
CommandConstants::toString( mode ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Ack Mode of this Subscription
|
||||
* @return mode setting.
|
||||
*/
|
||||
virtual CommandConstants::AckMode getAckMode(void) const{
|
||||
return CommandConstants::toAckMode(
|
||||
getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_ACK) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Message Selector that is associated with this
|
||||
* subscribe request
|
||||
* @param selector string
|
||||
*/
|
||||
virtual void setMessageSelector( const std::string& selector ) {
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_SELECTOR),
|
||||
selector );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Message Selector that is associated with this
|
||||
* subscribe request
|
||||
* @returns the selector string
|
||||
*/
|
||||
virtual const char* getMessageSelector(void) const{
|
||||
return getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_SELECTOR) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Subscription Name that is associated with this
|
||||
* subscribe request
|
||||
* @param Subscription Name
|
||||
*/
|
||||
virtual void setSubscriptionName( const std::string& name ) {
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_SUBSCRIPTIONNAME),
|
||||
name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Subscription Name that is associated with this
|
||||
* subscribe request
|
||||
* @returns the Subscription Name
|
||||
*/
|
||||
virtual const char* getSubscriptionName(void) const{
|
||||
return getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_SUBSCRIPTIONNAME) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets hether or not locally sent messages should be ignored for
|
||||
* subscriptions. Set to true to filter out locally sent messages
|
||||
* @return NoLocal value
|
||||
*/
|
||||
virtual bool getNoLocal(void) const {
|
||||
return util::Boolean::parseBoolean( getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_NOLOCAL ),
|
||||
"false" ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets hether or not locally sent messages should be ignored for
|
||||
* subscriptions. Set to true to filter out locally sent messages
|
||||
* @param NoLocal value
|
||||
*/
|
||||
virtual void setNoLocal( bool noLocal ) {
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_NOLOCAL ),
|
||||
util::Boolean::toString( noLocal ) );
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to init the
|
||||
* frame with data appropriate for the command type.
|
||||
* @param Frame to init
|
||||
*/
|
||||
virtual void initialize( StompFrame& frame )
|
||||
{
|
||||
frame.setCommand( CommandConstants::toString(
|
||||
CommandConstants::SUBSCRIBE ) );
|
||||
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_ACK),
|
||||
CommandConstants::toString(
|
||||
CommandConstants::ACK_AUTO ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to validate
|
||||
* the passed stomp frame before it is marshalled or unmarshaled
|
||||
* @param Frame to validate
|
||||
* @returns true if frame is valid
|
||||
*/
|
||||
virtual bool validate( const StompFrame& frame ) const
|
||||
{
|
||||
if((frame.getCommand() ==
|
||||
CommandConstants::toString( CommandConstants::SUBSCRIBE )) &&
|
||||
(frame.getProperties().hasProperty(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_DESTINATION ) ) ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_SUBSCRIBECOMMAND_H_*/
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_TEXTMESSAGECOMMAND_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_TEXTMESSAGECOMMAND_H_
|
||||
|
||||
#include <cms/TextMessage.h>
|
||||
#include <activemq/connector/stomp/commands/StompMessage.h>
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace commands{
|
||||
|
||||
class TextMessageCommand : public StompMessage< cms::TextMessage >
|
||||
{
|
||||
public:
|
||||
|
||||
TextMessageCommand(void) :
|
||||
StompMessage< cms::TextMessage >() {
|
||||
initialize( getFrame() );
|
||||
}
|
||||
TextMessageCommand( StompFrame* frame ) :
|
||||
StompMessage< cms::TextMessage >( frame ) {
|
||||
validate( getFrame() );
|
||||
}
|
||||
virtual ~TextMessageCommand(void) {}
|
||||
|
||||
/**
|
||||
* Clonse this message exactly, returns a new instance that the
|
||||
* caller is required to delete.
|
||||
* @return new copy of this message
|
||||
*/
|
||||
virtual cms::Message* clone(void) const {
|
||||
StompFrame* frame = getFrame().clone();
|
||||
|
||||
return new TextMessageCommand( frame );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the message character buffer.
|
||||
* @return The message character buffer.
|
||||
*/
|
||||
virtual const char* getText(void) const throw( cms::CMSException ) {
|
||||
return getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the message contents.
|
||||
* @param msg The message buffer.
|
||||
*/
|
||||
virtual void setText( const char* msg ) throw( cms::CMSException ) {
|
||||
setBytes( msg, strlen(msg) + 1, false );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_TEXTMESSAGECOMMAND_H_*/
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_UNSUBSCRIBECOMMAND_H_
|
||||
#define ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_UNSUBSCRIBECOMMAND_H_
|
||||
|
||||
#include <activemq/connector/stomp/commands/AbstractCommand.h>
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
#include <activemq/transport/Command.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace commands{
|
||||
|
||||
/**
|
||||
* Command sent to the broker to unsubscribe to a
|
||||
* topic or queue.
|
||||
*/
|
||||
class UnsubscribeCommand : public AbstractCommand< transport::Command >
|
||||
{
|
||||
public:
|
||||
|
||||
UnsubscribeCommand(void) :
|
||||
AbstractCommand< transport::Command >() {
|
||||
initialize( getFrame() );
|
||||
}
|
||||
UnsubscribeCommand( StompFrame* frame ) :
|
||||
AbstractCommand< transport::Command >( frame ) {
|
||||
validate( getFrame() );
|
||||
}
|
||||
virtual ~UnsubscribeCommand(void) {};
|
||||
|
||||
/**
|
||||
* Get the destination
|
||||
*/
|
||||
virtual const char* getDestination(void) const{
|
||||
return getPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_DESTINATION) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the destination
|
||||
*/
|
||||
virtual void setDestination( const std::string& dest ){
|
||||
setPropertyValue(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_DESTINATION) ,
|
||||
dest );
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to init the
|
||||
* frame with data appropriate for the command type.
|
||||
* @param Frame to init
|
||||
*/
|
||||
virtual void initialize( StompFrame& frame )
|
||||
{
|
||||
frame.setCommand( CommandConstants::toString(
|
||||
CommandConstants::UNSUBSCRIBE ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Inheritors are required to override this method to validate
|
||||
* the passed stomp frame before it is marshalled or unmarshaled
|
||||
* @param Frame to validate
|
||||
* @returns true if frame is valid
|
||||
*/
|
||||
virtual bool validate( const StompFrame& frame ) const
|
||||
{
|
||||
if((frame.getCommand() ==
|
||||
CommandConstants::toString( CommandConstants::UNSUBSCRIBE )) &&
|
||||
(frame.getProperties().hasProperty(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_DESTINATION ) ) ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_UNSUBSCRIBECOMMAND_H_*/
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef ACTIVEMQ_CONNECTOR_STOMP_MARSHALL_MARSHALEXCEPTION_H_
|
||||
#define ACTIVEMQ_CONNECTOR_STOMP_MARSHALL_MARSHALEXCEPTION_H_
|
||||
|
||||
#include <activemq/exceptions/ActiveMQException.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace marshal{
|
||||
|
||||
/*
|
||||
* Signals that an problem occurred during marshalling.
|
||||
*/
|
||||
class MarshalException : public exceptions::ActiveMQException
|
||||
{
|
||||
public:
|
||||
|
||||
MarshalException() {}
|
||||
MarshalException( const exceptions::ActiveMQException& ex ){
|
||||
*(ActiveMQException*)this = ex;
|
||||
}
|
||||
MarshalException( const MarshalException& ex ){
|
||||
*(exceptions::ActiveMQException*)this = ex;
|
||||
}
|
||||
MarshalException(const char* file, const int lineNumber,
|
||||
const char* msg, ...)
|
||||
{
|
||||
va_list vargs ;
|
||||
va_start(vargs, msg) ;
|
||||
buildMessage(msg, vargs) ;
|
||||
|
||||
// Set the first mark for this exception.
|
||||
setMark( file, lineNumber );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones this exception. This is useful for cases where you need
|
||||
* to preserve the type of the original exception as well as the message.
|
||||
* All subclasses should override.
|
||||
*/
|
||||
virtual exceptions::ActiveMQException* clone() const{
|
||||
return new MarshalException( *this );
|
||||
}
|
||||
virtual ~MarshalException() {}
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*ACTIVEMQ_CONNECTOR_STOMP_MARSHAL_MARSHALLEXCEPTION_H_*/
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef _ACTIVEMQ_CONNECTOR_STOMP_MARSHAL_MARSHALABLE_H_
|
||||
#define _ACTIVEMQ_CONNECTOR_STOMP_MARSHAL_MARSHALABLE_H_
|
||||
|
||||
#include <activemq/connector/stomp/StompFrame.h>
|
||||
#include <activemq/connector/stomp/marshal/MarshalException.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace marshal{
|
||||
|
||||
class Marshalable
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~Marshalable(void) {}
|
||||
|
||||
/**
|
||||
* Marshals the command to a stomp frame.
|
||||
* @returns the stomp frame representation of this
|
||||
* command.
|
||||
* @throws MarshalException if the command is not
|
||||
* in a state that can be marshalled.
|
||||
*/
|
||||
virtual const StompFrame& marshal(void) const
|
||||
throw ( marshal::MarshalException ) = 0;
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CONNECTOR_STOMP_MARSHAL_MARSHALABLE_H_*/
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#include <activemq/connector/stomp/marshal/Marshaler.h>
|
||||
|
||||
#include <activemq/transport/Command.h>
|
||||
#include <activemq/connector/stomp/marshal/MarshalException.h>
|
||||
#include <activemq/connector/stomp/commands/CommandConstants.h>
|
||||
#include <activemq/connector/stomp/commands/AbstractCommand.h>
|
||||
#include <activemq/connector/stomp/StompFrame.h>
|
||||
|
||||
// Commands we can receive
|
||||
#include <activemq/connector/stomp/commands/ConnectedCommand.h>
|
||||
#include <activemq/connector/stomp/commands/ReceiptCommand.h>
|
||||
#include <activemq/connector/stomp/commands/ErrorCommand.h>
|
||||
|
||||
// Message Commands we can receive
|
||||
#include <activemq/connector/stomp/commands/MessageCommand.h>
|
||||
#include <activemq/connector/stomp/commands/BytesMessageCommand.h>
|
||||
#include <activemq/connector/stomp/commands/TextMessageCommand.h>
|
||||
|
||||
using namespace activemq;
|
||||
using namespace activemq::exceptions;
|
||||
using namespace activemq::transport;
|
||||
using namespace activemq::connector::stomp;
|
||||
using namespace activemq::connector::stomp::commands;
|
||||
using namespace activemq::connector::stomp::marshal;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
transport::Command* Marshaler::marshal( StompFrame* frame )
|
||||
throw ( MarshalException )
|
||||
{
|
||||
try
|
||||
{
|
||||
CommandConstants::CommandId commandId =
|
||||
CommandConstants::toCommandId(frame->getCommand().c_str());
|
||||
transport::Command* command = NULL;
|
||||
|
||||
if(commandId == CommandConstants::CONNECTED){
|
||||
command = new ConnectedCommand( frame );
|
||||
}
|
||||
else if(commandId == CommandConstants::ERROR_CMD){
|
||||
command = new ErrorCommand( frame );
|
||||
}
|
||||
else if(commandId == CommandConstants::RECEIPT){
|
||||
command = new ReceiptCommand( frame );
|
||||
}
|
||||
else if(commandId == CommandConstants::MESSAGE){
|
||||
if( !frame->getProperties().hasProperty(
|
||||
CommandConstants::toString(
|
||||
CommandConstants::HEADER_CONTENTLENGTH ) ) )
|
||||
{
|
||||
command = new TextMessageCommand( frame );
|
||||
}
|
||||
else
|
||||
{
|
||||
command = new BytesMessageCommand( frame );
|
||||
}
|
||||
}
|
||||
|
||||
// We either got a command or a response, but if we got neither
|
||||
// then complain, something went wrong.
|
||||
if(command == NULL)
|
||||
{
|
||||
throw MarshalException(
|
||||
__FILE__, __LINE__,
|
||||
"Marshaler::marshal - No Command Created from frame");
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
AMQ_CATCH_RETHROW( MarshalException )
|
||||
AMQ_CATCH_EXCEPTION_CONVERT( ActiveMQException, MarshalException )
|
||||
AMQ_CATCHALL_THROW( MarshalException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const StompFrame& Marshaler::marshal( const transport::Command* command )
|
||||
throw ( MarshalException )
|
||||
{
|
||||
try
|
||||
{
|
||||
const Marshalable* marshalable =
|
||||
dynamic_cast<const Marshalable*>(command);
|
||||
|
||||
// Easy, just get the frame from the command
|
||||
if(marshalable != NULL)
|
||||
{
|
||||
return marshalable->marshal();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw MarshalException(
|
||||
__FILE__, __LINE__,
|
||||
"Marshaler::marshal - Invalid Command Type!");
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( MarshalException )
|
||||
AMQ_CATCH_EXCEPTION_CONVERT( ActiveMQException, MarshalException )
|
||||
AMQ_CATCHALL_THROW( MarshalException )
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef ACTIVEMQ_CONNECTOR_STOMP_MARSHALER_H_
|
||||
#define ACTIVEMQ_CONNECTOR_STOMP_MARSHALER_H_
|
||||
|
||||
#include <activemq/transport/Command.h>
|
||||
#include <activemq/connector/stomp/StompFrame.h>
|
||||
#include <activemq/connector/stomp/marshal/MarshalException.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace connector{
|
||||
namespace stomp{
|
||||
namespace marshal{
|
||||
|
||||
/**
|
||||
* Interface for all marshallers between Commands and
|
||||
* stomp frames.
|
||||
*/
|
||||
class Marshaler
|
||||
{
|
||||
public:
|
||||
|
||||
Marshaler(void) {}
|
||||
virtual ~Marshaler(void) {}
|
||||
|
||||
/**
|
||||
* Marshall a Stomp Frame to a Stomp Command, the frame is now
|
||||
* owned by this Command, caller should not use the frame again.
|
||||
* @param Frame to Marshall
|
||||
* @return Newly Marshaled Stomp Message
|
||||
* @throws MarshalException
|
||||
*/
|
||||
virtual transport::Command* marshal( StompFrame* frame )
|
||||
throw ( MarshalException );
|
||||
|
||||
/**
|
||||
* Marshal a Stomp Command to a Stom Frame, if the command that
|
||||
* is past is not castable to a Stomp Command an Exception will
|
||||
* be thrown
|
||||
* @param The Stomp Command to Marshal
|
||||
* @return newly Marshaled Stomp Frame
|
||||
* @throws MarshalException
|
||||
*/
|
||||
virtual const StompFrame& marshal(
|
||||
const transport::Command* command )
|
||||
throw ( MarshalException );
|
||||
|
||||
};
|
||||
|
||||
}}}}
|
||||
|
||||
#endif /*ACTIVEMQ_CONNECTOR_STOMP_MARSHALER_H_*/
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CORE_ACTIVEMQACKHANDLER_H_
|
||||
#define _ACTIVEMQ_CORE_ACTIVEMQACKHANDLER_H_
|
||||
|
||||
#include <cms/CMSException.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace core{
|
||||
|
||||
class ActiveMQMessage;
|
||||
|
||||
/**
|
||||
* Interface class that is used to give CMS Messages an interface to
|
||||
* Ack themselves with.
|
||||
*/
|
||||
class ActiveMQAckHandler
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~ActiveMQAckHandler(void) {};
|
||||
|
||||
/**
|
||||
* Method called to acknowledge the message passed
|
||||
* @param Message to Acknowlegde
|
||||
* @throw CMSException
|
||||
*/
|
||||
virtual void acknowledgeMessage( const ActiveMQMessage* message )
|
||||
throw ( cms::CMSException ) = 0;
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CORE_ACTIVEMQACKHANDLER_H_*/
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#include "ActiveMQConnection.h"
|
||||
|
||||
#include <cms/Session.h>
|
||||
#include <activemq/core/ActiveMQSession.h>
|
||||
#include <activemq/core/ActiveMQConsumer.h>
|
||||
#include <activemq/exceptions/NullPointerException.h>
|
||||
|
||||
using namespace cms;
|
||||
using namespace activemq;
|
||||
using namespace activemq::core;
|
||||
using namespace activemq::connector;
|
||||
using namespace activemq::exceptions;
|
||||
using namespace std;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ActiveMQConnection::ActiveMQConnection(ActiveMQConnectionData* connectionData)
|
||||
{
|
||||
this->connectionData = connectionData;
|
||||
this->started = false;
|
||||
this->exceptionListener = NULL;
|
||||
|
||||
// We want to be the sink for all messages from the Connector
|
||||
connectionData->getConnector()->setConsumerMessageListener( this );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ActiveMQConnection::~ActiveMQConnection(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
close();
|
||||
}
|
||||
AMQ_CATCH_NOTHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_NOTHROW( )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::Session* ActiveMQConnection::createSession(void)
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
return this->createSession( Session::AutoAcknowledge );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::Session* ActiveMQConnection::createSession(
|
||||
cms::Session::AcknowledgeMode ackMode )
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
return new ActiveMQSession(
|
||||
connectionData->getConnector()->createSession( ackMode ),
|
||||
connectionData->getProperties(),
|
||||
this );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string ActiveMQConnection::getClientId(void) const
|
||||
{
|
||||
return connectionData->getConnector()->getClientId();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQConnection::close(void) throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
// Once current deliveries are done this stops the delivery
|
||||
// of any new messages.
|
||||
started = false;
|
||||
|
||||
// Destroy the connection data
|
||||
delete connectionData;
|
||||
connectionData = NULL;
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQConnection::start(void) throw ( cms::CMSException )
|
||||
{
|
||||
// This starts or restarts the delivery of all incomming messages
|
||||
// messages delivered while this connection is stopped are dropped
|
||||
// and not acknowledged.
|
||||
started = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQConnection::stop(void) throw ( cms::CMSException )
|
||||
{
|
||||
// Once current deliveries are done this stops the delivery of any
|
||||
// new messages.
|
||||
started = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQConnection::addMessageListener( const unsigned int consumerId,
|
||||
ActiveMQMessageListener* listener )
|
||||
{
|
||||
// Place in Map
|
||||
synchronized(&mutex)
|
||||
{
|
||||
consumers[consumerId] = listener;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQConnection::removeMessageListener( const unsigned int consumerId )
|
||||
{
|
||||
// Remove from Map
|
||||
synchronized(&mutex)
|
||||
{
|
||||
consumers.erase( consumerId );
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQConnection::onConsumerMessage( connector::ConsumerInfo* consumer,
|
||||
core::ActiveMQMessage* message )
|
||||
{
|
||||
try
|
||||
{
|
||||
if( connectionData == NULL)
|
||||
{
|
||||
NullPointerException ex(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQConnection::onConsumerMessage - "
|
||||
"Connection Data Null, could be closed." );
|
||||
|
||||
fire( ex );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// When not started we drop incomming messages
|
||||
if( !started )
|
||||
{
|
||||
// Indicate to Broker that we received the message, but it
|
||||
// was not consumed.
|
||||
connectionData->getConnector()->acknowledge(
|
||||
consumer->getSessionInfo(),
|
||||
(Message*)message,
|
||||
Connector::DeliveredAck );
|
||||
|
||||
// Delete the message here
|
||||
delete message;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Started, so lock map and dispatch the message.
|
||||
synchronized(&mutex)
|
||||
{
|
||||
if(consumers.find(consumer->getConsumerId()) != consumers.end())
|
||||
{
|
||||
consumers[consumer->getConsumerId()]->
|
||||
onActiveMQMessage( message );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( exceptions::ActiveMQException& ex )
|
||||
{
|
||||
ex.setMark( __FILE__, __LINE__ );
|
||||
fire( ex );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
exceptions::ActiveMQException ex(
|
||||
__FILE__, __LINE__,
|
||||
"IOTransport::run - caught unknown exception" );
|
||||
fire( ex );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CORE_ACTIVEMQCONNECTION_H_
|
||||
#define _ACTIVEMQ_CORE_ACTIVEMQCONNECTION_H_
|
||||
|
||||
#include <cms/Connection.h>
|
||||
#include <cms/ExceptionListener.h>
|
||||
#include <activemq/concurrent/Mutex.h>
|
||||
#include <activemq/core/ActiveMQConnectionData.h>
|
||||
#include <activemq/core/ActiveMQMessageListener.h>
|
||||
#include <activemq/core/ActiveMQMessage.h>
|
||||
#include <activemq/connector/ConsumerMessageListener.h>
|
||||
#include <activemq/util/Properties.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace activemq{
|
||||
namespace core{
|
||||
|
||||
class cms::Session;
|
||||
class ActiveMQConsumer;
|
||||
|
||||
class ActiveMQConnection :
|
||||
public cms::Connection,
|
||||
public connector::ConsumerMessageListener
|
||||
{
|
||||
private:
|
||||
|
||||
// the registered exception listener
|
||||
cms::ExceptionListener* exceptionListener;
|
||||
|
||||
// All the data that is used to connect this Connection
|
||||
ActiveMQConnectionData* connectionData;
|
||||
|
||||
// Indicates if this Connection is started
|
||||
bool started;
|
||||
|
||||
// Map of Consumer Ids to ActiveMQMessageListeners
|
||||
std::map<unsigned int, ActiveMQMessageListener*> consumers;
|
||||
|
||||
// Mutex to lock the Consumers Map
|
||||
concurrent::Mutex mutex;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ActiveMQConnection(ActiveMQConnectionData* connectionData);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ActiveMQConnection(void);
|
||||
|
||||
public: // Connection Interface Methods
|
||||
|
||||
/**
|
||||
* Creates a new Session to work for this Connection
|
||||
*/
|
||||
virtual cms::Session* createSession(void) throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Creates a new Session to work for this Connection using the
|
||||
* specified acknowledgment mode
|
||||
* @param the Acknowledgement Mode to use.
|
||||
*/
|
||||
virtual cms::Session* createSession(cms::Session::AcknowledgeMode ackMode)
|
||||
throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Get the Client Id for this session
|
||||
* @return string version of Client Id
|
||||
*/
|
||||
virtual std::string getClientId(void) const;
|
||||
|
||||
/**
|
||||
* Retrieves the Connection Data object for this object.
|
||||
* @return pointer to a connection data object.
|
||||
*/
|
||||
virtual ActiveMQConnectionData* getConnectionData(void){
|
||||
return connectionData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the registered Exception Listener for this connection
|
||||
* @return pointer to an exception listnener or NULL
|
||||
*/
|
||||
virtual cms::ExceptionListener* getExceptionListener(void) const{
|
||||
return exceptionListener; };
|
||||
|
||||
/**
|
||||
* Sets the registed Exception Listener for this connection
|
||||
* @param pointer to and <code>ExceptionListener</code>
|
||||
*/
|
||||
virtual void setExceptionListener(cms::ExceptionListener* listener){
|
||||
exceptionListener = listener; };
|
||||
|
||||
/**
|
||||
* Close the currently open connection
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual void close(void) throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Starts or (restarts) a connections delivery of incoming messages
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual void start(void) throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Stop the flow of incoming messages
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual void stop(void) throw ( cms::CMSException );
|
||||
|
||||
public: // ActiveMQConnection Methods
|
||||
|
||||
/**
|
||||
* Adds the ActiveMQMessageListener to the Mapping of Consumer Id's
|
||||
* to listeners, all message to that id will be routed to the given
|
||||
* listener
|
||||
* @param Consumer Id String
|
||||
* @param ActiveMQMessageListener Pointer
|
||||
*/
|
||||
virtual void addMessageListener(const unsigned int consumerId,
|
||||
ActiveMQMessageListener* listener);
|
||||
|
||||
/**
|
||||
* Remove the Listener for the specified Consumer Id
|
||||
* @param Consumer Id string
|
||||
*/
|
||||
virtual void removeMessageListener(const unsigned int consumerId);
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Notify the excpetion listener
|
||||
*/
|
||||
void fire( exceptions::ActiveMQException& ex )
|
||||
{
|
||||
if( exceptionListener != NULL )
|
||||
{
|
||||
try
|
||||
{
|
||||
exceptionListener->onException( ex );
|
||||
}
|
||||
catch(...){}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to dispatch a message to a particular consumer.
|
||||
* @param consumer the target consumer of the dispatch.
|
||||
* @param msg the message to be dispatched.
|
||||
*/
|
||||
virtual void onConsumerMessage( connector::ConsumerInfo* consumer,
|
||||
core::ActiveMQMessage* message );
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*ACTIVEMQCONNECTION_H_*/
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CORE_ACTIVEMQCONNECTIONDATA_H_
|
||||
#define _ACTIVEMQ_CORE_ACTIVEMQCONNECTIONDATA_H_
|
||||
|
||||
#include <activemq/connector/Connector.h>
|
||||
#include <activemq/transport/Transport.h>
|
||||
#include <activemq/exceptions/IllegalArgumentException.h>
|
||||
#include <activemq/util/Properties.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace core{
|
||||
|
||||
/**
|
||||
* Container of the Data that is needed when creating a new connection
|
||||
* object. Each ActiveMQConnection owns one of these objects. This
|
||||
* object knows how to clean up the Connection Dependencies correctly
|
||||
*/
|
||||
class ActiveMQConnectionData
|
||||
{
|
||||
private:
|
||||
|
||||
// Connector Object
|
||||
connector::Connector* connector;
|
||||
|
||||
// Transport we are using
|
||||
transport::Transport* transport;
|
||||
|
||||
// Properties used to configure this connection.
|
||||
util::Properties* properties;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Creates a new Connection Data object, passing it the data that
|
||||
* it will manage for the parent connection object.
|
||||
* @param A connector instance
|
||||
* @param A Socket instance
|
||||
* @param A Transport instance
|
||||
* @throw IllegalArgumentException if an element is NULL
|
||||
*/
|
||||
ActiveMQConnectionData( connector::Connector* connector,
|
||||
transport::Transport* transport,
|
||||
util::Properties* properties )
|
||||
{
|
||||
if( connector == NULL ||
|
||||
transport == NULL ||
|
||||
properties == NULL )
|
||||
{
|
||||
throw exceptions::IllegalArgumentException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQConnectionData::ActiveMQConnectionData - "
|
||||
"Required Parameter was NULL.");
|
||||
}
|
||||
|
||||
this->connector = connector;
|
||||
this->transport = transport;
|
||||
this->properties = properties;
|
||||
}
|
||||
|
||||
virtual ~ActiveMQConnectionData(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
connector->close();
|
||||
delete connector;
|
||||
|
||||
transport->close();
|
||||
delete transport;
|
||||
|
||||
delete properties;
|
||||
}
|
||||
AMQ_CATCH_NOTHROW( exceptions::ActiveMQException )
|
||||
AMQ_CATCHALL_NOTHROW( )
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Connector that this Connection Data object holds
|
||||
* @return Connector Pointer
|
||||
*/
|
||||
virtual connector::Connector* getConnector(void){
|
||||
return connector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Connector that this Connection Data object holds
|
||||
* @return Connector Pointer
|
||||
*/
|
||||
virtual transport::Transport* getTransport(void){
|
||||
return transport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to the properties that were used to configure
|
||||
* this Connection.
|
||||
* @return Properties object reference.
|
||||
*/
|
||||
virtual const util::Properties& getProperties(void) const {
|
||||
return *properties;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CORE_ACTIVEMQCONNECTIONDATA_H_*/
|
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#include "ActiveMQConnectionFactory.h"
|
||||
|
||||
#include <activemq/util/Guid.h>
|
||||
#include <activemq/util/SimpleProperties.h>
|
||||
#include <activemq/util/StringTokenizer.h>
|
||||
#include <activemq/connector/ConnectorFactoryMap.h>
|
||||
#include <activemq/network/SocketFactory.h>
|
||||
#include <activemq/transport/TransportFactoryMap.h>
|
||||
#include <activemq/network/Socket.h>
|
||||
#include <activemq/exceptions/NullPointerException.h>
|
||||
#include <activemq/core/ActiveMQConnection.h>
|
||||
#include <activemq/util/StringTokenizer.h>
|
||||
#include <activemq/support/LibraryInit.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace activemq;
|
||||
using namespace activemq::core;
|
||||
using namespace activemq::util;
|
||||
using namespace activemq::connector;
|
||||
using namespace activemq::exceptions;
|
||||
using namespace activemq::network;
|
||||
using namespace activemq::transport;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ActiveMQConnectionFactory::ActiveMQConnectionFactory(void)
|
||||
{
|
||||
brokerURL = "tcp://localhost:61616";
|
||||
|
||||
this->username = "";
|
||||
this->password = "";
|
||||
this->clientId = "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ActiveMQConnectionFactory::ActiveMQConnectionFactory(const std::string& url,
|
||||
const std::string& username,
|
||||
const std::string& password,
|
||||
const std::string& clientId)
|
||||
{
|
||||
brokerURL = url;
|
||||
|
||||
this->username = username;
|
||||
this->password = password;
|
||||
this->clientId = clientId;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::Connection* ActiveMQConnectionFactory::createConnection(void)
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
return createConnection(username, password);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::Connection* ActiveMQConnectionFactory::createConnection(
|
||||
const std::string& username,
|
||||
const std::string& password,
|
||||
const std::string& clientId )
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
// Declared here so that they can be deleted in the catch block
|
||||
SimpleProperties* properties = NULL;
|
||||
Transport* transport = NULL;
|
||||
Connector* connector = NULL;
|
||||
ActiveMQConnectionData* connectionData = NULL;
|
||||
ActiveMQConnection* connection = NULL;
|
||||
|
||||
this->username = username;
|
||||
this->password = password;
|
||||
this->clientId = clientId;
|
||||
|
||||
try
|
||||
{
|
||||
properties = new SimpleProperties;
|
||||
|
||||
// if no Client Id specified, create one
|
||||
if( this->clientId == "" )
|
||||
{
|
||||
this->clientId = Guid::createGUIDString();
|
||||
}
|
||||
|
||||
// Store login data in the properties
|
||||
properties->setProperty( "username", this->username );
|
||||
properties->setProperty( "password", this->password );
|
||||
properties->setProperty( "clientId", this->clientId );
|
||||
|
||||
// Parse out the properties from the URI
|
||||
parseURL( brokerURL, *properties );
|
||||
|
||||
// Create the Transport that the Connector will use.
|
||||
string factoryName =
|
||||
properties->getProperty( "transport", "tcp" );
|
||||
TransportFactory* factory =
|
||||
TransportFactoryMap::getInstance().lookup( factoryName );
|
||||
if( factory == NULL ){
|
||||
throw ActiveMQException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQConnectionFactory::createConnection - "
|
||||
"unknown transport factory");
|
||||
}
|
||||
|
||||
// Create the transport.
|
||||
transport = factory->createTransport( *properties );
|
||||
if( transport == NULL ){
|
||||
throw ActiveMQException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQConnectionFactory::createConnection - "
|
||||
"failed creating new Transport");
|
||||
}
|
||||
|
||||
// What wire format are we using, defaults to Stomp
|
||||
std::string wireFormat =
|
||||
properties->getProperty( "wireFormat", "stomp" );
|
||||
|
||||
// Now try and find a factory to create the Connector
|
||||
ConnectorFactory* connectorfactory =
|
||||
ConnectorFactoryMap::getInstance()->lookup( wireFormat );
|
||||
|
||||
if( connectorfactory == NULL )
|
||||
{
|
||||
throw NullPointerException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQConnectionFactory::createConnection - "
|
||||
"Connector for Wire Format not registered in Map");
|
||||
}
|
||||
|
||||
// Create the Connector.
|
||||
connector = connectorfactory->createConnector( *properties, transport );
|
||||
|
||||
if(connector == NULL)
|
||||
{
|
||||
throw NullPointerException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQConnectionFactory::createConnection - "
|
||||
"Failed to Create the Connector");
|
||||
}
|
||||
|
||||
// Start the Connector
|
||||
connector->start();
|
||||
|
||||
// Create Holder and store the data for the Connection
|
||||
connectionData = new ActiveMQConnectionData(
|
||||
connector, transport, properties );
|
||||
|
||||
// Create and Return the new connection object.
|
||||
connection = new ActiveMQConnection( connectionData );
|
||||
|
||||
return connection;
|
||||
}
|
||||
catch( exceptions::ActiveMQException& ex )
|
||||
{
|
||||
ex.setMark( __FILE__, __LINE__ );
|
||||
|
||||
delete connection;
|
||||
delete connector;
|
||||
delete transport;
|
||||
delete properties;
|
||||
|
||||
throw ex;
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
exceptions::ActiveMQException ex(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQConnectionFactory::create - "
|
||||
"caught unknown exception" );
|
||||
|
||||
delete connection;
|
||||
delete connector;
|
||||
delete transport;
|
||||
delete properties;
|
||||
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQConnectionFactory::parseURL(const std::string& URI,
|
||||
Properties& properties)
|
||||
throw ( exceptions::IllegalArgumentException )
|
||||
{
|
||||
try
|
||||
{
|
||||
StringTokenizer tokenizer(URI, ":/");
|
||||
|
||||
std::vector<std::string> tokens;
|
||||
|
||||
// Require that there be three tokens at the least, these are
|
||||
// transport, url, port.
|
||||
if(tokenizer.countTokens() < 3)
|
||||
{
|
||||
throw exceptions::IllegalArgumentException(
|
||||
__FILE__, __LINE__,
|
||||
(string("ActiveMQConnectionFactory::parseURL - "
|
||||
"Marlformed URI: ") + URI).c_str());
|
||||
}
|
||||
|
||||
// First element should be the Transport Type, following that is the
|
||||
// URL and any params.
|
||||
properties.setProperty( "transport", tokenizer.nextToken() );
|
||||
|
||||
// Parse URL and Port as one item, optional params follow the ?
|
||||
// and then each param set is delimited with & we extract first
|
||||
// three chars as they are the left over ://
|
||||
properties.setProperty( "uri", tokenizer.nextToken("&?").substr(3) );
|
||||
|
||||
// Now get all the optional parameters and store them as properties
|
||||
int count = tokenizer.toArray(tokens);
|
||||
|
||||
for(int i = 0; i < count; ++i)
|
||||
{
|
||||
tokenizer.reset(tokens[i], "=");
|
||||
|
||||
if(tokenizer.countTokens() != 2)
|
||||
{
|
||||
throw exceptions::IllegalArgumentException(
|
||||
__FILE__, __LINE__,
|
||||
(string("ActiveMQConnectionFactory::parseURL - "
|
||||
"Marlformed Parameter = ") + tokens[i]).c_str());
|
||||
}
|
||||
|
||||
// Store this param as a property
|
||||
properties.setProperty(tokenizer.nextToken(), tokenizer.nextToken());
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( IllegalArgumentException )
|
||||
AMQ_CATCH_EXCEPTION_CONVERT( ActiveMQException, IllegalArgumentException )
|
||||
AMQ_CATCHALL_THROW( IllegalArgumentException )
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CORE_ACTIVEMQCONNECTIONFACTORY_H_
|
||||
#define _ACTIVEMQ_CORE_ACTIVEMQCONNECTIONFACTORY_H_
|
||||
|
||||
#include <cms/ConnectionFactory.h>
|
||||
#include <cms/Connection.h>
|
||||
|
||||
#include <activemq/exceptions/IllegalArgumentException.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace core{
|
||||
|
||||
class util::Properties;
|
||||
|
||||
class ActiveMQConnectionFactory : public cms::ConnectionFactory
|
||||
{
|
||||
private:
|
||||
|
||||
// The user name this factory will use to connect
|
||||
std::string username;
|
||||
|
||||
// The password this factory will use to connect
|
||||
std::string password;
|
||||
|
||||
// The client id to assign to the connection created
|
||||
std::string clientId;
|
||||
|
||||
// The URL of the Broker, the default is:
|
||||
// "tcp://localhost:61616"
|
||||
std::string brokerURL;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ActiveMQConnectionFactory(void);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param the URL of the Broker we are connecting to.
|
||||
* @param username to authenticate with, defaults to ""
|
||||
* @param password to authenticate with, defaults to ""
|
||||
* @param client Id to assign to connection, defaults to ""
|
||||
*/
|
||||
ActiveMQConnectionFactory(const std::string& url,
|
||||
const std::string& username = "",
|
||||
const std::string& password = "",
|
||||
const std::string& clientId = "");
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ActiveMQConnectionFactory(void) {}
|
||||
|
||||
/**
|
||||
* Creates a connection with the default user identity. The
|
||||
* connection is created in stopped mode. No messages will be
|
||||
* delivered until the Connection.start method is explicitly
|
||||
* called.
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual cms::Connection* createConnection(void) throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Creates a connection with the specified user identity. The
|
||||
* connection is created in stopped mode. No messages will be
|
||||
* delivered until the Connection.start method is explicitly called.
|
||||
* @throw CMSException.
|
||||
*/
|
||||
virtual cms::Connection* createConnection(const std::string& username,
|
||||
const std::string& password,
|
||||
const std::string& clientId = "")
|
||||
throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Sets the username that should be used when creating a new connection
|
||||
* @param username string
|
||||
*/
|
||||
virtual void setUsername(const std::string& username){
|
||||
this->username = username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the username that this factory will use when creating a new
|
||||
* connection instance.
|
||||
* @return username string, "" for default credentials
|
||||
*/
|
||||
virtual const std::string& getUsername(void) const {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the password that should be used when creating a new connection
|
||||
* @param password string
|
||||
*/
|
||||
virtual void setPassword(const std::string& password){
|
||||
this->password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the password that this factory will use when creating a new
|
||||
* connection instance.
|
||||
* @return password string, "" for default credentials
|
||||
*/
|
||||
virtual const std::string& getPassword(void) const {
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Broker URL that should be used when creating a new
|
||||
* connection instance
|
||||
* @param brokerURL string
|
||||
*/
|
||||
virtual void setBrokerURL(const std::string& brokerURL){
|
||||
this->brokerURL = brokerURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Broker URL that this factory will use when creating a new
|
||||
* connection instance.
|
||||
* @return brokerURL string
|
||||
*/
|
||||
virtual const std::string& getBrokerURL(void) const {
|
||||
return brokerURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Client Id that should be used when creating a new
|
||||
* connection instance
|
||||
* @param clientId string
|
||||
*/
|
||||
virtual void setClientId(const std::string& clientId){
|
||||
this->clientId = clientId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Client Id that this factory will use when creating a new
|
||||
* connection instance.
|
||||
* @return clientId string
|
||||
*/
|
||||
virtual const std::string& getClientId(void) const {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Parses the properties out of the provided Broker URI and sets
|
||||
* them in the passed Properties Object.
|
||||
* @param a Broker URI to parse
|
||||
* @param a Properties object to set the parsed values in
|
||||
* @throws IllegalArgumentException if the passed URI is invalid
|
||||
*/
|
||||
virtual void parseURL(const std::string& URI,
|
||||
util::Properties& properties)
|
||||
throw ( exceptions::IllegalArgumentException );
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CORE_ACTIVEMQCONNECTIONFACTORY_H_*/
|
|
@ -0,0 +1,443 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#include "ActiveMQConsumer.h"
|
||||
|
||||
#include <activemq/exceptions/NullPointerException.h>
|
||||
#include <activemq/core/ActiveMQSession.h>
|
||||
#include <activemq/core/ActiveMQMessage.h>
|
||||
#include <cms/ExceptionListener.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace cms;
|
||||
using namespace activemq;
|
||||
using namespace activemq::core;
|
||||
using namespace activemq::exceptions;
|
||||
using namespace activemq::concurrent;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ActiveMQConsumer::ActiveMQConsumer(connector::ConsumerInfo* consumerInfo,
|
||||
ActiveMQSession* session)
|
||||
{
|
||||
if(session == NULL || consumerInfo == NULL)
|
||||
{
|
||||
throw NullPointerException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQConsumer::ActiveMQConsumer - Init with NULL Session");
|
||||
}
|
||||
|
||||
// Init Producer Data
|
||||
this->session = session;
|
||||
this->consumerInfo = consumerInfo;
|
||||
this->listenerThread = NULL;
|
||||
this->listener = NULL;
|
||||
this->shutdown = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ActiveMQConsumer::~ActiveMQConsumer(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Dispose of the Consumer Info, this should stop us from getting
|
||||
// any more messages.
|
||||
session->onDestroySessionResource(this);
|
||||
|
||||
// Stop the asynchronous message processin thread if it's
|
||||
// running.
|
||||
stopThread();
|
||||
|
||||
// Purge all the pending messages
|
||||
purgeMessages();
|
||||
}
|
||||
AMQ_CATCH_NOTHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_NOTHROW( )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string ActiveMQConsumer::getMessageSelector(void) const
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
// Fetch the Selector
|
||||
return consumerInfo->getMessageSelector();
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::Message* ActiveMQConsumer::receive(void) throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized(&msgQueue)
|
||||
{
|
||||
// Check for empty in case of spurious wakeup, or race to
|
||||
// queue lock.
|
||||
while(!shutdown && msgQueue.empty())
|
||||
{
|
||||
msgQueue.wait();
|
||||
}
|
||||
|
||||
// This will only happen when this object is being
|
||||
// destroyed in another thread context - kind of
|
||||
// scary.
|
||||
if( shutdown ){
|
||||
throw ActiveMQException( __FILE__, __LINE__,
|
||||
"Consumer is being destroyed in another thread" );
|
||||
}
|
||||
|
||||
// Fetch the Message then copy it so it can be handed off
|
||||
// to the user.
|
||||
cms::Message* message = msgQueue.pop();
|
||||
cms::Message* result = message->clone();
|
||||
|
||||
// The Message is cleaned up here if the Session is not
|
||||
// transacted, otherwise we let the transaction clean up
|
||||
// this message as it will have already been ack'd and
|
||||
// stored for later redelivery.
|
||||
destroyMessage( message );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::Message* ActiveMQConsumer::receive(int millisecs)
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized(&msgQueue)
|
||||
{
|
||||
// Check for empty, and wait if its not
|
||||
if( msgQueue.empty() ){
|
||||
msgQueue.wait(millisecs);
|
||||
|
||||
// if its still empty...bail
|
||||
if( msgQueue.empty() ) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch the Message then copy it so it can be handed off
|
||||
// to the user.
|
||||
cms::Message* message = msgQueue.pop();
|
||||
cms::Message* result = message->clone();
|
||||
|
||||
// The Message is cleaned up here if the Session is not
|
||||
// transacted, otherwise we let the transaction clean up
|
||||
// this message as it will have already been ack'd and
|
||||
// stored for later redelivery.
|
||||
destroyMessage( message );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::Message* ActiveMQConsumer::receiveNoWait(void)
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized(&msgQueue)
|
||||
{
|
||||
if(!msgQueue.empty())
|
||||
{
|
||||
// Fetch the Message then copy it so it can be handed off
|
||||
// to the user.
|
||||
cms::Message* message = msgQueue.pop();
|
||||
cms::Message* result = message->clone();
|
||||
|
||||
// The Message is cleaned up here if the Session is not
|
||||
// transacted, otherwise we let the transaction clean up
|
||||
// this message as it will have already been ack'd and
|
||||
// stored for later redelivery.
|
||||
destroyMessage( message );
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQConsumer::setMessageListener(cms::MessageListener* listener)
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized(&listenerLock)
|
||||
{
|
||||
this->listener = listener;
|
||||
}
|
||||
|
||||
// Start the thread if it isn't already running.
|
||||
// If it is already running, this method will wake the thread up
|
||||
// to notify it that there is a message listener, so that it may
|
||||
// get rid of backed up messages.
|
||||
startThread();
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQConsumer::acknowledgeMessage( const ActiveMQMessage* message )
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
// Delegate the Ack to the Session, we cast away copnstness since
|
||||
// in a transactional session we might need to redeliver this
|
||||
// message and update its data.
|
||||
session->acknowledge(this, const_cast< ActiveMQMessage*>( message ) );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQConsumer::run(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
while(!shutdown)
|
||||
{
|
||||
Message* message = NULL;
|
||||
|
||||
synchronized(&msgQueue)
|
||||
{
|
||||
|
||||
// Gaurd against spurious wakeup or race to sync lock
|
||||
// also if the listner has been unregistered we don't
|
||||
// have anyone to notify, so we wait till a new one is
|
||||
// registered, and then we will deliver the backlog
|
||||
while(msgQueue.empty() || listener == NULL)
|
||||
{
|
||||
if( shutdown )
|
||||
{
|
||||
break;
|
||||
}
|
||||
msgQueue.wait();
|
||||
}
|
||||
|
||||
// don't want to process messages if we are shutting down.
|
||||
if(shutdown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Dispatch the message
|
||||
message = msgQueue.pop();
|
||||
}
|
||||
|
||||
// Notify the listener
|
||||
notifyListener( message );
|
||||
|
||||
// The Message is cleaned up here if the Session is not
|
||||
// transacted, otherwise we let the transaction clean up
|
||||
// this message as it will have already been ack'd and
|
||||
// stored for later redelivery.
|
||||
destroyMessage( message );
|
||||
}
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
cms::ExceptionListener* listener = session->getExceptionListener();
|
||||
|
||||
if(listener != NULL)
|
||||
{
|
||||
listener->onException( ActiveMQException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQConsumer::run - "
|
||||
"MessageListener threw an unknown Exception, recovering..."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQConsumer::dispatch(ActiveMQMessage* message)
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
// If the Session is in ClientAcknowledge mode, then we set the
|
||||
// handler in the message to this object and send it out. Otherwise
|
||||
// we ack it here for all the other Modes.
|
||||
if(session->getAcknowledgeMode() == Session::ClientAcknowledge)
|
||||
{
|
||||
// Register ourself so that we can handle the Message's
|
||||
// acknowledge method.
|
||||
message->setAckHandler(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
session->acknowledge(this, message);
|
||||
}
|
||||
|
||||
// No listener, so we queue it
|
||||
synchronized(&msgQueue)
|
||||
{
|
||||
msgQueue.push( dynamic_cast< cms::Message* >( message ) );
|
||||
msgQueue.notifyAll();
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQConsumer::purgeMessages(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized(&msgQueue)
|
||||
{
|
||||
while(!msgQueue.empty())
|
||||
{
|
||||
// destroy these messages if this is not a transacted
|
||||
// session, if it is then the tranasction will clean
|
||||
// the messages up.
|
||||
destroyMessage( msgQueue.pop() );
|
||||
}
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQConsumer::onActiveMQMessage( ActiveMQMessage* message )
|
||||
throw ( ActiveMQException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if( message == NULL )
|
||||
{
|
||||
throw ActiveMQException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQConsumer::onActiveMQMessage - Passed a Null Message");
|
||||
}
|
||||
|
||||
this->dispatch( message );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQConsumer::notifyListener( Message* message ){
|
||||
|
||||
try
|
||||
{
|
||||
MessageListener* listener = NULL;
|
||||
synchronized(&listenerLock)
|
||||
{
|
||||
listener = getMessageListener();
|
||||
}
|
||||
if(listener != NULL)
|
||||
{
|
||||
listener->onMessage(*message);
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQConsumer::destroyMessage( Message* message ){
|
||||
|
||||
try
|
||||
{
|
||||
/**
|
||||
* Only destroy the message if the session is NOT transacted. If
|
||||
* it is, the session will take care of it.
|
||||
*/
|
||||
if( message != NULL && !session->isTransacted() )
|
||||
{
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQConsumer::startThread(){
|
||||
|
||||
try
|
||||
{
|
||||
// Start the thread, if it's not already started.
|
||||
if(listenerThread == NULL)
|
||||
{
|
||||
listenerThread = new Thread(this);
|
||||
listenerThread->start();
|
||||
}
|
||||
|
||||
// notify the Queue so that any pending messages get delivered
|
||||
synchronized(&msgQueue)
|
||||
{
|
||||
msgQueue.notifyAll();
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQConsumer::stopThread(){
|
||||
|
||||
try
|
||||
{
|
||||
shutdown = true;
|
||||
|
||||
// if the thread is running signal it to quit and then
|
||||
// wait for run to return so thread can die
|
||||
if(listenerThread != NULL)
|
||||
{
|
||||
synchronized( &msgQueue )
|
||||
{
|
||||
// Force a wakeup if run is in a wait.
|
||||
msgQueue.notifyAll();
|
||||
}
|
||||
|
||||
// Wait for it to die and then delete it.
|
||||
listenerThread->join();
|
||||
delete listenerThread;
|
||||
listenerThread = NULL;
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CORE_ACTIVEMQCONSUMER_H_
|
||||
#define _ACTIVEMQ_CORE_ACTIVEMQCONSUMER_H_
|
||||
|
||||
#include <cms/MessageConsumer.h>
|
||||
#include <cms/MessageListener.h>
|
||||
#include <cms/Message.h>
|
||||
#include <cms/CMSException.h>
|
||||
|
||||
#include <activemq/connector/ConsumerInfo.h>
|
||||
#include <activemq/util/Queue.h>
|
||||
#include <activemq/core/ActiveMQAckHandler.h>
|
||||
#include <activemq/core/ActiveMQMessageListener.h>
|
||||
#include <activemq/core/ActiveMQSessionResource.h>
|
||||
#include <activemq/concurrent/Runnable.h>
|
||||
#include <activemq/concurrent/Mutex.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace core{
|
||||
|
||||
class ActiveMQSession;
|
||||
|
||||
class ActiveMQConsumer :
|
||||
public cms::MessageConsumer,
|
||||
public ActiveMQAckHandler,
|
||||
public concurrent::Runnable,
|
||||
public ActiveMQMessageListener,
|
||||
public ActiveMQSessionResource
|
||||
{
|
||||
private:
|
||||
|
||||
// The session that owns this Consumer
|
||||
ActiveMQSession* session;
|
||||
|
||||
// The Consumer info for this Consumer
|
||||
connector::ConsumerInfo* consumerInfo;
|
||||
|
||||
// The Message Listener for this Consumer
|
||||
cms::MessageListener* listener;
|
||||
|
||||
// Lock to protect us from dispatching to a dead listener
|
||||
concurrent::Mutex listenerLock;
|
||||
|
||||
// Message Queue
|
||||
util::Queue<cms::Message*> msgQueue;
|
||||
|
||||
// Thread to notif a listener if one is added
|
||||
concurrent::Thread* listenerThread;
|
||||
|
||||
// Boolean to indicate that the listener Thread is shutting
|
||||
// down and the run method should return.
|
||||
bool shutdown;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ActiveMQConsumer(connector::ConsumerInfo* consumerInfo,
|
||||
ActiveMQSession* session);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ActiveMQConsumer(void);
|
||||
|
||||
public: // Interface Implementation
|
||||
|
||||
/**
|
||||
* Synchronously Receive a Message
|
||||
* @return new message
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual cms::Message* receive(void) throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Synchronously Receive a Message, time out after defined interval.
|
||||
* Returns null if nothing read.
|
||||
* @return new message
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual cms::Message* receive(int millisecs) throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Receive a Message, does not wait if there isn't a new message
|
||||
* to read, returns NULL if nothing read.
|
||||
* @return new message
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual cms::Message* receiveNoWait(void) throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Sets the MessageListener that this class will send notifs on
|
||||
* @param MessageListener interface pointer
|
||||
*/
|
||||
virtual void setMessageListener(cms::MessageListener* listener);
|
||||
|
||||
/**
|
||||
* Gets the MessageListener that this class will send notifs on
|
||||
* @param MessageListener interface pointer
|
||||
*/
|
||||
virtual cms::MessageListener* getMessageListener(void) const {
|
||||
return this->listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this message consumer's message selector expression.
|
||||
* @return This Consumer's selector expression or "".
|
||||
* @throws cms::CMSException
|
||||
*/
|
||||
virtual std::string getMessageSelector(void) const
|
||||
throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Method called to acknowledge the message passed
|
||||
* @param Message to Acknowlegde
|
||||
* @throw CMSException
|
||||
*/
|
||||
virtual void acknowledgeMessage( const ActiveMQMessage* message )
|
||||
throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Run method that is called from the Thread class when this object
|
||||
* is registered with a Thread and started. This function reads from
|
||||
* the message queue and dispatches calls to the MessageConsumer that
|
||||
* is registered with this class.
|
||||
*
|
||||
* It is a error for a MessageListener to throw an exception in their
|
||||
* onMessage method, but if it does happen this function will get any
|
||||
* registered exception listener from the session and notify it.
|
||||
*/
|
||||
virtual void run(void);
|
||||
|
||||
public: // ActiveMQMessageListener Methods
|
||||
|
||||
/**
|
||||
* Called asynchronously when a new message is received, the message
|
||||
* that is passed is now the property of the callee, and the caller
|
||||
* will disavowe all knowledge of the message, i.e Callee must delete.
|
||||
* @param Message object pointer
|
||||
*/
|
||||
virtual void onActiveMQMessage( ActiveMQMessage* message )
|
||||
throw ( exceptions::ActiveMQException );
|
||||
|
||||
public: // ActiveMQSessionResource
|
||||
|
||||
/**
|
||||
* Retrieve the Connector resource that is associated with
|
||||
* this Session resource.
|
||||
* @return pointer to a Connector Resource, can be NULL
|
||||
*/
|
||||
virtual connector::ConnectorResource* getConnectorResource(void) {
|
||||
return consumerInfo;
|
||||
}
|
||||
|
||||
public: // ActiveMQConsumer Methods
|
||||
|
||||
/**
|
||||
* Called to dispatch a message to this consumer, this is usually
|
||||
* called from the context of another thread. This will enqueue a
|
||||
* message on the Consumers Queue, or notify a listener if one is
|
||||
* currently registered.
|
||||
* @param cms::Message pointer to the message to dispatch
|
||||
* @throw cms::CMSException
|
||||
*/
|
||||
virtual void dispatch(ActiveMQMessage* message)
|
||||
throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Get the Consumer information for this consumer
|
||||
* @return Pointer to a Consumer Info Object
|
||||
*/
|
||||
virtual connector::ConsumerInfo* getConsumerInfo(void) {
|
||||
return consumerInfo;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Purges all messages currently in the queue. This can be as a
|
||||
* result of a rollback, or of the consumer being shutdown.
|
||||
*/
|
||||
virtual void purgeMessages(void);
|
||||
|
||||
/**
|
||||
* Destroys the message if the session is transacted, otherwise
|
||||
* does nothing.
|
||||
*/
|
||||
virtual void destroyMessage( cms::Message* message );
|
||||
|
||||
/**
|
||||
* Notifies the listener of a message.
|
||||
*/
|
||||
void notifyListener( cms::Message* message );
|
||||
|
||||
/**
|
||||
* Starts the message processing thread to receive messages
|
||||
* asynchronously. This thread is started when setMessageListener
|
||||
* is invoked, which means that the caller is choosing to use this
|
||||
* consumer asynchronously instead of synchronously (receive).
|
||||
*/
|
||||
void startThread();
|
||||
|
||||
/**
|
||||
* Stops the asynchronous message processing thread if it's started.
|
||||
*/
|
||||
void stopThread();
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CORE_ACTIVEMQCONSUMER_H_*/
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CORE_ACTIVEMQMESSAGE_H_
|
||||
#define _ACTIVEMQ_CORE_ACTIVEMQMESSAGE_H_
|
||||
|
||||
#include <cms/Message.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace core{
|
||||
|
||||
class ActiveMQAckHandler;
|
||||
|
||||
/**
|
||||
* Interface for all ActiveMQ Messages that will pass through the core
|
||||
* API layer. This interface defines a method that the API uses to set
|
||||
* an Acknowledgement handler that will be called by the message when
|
||||
* a user calls the <code>acknowledge</code> method of the Message
|
||||
* interface. This is only done when the Session that this message
|
||||
* passes through is in Client Acknowledge mode.
|
||||
*/
|
||||
class ActiveMQMessage
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ActiveMQMessage(void) {}
|
||||
|
||||
/**
|
||||
* Sets the Acknowledgement Handler that this Message will use
|
||||
* when the Acknowledge method is called.
|
||||
* @param ActiveMQAckHandler
|
||||
*/
|
||||
virtual void setAckHandler(ActiveMQAckHandler* handler) = 0;
|
||||
|
||||
/**
|
||||
* Gets the number of times this message has been redelivered.
|
||||
* @return redelivery count
|
||||
*/
|
||||
virtual int getRedeliveryCount(void) const = 0;
|
||||
|
||||
/**
|
||||
* Sets the count of the number of times this message has been
|
||||
* redelivered
|
||||
* @param redelivery count
|
||||
*/
|
||||
virtual void setRedeliveryCount(int count) = 0;
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CORE_ACTIVEMQMESSAGE_H_*/
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
|
||||
#ifndef _ACTIVEMQ_CORE_ACTIVEMQMESSAGELISTENER_H_
|
||||
#define _ACTIVEMQ_CORE_ACTIVEMQMESSAGELISTENER_H_
|
||||
|
||||
#include <activemq/exceptions/ActiveMQException.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace core{
|
||||
|
||||
class ActiveMQMessage;
|
||||
|
||||
class ActiveMQMessageListener
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~ActiveMQMessageListener(void) {}
|
||||
|
||||
/**
|
||||
* Called asynchronously when a new message is received, the message
|
||||
* that is passed is now the property of the callee, and the caller
|
||||
* will disavowe all knowledge of the message, i.e Callee must delete.
|
||||
* @param Message object pointer
|
||||
*/
|
||||
virtual void onActiveMQMessage( ActiveMQMessage* message )
|
||||
throw ( exceptions::ActiveMQException ) = 0;
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CORE_ACTIVEMQMESSAGELISTENER_H_*/
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#include "ActiveMQProducer.h"
|
||||
|
||||
#include <activemq/core/ActiveMQSession.h>
|
||||
#include <activemq/exceptions/NullPointerException.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace activemq;
|
||||
using namespace activemq::core;
|
||||
using namespace activemq::connector;
|
||||
using namespace activemq::exceptions;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ActiveMQProducer::ActiveMQProducer(connector::ProducerInfo* producerInfo,
|
||||
ActiveMQSession* session)
|
||||
{
|
||||
if(session == NULL || producerInfo == NULL)
|
||||
{
|
||||
throw NullPointerException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQProducer::ActiveMQProducer - Init with NULL Session");
|
||||
}
|
||||
|
||||
// Init Producer Data
|
||||
this->session = session;
|
||||
this->producerInfo = producerInfo;
|
||||
|
||||
// Default the Delivery options
|
||||
deliveryMode = cms::Message::PERSISTANT;
|
||||
disableMsgId = false;
|
||||
disableTimestamps = false;
|
||||
priority = 4;
|
||||
timeToLive = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ActiveMQProducer::~ActiveMQProducer(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Dispose of the ProducerInfo
|
||||
session->onDestroySessionResource(this);
|
||||
}
|
||||
AMQ_CATCH_NOTHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_NOTHROW( )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQProducer::send(cms::Message& message)
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
send(producerInfo->getDestination(), message);
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQProducer::send(const cms::Destination& destination,
|
||||
cms::Message& message) throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
// configure the message
|
||||
message.setCMSDestination(destination);
|
||||
message.setCMSDeliveryMode(deliveryMode);
|
||||
message.setCMSPriority(priority);
|
||||
message.setCMSExpiration(timeToLive);
|
||||
|
||||
session->send(&message, this);
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CORE_ACTIVEMQPRODUCER_H_
|
||||
#define _ACTIVEMQ_CORE_ACTIVEMQPRODUCER_H_
|
||||
|
||||
#include <cms/MessageProducer.h>
|
||||
#include <cms/Message.h>
|
||||
#include <cms/Destination.h>
|
||||
|
||||
#include <activemq/core/ActiveMQSessionResource.h>
|
||||
#include <activemq/connector/ProducerInfo.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace core{
|
||||
|
||||
class ActiveMQSession;
|
||||
|
||||
class ActiveMQProducer : public cms::MessageProducer,
|
||||
public ActiveMQSessionResource
|
||||
{
|
||||
private:
|
||||
|
||||
// Delivery Mode of this Producer
|
||||
cms::Message::DeliveryMode deliveryMode;
|
||||
|
||||
// Disable the Message Id
|
||||
bool disableMsgId;
|
||||
|
||||
// Disable sending timestamps
|
||||
bool disableTimestamps;
|
||||
|
||||
// Priority Level to send at
|
||||
int priority;
|
||||
|
||||
// Time to live setting for message
|
||||
int timeToLive;
|
||||
|
||||
// Session that this producer sends to.
|
||||
ActiveMQSession* session;
|
||||
|
||||
// This Producers protocal specific info object
|
||||
connector::ProducerInfo* producerInfo;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ActiveMQProducer( connector::ProducerInfo* producerInfo,
|
||||
ActiveMQSession* session );
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ActiveMQProducer(void);
|
||||
|
||||
/**
|
||||
* Sends the message to the default producer destination.
|
||||
* @param a Message Object Pointer
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual void send( cms::Message& message ) throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Sends the message to the designated destination.
|
||||
* @param a Message Object Pointer
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual void send( const cms::Destination& destination,
|
||||
cms::Message& message) throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Sets the delivery mode for this Producer
|
||||
* @param The DeliveryMode
|
||||
*/
|
||||
virtual void setDeliveryMode(cms::Message::DeliveryMode mode) {
|
||||
deliveryMode = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the delivery mode for this Producer
|
||||
* @return The DeliveryMode
|
||||
*/
|
||||
virtual cms::Message::DeliveryMode getDeliveryMode(void) const {
|
||||
return deliveryMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if Message Ids are disbled for this Producer
|
||||
* @param boolean indicating enable / disable (true / false)
|
||||
*/
|
||||
virtual void setDisableMessageId( bool value ) {
|
||||
disableMsgId = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if Message Ids are disbled for this Producer
|
||||
* @param boolean indicating enable / disable (true / false)
|
||||
*/
|
||||
virtual bool getDisableMessageId(void) const {
|
||||
return disableMsgId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if Message Time Stamps are disbled for this Producer
|
||||
* @param boolean indicating enable / disable (true / false)
|
||||
*/
|
||||
virtual void setDisableMessageTimeStamp( bool value ) {
|
||||
disableTimestamps = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if Message Time Stamps are disbled for this Producer
|
||||
* @param boolean indicating enable / disable (true / false)
|
||||
*/
|
||||
virtual bool getDisableMessageTimeStamp(void) const {
|
||||
return disableTimestamps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Priority that this Producers sends messages at
|
||||
* @param int value for Priority level
|
||||
*/
|
||||
virtual void setPriority( int priority ) {
|
||||
this->priority = priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Priority level that this producer sends messages at
|
||||
* @return int based priority level
|
||||
*/
|
||||
virtual int getPriority(void) const {
|
||||
return priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Time to Live that this Producers sends messages with
|
||||
* @param int value for time to live
|
||||
*/
|
||||
virtual void setTimeToLive( int time ) {
|
||||
timeToLive = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Time to Live that this producer sends messages with
|
||||
* @return int based Time to Live
|
||||
*/
|
||||
virtual int getTimeToLive(void) const {
|
||||
return timeToLive;
|
||||
}
|
||||
|
||||
public: // ActiveMQSessionResource
|
||||
|
||||
/**
|
||||
* Retrieve the Connector resource that is associated with
|
||||
* this Session resource.
|
||||
* @return pointer to a Connector Resource, can be NULL
|
||||
*/
|
||||
virtual connector::ConnectorResource* getConnectorResource(void) {
|
||||
return producerInfo;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Retrives this object ProducerInfo pointer
|
||||
* @return ProducerInfo pointer
|
||||
*/
|
||||
virtual connector::ProducerInfo* getProducerInfo(void){
|
||||
return producerInfo;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CORE_ACTIVEMQPRODUCER_H_*/
|
|
@ -0,0 +1,545 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#include "ActiveMQSession.h"
|
||||
|
||||
#include <activemq/exceptions/InvalidStateException.h>
|
||||
#include <activemq/exceptions/NullPointerException.h>
|
||||
|
||||
#include <activemq/core/ActiveMQConnection.h>
|
||||
#include <activemq/core/ActiveMQTransaction.h>
|
||||
#include <activemq/core/ActiveMQConsumer.h>
|
||||
#include <activemq/core/ActiveMQMessage.h>
|
||||
#include <activemq/core/ActiveMQProducer.h>
|
||||
|
||||
#include <activemq/connector/TransactionInfo.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace cms;
|
||||
using namespace activemq;
|
||||
using namespace activemq::core;
|
||||
using namespace activemq::util;
|
||||
using namespace activemq::connector;
|
||||
using namespace activemq::exceptions;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ActiveMQSession::ActiveMQSession( SessionInfo* sessionInfo,
|
||||
const Properties& properties,
|
||||
ActiveMQConnection* connection)
|
||||
{
|
||||
if(sessionInfo == NULL || connection == NULL)
|
||||
{
|
||||
throw NullPointerException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQSession::ActiveMQSession - Init with NULL data");
|
||||
}
|
||||
|
||||
this->sessionInfo = sessionInfo;
|
||||
this->transaction = NULL;
|
||||
this->connection = connection;
|
||||
this->closed = false;
|
||||
|
||||
// Create a Transaction object only if the session is transactional
|
||||
if(isTransacted())
|
||||
{
|
||||
transaction =
|
||||
new ActiveMQTransaction(connection, this, properties );
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ActiveMQSession::~ActiveMQSession(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Destroy this session's resources
|
||||
close();
|
||||
}
|
||||
AMQ_CATCH_NOTHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_NOTHROW( )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQSession::close(void) throw ( cms::CMSException )
|
||||
{
|
||||
if(closed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Destry the Transaction
|
||||
delete transaction;
|
||||
|
||||
// Destroy this sessions resources
|
||||
connection->getConnectionData()->
|
||||
getConnector()->destroyResource(sessionInfo);
|
||||
|
||||
// mark as done
|
||||
closed = true;
|
||||
}
|
||||
AMQ_CATCH_NOTHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_NOTHROW( )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQSession::commit(void) throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if(closed || !isTransacted())
|
||||
{
|
||||
throw InvalidStateException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQSession::commit - This Session Can't Commit");
|
||||
}
|
||||
|
||||
// Commit the Transaction
|
||||
transaction->commit();
|
||||
}
|
||||
AMQ_CATCH_NOTHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_NOTHROW( )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQSession::rollback(void) throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if(closed || !isTransacted())
|
||||
{
|
||||
throw InvalidStateException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQSession::rollback - This Session Can't Rollback");
|
||||
}
|
||||
|
||||
// Rollback the Transaction
|
||||
transaction->rollback();
|
||||
}
|
||||
AMQ_CATCH_NOTHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_NOTHROW( )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::MessageConsumer* ActiveMQSession::createConsumer(
|
||||
cms::Destination& destination)
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if(closed)
|
||||
{
|
||||
throw InvalidStateException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQSession::createConsumer - Session Already Closed");
|
||||
}
|
||||
|
||||
return createConsumer(destination, "");
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::MessageConsumer* ActiveMQSession::createConsumer(
|
||||
cms::Destination& destination,
|
||||
const std::string& selector)
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if(closed)
|
||||
{
|
||||
throw InvalidStateException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQSession::createConsumer - Session Already Closed");
|
||||
}
|
||||
|
||||
ActiveMQConsumer* consumer = new ActiveMQConsumer(
|
||||
connection->getConnectionData()->getConnector()->
|
||||
createConsumer(&destination, sessionInfo, selector), this);
|
||||
|
||||
connection->addMessageListener(
|
||||
consumer->getConsumerInfo()->getConsumerId(), consumer );
|
||||
|
||||
return consumer;
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::MessageConsumer* ActiveMQSession::createDurableConsumer(
|
||||
cms::Topic& destination,
|
||||
const std::string& name,
|
||||
const std::string& selector,
|
||||
bool noLocal )
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if(closed)
|
||||
{
|
||||
throw InvalidStateException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQSession::createProducer - Session Already Closed");
|
||||
}
|
||||
|
||||
ActiveMQConsumer* consumer = new ActiveMQConsumer(
|
||||
connection->getConnectionData()->getConnector()->
|
||||
createDurableConsumer( &destination, sessionInfo, name, selector, noLocal ), this);
|
||||
|
||||
connection->addMessageListener(
|
||||
consumer->getConsumerInfo()->getConsumerId(), consumer );
|
||||
|
||||
return consumer;
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::MessageProducer* ActiveMQSession::createProducer(
|
||||
cms::Destination& destination)
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if(closed)
|
||||
{
|
||||
throw InvalidStateException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQSession::createProducer - Session Already Closed");
|
||||
}
|
||||
|
||||
return new ActiveMQProducer(
|
||||
connection->getConnectionData()->getConnector()->
|
||||
createProducer(&destination, sessionInfo), this);
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::Queue* ActiveMQSession::createQueue(const std::string& queueName)
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if(closed)
|
||||
{
|
||||
throw InvalidStateException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQSession::createQueue - Session Already Closed");
|
||||
}
|
||||
|
||||
return connection->getConnectionData()->
|
||||
getConnector()->createQueue(queueName, sessionInfo);
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::Topic* ActiveMQSession::createTopic(const std::string& topicName)
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if(closed)
|
||||
{
|
||||
throw InvalidStateException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQSession::createTopic - Session Already Closed");
|
||||
}
|
||||
|
||||
return connection->getConnectionData()->
|
||||
getConnector()->createTopic(topicName, sessionInfo);
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::TemporaryQueue* ActiveMQSession::createTemporaryQueue(void)
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if(closed)
|
||||
{
|
||||
throw InvalidStateException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQSession::createTemporaryQueue - Session Already Closed");
|
||||
}
|
||||
|
||||
return connection->getConnectionData()->
|
||||
getConnector()->createTemporaryQueue(sessionInfo);
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::TemporaryTopic* ActiveMQSession::createTemporaryTopic(void)
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if(closed)
|
||||
{
|
||||
throw InvalidStateException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQSession::createTemporaryTopic - Session Already Closed");
|
||||
}
|
||||
|
||||
return connection->getConnectionData()->
|
||||
getConnector()->createTemporaryTopic(sessionInfo);
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::Message* ActiveMQSession::createMessage(void)
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if(closed)
|
||||
{
|
||||
throw InvalidStateException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQSession::createMessage - Session Already Closed");
|
||||
}
|
||||
|
||||
return connection->getConnectionData()->
|
||||
getConnector()->createMessage( sessionInfo, transaction );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::BytesMessage* ActiveMQSession::createBytesMessage(void)
|
||||
throw ( cms::CMSException)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(closed)
|
||||
{
|
||||
throw InvalidStateException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQSession::createBytesMessage - Session Already Closed");
|
||||
}
|
||||
|
||||
return connection->getConnectionData()->
|
||||
getConnector()->createBytesMessage( sessionInfo, transaction );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::BytesMessage* ActiveMQSession::createBytesMessage(
|
||||
const unsigned char* bytes,
|
||||
unsigned long bytesSize)
|
||||
throw ( cms::CMSException)
|
||||
{
|
||||
try
|
||||
{
|
||||
BytesMessage* msg = createBytesMessage();
|
||||
|
||||
msg->setBodyBytes(bytes, bytesSize);
|
||||
|
||||
return msg;
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::TextMessage* ActiveMQSession::createTextMessage(void)
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if(closed)
|
||||
{
|
||||
throw InvalidStateException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQSession::createTextMessage - Session Already Closed");
|
||||
}
|
||||
|
||||
return connection->getConnectionData()->
|
||||
getConnector()->createTextMessage( sessionInfo, transaction );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::TextMessage* ActiveMQSession::createTextMessage(const std::string& text)
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
TextMessage* msg = createTextMessage();
|
||||
|
||||
msg->setText(text.c_str());
|
||||
|
||||
return msg;
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::MapMessage* ActiveMQSession::createMapMessage(void)
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if(closed)
|
||||
{
|
||||
throw InvalidStateException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQSession::createMapMessage - Session Already Closed");
|
||||
}
|
||||
|
||||
return connection->
|
||||
getConnectionData()->
|
||||
getConnector()->createMapMessage( sessionInfo, transaction );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::Session::AcknowledgeMode ActiveMQSession::getAcknowledgeMode(void) const
|
||||
{
|
||||
return sessionInfo != NULL ?
|
||||
sessionInfo->getAckMode() : Session::AutoAcknowledge;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool ActiveMQSession::isTransacted(void) const
|
||||
{
|
||||
return sessionInfo != NULL ?
|
||||
sessionInfo->getAckMode() == Session::Transactional : false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQSession::acknowledge(ActiveMQConsumer* consumer,
|
||||
ActiveMQMessage* message)
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if( closed )
|
||||
{
|
||||
throw InvalidStateException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQSession::acknowledgeMessage - Session Already Closed");
|
||||
}
|
||||
|
||||
// Stores the Message and its consumer in the tranasction, if the
|
||||
// session is a transactional one.
|
||||
if(isTransacted())
|
||||
{
|
||||
transaction->addToTransaction( message, consumer );
|
||||
}
|
||||
|
||||
// Delegate to connector to ack this message.
|
||||
return connection->getConnectionData()->
|
||||
getConnector()->acknowledge(
|
||||
sessionInfo, dynamic_cast< cms::Message* >( message ) );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQSession::send(cms::Message* message, ActiveMQProducer* producer)
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if(closed)
|
||||
{
|
||||
throw InvalidStateException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQSession::onProducerClose - Session Already Closed");
|
||||
}
|
||||
|
||||
// Send via the connection
|
||||
connection->getConnectionData()->
|
||||
getConnector()->send( message, producer->getProducerInfo() );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQSession::onDestroySessionResource(
|
||||
ActiveMQSessionResource* resource )
|
||||
throw ( cms::CMSException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if(closed)
|
||||
{
|
||||
throw InvalidStateException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQSession::onProducerClose - Session Already Closed");
|
||||
}
|
||||
|
||||
ActiveMQConsumer* consumer =
|
||||
dynamic_cast< ActiveMQConsumer*>( resource );
|
||||
|
||||
if( consumer != NULL )
|
||||
{
|
||||
// Remove this Consumer from the Connection
|
||||
connection->removeMessageListener(
|
||||
consumer->getConsumerInfo()->getConsumerId());
|
||||
|
||||
// Remove this consumer from the Transaction if we are
|
||||
// transactional
|
||||
if( transaction != NULL )
|
||||
{
|
||||
transaction->removeFromTransaction(consumer);
|
||||
}
|
||||
}
|
||||
|
||||
// Free its resources.
|
||||
connection->getConnectionData()->
|
||||
getConnector()->destroyResource( resource->getConnectorResource() );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
cms::ExceptionListener* ActiveMQSession::getExceptionListener(void)
|
||||
{
|
||||
if(connection != NULL)
|
||||
{
|
||||
return connection->getExceptionListener();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,271 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CORE_ACTIVEMQSESSION_H_
|
||||
#define _ACTIVEMQ_CORE_ACTIVEMQSESSION_H_
|
||||
|
||||
#include <cms/Session.h>
|
||||
#include <cms/ExceptionListener.h>
|
||||
#include <activemq/connector/SessionInfo.h>
|
||||
#include <activemq/core/ActiveMQSessionResource.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace core{
|
||||
|
||||
class ActiveMQTransaction;
|
||||
class ActiveMQConnection;
|
||||
class ActiveMQConsumer;
|
||||
class ActiveMQMessage;
|
||||
class ActiveMQProducer;
|
||||
class ActiveMQConsumer;
|
||||
|
||||
class ActiveMQSession : public cms::Session
|
||||
{
|
||||
private:
|
||||
|
||||
// SessionInfo for this Session
|
||||
connector::SessionInfo* sessionInfo;
|
||||
|
||||
// Transaction Management object
|
||||
ActiveMQTransaction* transaction;
|
||||
|
||||
// Connection
|
||||
ActiveMQConnection* connection;
|
||||
|
||||
// Bool to indicate if this session was closed.
|
||||
bool closed;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ActiveMQSession( connector::SessionInfo* sessionInfo,
|
||||
const util::Properties& properties,
|
||||
ActiveMQConnection* connection);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ActiveMQSession(void);
|
||||
|
||||
public: // Implements Mehtods
|
||||
|
||||
/**
|
||||
* Closes the Session
|
||||
* @throw CMSException
|
||||
*/
|
||||
virtual void close(void) throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Commits all messages done in this transaction and releases any
|
||||
* locks currently held.
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual void commit(void) throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Rollsback all messages done in this transaction and releases any
|
||||
* locks currently held.
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual void rollback(void) throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Creates a MessageConsumer for the specified destination.
|
||||
* @param the Destination that this consumer receiving messages for.
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual cms::MessageConsumer* createConsumer(cms::Destination& destination)
|
||||
throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Creates a MessageConsumer for the specified destination, using a
|
||||
* message selector.
|
||||
* @param the Destination that this consumer receiving messages for.
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual cms::MessageConsumer* createConsumer(cms::Destination& destination,
|
||||
const std::string& selector)
|
||||
throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Creates a durable subscriber to the specified topic, using a
|
||||
* message selector
|
||||
* @param the topic to subscribe to
|
||||
* @param name used to identify the subscription
|
||||
* @param only messages matching the selector are received
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual cms::MessageConsumer* createDurableConsumer(
|
||||
cms::Topic& destination,
|
||||
const std::string& name,
|
||||
const std::string& selector,
|
||||
bool noLocal = false)
|
||||
throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Creates a MessageProducer to send messages to the specified
|
||||
* destination.
|
||||
* @param the Destination to publish on
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual cms::MessageProducer* createProducer(cms::Destination& destination)
|
||||
throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Creates a queue identity given a Queue name.
|
||||
* @param the name of the new Queue
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual cms::Queue* createQueue(const std::string& queueName)
|
||||
throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Creates a topic identity given a Queue name.
|
||||
* @param the name of the new Topic
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual cms::Topic* createTopic(const std::string& topicName)
|
||||
throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Creates a TemporaryQueue object.
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual cms::TemporaryQueue* createTemporaryQueue(void)
|
||||
throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Creates a TemporaryTopic object.
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual cms::TemporaryTopic* createTemporaryTopic(void)
|
||||
throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Creates a new Message
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual cms::Message* createMessage(void)
|
||||
throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Creates a BytesMessage
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual cms::BytesMessage* createBytesMessage(void)
|
||||
throw ( cms::CMSException);
|
||||
|
||||
/**
|
||||
* Creates a BytesMessage and sets the paylod to the passed value
|
||||
* @param an array of bytes to set in the message
|
||||
* @param the size of the bytes array, or number of bytes to use
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual cms::BytesMessage* createBytesMessage(const unsigned char* bytes,
|
||||
unsigned long bytesSize)
|
||||
throw ( cms::CMSException);
|
||||
|
||||
/**
|
||||
* Creates a new TextMessage
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual cms::TextMessage* createTextMessage(void)
|
||||
throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Creates a new TextMessage and set the text to the value given
|
||||
* @param the initial text for the message
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual cms::TextMessage* createTextMessage(const std::string& text)
|
||||
throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Creates a new TextMessage
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual cms::MapMessage* createMapMessage(void)
|
||||
throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Returns the acknowledgement mode of the session.
|
||||
* @return the Sessions Acknowledge Mode
|
||||
*/
|
||||
virtual cms::Session::AcknowledgeMode getAcknowledgeMode(void) const;
|
||||
|
||||
/**
|
||||
* Gets if the Sessions is a Transacted Session
|
||||
* @return transacted true - false.
|
||||
*/
|
||||
virtual bool isTransacted(void) const;
|
||||
|
||||
public: // ActiveMQSession specific Methods
|
||||
|
||||
/**
|
||||
* Sends a message from the Producer specified
|
||||
* @param cms::Message pointer
|
||||
* @param Producer Information
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual void send(cms::Message* message, ActiveMQProducer* producer)
|
||||
throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* When a ActiveMQ core object is closed or destroyed it should call
|
||||
* back and let the session know that it is going away, this allows
|
||||
* the session to clean up any associated resources. This method
|
||||
* destroy's the data that is associated with a Producer object
|
||||
* @param The Producer that is being destoryed
|
||||
* @throw CMSException
|
||||
*/
|
||||
virtual void onDestroySessionResource( ActiveMQSessionResource* resource )
|
||||
throw ( cms::CMSException );
|
||||
|
||||
/**
|
||||
* Called to acknowledge the receipt of a message.
|
||||
* @param The consumer that received the message
|
||||
* @param The Message to acknowledge.
|
||||
* @throws CMSException
|
||||
*/
|
||||
virtual void acknowledge(ActiveMQConsumer* consumer,
|
||||
ActiveMQMessage* message)
|
||||
throw ( cms::CMSException);
|
||||
|
||||
/**
|
||||
* This method gets any registered exception listener of this sessions
|
||||
* connection and returns it. Mainly intended for use by the objects
|
||||
* that this session creates so that they can notify the client of
|
||||
* exceptions that occur in the context of another thread.
|
||||
* @returns cms::ExceptionListener pointer or NULL
|
||||
*/
|
||||
virtual cms::ExceptionListener* getExceptionListener(void);
|
||||
|
||||
/**
|
||||
* Gets the Session Information object for this session, if the
|
||||
* session is closed than this returns null
|
||||
* @return SessionInfo Pointer
|
||||
*/
|
||||
virtual connector::SessionInfo* getSessionInfo(void) {
|
||||
return sessionInfo;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CORE_ACTIVEMQSESSION_H_*/
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CORE_ACTIVEMQSESSIONRESOURCE_H_
|
||||
#define _ACTIVEMQ_CORE_ACTIVEMQSESSIONRESOURCE_H_
|
||||
|
||||
#include <activemq/connector/ConnectorResource.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace core{
|
||||
|
||||
class ActiveMQSessionResource
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~ActiveMQSessionResource(void) {}
|
||||
|
||||
/**
|
||||
* Retrieve the Connector resource that is associated with
|
||||
* this Session resource.
|
||||
* @return pointer to a Connector Resource, can be NULL
|
||||
*/
|
||||
virtual connector::ConnectorResource* getConnectorResource(void) = 0;
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CORE_ACTIVEMQSESSIONRESOURCE_H_*/
|
|
@ -0,0 +1,343 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#include "ActiveMQTransaction.h"
|
||||
|
||||
#include <activemq/exceptions/NullPointerException.h>
|
||||
#include <activemq/core/ActiveMQSession.h>
|
||||
#include <activemq/core/ActiveMQConnection.h>
|
||||
#include <activemq/core/ActiveMQConsumer.h>
|
||||
#include <activemq/core/ActiveMQMessage.h>
|
||||
#include <activemq/util/Integer.h>
|
||||
|
||||
#include <activemq/concurrent/ThreadPool.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace cms;
|
||||
using namespace activemq;
|
||||
using namespace activemq::core;
|
||||
using namespace activemq::util;
|
||||
using namespace activemq::connector;
|
||||
using namespace activemq::concurrent;
|
||||
using namespace activemq::exceptions;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ActiveMQTransaction::ActiveMQTransaction( ActiveMQConnection* connection,
|
||||
ActiveMQSession* session,
|
||||
const Properties& properties )
|
||||
{
|
||||
try
|
||||
{
|
||||
if(connection == NULL || session == NULL)
|
||||
{
|
||||
throw NullPointerException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQTransaction::ActiveMQTransaction - "
|
||||
"Initialized with a NULL connection data");
|
||||
}
|
||||
|
||||
// Store State Data
|
||||
this->connection = connection;
|
||||
this->session = session;
|
||||
this->taskCount = 0;
|
||||
|
||||
// convert from property Strings to int.
|
||||
redeliveryDelay = Integer::parseInt(
|
||||
properties.getProperty("transaction.redeliveryDelay", "25") );
|
||||
maxRedeliveries = Integer::parseInt(
|
||||
properties.getProperty("transaction.maxRedeliveryCount", "5") );
|
||||
|
||||
// Start a new Transaction
|
||||
transactionInfo = connection->getConnectionData()->
|
||||
getConnector()->startTransaction( session->getSessionInfo() );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ActiveMQTransaction::~ActiveMQTransaction(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Inform the connector we are rolling back before we close so that
|
||||
// the provider knows we didn't complete this transaction
|
||||
connection->getConnectionData()->getConnector()->
|
||||
rollback(transactionInfo, session->getSessionInfo());
|
||||
|
||||
// Clean up
|
||||
clearTransaction();
|
||||
|
||||
// Must allow all the tasks to complete before we destruct otherwise
|
||||
// the callbacks will cause an exception.
|
||||
synchronized(&tasksDone)
|
||||
{
|
||||
while(taskCount != 0)
|
||||
{
|
||||
tasksDone.wait(1000);
|
||||
|
||||
// TODO - Log Here to get some indication if we are stuck
|
||||
}
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_NOTHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_NOTHROW( )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQTransaction::clearTransaction(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(transactionInfo != NULL)
|
||||
{
|
||||
// Dispose of the ProducerInfo
|
||||
connection->getConnectionData()->
|
||||
getConnector()->destroyResource(transactionInfo);
|
||||
}
|
||||
|
||||
synchronized(&rollbackLock)
|
||||
{
|
||||
// If there are any messages that are being transacted, then
|
||||
// they die once and for all here.
|
||||
RollbackMap::iterator itr = rollbackMap.begin();
|
||||
|
||||
for(; itr != rollbackMap.end(); ++itr)
|
||||
{
|
||||
MessageList::iterator msgItr = itr->second.begin();
|
||||
|
||||
for(; msgItr != itr->second.end(); ++msgItr)
|
||||
{
|
||||
delete *msgItr;
|
||||
}
|
||||
}
|
||||
|
||||
rollbackMap.clear();
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQTransaction::addToTransaction( ActiveMQMessage* message,
|
||||
ActiveMQMessageListener* listener )
|
||||
{
|
||||
synchronized(&rollbackLock)
|
||||
{
|
||||
// Store in the Multi Map
|
||||
rollbackMap[listener].push_back(message);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQTransaction::removeFromTransaction(
|
||||
ActiveMQMessageListener* listener )
|
||||
{
|
||||
try
|
||||
{
|
||||
// Delete all the messages, then remove the consumer's entry from
|
||||
// the Rollback Map.
|
||||
synchronized(&rollbackLock)
|
||||
{
|
||||
RollbackMap::iterator rb_itr = rollbackMap.find( listener );
|
||||
|
||||
if( rb_itr == rollbackMap.end() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MessageList::iterator itr = rb_itr->second.begin();
|
||||
|
||||
for(; itr != rollbackMap[listener].end(); ++itr)
|
||||
{
|
||||
delete *itr;
|
||||
}
|
||||
|
||||
// Erase the entry from the map
|
||||
rollbackMap.erase(listener);
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQTransaction::commit(void) throw ( exceptions::ActiveMQException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if(this->transactionInfo == NULL)
|
||||
{
|
||||
throw InvalidStateException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQTransaction::begin - "
|
||||
"Commit called before transaction was started.");
|
||||
}
|
||||
|
||||
// Commit the current Transaction
|
||||
connection->getConnectionData()->getConnector()->
|
||||
commit( transactionInfo, session->getSessionInfo() );
|
||||
|
||||
// Clean out the Transaction
|
||||
clearTransaction();
|
||||
|
||||
// Start a new Transaction
|
||||
transactionInfo = connection->getConnectionData()->
|
||||
getConnector()->startTransaction( session->getSessionInfo() );
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQTransaction::rollback(void) throw ( exceptions::ActiveMQException )
|
||||
{
|
||||
try
|
||||
{
|
||||
if(this->transactionInfo == NULL)
|
||||
{
|
||||
throw InvalidStateException(
|
||||
__FILE__, __LINE__,
|
||||
"ActiveMQTransaction::rollback - "
|
||||
"Rollback called before transaction was started.");
|
||||
}
|
||||
|
||||
// Rollback the Transaction
|
||||
connection->getConnectionData()->getConnector()->
|
||||
rollback( transactionInfo, session->getSessionInfo() );
|
||||
|
||||
// Dispose of the ProducerInfo
|
||||
connection->getConnectionData()->
|
||||
getConnector()->destroyResource(transactionInfo);
|
||||
|
||||
// Start a new Transaction
|
||||
transactionInfo = connection->getConnectionData()->
|
||||
getConnector()->startTransaction( session->getSessionInfo() );
|
||||
|
||||
// Create a task for each consumer and copy its message list out
|
||||
// to the Rollback task so we can clear the list for new messages
|
||||
// that might come in next.
|
||||
// NOTE - This could be turned into a Thread so that the connection
|
||||
// doesn't have to wait on this method to complete an release its
|
||||
// mutex so it can dispatch new messages. That would however requre
|
||||
// copying the whole map over to the thread.
|
||||
synchronized(&rollbackLock)
|
||||
{
|
||||
RollbackMap::iterator itr = rollbackMap.begin();
|
||||
|
||||
for(; itr != rollbackMap.end(); ++itr)
|
||||
{
|
||||
ThreadPool::getInstance()->queueTask(make_pair(
|
||||
new RollbackTask( itr->first,
|
||||
connection,
|
||||
session,
|
||||
itr->second,
|
||||
maxRedeliveries,
|
||||
redeliveryDelay) , this));
|
||||
|
||||
// Count the tasks started.
|
||||
taskCount++;
|
||||
|
||||
}
|
||||
|
||||
// Clear the map. Ownership of the messages is now handed off
|
||||
// to the rollback tasks.
|
||||
rollbackMap.clear();
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQTransaction::onTaskComplete( Runnable* task )
|
||||
{
|
||||
try
|
||||
{
|
||||
// Delete the task
|
||||
delete task;
|
||||
|
||||
taskCount--;
|
||||
|
||||
if(taskCount == 0)
|
||||
{
|
||||
synchronized(&tasksDone)
|
||||
{
|
||||
tasksDone.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_NOTHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_NOTHROW( )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQTransaction::onTaskException( Runnable* task,
|
||||
exceptions::ActiveMQException& ex )
|
||||
{
|
||||
try
|
||||
{
|
||||
// Delegate
|
||||
onTaskComplete(task);
|
||||
|
||||
// Route the Error
|
||||
ExceptionListener* listener = connection->getExceptionListener();
|
||||
|
||||
if(listener != NULL)
|
||||
{
|
||||
listener->onException( ex );
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_NOTHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_NOTHROW( )
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQTransaction::RollbackTask::run(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
MessageList::iterator itr = messages.begin();
|
||||
|
||||
for(; itr != messages.end(); ++itr)
|
||||
{
|
||||
(*itr)->setRedeliveryCount((*itr)->getRedeliveryCount() + 1);
|
||||
|
||||
// Redeliver Messages at some point in the future
|
||||
Thread::sleep(redeliveryDelay);
|
||||
|
||||
if((*itr)->getRedeliveryCount() >= maxRedeliveries)
|
||||
{
|
||||
// Poison Ack the Message, we give up processing this one
|
||||
connection->getConnectionData()->getConnector()->
|
||||
acknowledge(
|
||||
session->getSessionInfo(),
|
||||
dynamic_cast< Message* >(*itr),
|
||||
Connector::PoisonAck );
|
||||
|
||||
// Won't redeliver this so we kill it here.
|
||||
delete *itr;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
listener->onActiveMQMessage(*itr);
|
||||
}
|
||||
}
|
||||
AMQ_CATCH_RETHROW( ActiveMQException )
|
||||
AMQ_CATCHALL_THROW( ActiveMQException )
|
||||
}
|
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_CORE_ACTIVEMQTRANSACTION_H_
|
||||
#define _ACTIVEMQ_CORE_ACTIVEMQTRANSACTION_H_
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
#include <cms/Message.h>
|
||||
#include <cms/CMSException.h>
|
||||
|
||||
#include <activemq/concurrent/Mutex.h>
|
||||
#include <activemq/concurrent/TaskListener.h>
|
||||
#include <activemq/concurrent/Runnable.h>
|
||||
#include <activemq/connector/TransactionInfo.h>
|
||||
#include <activemq/exceptions/InvalidStateException.h>
|
||||
#include <activemq/exceptions/IllegalArgumentException.h>
|
||||
#include <activemq/util/Properties.h>
|
||||
#include <activemq/core/ActiveMQSessionResource.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace core{
|
||||
|
||||
class ActiveMQConnection;
|
||||
class ActiveMQSession;
|
||||
class ActiveMQMessage;
|
||||
class ActiveMQMessageListener;
|
||||
|
||||
/**
|
||||
* Transaction Management class, hold messages that are to be redelivered
|
||||
* upon a request to rollback. The Tranasction represents an always
|
||||
* running transaction, when it is committed or rolled back it silently
|
||||
* creates a new transaction for the next set of messages. The only
|
||||
* way to permanently end this tranaction is to delete it.
|
||||
*
|
||||
* Configuration options
|
||||
*
|
||||
* transaction.redeliveryDelay
|
||||
* Wait time between the redelivery of each message
|
||||
*
|
||||
* transaction.maxRedeliveryCount
|
||||
* Max number of times a message can be redelivered, if the session is
|
||||
* rolled back more than this many time, the message is dropped.
|
||||
*/
|
||||
class ActiveMQTransaction : public concurrent::TaskListener,
|
||||
public connector::TransactionInfo,
|
||||
public ActiveMQSessionResource
|
||||
{
|
||||
private:
|
||||
|
||||
// List type for holding messages
|
||||
typedef std::list< ActiveMQMessage* > MessageList;
|
||||
|
||||
// Mapping of MessageListener Ids to Lists of Messages that are
|
||||
// redelivered on a Rollback
|
||||
typedef std::map< ActiveMQMessageListener*, MessageList > RollbackMap;
|
||||
|
||||
private:
|
||||
|
||||
// Connection this Transaction is associated with
|
||||
ActiveMQConnection* connection;
|
||||
|
||||
// Session this Transaction is associated with
|
||||
ActiveMQSession* session;
|
||||
|
||||
// Transaction Info for the current Transaction
|
||||
connector::TransactionInfo* transactionInfo;
|
||||
|
||||
// Map of ActiveMQMessageListener to Messages to Rollback
|
||||
RollbackMap rollbackMap;
|
||||
|
||||
// Lock object to protect the rollback Map
|
||||
concurrent::Mutex rollbackLock;
|
||||
|
||||
// Max number of redeliveries before we quit
|
||||
int maxRedeliveries;
|
||||
|
||||
// Wait time between sends of message on a rollback
|
||||
int redeliveryDelay;
|
||||
|
||||
// Mutex that is signaled when all tasks complete.
|
||||
concurrent::Mutex tasksDone;
|
||||
|
||||
// Count of Tasks that are outstanding
|
||||
int taskCount;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
ActiveMQTransaction( ActiveMQConnection* connection,
|
||||
ActiveMQSession* session,
|
||||
const util::Properties& properties );
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ActiveMQTransaction(void);
|
||||
|
||||
/**
|
||||
* Adds the Message as a part of the Transaction for the specified
|
||||
* ActiveMQConsumer.
|
||||
* @param ActiveMQMessage
|
||||
* @param ActiveMQMessageListener
|
||||
*/
|
||||
virtual void addToTransaction( ActiveMQMessage* message,
|
||||
ActiveMQMessageListener* listener );
|
||||
|
||||
/**
|
||||
* Removes the ActiveMQMessageListener and all of its transacted
|
||||
* messages from the Transaction, this is usually only done when
|
||||
* a ActiveMQMessageListener is destroyed.
|
||||
* @param consumer who is to be removed.
|
||||
*/
|
||||
virtual void removeFromTransaction( ActiveMQMessageListener* listener );
|
||||
|
||||
/**
|
||||
* Commit the current Transaction
|
||||
* @throw CMSException
|
||||
*/
|
||||
virtual void commit(void) throw ( exceptions::ActiveMQException );
|
||||
|
||||
/**
|
||||
* Rollback the current Transaction
|
||||
* @throw CMSException
|
||||
*/
|
||||
virtual void rollback(void) throw ( exceptions::ActiveMQException );
|
||||
|
||||
/**
|
||||
* Get the Transaction Information object for the current
|
||||
* Transaction, returns NULL if no transaction is running
|
||||
* @return TransactionInfo
|
||||
*/
|
||||
virtual connector::TransactionInfo* getTransactionInfo(void) const {
|
||||
return transactionInfo;
|
||||
}
|
||||
|
||||
public: // TransactionInfo Interface
|
||||
|
||||
/**
|
||||
* Gets the Transction Id
|
||||
* @return unsigned int Id
|
||||
*/
|
||||
virtual unsigned int getTransactionId(void) const {
|
||||
return transactionInfo->getTransactionId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Transction Id
|
||||
* @param unsigned int Id
|
||||
*/
|
||||
virtual void setTransactionId( const unsigned int id ) {
|
||||
transactionInfo->setTransactionId( id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Session Info that this transaction is attached too
|
||||
* @return SessionnInfo pointer
|
||||
*/
|
||||
virtual const connector::SessionInfo* getSessionInfo(void) const {
|
||||
return transactionInfo->getSessionInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Session Info that this transaction is attached too
|
||||
* @return SessionnInfo pointer
|
||||
*/
|
||||
virtual void setSessionInfo( const connector::SessionInfo* session ) {
|
||||
transactionInfo->setSessionInfo( session );
|
||||
}
|
||||
|
||||
protected: // Task Listener Interface
|
||||
|
||||
/**
|
||||
* Called when a queued task has completed, the task that
|
||||
* finished is passed along for user consumption. The task is
|
||||
* deleted and the count of outstanding tasks is reduced.
|
||||
* @param Runnable Pointer to the task that finished
|
||||
*/
|
||||
virtual void onTaskComplete( concurrent::Runnable* task );
|
||||
|
||||
/**
|
||||
* Called when a queued task has thrown an exception while
|
||||
* being run. The Callee should assume that this was an
|
||||
* unrecoverable exeption and that this task is now defunct.
|
||||
* Deletes the Task and notifies the connection that the
|
||||
* exception has occurred. Reduce the outstanding task count.
|
||||
* @param Runnable Pointer to the task
|
||||
* @param The ActiveMQException that was thrown.
|
||||
*/
|
||||
virtual void onTaskException( concurrent::Runnable* task,
|
||||
exceptions::ActiveMQException& ex );
|
||||
|
||||
public: // ActiveMQSessionResource
|
||||
|
||||
/**
|
||||
* Retrieve the Connector resource that is associated with
|
||||
* this Session resource.
|
||||
* @return pointer to a Connector Resource, can be NULL
|
||||
*/
|
||||
virtual connector::ConnectorResource* getConnectorResource(void) {
|
||||
return transactionInfo;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Clean out all Messages from the Rollback Map, deleting the
|
||||
* messages as it goes. Destroys the Transaction Info object as
|
||||
* well.
|
||||
* @throw ActiveMQException
|
||||
*/
|
||||
virtual void clearTransaction(void);
|
||||
|
||||
private:
|
||||
|
||||
// Internal class that is used to redeliver one consumers worth
|
||||
// of messages from this transaction.
|
||||
class RollbackTask : public concurrent::Runnable
|
||||
{
|
||||
private:
|
||||
|
||||
// Wait time before redelivery in millisecs
|
||||
int redeliveryDelay;
|
||||
|
||||
// Max number of time to redeliver this message
|
||||
int maxRedeliveries;
|
||||
|
||||
// Messages to Redeliver
|
||||
MessageList messages;
|
||||
|
||||
// Consumer we are redelivering to
|
||||
ActiveMQMessageListener* listener;
|
||||
|
||||
// Connection to use for sending message acks
|
||||
ActiveMQConnection* connection;
|
||||
|
||||
// Session for this Transaction
|
||||
ActiveMQSession* session;
|
||||
|
||||
public:
|
||||
|
||||
RollbackTask( ActiveMQMessageListener* listener,
|
||||
ActiveMQConnection* connection,
|
||||
ActiveMQSession* session,
|
||||
MessageList& messages,
|
||||
int maxRedeliveries,
|
||||
int redeliveryDelay ){
|
||||
|
||||
// Store State Data.
|
||||
this->messages = messages;
|
||||
this->listener = listener;
|
||||
this->redeliveryDelay = redeliveryDelay;
|
||||
this->maxRedeliveries = maxRedeliveries;
|
||||
this->session = session;
|
||||
this->connection = connection;
|
||||
}
|
||||
|
||||
// Dispatches the Messages to the Consumer.
|
||||
virtual void run(void);
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*_ACTIVEMQ_CORE_ACTIVEMQTRANSACTION_H_*/
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "ActiveMQException.h"
|
||||
#include <activemq/logger/LoggerDefines.h>
|
||||
|
||||
using namespace activemq;
|
||||
using namespace activemq::exceptions;
|
||||
using namespace std;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQException::buildMessage(const char* format, va_list& vargs)
|
||||
{
|
||||
// Allocate buffer with a guess of it's size
|
||||
int size = 128;
|
||||
|
||||
// Format string
|
||||
while( true ){
|
||||
|
||||
// Allocate a buffer of the specified size.
|
||||
char* buffer = new char[size];
|
||||
|
||||
int written = vsnprintf(buffer, size, format, vargs);
|
||||
if (written > -1 && written < size-1) {
|
||||
|
||||
// Guessed size was enough. Assign the string.
|
||||
message.assign (buffer, written);
|
||||
break;
|
||||
}
|
||||
|
||||
// Our buffer wasn't big enough - destroy the old buffer,
|
||||
// double the size and try again.
|
||||
delete [] buffer;
|
||||
size *= 2;
|
||||
}
|
||||
|
||||
activemq::logger::SimpleLogger logger("com.yadda1");
|
||||
logger.log( message );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ActiveMQException::setMark( const char* file, const int lineNumber ){
|
||||
|
||||
// Add this mark to the end of the stack trace.
|
||||
stackTrace.push_back( std::make_pair( (std::string)file, (int)lineNumber ) );
|
||||
|
||||
ostringstream stream;
|
||||
stream << "\tFILE: " << stackTrace[stackTrace.size()-1].first;
|
||||
stream << ", LINE: " << stackTrace[stackTrace.size()-1].second;
|
||||
|
||||
activemq::logger::SimpleLogger logger("com.yadda2");
|
||||
logger.log( stream.str() );
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef ACTIVEMQ_EXCEPTIONS_ACTIVEMQEXCEPTION_H
|
||||
#define ACTIVEMQ_EXCEPTIONS_ACTIVEMQEXCEPTION_H
|
||||
|
||||
#include <cms/CMSException.h>
|
||||
#include <activemq/exceptions/ExceptionDefines.h>
|
||||
#include <stdarg.h>
|
||||
#include <sstream>
|
||||
|
||||
namespace activemq{
|
||||
namespace exceptions{
|
||||
|
||||
/*
|
||||
* Base class for all exceptions.
|
||||
*/
|
||||
class ActiveMQException : public cms::CMSException
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* The cause of this exception.
|
||||
*/
|
||||
std::string message;
|
||||
|
||||
/**
|
||||
* The stack trace.
|
||||
*/
|
||||
std::vector< std::pair< std::string, int> > stackTrace;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Default Constructor
|
||||
*/
|
||||
ActiveMQException(void) {}
|
||||
|
||||
/**
|
||||
* Copy Constructor
|
||||
*/
|
||||
ActiveMQException( const ActiveMQException& ex ){
|
||||
*this = ex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor - Initializes the file name and line number where
|
||||
* this message occured. Sets the message to report, using an
|
||||
* optional list of arguments to parse into the message
|
||||
* @param file name where exception occurs
|
||||
* @param line number where the exception occurred.
|
||||
* @param message to report
|
||||
* @param list of primitives that are formatted into the message
|
||||
*/
|
||||
ActiveMQException(const char* file, const int lineNumber,
|
||||
const char* msg, ...)
|
||||
{
|
||||
va_list vargs ;
|
||||
va_start(vargs, msg) ;
|
||||
buildMessage(msg, vargs) ;
|
||||
|
||||
// Set the first mark for this exception.
|
||||
setMark( file, lineNumber );
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ActiveMQException(){}
|
||||
|
||||
/**
|
||||
* Gets the message for this exception.
|
||||
*/
|
||||
virtual const char* getMessage() const{ return message.c_str(); }
|
||||
|
||||
/**
|
||||
* Sets the cause for this exception.
|
||||
* @param msg the format string for the msg.
|
||||
*/
|
||||
virtual void setMessage( const char* msg, ... ){
|
||||
va_list vargs ;
|
||||
va_start(vargs, msg) ;
|
||||
buildMessage(msg, vargs) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a file/line number to the stack trace.
|
||||
* @param file The name of the file calling this method (use __FILE__).
|
||||
* @param lineNumber The line number in the calling file (use __LINE__).
|
||||
*/
|
||||
virtual void setMark( const char* file, const int lineNumber );
|
||||
|
||||
/**
|
||||
* Clones this exception. This is useful for cases where you need
|
||||
* to preserve the type of the original exception as well as the message.
|
||||
* All subclasses should override.
|
||||
*/
|
||||
virtual ActiveMQException* clone() const{
|
||||
return new ActiveMQException( *this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the stack trace for every point where
|
||||
* this exception was caught, marked, and rethrown. The first
|
||||
* item in the returned vector is the first point where the mark
|
||||
* was set (e.g. where the exception was created).
|
||||
* @return the stack trace.
|
||||
*/
|
||||
virtual std::vector< std::pair< std::string, int> > getStackTrace() const{
|
||||
return stackTrace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the stack trace to std::err
|
||||
*/
|
||||
virtual void printStackTrace() const{
|
||||
printStackTrace( std::cerr );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the stack trace to the given output stream.
|
||||
* @param stream the target output stream.
|
||||
*/
|
||||
virtual void printStackTrace( std::ostream& stream ) const{
|
||||
stream << getStackTraceString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the stack trace as one contiguous string.
|
||||
*/
|
||||
virtual std::string getStackTraceString() const{
|
||||
|
||||
// Create the output stream.
|
||||
std::ostringstream stream;
|
||||
|
||||
// Write the message and each stack entry.
|
||||
stream << message << std::endl;
|
||||
for( unsigned int ix=0; ix<stackTrace.size(); ++ix ){
|
||||
stream << "\tFILE: " << stackTrace[ix].first;
|
||||
stream << ", LINE: " << stackTrace[ix].second;
|
||||
stream << std::endl;
|
||||
}
|
||||
|
||||
// Return the string from the output stream.
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assignment operator.
|
||||
*/
|
||||
virtual ActiveMQException& operator =( const ActiveMQException& ex ){
|
||||
this->message = ex.message;
|
||||
this->stackTrace = ex.stackTrace;
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual void buildMessage(const char* format, va_list& vargs);
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*ACTIVEMQ_EXCEPTIONS_ACTIVEMQEXCEPTION_H*/
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef _ACTIVEMQ_EXCEPTIONS_EXCEPTIONDEFINES_H_
|
||||
#define _ACTIVEMQ_EXCEPTIONS_EXCEPTIONDEFINES_H_
|
||||
|
||||
/**
|
||||
* Macro for catching and rethrowing an exception of
|
||||
* a given type.
|
||||
* @param type The type of the exception to throw
|
||||
* (e.g. ActiveMQException ).
|
||||
*/
|
||||
#define AMQ_CATCH_RETHROW( type ) \
|
||||
catch( type& ex ){ \
|
||||
ex.setMark( __FILE__, __LINE__ ); \
|
||||
throw ex; \
|
||||
}
|
||||
|
||||
/**
|
||||
* Macro for catching an exception of one type and then rethrowing
|
||||
* as another type.
|
||||
* @param sourceType the type of the exception to be caught.
|
||||
* @param targetType the type of the exception to be thrown.
|
||||
*/
|
||||
#define AMQ_CATCH_EXCEPTION_CONVERT( sourceType, targetType ) \
|
||||
catch( sourceType& ex ){ \
|
||||
targetType target( ex ); \
|
||||
target.setMark( __FILE__, __LINE__ ); \
|
||||
throw target; \
|
||||
}
|
||||
|
||||
/**
|
||||
* A catch-all that throws a known exception.
|
||||
* @param type the type of exception to be thrown.
|
||||
*/
|
||||
#define AMQ_CATCHALL_THROW( type ) \
|
||||
catch( ... ){ \
|
||||
type ex( __FILE__, __LINE__, \
|
||||
"caught unknown exception" ); \
|
||||
throw ex; \
|
||||
}
|
||||
|
||||
/**
|
||||
* A catch-all that does not throw an exception, one use would
|
||||
* be to catch any exception in a destructor and mark it, but not
|
||||
* throw so that cleanup would continue as normal.
|
||||
*/
|
||||
#define AMQ_CATCHALL_NOTHROW( ) \
|
||||
catch( ... ){ \
|
||||
exceptions::ActiveMQException ex( __FILE__, __LINE__, \
|
||||
"caught unknown exception, not rethrowing" ); \
|
||||
}
|
||||
|
||||
/**
|
||||
* Macro for catching and rethrowing an exception of
|
||||
* a given type.
|
||||
* @param type The type of the exception to throw
|
||||
* (e.g. ActiveMQException ).
|
||||
*/
|
||||
#define AMQ_CATCH_NOTHROW( type ) \
|
||||
catch( type& ex ){ \
|
||||
ex.setMark( __FILE__, __LINE__ ); \
|
||||
}
|
||||
|
||||
#endif /*_ACTIVEMQ_EXCEPTIONS_EXCEPTIONDEFINES_H_*/
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef ACTIVEMQ_EXCEPTIONS_ILLEGALARGUMENTEXCEPTION_H_
|
||||
#define ACTIVEMQ_EXCEPTIONS_ILLEGALARGUMENTEXCEPTION_H_
|
||||
|
||||
#include <activemq/exceptions/ActiveMQException.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace exceptions{
|
||||
|
||||
/*
|
||||
* Thrown when an illegal argument was passed into a method.
|
||||
*/
|
||||
class IllegalArgumentException : public ActiveMQException
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Default Constructor
|
||||
*/
|
||||
IllegalArgumentException(){};
|
||||
|
||||
/**
|
||||
* Conversion Constructor from some other ActiveMQException
|
||||
* @param An exception that should become this type of Exception
|
||||
*/
|
||||
IllegalArgumentException( const ActiveMQException& ex ){
|
||||
*(ActiveMQException*)this = ex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy Constructor
|
||||
*/
|
||||
IllegalArgumentException( const IllegalArgumentException& ex ){
|
||||
*(ActiveMQException*)this = ex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor - Initializes the file name and line number where
|
||||
* this message occured. Sets the message to report, using an
|
||||
* optional list of arguments to parse into the message
|
||||
* @param file name where exception occurs
|
||||
* @param line number where the exception occurred.
|
||||
* @param message to report
|
||||
* @param list of primitives that are formatted into the message
|
||||
*/
|
||||
IllegalArgumentException(const char* file, const int lineNumber,
|
||||
const char* msg, ...)
|
||||
{
|
||||
va_list vargs ;
|
||||
va_start(vargs, msg) ;
|
||||
buildMessage(msg, vargs) ;
|
||||
|
||||
// Set the first mark for this exception.
|
||||
setMark( file, lineNumber );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones this exception. This is useful for cases where you need
|
||||
* to preserve the type of the original exception as well as the message.
|
||||
* All subclasses should override.
|
||||
*/
|
||||
virtual ActiveMQException* clone() const{
|
||||
return new IllegalArgumentException( *this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~IllegalArgumentException(){}
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*ACTIVEMQ_EXCEPTIONS_ILLEGALARGUMENTEXCEPTION_H_*/
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
*/
|
||||
#ifndef ACTIVEMQ_EXCEPTIONS_ILLEGALMONITORSTATEEXCEPTION_H_
|
||||
#define ACTIVEMQ_EXCEPTIONS_ILLEGALMONITORSTATEEXCEPTION_H_
|
||||
|
||||
#include <activemq/exceptions/ActiveMQException.h>
|
||||
|
||||
namespace activemq{
|
||||
namespace exceptions{
|
||||
|
||||
/*
|
||||
* Thrown when an error occurs from calling a method from syncronizable
|
||||
* and the caller doesn't hold a lock on the object.
|
||||
*/
|
||||
class IllegalMonitorStateException : public ActiveMQException
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Default Constructor
|
||||
*/
|
||||
IllegalMonitorStateException(void) {};
|
||||
|
||||
/**
|
||||
* Conversion Constructor from some other ActiveMQException
|
||||
* @param An exception that should become this type of Exception
|
||||
*/
|
||||
IllegalMonitorStateException(const ActiveMQException& ex){
|
||||
*(ActiveMQException*)this = ex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy Constructor
|
||||
*/
|
||||
IllegalMonitorStateException(const IllegalMonitorStateException& ex){
|
||||
*(ActiveMQException*)this = ex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor - Initializes the file name and line number where
|
||||
* this message occured. Sets the message to report, using an
|
||||
* optional list of arguments to parse into the message
|
||||
* @param file name where exception occurs
|
||||
* @param line number where the exception occurred.
|
||||
* @param message to report
|
||||
* @param list of primitives that are formatted into the message
|
||||
*/
|
||||
IllegalMonitorStateException(const char* file,
|
||||
const int lineNumber,
|
||||
const char* msg, ...)
|
||||
{
|
||||
va_list vargs;
|
||||
va_start(vargs, msg);
|
||||
buildMessage(msg, vargs);
|
||||
|
||||
// Set the first mark for this exception.
|
||||
setMark(file, lineNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones this exception. This is useful for cases where you need
|
||||
* to preserve the type of the original exception as well as the message.
|
||||
* All subclasses should override.
|
||||
*/
|
||||
virtual ActiveMQException* clone(void) const{
|
||||
return new IllegalMonitorStateException(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~IllegalMonitorStateException(void) {}
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /*ACTIVEMQ_EXCEPTIONS_ILLEGALMONITORSTATEEXCEPTION_H_*/
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue