RAT (Release Audit Tool) results

The following document contains the results of RAT (Release Audit Tool).

*****************************************************
Summary
-------
Notes: 4
Binaries: 4
Archives: 0
Standards: 104

Apache Licensed: 12
Generated Documents: 0

JavaDocs are generated and so license header is optional
Generated files do not required license headers

92 Unknown Licenses

*******************************

Archives (+ indicates readable, $ unreadable): 

 
*****************************************************
  Files with AL headers will be marked L
  Binary files (which do not require AL headers) will be marked B
  Compressed archives will be marked A
  Notices, licenses etc will be marked N
 !????? build-gump.xml
 !????? build-legacy.xml
 !????? build.properties.sample
 !????? build.xml
  N     LICENSE.txt
 !????? maven.xml
  N     NOTICE.txt
  AL    pom.xml
 !????? project.properties
 !????? project.xml
  N     README.txt
  N     RELEASE-NOTES.txt
 !????? src/conf/MANIFEST.MF
 !????? src/conf/messenger.dtd
 !????? src/conf/Messenger.xml
 !????? src/conf/MessengerAshna.xml
 !????? src/conf/MessengerJBoss.xml
 !????? src/conf/MessengerOpenjms.xml
 !????? src/conf/MessengerSpiritWave.xml
 !????? src/conf/MessengerWebLogic.xml
 !????? src/conf/sampleMessage.txt
 !????? src/conf/subscribe.xml
 !????? src/conf/subscriptions.dtd
 !????? src/conf/test-connections.xml
 !????? src/java/org/apache/commons/messagelet/BridgeMDO.java
 !????? src/java/org/apache/commons/messagelet/ConsumerThread.java
 !????? src/java/org/apache/commons/messagelet/DistributeBridgeMDO.java
 !????? src/java/org/apache/commons/messagelet/impl/BufferedServletInputStream.java
 !????? src/java/org/apache/commons/messagelet/impl/BufferedServletOutputStream.java
 !????? src/java/org/apache/commons/messagelet/impl/HttpMessageletRequestImpl.java
 !????? src/java/org/apache/commons/messagelet/impl/HttpMessageletResponseImpl.java
  AL    src/java/org/apache/commons/messagelet/impl/HttpServletRequestImpl.java
  AL    src/java/org/apache/commons/messagelet/impl/HttpServletResponseImpl.java
  AL    src/java/org/apache/commons/messagelet/impl/HttpSessionImpl.java
 !????? src/java/org/apache/commons/messagelet/impl/MessageHttpServletDispatcher.java
 !????? src/java/org/apache/commons/messagelet/impl/MessageletRequestImpl.java
 !????? src/java/org/apache/commons/messagelet/impl/MessageletResponseImpl.java
 !????? src/java/org/apache/commons/messagelet/impl/MessageServletDispatcher.java
 !????? src/java/org/apache/commons/messagelet/impl/package.html
  AL    src/java/org/apache/commons/messagelet/impl/RequestUtil.java
  AL    src/java/org/apache/commons/messagelet/impl/ServletRequestImpl.java
  AL    src/java/org/apache/commons/messagelet/impl/ServletResponseImpl.java
 !????? src/java/org/apache/commons/messagelet/Main.java
 !????? src/java/org/apache/commons/messagelet/ManagerServlet.java
 !????? src/java/org/apache/commons/messagelet/MessageDrivenObject.java
 !????? src/java/org/apache/commons/messagelet/MessageDrivenObjectSupport.java
 !????? src/java/org/apache/commons/messagelet/Messagelet.java
 !????? src/java/org/apache/commons/messagelet/MessageletRequest.java
 !????? src/java/org/apache/commons/messagelet/MessageletResponse.java
 !????? src/java/org/apache/commons/messagelet/MessengerMDO.java
 !????? src/java/org/apache/commons/messagelet/model/package.html
 !????? src/java/org/apache/commons/messagelet/model/Subscription.java
 !????? src/java/org/apache/commons/messagelet/model/SubscriptionDigester.java
 !????? src/java/org/apache/commons/messagelet/model/SubscriptionList.java
 !????? src/java/org/apache/commons/messagelet/package.html
 !????? src/java/org/apache/commons/messagelet/SubscriptionManager.java
 !????? src/java/org/apache/commons/messagelet/XAConsumerThread.java
  AL    src/java/org/apache/commons/messenger/DefaultMessenger.java
 !????? src/java/org/apache/commons/messenger/DefaultServerSession.java
 !????? src/java/org/apache/commons/messenger/DefaultServerSessionPool.java
 !????? src/java/org/apache/commons/messenger/InitMessengerServlet.java
 !????? src/java/org/apache/commons/messenger/JNDISessionFactory.java
 !????? src/java/org/apache/commons/messenger/ListenerKey.java
 !????? src/java/org/apache/commons/messenger/Lock.java
  AL    src/java/org/apache/commons/messenger/Messenger.java
 !????? src/java/org/apache/commons/messenger/MessengerDigester.java
 !????? src/java/org/apache/commons/messenger/MessengerListener.java
 !????? src/java/org/apache/commons/messenger/MessengerListenerSupport.java
 !????? src/java/org/apache/commons/messenger/MessengerManager.java
 !????? src/java/org/apache/commons/messenger/MessengerServlet.java
 !????? src/java/org/apache/commons/messenger/MessengerSession.java
 !????? src/java/org/apache/commons/messenger/MessengerSupport.java
 !????? src/java/org/apache/commons/messenger/package.html
 !????? src/java/org/apache/commons/messenger/SessionFactory.java
  AL    src/java/org/apache/commons/messenger/SimpleMessenger.java
 !????? src/java/org/apache/commons/messenger/task/ConsumerTask.java
 !????? src/java/org/apache/commons/messenger/task/package.html
 !????? src/java/org/apache/commons/messenger/task/ProducerTask.java
 !????? src/java/org/apache/commons/messenger/tool/Caller.java
 !????? src/java/org/apache/commons/messenger/tool/Consumer.java
 !????? src/java/org/apache/commons/messenger/tool/package.html
 !????? src/java/org/apache/commons/messenger/tool/Producer.java
 !????? src/java/org/apache/commons/messenger/tool/StopWatchMessageListener.java
 !????? src/java/org/apache/commons/messenger/XACapable.java
 !????? src/java/org/apache/commons/messenger/XACapableAdapter.java
 !????? src/java/org/apache/commons/messenger/XAMessenger.java
  B     src/site/resources/images/messenger-logo-white.png
  B     src/site/resources/images/messenger-logo-white.xcf
  AL    src/site/site.xml
 !????? src/test/org/apache/commons/messenger/LockTest.java
 !????? src/test/org/apache/commons/messenger/LoggingMDO.java
 !????? src/test/org/apache/commons/messenger/TestAll.java
 !????? src/test/org/apache/commons/messenger/TestMessenger.java
 !????? src/webapp/conf/subscriptions.xml
 !????? src/webapp/conf/web.xml
 !????? src/webapp/jms/time.jsp
 !????? src/webapp/src/EchoMDO.java
 !????? src/webapp/src/EchoMessagelet.java
 !????? src/webapp/src/EchoServlet.java
 !????? src/webapp/web/default.css
 !????? src/webapp/web/index.jsp
 !????? src/webapp/web/jms/time.jsp
 !????? src/webapp/WEB-INF/src/EchoMDO.java
 !????? src/webapp/WEB-INF/src/EchoMessagelet.java
 !????? src/webapp/WEB-INF/src/EchoServlet.java
 !????? src/webapp/WEB-INF/subscriptions.xml
 !????? src/webapp/WEB-INF/web.xml
 !????? TODO.txt
  B     xdocs/images/messenger-logo-white.png
  B     xdocs/images/messenger-logo-white.xcf
 !????? xdocs/index.xml
  AL    xdocs/navigation.xml
 
 *****************************************************
 Printing headers for files without AL header...
 
 
 =======================================================================
 ==build-gump.xml
 =======================================================================
 <!--

  WARNING: This file is generated! Do not edit by hand!
  
-->

<project name="maven" default="jar" basedir=".">

  <target
    name="jar">
    
    <property name="maven.build.dir" value="target"/>
    <property name="maven.build.dest" value="${maven.build.dir}/classes"/>
    
    <mkdir dir="${maven.build.dest}"/>
    
    <javac
      destdir="${maven.build.dest}"
      excludes="**/package.html"
      debug="false"
      deprecation="false"
      optimize="false">
      <src>
         <pathelement location="src/java"/>
      </src>
    </javac>

    <jar
      jarfile="${maven.build.dir}/${maven.final.name}.jar"
      basedir="${maven.build.dest}"
      excludes="**/package.html"
    />
    
  </target>

</project>

 =======================================================================
 ==build-legacy.xml
 =======================================================================
 <project name="messenger" default="compile" basedir=".">

<!--
        "messenger" component of the Apache Commons Subproject
        $Id: build-legacy.xml 561366 2007-07-31 15:58:29Z rahul $
-->

<!-- ========== Initialize Properties ===================================== -->


  <property file="build.properties"/>                <!-- Component local   -->
  <property file="../build.properties"/>             <!-- Commons local     -->
  <property file="${user.home}/build.properties"/>   <!-- User local        -->


  <!-- Allow any user specific values to override the defaults -->
  <property file="${user.home}/build.properties" />
  <!-- Allow user defaults for this project -->
  <property file="build.properties" />
  <!-- Set default values for the build -->
  <property file="project.properties" />
  
  <!-- maven:start -->
  
  <!-- ================================================================== -->
  <!-- D E F I N E   A N T   T A S K S                                    -->
  <!-- ================================================================== -->
  <taskdef
	name="maven-ant"
	classname="org.apache.maven.ant.Ant">
	<classpath>
      <pathelement location="${lib.repo}/maven.jar"/>
	</classpath>
  </taskdef>

        
  <!-- ================================================================== -->
  <!-- D E L E G A T O R S                                                -->
  <!-- ================================================================== -->
        
	<target name="maven:gump-descriptor">
	  <maven-ant antfile="${maven.home}/plugins/core/build.xml" target="gump-descriptor"/>
	</target>
	
	<target name="maven:maven-update">
	  <maven-ant antfile="${maven.home}/plugins/core/build.xml" target="maven-update"/>
	</target>
	
	<target name="maven:update-jars">
	  <maven-ant antfile="${maven.home}/plugins/core/build.xml" target="update-jars"/>

 =======================================================================
 ==build.properties.sample
 =======================================================================
 #
# Compile-time dependencies
#

jms.jar=/java/jms/jms.jar

servlet.jar=/java/servlet/servlet.jar

# jakarta commons-digester.jar
commons-digester.jar=../../jakarta-commons/digester/dist/commons-digester.jar

# jakarta commons-collections.jar
commons-collections.jar=../../jakarta-commons/collections/dist/commons-collections.jar

# jakarta commons-beanutils.jar
commons-beanutils.jar=../../jakarta-commons/beanutils/dist/commons-beanutils.jar

# jakarta commons-logging.jar
commons-logging.jar=../../jakarta-commons/logging/dist/commons-logging.jar



#
# Runtime dependencies
#

# junit.jar - JUnit 3.2+ Classpath
junit.jar=/java/junit/junit.jar

# j2sdkee installation
j2sdkee=/j2sdkee1.3

# Messenger deployment config to use in tests, defaults to Suns RI
messenger.xml=src/conf/Messenger.xml

# Directory where the JMS implementation JARs reside
# which are copied to WEB-INF/lib
jms.lib.dir=lib

# Directory where the JMS classes or properties files reside 
# which are copied to WEB-INF/classes
jms.classes.dir=conf

 =======================================================================
 ==build.xml
 =======================================================================
 <?xml version="1.0" encoding="UTF-8"?>

<project default="jar" name="commons-messenger" basedir=".">
  <property name="defaulttargetdir" value="target">
  </property>
  <property name="libdir" value="target/lib">
  </property>
  <property name="classesdir" value="target/classes">
  </property>
  <property name="testclassesdir" value="target/test-classes">
  </property>
  <property name="testreportdir" value="target/test-reports">
  </property>
  <property name="distdir" value="dist">
  </property>
  <property name="javadocdir" value="dist/docs/api">
  </property>
  <property name="final.name" value="commons-messenger-1.0-dev-10">
  </property>
  <target name="init" description="o Initializes some properties">
    <mkdir dir="${libdir}">
    </mkdir>
    <condition property="noget">
      <equals arg2="only" arg1="${build.sysclasspath}">
      </equals>
    </condition>
  </target>
  <target name="compile" description="o Compile the code" depends="get-deps">
    <mkdir dir="${classesdir}">
    </mkdir>
    <javac destdir="${classesdir}" deprecation="true" debug="true" optimize="false" excludes="**/package.html">
      <src>
        <pathelement location="src/java">
        </pathelement>
      </src>
      <classpath>
        <fileset dir="${libdir}">
          <include name="*.jar">
          </include>
        </fileset>
      </classpath>
    </javac>
  </target>
  <target name="jar" description="o Create the jar" depends="compile,test">
    <jar jarfile="target/${final.name}.jar" excludes="**/package.html" basedir="${classesdir}">
      <metainf dir="${basedir}">
        <include name="LICENSE.txt">
        </include>
      </metainf>
      <manifest>

 =======================================================================
 ==maven.xml
 =======================================================================
 <project default="java:jar" xmlns:j="jelly:core" xmlns:util="jelly:util">

  <goal name="set.classpath" prereqs="java:compile, test:compile">

  	<echo>
		Using JMS from lib dir ${jms.lib.dir} and config dir ${jms.classes.dir}
		Connecting via ${messenger.xml}
    </echo>
    
    <path id="jms.classpath">
    	<!--
      <pathelement path="target/classes"/>
      -->
      <pathelement path="target/test-classes"/>
      <pathelement path="${maven.build.dest}"/>
	  	<path refid="maven.dependency.classpath"/>
	  
      <!-- add the JARs required for a pluggable JMS provider -->
      <pathelement path="${jms.classes.dir}"/>
      <fileset dir="${jms.lib.dir}">
        <include name="**/*.jar"/>
      </fileset>
	</path>
	
  </goal>
  		
  <!-- runs a sample number of subscriptions -->	
  <goal name="demo:subscribe" prereqs="set.classpath"
  	description="Subscribes to various destinations waiting for JMS messages">
  
    <java classname="org.apache.commons.messagelet.Main" fork="yes">
      <classpath refid="jms.classpath"/>

      <arg value="src/conf/subscribe.xml"/>
      <arg value="${messenger.xml}"/>
    </java>
  </goal>
	
  <goal name="demo:send" prereqs="set.classpath"
    description="Sends a message for processing by an MDO">
    
    <java classname="org.apache.commons.messenger.tool.Producer" fork="yes">
      <classpath refid="jms.classpath"/>
      <arg value="queue"/>
      <arg value="echo.queue2"/>
      <arg value="src/conf/sampleMessage.txt"/>
      <sysproperty key="org.apache.commons.messenger" value="${messenger.xml}"/>
    </java>
  </goal>


 =======================================================================
 ==project.properties
 =======================================================================
 # -------------------------------------------------------------------
# P R O J E C T  P R O P E R T I E S
# -------------------------------------------------------------------

# -------------------------------------------------------------------
# JMS provider details 
# -------------------------------------------------------------------
messenger.xml=src/conf/Messenger.xml
jms.lib.dir=jms/lib
jms.classes.dir=jms/classes

# -------------------------------------------------------------------
# General Maven stuff
# -------------------------------------------------------------------
maven.changelog.factory=org.apache.maven.svnlib.SvnChangeLogFactory

maven.xdoc.jsl=../commons-build/commons-site.jsl
maven.xdoc.date=bottom
maven.xdoc.poweredby.image=maven-feather.png
maven.xdoc.version=${pom.currentVersion}
maven.xdoc.developmentProcessUrl=http://commons.apache.org/charter.html
maven.xdoc.includeProjectDocumentation=yes

compile.debug = on
compile.optimize = off
compile.deprecation = off

maven.jarResources.basedir=${basedir}/src/java
 

# use Sun coding standards

maven.checkstyle.lcurly.type = eol
maven.checkstyle.lcurly.method = eol
maven.checkstyle.lcurly.other = eol
#maven.checkstyle.header.file = src/conf/checkstyle-LICENSE.txt
maven.checkstyle.header.ignore.line = 1,2,3,4,5,6
maven.checkstyle.const.pattern = ^[a-z][a-zA-Z0-9]*$

# disable these non-critical errors to highlight
# more important ones line missing javadoc

maven.checkstyle.max.line.len = 100
maven.checkstyle.ignore.whitespace = true
maven.checkstyle.ignore.public.in.interface = true



 =======================================================================
 ==project.xml
 =======================================================================
 <?xml version="1.0" encoding="UTF-8"?>

<project>
  <extend>../commons-build/sandbox-project.xml</extend>
  <name>Commons messenger</name>
  <id>commons-messenger</id>
  <logo>/images/messenger-logo-white.png</logo>
  <currentVersion>1.0-dev-14</currentVersion>
  <inceptionYear>2002</inceptionYear>
  <package>org.apache.commons</package>
  <shortDescription>Commons Messenger</shortDescription>
  
  <description>
  	Commons Messenger is a JMS framework for working with JMS in web applications and web services
  </description>
  
  <developers>
    <developer>
      <name>James Strachan</name>
      <id>jstrachan</id>
      <email>jstrachan@apache.org</email>
      <organization>SpiritSoft, Inc.</organization>
    </developer>
    <developer>
      <name>Saimon Moore</name>
      <id>saimon</id>
      <email>saimonmoore@yahoo.co.uk</email>
      <organization></organization>
    </developer>
  </developers>
  
  <contributors>
    <contributor>
      <name>Bill Christian</name>
    </contributor>
    <contributor>
      <name>Colin Crist</name>
    </contributor>
    <contributor>
      <name>Louis Burroughs</name>
    </contributor>
  </contributors>
  
  <dependencies>
    
    <dependency>
      <id>commons-logging</id>
      <version>1.0.1</version>
    </dependency>


 =======================================================================
 ==src/conf/MANIFEST.MF
 =======================================================================
 Extension-Name: org.apache.commons.messenger
Specification-Vendor: Apache Software Foundation
Specification-Version: 1.0
Implementation-Vendor: Apache Software Foundation
Implementation-Version: 1.0-dev


 =======================================================================
 ==src/conf/messenger.dtd
 =======================================================================
 <!-- 
	|| $Id: messenger.dtd 155459 2005-02-26 13:24:44Z dirkv $
  || Created by Michael Rimov (rimovm@centercomp.com) 
  || Please mail the commons-dev apache mail list if you have any corrections
  -->
  
<!ELEMENT manager (messenger+)>
<!ATTLIST manager
	className CDATA #IMPLIED
>

<!-- 
	creates a Messenger (a JMS connection with session pools)
	
	name 							- the name of the messenger instance. Can be any String
	jndiDestinations 	- whether destinations should be created or pulled from JNDI
	cacheProducers 		- should MessageProducers be cached (defaults to true)
	durable					  - sets whether topic subscribers are durable or not
	durableName				- the durable name used for durable topic subscriptions
	noLocal						- whether local messages are ignored when using topic subscriptions
	persitentDelivery	- sets whether or not message delivery should be persistent
-->
	
<!ELEMENT messenger (jndi|factory)>
<!ATTLIST messenger
	name CDATA #REQUIRED
	jndiDestinations (false | true) #IMPLIED
	cacheProducers (false | true) #IMPLIED
	durable (false | true) #IMPLIED
	durableName CDATA #IMPLIED
	noLocal (false | true) #IMPLIED
	persitentDelivery (false | true) #IMPLIED
>

<!-- 
	specifies a custom factory of Connection and Session objects 

	className					- specifies the SessionFactory implementation class to use
	username					- the user name to use for the Connection
	password					- the password to use for the connection
	
	acknowlege				- sets the acknowledgement mode to auto, client or duplicates ok
	clientID 					- sets the clientID on the JMS Connection
	topic							- whether or not the Connection should be considered a topic of queue connection
										  (some JMS Connections can implement both mechanisms).
										  	 
	transacted				- whether or not the connection should behave in transacted mode
-->

<!ELEMENT factory (property*)>

 =======================================================================
 ==src/conf/Messenger.xml
 =======================================================================
 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE manager SYSTEM "messenger.dtd">
<manager>

  <!-- this example Messenger XML config file should work with J2EE SDK -->
  <!-- when running inside of a J2EE container                          -->

  <messenger name="topic" jndiDestinations="false" persistentDelivery="true">
    <jndi lookupName="TopicConnectionFactory" topic="true" acknowledge="auto">
<!--
    for some reason these don't work too well with J2EE SDK

    <jndi lookupName="java:comp/env/TopicConnectionFactory" topic="true">
-->
      <property>
        <name>com.sun.jms.internal.java.naming.factory.initial</name>
        <value>com.sun.enterprise.naming.SerialInitContextFactory</value>
      </property>
    </jndi>
  </messenger>

  <messenger name="queue" jndiDestinations="false">
    <jndi lookupName="QueueConnectionFactory" topic="false">
<!--
    for some reason these don't work too well with J2EE SDK

    <jndi lookupName="java:comp/env/QueueConnectionFactory" topic="false">
-->
      <property>
        <name>com.sun.jms.internal.java.naming.factory.initial</name>
        <value>com.sun.enterprise.naming.SerialInitContextFactory</value>
      </property>
    </jndi>
  </messenger>

</manager>

 =======================================================================
 ==src/conf/MessengerAshna.xml
 =======================================================================
 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE manager SYSTEM "messenger.dtd">
<manager>

  <!-- this example Messenger XML config file should work with J2EE SDK -->
  <!-- when running outside of a J2EE container                         -->

  <messenger name="topic" jndiDestinations="true">
    <jndi lookupName="TopicConnectionFactory" topic="true">
      <property>
        <name>java.naming.factory.initial</name>
        <value>com.ashnasoft.jms.client.jndi.InitialContextFactoryImpl</value>
      </property>
      <property>
        <name>java.naming.provider.url</name>
        <value>jndi:Ashna://localhost:9090/USERNAME=admin/PASSWORD=/SECURE=false</value>
      </property>
    </jndi>
  </messenger>

  <messenger name="queue" jndiDestinations="true">
    <jndi lookupName="QueueConnectionFactory" topic="false">
      <property>
        <name>java.naming.factory.initial</name>
        <value>com.ashnasoft.jms.client.jndi.InitialContextFactoryImpl</value>
      </property>
      <property>
        <name>java.naming.provider.url</name>
        <value>jndi:Ashna://localhost:9090/USERNAME=admin/PASSWORD=/SECURE=false</value>
      </property>
    </jndi>
  </messenger>

</manager>

 =======================================================================
 ==src/conf/MessengerJBoss.xml
 =======================================================================
 <?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE manager SYSTEM "messenger.dtd">

<!-- 
  || JBoss Sample configuration.  
  ||
  || One final point is that all queues that you
  || create must have the name queue/[your queuename]  and/or 
  || topic/[your topic name].      
  || The UserName and Password are the default for Jboss' user security, you'll want 
  || to modify it as needed.  And finally by changing the lookup name to things like 
  || RMIConnectionFactory, or one of the other JBoss JMS protocols, 
  || you can change the underlying JMS transport
  -->

<manager>
	<messenger name="topic" jndiDestinations="true">
		<jndi lookupName="ConnectionFactory" topic="true">
			<property>
				<name>java.naming.factory.initial</name>
				<value>org.jnp.interfaces.NamingContextFactory</value>
			</property>
			<property>
				<name>java.naming.provider.url</name>
				<value>jnp://localhost:1099</value>
			</property>
			<property>
				<name>java.naming.factory.url.pkgs</name>
				<value>org.jboss.naming:org.jnp.interfaces</value>
			</property>
			<property>
				<name>UserName</name>
				<value>john</value>
			</property>
			<property>
				<name>Password</name>
				<value>needle</value>
			</property>
		</jndi>
	</messenger>
	<messenger name="queue" jndiDestinations="true">
		<jndi lookupName="ConnectionFactory" topic="false" transacted="true">
			<property>
				<name>java.naming.factory.initial</name>
				<value>org.jnp.interfaces.NamingContextFactory</value>
			</property>
			<property>
				<name>java.naming.provider.url</name>
				<value>jnp://localhost:1099</value>

 =======================================================================
 ==src/conf/MessengerOpenjms.xml
 =======================================================================
 <?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE manager SYSTEM "messenger.dtd">

<!--
  || Sample Connection file for working with Exolab's OpenJMS server using 
  || the default rmi_jms.xml configuration file.  
  || You will most likely need to modify the connection information if you use one of 
  || the other configuraiton files.  I've had
  || troubles with using the call() statements with OpenJMS, but other messages
  || seem to work well.
  -->
<manager>
	<messenger name="topic">
		<jndi lookupName="JmsTopicConnectionFactory">
			<property>
				<name>java.naming.factory.initial</name>
				<value>org.exolab.jms.jndi.rmi.RmiJndiInitialContextFactory</value>
			</property>
			<property>
				<name>java.naming.provider.url</name>
				<value>rmi://localhost:1099/JndiServer</value>
			</property>
		</jndi>
	</messenger>
	<messenger name="queue">
		<jndi lookupName="JmsQueueConnectionFactory">
			<property>
				<name>java.naming.factory.initial</name>
				<value>org.exolab.jms.jndi.rmi.RmiJndiInitialContextFactory</value>
			</property>
			<property>
				<name>java.naming.provider.url</name>
				<value>rmi://localhost:1099/JndiServer</value>
			</property>
		</jndi>
	</messenger>
</manager>

 =======================================================================
 ==src/conf/MessengerSpiritWave.xml
 =======================================================================
 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE manager SYSTEM "messenger.dtd">
<manager>

  <messenger name="topic" persistentDeliver="true">
    <factory className="com.spirit.messenger.WaveTopicSessionFactory" acknowledge="auto">
    </factory>
  </messenger>
  <messenger name="queue" persistentDeliver="true">
    <factory className="com.spirit.messenger.WaveQueueSessionFactory" acknowledge="auto">
    </factory>
  </messenger>
</manager>

 =======================================================================
 ==src/conf/MessengerWebLogic.xml
 =======================================================================
 <?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE manager SYSTEM "messenger.dtd">

<!--
  || Sample Connection file for working with WebLogic's JMS
  || for WLS 7 + SP1
  ||
  || Created by Jukka Nikki
  -->
  
<manager>
  
  <messenger name="myQueueConnection" jndiDestinations="true">
    <jndi lookupName="weblogic.examples.jms.QueueConnectionFactory" topic="false">
      <property>
        <name>java.naming.factory.initial</name>
        <value>weblogic.jndi.WLInitialContextFactory</value>
      </property>
      <property>
        <name>java.naming.provider.url</name>
        <value>t3://127.0.0.1:7001</value>
      </property>
    </jndi>
  </messenger>
  
  <messenger name="myTopicConnection" jndiDestinations="true">
    <jndi lookupName="weblogic.examples.jms.TopicConnectionFactory" topic="true">
      <property>
        <name>java.naming.factory.initial</name>
        <value>weblogic.jndi.WLInitialContextFactory</value>
      </property>
      <property>
        <name>java.naming.provider.url</name>
        <value>t3://127.0.0.1:7001</value>
      </property>
    </jndi>
  </messenger>
</manager>

 =======================================================================
 ==src/conf/sampleMessage.txt
 =======================================================================
 This is a sample message!

 =======================================================================
 ==src/conf/subscribe.xml
 =======================================================================
 <?xml version="1.0" encoding="UTF-8"?>
<subscriptions>

	<!-- a simple echo consumer -->
  <subscription connection="queue" subject="echo.queue">
    <listener className="org.apache.commons.messenger.LoggingMDO"/>
  </subscription>

  <subscription connection="queue" subject="echo.queue2">
  	<consumerThread/>
    <listener className="org.apache.commons.messenger.LoggingMDO"/>
  </subscription>

  <!-- bridge to another JMS provider -->
  <subscription connection="queue" subject="my.input2" selector="b='12'">
    <bridge outputConnection="queue" outputSubject="my.output"/>
  </subscription>

  <!-- distribute messages to multiple output queues -->
  <subscription connection="queue" subject="my.input">
    <distributeBridge outputConnection="queue">
		  <subject>output.A</subject>		    	
		  <subject>output.B</subject>		    	
		  <subject>output.C</subject>		    	
		  <subject>output.D</subject>		    	
    </distributeBridge>
	</subscription>


  <!-- consume the output queues and report throughput -->
  <subscription connection="queue" subject="output.A">
    <stopWatch groupSize="100"/>
  </subscription>
  <subscription connection="queue" subject="output.B">
    <stopWatch groupSize="100"/>
  </subscription>
  <subscription connection="queue" subject="output.C">
    <stopWatch groupSize="100"/>
  </subscription>
  <subscription connection="queue" subject="output.D">
    <stopWatch groupSize="100"/>
  </subscription>




  <!-- An example of how subscriptions can look... -->
  <!-- the output of the servlet will reply to the original message -->
<!--  
  <subscription connection="queue" subject="my.queue" selector="b='12'">

 =======================================================================
 ==src/conf/subscriptions.dtd
 =======================================================================
 <?xml version="1.0" encoding="UTF-8"?>
<!-- 
  || Authored by Michael Rimov (rimovm@centercomp.com) in an attempt at reading the
  || digester code.  No Guarantee as to it's accuracy!  Please email me if you have 
  || corrections 
  -->
 
<!ELEMENT subscriptions (subscription+)>

<!ELEMENT subscription (listener | servlet | bridge | distributeBridge | stopWatch )+ (consumerThread)?>
<!ATTLIST subscription
	connection (queue|topic) #REQUIRED
	subject CDATA #REQUIRED
	className CDATA #IMPLIED
	selector CDATA #IMPLIED
>

<!ELEMENT listener EMPTY>
<!ATTLIST listener
	className CDATA #REQUIRED
>

<!ELEMENT servlet EMPTY>
<!ATTLIST servlet
	url CDATA #REQUIRED
>

<!ELEMENT bridge EMPTY>
<!ATTLIST bridge
	outputConnection CDATA #REQUIRED
	outputSubject CDATA #REQUIRED
>

<!ELEMENT distributeBridge (subject)+>
<!ATTLIST distributeBridge
	outputConnection CDATA #REQUIRED
>
<!ELEMENT subject (#PCDATA)>

<!ELEMENT stopWatch EMPTY>
<!ATTLIST stopWatch 
	groupSize CDATA #IMPLIED
>

 =======================================================================
 ==src/conf/test-connections.xml
 =======================================================================
 <?xml version="1.0" encoding="UTF-8"?>
<manager>

  <!-- this example Messenger XML config file should work with J2EE SDK -->
  <!-- when running outside of a J2EE container                         -->

  <messenger name="topic">
    <jndi lookupName="TopicConnectionFactory" topic="true">
      <property>
        <name>com.sun.jms.internal.java.naming.factory.initial</name>
        <value>com.sun.enterprise.naming.SerialInitContextFactory</value>
      </property>          
    </jndi>
  </messenger>

  <messenger name="queue">
    <jndi lookupName="QueueConnectionFactory" topic="false">
      <property>
        <name>com.sun.jms.internal.java.naming.factory.initial</name>
        <value>com.sun.enterprise.naming.SerialInitContextFactory</value>
      </property>          
    </jndi>
  </messenger>

</manager>

 =======================================================================
 ==src/java/org/apache/commons/messagelet/BridgeMDO.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: BridgeMDO.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet;

import java.util.Enumeration;

import javax.jms.BytesMessage;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.StreamMessage;
import javax.jms.TextMessage;
import javax.servlet.ServletException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.messenger.Messenger;


/** <p><code>BridgeMDO</code> is an MDO which implements a JMS bridge
 * from one JMS destination and connection to another.
 * This allows messages to be consumed on one destination and sent to 
 * another JMS destination, using possibly different JMS providers.
 * For example this can be used to bridge from SpiritWave to MQSeries. 
 * </p>
 * <p>
 * This class is a useful base class to other possible bridge implementations
 * such as 2 phase commit bridges or bridges with some complex transformation etc.
 * This class has a number of Factory and Strategy methods to further customize
 * the acknowledgement and transaction management, the message construction, 
 * transformation and how to handle message headers etc.
 * </p>
 *
 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 * @version $Revision: 155459 $
 */
public class BridgeMDO extends MessengerMDO {

    /** Logger */
    private static final Log log = LogFactory.getLog(BridgeMDO.class);
  

 =======================================================================
 ==src/java/org/apache/commons/messagelet/ConsumerThread.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: ConsumerThread.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.messenger.Messenger;

/** 
 * <p><code>ConsumerThread</code> is a thread which will repeatedly consume JMS messages
 * using a receive() method on Messenger and then process the message.
 * This class is a good base class when implementing some kind of transactional processing of 
 * JMS messages
 *
 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 * @version $Revision: 155459 $
 */
public class ConsumerThread extends Thread {

    /** Logger */
    private static final Log log = LogFactory.getLog(ConsumerThread.class);


    private MessageConsumer consumer;
    private Messenger messenger;
    private Destination destination;
    private String selector;
    private MessageListener listener;
    private boolean shouldStop;
    
    public ConsumerThread() {
        setName("Consumer" + getName());
    }


    /**
     * Starts all the JMS connections and consumes JMS messages, 

 =======================================================================
 ==src/java/org/apache/commons/messagelet/DistributeBridgeMDO.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: DistributeBridgeMDO.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet;

import java.util.ArrayList;
import java.util.List;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.servlet.ServletException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


/** 
 * <p><code>DistributeBridgeMDO</code> is an MDO which 
 * consumes JMS from one destination and randomly distributes
 * them across a number of other destinations.
 * This MDO can be used to provide a simple load balancing mechanism
 * consuming from one destination and sending messages to a number of different
 * physical destinations.
 * </p>
 *
 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 * @version $Revision: 155459 $
 */
public class DistributeBridgeMDO extends BridgeMDO {

    /** Logger */
    private static final Log log = LogFactory.getLog(DistributeBridgeMDO.class);

    /** a List of output Destination objects */
    private List outputDestinations = new ArrayList();
      
    public DistributeBridgeMDO() {
    }
    
    // Properties
    //-------------------------------------------------------------------------

    /**
     * @return a List of output Destinations

 =======================================================================
 ==src/java/org/apache/commons/messagelet/impl/BufferedServletInputStream.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: BufferedServletInputStream.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet.impl;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.servlet.ServletInputStream;

/** 
 * <p><code>BufferedServletInputStream</code> implements
 * a ServletInputStream using an underlying InputStream.</p>
 *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
 */
public class BufferedServletInputStream extends ServletInputStream {
    
    protected static final byte[] NO_DATA = new byte[0];
    
    /** The underlying <code>InputStream</code> */
    private InputStream in;
    
    
    public BufferedServletInputStream() {
        this.in = new ByteArrayInputStream( NO_DATA );
    }
    
    public BufferedServletInputStream(InputStream in) {
        this.in = in;
    }
    
    public BufferedServletInputStream(String text) {
        in = new ByteArrayInputStream( text.getBytes() );
    }
    
    public BufferedServletInputStream(byte[] data) {
        in = new ByteArrayInputStream(data);
    }
    
    // Delegating methods from InputStream
    //-------------------------------------------------------------------------    

 =======================================================================
 ==src/java/org/apache/commons/messagelet/impl/BufferedServletOutputStream.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: BufferedServletOutputStream.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet.impl;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

import javax.servlet.ServletOutputStream;

/** 
 * <p><code>BufferedServletOutputStream</code> implements
 * a buffered ServletOutputStream in a similar way to
 * ByteArrayOutputStream represents a buffered OutputStream.</p>
 *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
 */
public class BufferedServletOutputStream extends ServletOutputStream {
    
    /** The underlying <code>ByteArrayOutputStream</code> that the output
     * is written to */
    protected ByteArrayOutputStream buffer;
    
    
    public BufferedServletOutputStream() {
        buffer = new ByteArrayOutputStream();
    }
    
    public BufferedServletOutputStream(int size) {
        buffer = new ByteArrayOutputStream(size);
    }
    
    // Delegating methods from OutputStream
    //-------------------------------------------------------------------------    
    
    public void write(byte[] b) throws  IOException {
        buffer.write(b);
    }
    
    public void write(byte[] b, int off, int len) throws  IOException {
        buffer.write(b, off, len);

 =======================================================================
 ==src/java/org/apache/commons/messagelet/impl/HttpMessageletRequestImpl.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: HttpMessageletRequestImpl.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet.impl;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.TextMessage;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.commons.messagelet.MessageletRequest;
import org.apache.commons.messenger.Messenger;

/** <p><code>HttpMessageletRequestImpl</code> represents a servlet request from
  * a JMS Message source which appears to be a HTTP request so that JSP can process
  * the request as if it were a HTTP request.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class HttpMessageletRequestImpl extends HttpServletRequestWrapper implements MessageletRequest {

    /** The Message which caused this request */
    private Message message;
    /** The stream to read the body of the current Message */
    private ServletInputStream stream;
    
    public HttpMessageletRequestImpl(HttpServletRequest request) {
        super(request);
    }

    public void setMessage(Message message) throws JMSException {
        this.message = message;
        this.stream = createInputStream();
        
        // also publish the message as a request scope attribute
        setAttribute( "message", message );
    }


 =======================================================================
 ==src/java/org/apache/commons/messagelet/impl/HttpMessageletResponseImpl.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: HttpMessageletResponseImpl.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet.impl;

import java.io.IOException;
import java.io.PrintWriter;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

import org.apache.commons.messagelet.MessageletResponse;
import org.apache.commons.messenger.Messenger;

/** <p><code>HttpMessageletResponseImpl</code> represents a servlet request from
  * a JMS Message source which appears like a HTTP request.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class HttpMessageletResponseImpl extends HttpServletResponseWrapper implements MessageletResponse {

    /** the messenger used to send replies to */
    private Messenger messenger;
    /** the reply to destination to send replies to */
    private Destination replyToDestination;
    
    /** The BufferedServletOutputStream that is given to the servlet to capture
     * the response 
     */
    private BufferedServletOutputStream stream = null;
    /** The PrintWriter that has been returned by getWriter(), if any */
    protected PrintWriter writer;
    
    public HttpMessageletResponseImpl(HttpServletResponse response) {
        super(response);
    }

    /** Resets the response, ready for a new request */
    public void reset() {

 =======================================================================
 ==src/java/org/apache/commons/messagelet/impl/MessageHttpServletDispatcher.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: MessageHttpServletDispatcher.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet.impl;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.servlet.ServletException;

import org.apache.commons.messagelet.MessageDrivenObjectSupport;
import org.apache.commons.messenger.Messenger;
import org.apache.commons.messenger.MessengerListener;

/** <p><code>MessageHttpServletDispatcher</code> dispatches JMS Messages
  * into a HttpServlet for procesing.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class MessageHttpServletDispatcher extends MessageDrivenObjectSupport implements MessengerListener {

    /**
     * The HttpServletRequest object we will pass to the servlet engine
     */
    private HttpMessageletRequestImpl request;

    /**
     * The HttpServletResponse object we will pass to the servlet engine
     */
    private HttpMessageletResponseImpl response;
    
    /** 
     * The reply to messenger
     */
    private Messenger messenger;
    
    /** Holds value of property path. */
    private String path;    

    
    public MessageHttpServletDispatcher() {
        //request.setResponse(response);
        //response.setRequest(request);        
    }

 =======================================================================
 ==src/java/org/apache/commons/messagelet/impl/MessageletRequestImpl.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: MessageletRequestImpl.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet.impl;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.TextMessage;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestWrapper;

import org.apache.commons.messagelet.MessageletRequest;
import org.apache.commons.messenger.Messenger;

/** <p><code>MessageletRequestImpl</code> represents a servlet request from
  * a JMS Message source.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class MessageletRequestImpl extends ServletRequestWrapper implements MessageletRequest {

    /** The Message which caused this request */
    private Message message;
    /** The stream to read the body of the current Message */
    private ServletInputStream stream;
    
    public MessageletRequestImpl(ServletRequest request) {
        super(request);
    }

    public void setMessage(Message message) throws JMSException {
        this.message = message;
        this.stream = createInputStream();
        
        // also publish the message as a request scope attribute
        setAttribute( "message", message );
    }

    public void setMessenger(Messenger messenger) {

 =======================================================================
 ==src/java/org/apache/commons/messagelet/impl/MessageletResponseImpl.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: MessageletResponseImpl.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet.impl;

import java.io.IOException;
import java.io.PrintWriter;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletResponse;
import javax.servlet.ServletResponseWrapper;

import org.apache.commons.messagelet.MessageletResponse;
import org.apache.commons.messenger.Messenger;

/** <p><code>MessageletResponseImpl</code> represents a servlet request from
  * a JMS Message source.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class MessageletResponseImpl extends ServletResponseWrapper implements MessageletResponse {

    /** the messenger used to send replies to */
    private Messenger messenger;
    /** the reply to destination to send replies to */
    private Destination replyToDestination;
    
    /** The BufferedServletOutputStream that is given to the servlet to capture
     * the response 
     */
    private BufferedServletOutputStream stream = null;
    /** The PrintWriter that has been returned by getWriter(), if any */
    protected PrintWriter writer;
    
    public MessageletResponseImpl(ServletResponse response) {
        super(response);
    }

    /** Resets the response, ready for a new request */
    public void reset() {

 =======================================================================
 ==src/java/org/apache/commons/messagelet/impl/MessageServletDispatcher.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: MessageServletDispatcher.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet.impl;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.servlet.ServletException;

import org.apache.commons.messagelet.MessageDrivenObjectSupport;
import org.apache.commons.messenger.Messenger;
import org.apache.commons.messenger.MessengerListener;

/** <p><code>MessageDispatcher</code> dispatches JMS Messages
  * into a Servlet engine for procesing.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class MessageServletDispatcher extends MessageDrivenObjectSupport implements MessengerListener {

    /**
     * The ServletRequest object we will pass to the servlet engine
     */
    private MessageletRequestImpl request;

    /**
     * The ServletResponse object we will pass to the servlet engine
     */
    private MessageletResponseImpl response;
    
    /** 
     * The reply to messenger
     */
    private Messenger messenger;
    
    /** Holds value of property path. */
    private String path;    

    
    public MessageServletDispatcher() {
        //request.setResponse(response);
        //response.setRequest(request);        
    }

 =======================================================================
 ==src/java/org/apache/commons/messagelet/impl/package.html
 =======================================================================
 <html>
<head>
</head>
<body>

  <p>This package contains implementation classes to support both MDO's as well
  as to be able to dispatch into a Servlet engine to be able to process 
  Messagelets.
  </p>

  <p>This package also contains the necessary Digester support classes to be able
  to read a set of subscriptions (MDOs + Messagelets) from an XML config file
  </p>

</body>
</html>

 =======================================================================
 ==src/java/org/apache/commons/messagelet/Main.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: Main.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet;

import java.util.Iterator;

import javax.jms.JMSException;
import javax.servlet.ServletContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.messagelet.model.SubscriptionDigester;
import org.apache.commons.messagelet.model.SubscriptionList;
import org.apache.commons.messenger.Messenger;
import org.apache.commons.messenger.MessengerManager;

/** 
 * <p><code>Main</code> is a simple command line program that will
 * create a number of subscriptions and consume messages using just regular 
 * MDO and MessageListener classes.
 *
 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 * @version $Revision: 155459 $
 */
public class Main {

    /** Logger */
    private static final Log log = LogFactory.getLog(Main.class);

    /** The JMS connections */    
    private MessengerManager manager;

    /** The JMS Subscriptions */
    private SubscriptionList subscriptionList;
    
    /** The URI that connections are loaded from */
    private String connectionsConfig = "Messenger.xml";
    
    /** The URI where subscriptions are loaded from */
    private String subscriptionsConfig = "subscriptions.xml";

    /** Should we use a stopwatch to output performance metrics */
    private boolean useStopWatch = false;

 =======================================================================
 ==src/java/org/apache/commons/messagelet/ManagerServlet.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: ManagerServlet.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet;

import java.net.URL;
import java.util.Iterator;

import javax.jms.JMSException;
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.apache.commons.messagelet.model.SubscriptionDigester;
import org.apache.commons.messagelet.model.SubscriptionList;
import org.apache.commons.messenger.Messenger;
import org.apache.commons.messenger.MessengerManager;

/** <p><code>ManagerServlet</code> manages the 
  * initialisation and destruction of the Messenger connections
  * and use of MessageListener beans for a given ServletContext.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class ManagerServlet extends GenericServlet {

    /** Should HTTP servlets be used or generic servlets. If true then JSP can be dispatched to easily */
    private static final boolean USE_HTTP_SERVLETS = true;

    private static final String KEY_CONNECTIONS = "connections";
    private static final String KEY_SUBSCRIPTIONS = "subscriptions";

    /** 
     * Whether exceptions occurring during subscriptions on startup should 
     * terminate the initialization
     */
    private boolean continueOnSubscribeException;
    
    public ManagerServlet() {
    }
    
    public SubscriptionManager getSubscriptionManager() {

 =======================================================================
 ==src/java/org/apache/commons/messagelet/MessageDrivenObject.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: MessageDrivenObject.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet;

import javax.jms.MessageListener;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;

/** <p><code>MessageDrivenObject</code> is a message driven bean
  * which is deployed in a Servlet engine as its application server.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public interface MessageDrivenObject extends MessageListener {

    /** 
     * Called when this message listener bean is initialized
     * by the Serlvet container.
     */
    public void init(ServletContext context) throws ServletException;

    
    /** 
     * Called when the web application (servlet context) is being 
     * destroyed, giving the bean chance to do a graceful shutdown
     */
    public void destroy();    
}


 =======================================================================
 ==src/java/org/apache/commons/messagelet/MessageDrivenObjectSupport.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: MessageDrivenObjectSupport.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/** <p><code>MessageDrivenObjectSupport</code> is an abstract base
  * class for implementing your own MessageDrivenObject instance
  * with some useful implementation level methods.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public abstract class MessageDrivenObjectSupport implements MessageDrivenObject {

    
    /** The Log to which logging calls will be made. */
    private Log log = LogFactory.getLog( getClass() );
    
    /**
     * The ServletContext with which this dispatcher is associated.
     */
    private ServletContext context;


    
    public MessageDrivenObjectSupport() {
    }

    public ServletContext getServletContext() {
        return context;
    }
    
    /** 
     * This method allows the init() method to be overriden without having to 
     * call the super.init( ServletContext ) method first. This is similar
     * to the init() method in {@link javax.servlet.GenericServlet}.
     */
    public void init() throws ServletException {

 =======================================================================
 ==src/java/org/apache/commons/messagelet/Messagelet.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: Messagelet.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet;

import java.io.IOException;

import javax.jms.JMSException;
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/** <p><code>Messengerlet</code> the base class for a servlet which processes 
  * JMS messages via a MessageletRequest and MessageletResponse.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public abstract class Messagelet extends GenericServlet {

    public abstract void service( MessageletRequest request, MessageletResponse response ) 
        throws IOException, JMSException, ServletException;
    
    
    public void service( ServletRequest req, ServletResponse res ) throws ServletException, IOException {
        MessageletRequest request;
        MessageletResponse response;
        
    try {
        request = (MessageletRequest) req;
        response = (MessageletResponse) res;
            
    } 
        catch (ClassCastException e) {
        throw new ServletException("non-Message request or response");
    }
        
        try {
            service(request, response);
        }
        catch (JMSException e) {
            throw new ServletException(e);
        }

 =======================================================================
 ==src/java/org/apache/commons/messagelet/MessageletRequest.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: MessageletRequest.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet;

import javax.jms.Message;
import javax.servlet.ServletRequest;


/** <p><code>MessageletRequest</code> represents a servlet request that
  * resulted from a JMS Message being received.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public interface MessageletRequest extends ServletRequest {

    /** @return the Message which originated this request */
    public Message getMessage();
    
}


 =======================================================================
 ==src/java/org/apache/commons/messagelet/MessageletResponse.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: MessageletResponse.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.servlet.ServletResponse;

import org.apache.commons.messenger.Messenger;


/** <p><code>MessageletResponse</code> represents a servlet response from
  * a JMS Message.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public interface MessageletResponse extends ServletResponse {

    /** Sends a reply to the original message */
    public void sendReply(Message reply) throws JMSException;

    
    /** Returns the Messenger that should be used for sending replies to this incoming request */
    public Messenger getReplyMessenger() throws JMSException;
    
    /** Returns the destination that reply to messages are sent */
    public Destination getReplyToDestination() throws JMSException;
}


 =======================================================================
 ==src/java/org/apache/commons/messagelet/MessengerMDO.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: MessengerMDO.java 155459 2005-02-26 13:24:44Z dirkv $
 */

package org.apache.commons.messagelet;

import javax.jms.JMSException;

import org.apache.commons.messenger.Messenger;
import org.apache.commons.messenger.MessengerListener;
import org.apache.commons.messenger.MessengerManager;

/** <p><code>MessengerMDO</code> is an abstract base
  * class for Messenger based MDO implementations. 
  * It provides access to the Messenger that was used to receive messages
  * so that responses can be sent to the originating Messenger object
  * and so reuse the same JMS Session and Connection for responses.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */

public abstract class MessengerMDO
    extends MessageDrivenObjectSupport
    implements MessengerListener {

    /** the Messenger with which this MDO is associated */
    private Messenger messenger;

    /** the MessengerManager which manages the Messenger */
    private MessengerManager messengerManager;

    public MessengerMDO() {

    }

    /** 
     * Provides access to the current Messenger which was used to generate the current
     * Message. This allows replies to be sent directly to the originating Messenger
     * (and so the same JMS Session and Connection) which received the message
     */
    public Messenger getMessenger() {
        return messenger;
    }

 =======================================================================
 ==src/java/org/apache/commons/messagelet/model/package.html
 =======================================================================
 <html>
<head>
</head>
<body>

  <p>
  	This package represents the subscription model of a Messagelet engine.
  </p>

</body>
</html>

 =======================================================================
 ==src/java/org/apache/commons/messagelet/model/Subscription.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: Subscription.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet.model;

import javax.jms.MessageListener;

import org.apache.commons.messagelet.ConsumerThread;

/** <p><code>SubscriptionList</code> a bean used by the digester to 
  * create a list of JMS subscriptions.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class Subscription {

    /** Holds value of property connection. */
    private String connection;
    
    /** Holds value of property subject. */
    private String subject;
    
    /** Holds value of property selector. */
    private String selector;
    
    /** Holds value of property messageListener. */
    private MessageListener messageListener;
    
    /** Holds value of property servlet. */
    private String servlet;

    /** should a ConsumerThread be used to consume these messages */
    private ConsumerThread consumerThread;    
    
    public Subscription() {
    }        
        
    /** Getter for property connection.
     * @return Value of property connection.
     */
    public String getConnection() {
        return connection;
    }

 =======================================================================
 ==src/java/org/apache/commons/messagelet/model/SubscriptionDigester.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: SubscriptionDigester.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet.model;

import org.apache.commons.digester.Digester;

/** <p><code>MessengerDigester</code> is a digester of Messenger objects so 
  * that JMS Messengers can be created from an XML config file.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class SubscriptionDigester extends Digester {

    // default implementation classes
    private String subscriptionsClass = "org.apache.commons.messagelet.model.SubscriptionList";
    private String subscriptionClass = "org.apache.commons.messagelet.model.Subscription";
    private String listenerClass = "org.apache.commons.messagelet.impl.MessageServletDispatcher";
    private String bridgeClass = "org.apache.commons.messagelet.BridgeMDO";
    private String distributeBridgeClass = "org.apache.commons.messagelet.DistributeBridgeMDO";
    private String stopWatchClass = "org.apache.commons.messenger.tool.StopWatchMessageListener";
    private String consumerThreadClass = "org.apache.commons.messagelet.ConsumerThread";
    
    public SubscriptionDigester() {
    }
    
    // Implementation methods
    //-------------------------------------------------------------------------    

    /** Configure the parsing rules that will be used to process 
     * the cache config file
     */
    protected void configure() {
        if (configured) {
            return;
        }
        else {
            configured = true;
        }
        
        String path = "subscriptions";
        
        addObjectCreate( path, subscriptionsClass, "className" );

 =======================================================================
 ==src/java/org/apache/commons/messagelet/model/SubscriptionList.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: SubscriptionList.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet.model;

import java.util.ArrayList;
import java.util.List;

/** <p><code>SubscriptionList</code> a bean used by the digester to 
  * create a list of JMS subscriptions.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class SubscriptionList {

    private List subscriptions = new ArrayList();
    
    public SubscriptionList() {
    }
    
/*    
    public void subscribe(JmsConnector connector) throws JMSException {
        for ( Iterator iter = subscriptions.iterator(); iter.hasNext(); ) {
            Subscription subscription = (Subscription) iter.next();
            subscription.subscribe( connector );
        }
    }
*/
    
    public void addSubscription(Subscription subscription) {
        subscriptions.add( subscription );
    }
    
    public void removeSubscription(Subscription subscription) {
        subscriptions.remove( subscription );
    }
    
    public List getSubscriptions() {
        return subscriptions;
    }
    
    public void setSubscriptions(List subscriptions) {
        this.subscriptions = subscriptions;

 =======================================================================
 ==src/java/org/apache/commons/messagelet/package.html
 =======================================================================
 <html>
<head>
</head>
<body>

  <p>This package provides the mechansim to deploy MessageListener beans in a 
  servlet application server which are intialized and destroyed with a web-application
  as well as introducing MessageDrivenObjects which are MessageListeners which
  receive servlet-style lifecycle events and Messagelets which are servlets that 
  process Messages.
  </p>

  <p>So this package introduces the interface MessageDrivenObject which is a 
    servlet equivalent of a Message Driven EJB which is part of the EJB 2.0 spec.
  </p>

  <p>In addition this package provides support for Messagelets which are servlets used
  to process JMS messages. They reuse the same message listener beans infrastructure but
  dispatch JMS Messages to a servlet for further processing.
  </p>

  <p>2 new interfaces are introduced, {@link org.apache.commons.messagelet.MessageletRequest}
  which extends {@link javax.servlet.ServletRequest} and 
  {@link org.apache.commons.messagelet.MessageletResponse}
  which extends {@link javax.servlet.ServletResponse} which adds some extra JMS based semantics
  such as access to the Messenger which was used to receive the JMS Message..</p>
  
</body>
</html>

 =======================================================================
 ==src/java/org/apache/commons/messagelet/SubscriptionManager.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: SubscriptionManager.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet;

import java.util.Iterator;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageListener;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.messagelet.model.Subscription;
import org.apache.commons.messagelet.model.SubscriptionList;
import org.apache.commons.messenger.Messenger;
import org.apache.commons.messenger.MessengerManager;
import org.apache.commons.messenger.tool.StopWatchMessageListener;

/** 
 * <p><code>SubscriptionManager</code> is a simple command line program that will
 * create a number of subscriptions and consume messages using just regular 
 * MDO and MessageListener classes.
 *
 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 * @version $Revision: 155459 $
 */
public class SubscriptionManager {

    /** Logger */
    private static final Log log = LogFactory.getLog(SubscriptionManager.class);

    /** The JMS connections */    
    private MessengerManager manager;

    /** The JMS Subscriptions */
    private SubscriptionList subscriptionList;

    /** The context passed into MDOs */
    private ServletContext servletContext;
        
    /** Should we use a stopwatch to output performance metrics */

 =======================================================================
 ==src/java/org/apache/commons/messagelet/XAConsumerThread.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: XAConsumerThread.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messagelet;

import javax.jms.MessageListener;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.xa.XAResource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.messenger.Messenger;
import org.apache.commons.messenger.XACapable;
import org.apache.commons.messenger.XACapableAdapter;

/** 
 * <p><code>XAConsumerThread</code> is a thread which will perform XA processing
 * of messages
 *
 * @author damon.hamacha
 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 * @version $Revision: 155459 $
 */
public class XAConsumerThread extends ConsumerThread {

	/** Logger */
	private static final Log log = LogFactory.getLog(XAConsumerThread.class);

	private TransactionManager transctionManager;
	private Transaction transaction;

	public XAConsumerThread() {
		setName("XAConsumer" + getName());
	}

	/**
	 * @return the TransactionManager to be used
	 * @throws SystemException
	 */
	public TransactionManager getTransactionManager() throws SystemException {
		if (transctionManager == null) {
			transctionManager = createTransactionManager();

 =======================================================================
 ==src/java/org/apache/commons/messenger/DefaultServerSession.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: DefaultServerSession.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;

import javax.jms.JMSException;
import javax.jms.ServerSession;
import javax.jms.Session;


/** <p><code>DefaultServerSession</code> is a default implementation of
  * the JMS ServerSession interface.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class DefaultServerSession extends Thread implements ServerSession {

    /** The JMS Session on which this ServerSession is based */
    private Session session;
    /** Indicates whether the session has been started */
    private boolean started = false;
    
    public DefaultServerSession(Session session) throws JMSException {
        this.session = session;
    }

    /**
     * Return the ServerSession's Session. This must be a Session
     * created by the same Connection which will be dispatching messages
     * to it. The provider will assign one or more messages to the Session
     * and then call start on the ServerSession.
     *
     * @return the server session's session.
     *
     * @exception JMSException if a JMS error occurs.
     */
    public Session getSession() throws JMSException {
        return session;
    }

    /** 
     * Cause the session's run method to be called to process messages
     * that were just assigned to it.

 =======================================================================
 ==src/java/org/apache/commons/messenger/DefaultServerSessionPool.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: DefaultServerSessionPool.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;

import java.util.LinkedList;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ServerSession;
import javax.jms.ServerSessionPool;
import javax.jms.Session;


/** <p><code>DefaultServerSessionPool</code> is a default implementation of
  * the JMS ServerSessionPool interface.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class DefaultServerSessionPool implements ServerSessionPool {

    /** the list of ServerSession objects */
    private LinkedList list = new LinkedList();
    /** the factory used to create new Sessions */
    private SessionFactory sessionFactory;
    /** The MessageListener which are fired by new JMS Sessions */
    private MessageListener listener;    
    /** maximum blocking time, just in case a notify goes walkies */
    private long timeout = 5000;
    
    public DefaultServerSessionPool() {
    }
    
    public DefaultServerSessionPool(SessionFactory sessionFactory, MessageListener listener, int numberOfServerSessions) throws JMSException {
        this.sessionFactory = sessionFactory;
        this.listener = listener;
        
        for ( int i = 0; i < numberOfServerSessions; i++ ) {
            list.add( createServerSession() );
        }
    }
    

 =======================================================================
 ==src/java/org/apache/commons/messenger/InitMessengerServlet.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 *
 * $Id: InitMessengerServlet.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;

import java.net.URL;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;


/** <p><code>InitMessengerServlet</code> is a simple servlet that
 * will initialize the MessengerManager from a URL specified in the
 * web.xml deployment descriptor.</p>
 *
 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 * @version $Revision: 155459 $
 */
public class InitMessengerServlet extends HttpServlet {

    private static boolean initialized = false;
    
    public InitMessengerServlet() {
    }
    
    public void init() throws ServletException {
        if ( ! initialized ) {
            initialized = true;
            
            getServletContext().log( "About to initialize MessengerManager" );
            
            String config = getRequiredInitParmeter( "config", "The URL of the Messenger XML deployment document" );
            try {            
                URL url = getServletContext().getResource( config );
                MessengerManager.configure( url.toString() );
            }
            catch (Exception e) {
                throw new ServletException( "Failed to initialise MessengerManager from config: " + config + ". Reason : " + e, e );
            }
        }
    }
    
    // Implementation methods
    //-------------------------------------------------------------------------        

 =======================================================================
 ==src/java/org/apache/commons/messenger/JNDISessionFactory.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 *
 * $Id: JNDISessionFactory.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.Session;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


/** <p><code>JNDISessionFactory</code> is a Factory of JMS Session objects
  * which looks up the ConnectionFactory object from JNDI.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class JNDISessionFactory extends SessionFactory {

    /** Logger */
    private static final Log log = LogFactory.getLog( JNDISessionFactory.class );
    
    /** the initial JNDI context used to lookup ConnectionFactory objects */
    public Context context;

    /** the name used to lookup the ConnectionFactory */
    private String lookupName = "TopicConnectionFactory";


    // Properties
    //-------------------------------------------------------------------------

    /** The JNDI Name of the ConnectionFactory */
    public String getLookupName() {

 =======================================================================
 ==src/java/org/apache/commons/messenger/ListenerKey.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: ListenerKey.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;

import javax.jms.Destination;
import javax.jms.MessageListener;


/** <p><code>ListenerKey</code> is an implementation class allowing a Destination, 
  * MessageListener and an optional selector to be used as a key to a Map so that 
  * a single subscription can be easily associated with a MessageConsumer.
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
class ListenerKey {

    private Destination destination;
    private MessageListener messageListener;
    private String selector;
    private int hashCode;
    
    public ListenerKey(Destination destination, MessageListener messageListener) {
        this( destination, messageListener, null );
    }
    
    public ListenerKey(Destination destination, MessageListener messageListener, String selector) {
        this.destination = destination;
        this.messageListener = messageListener;
        this.selector = selector;
        this.hashCode = destination.hashCode() ^ messageListener.hashCode();
        if ( selector != null ) {
            this.hashCode ^= selector.hashCode();
        }
    }
    
    public int hashCode() {
        return hashCode;
    }
    
    public boolean equals(Object that) {
        if ( this == that ) {
            return true;

 =======================================================================
 ==src/java/org/apache/commons/messenger/Lock.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: Lock.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;

import javax.jms.JMSException;

/** <p><code>Lock</code> is a simple lock.
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class Lock {

    private Thread owner;
    private int count;

    /**
     * Acquires the lock, blocking until the lock can be acquired
     * @throws InterruptedException
     */
    public void acquire() {
        Thread caller = Thread.currentThread();
        synchronized (this) {
            if (caller == owner) {
                count++;
            }
            else {
                while (owner != null) {
                    try {
                        wait();
                    }
                    catch (InterruptedException ex) {
                        // ignore
                    }
                }
                owner = caller;
                count = 1;
                
//                System.out.println("Lock: " + this + " acquired by + "+ caller );
//                new Exception().printStackTrace();
            }
        }
    }

 =======================================================================
 ==src/java/org/apache/commons/messenger/MessengerDigester.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: MessengerDigester.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;

import org.apache.commons.digester.Digester;

/** <p><code>MessengerDigester</code> is a digester of Messenger objects so 
  * that JMS Messengers can be created from an XML config file.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class MessengerDigester extends Digester {

    // default implementation classes
    private String messengerManagerClass = "org.apache.commons.messenger.MessengerManager";
    private String messengerClass = "org.apache.commons.messenger.DefaultMessenger";
    private String xaMessengerClass = "org.apache.commons.messenger.XAMessenger";
    private String sessionFactory = "org.apache.commons.messenger.SessionFactory";
    private String connectionFactory = "org.apache.commons.messenger.DummyConnectionFactory";
    private String jndiSessionFactory = "org.apache.commons.messenger.JNDISessionFactory";

    
    public MessengerDigester() {
    }
    
    // Implementation methods
    //-------------------------------------------------------------------------    

    /** Configure the parsing rules that will be used to process 
     * the cache config file
     */
    protected void configure() {
        if (configured) {
            return;
        }
        else {
            configured = true;
        }
        
        addObjectCreate( "manager", messengerManagerClass, "className" );
        addSetProperties( "manager" );


 =======================================================================
 ==src/java/org/apache/commons/messenger/MessengerListener.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: MessengerListener.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;

import javax.jms.MessageListener;

/** <p><code>MessengerListener</code> is a JMS MessageListener 
  * which is associated with a Messenger instance
  * so that it can send replies or send other messages using 
  * the same JMS connection to which its listening.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public interface MessengerListener extends MessageListener {

    /** 
     * Called whenever this MessageListener is added to a 
     * Messenger via the addListener() method to associate
     * this MessageListener with a Messenger instance..
     */
    public void setMessenger(Messenger messager);

}


 =======================================================================
 ==src/java/org/apache/commons/messenger/MessengerListenerSupport.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: MessengerListenerSupport.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;


/** 
 * <p><code>MessengerListenerSupport</code> is an abstract base
 * class for a MessengerListener objects which is useful for
 * implementation inheritence.
 * This object has a messenger property which can be used to send replies
 * to incoming messages or to send other messages using the same Messenger
 * (JMS connection).</p>
 *
 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 * @version $Revision: 155459 $
 */
public abstract class MessengerListenerSupport implements MessengerListener {

    private Messenger messenger;
    
    /** 
     * Called whenever this MessageListener is added to a 
     * Messenger via the addListener() method to associate
     * this MessageListener with a Messenger instance..
     */
    public void setMessenger(Messenger messenger) {
        this.messenger = messenger;
    }
    
    /** 
     * Returns the Messenger that this MessageListener is associated with
     * making it easy to send replies or other messages using
     * the same Messenger instance that this object is listening to.
     */
    public Messenger getMessenger() {
        return messenger;
    }
}


 =======================================================================
 ==src/java/org/apache/commons/messenger/MessengerManager.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: MessengerManager.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;

import java.net.URL;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

import javax.jms.JMSException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/** <p><code>MessengerManager</code> is a manager of {@link Messenger} instances.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class MessengerManager {
    
    /** Logger */
    private static final Log log = LogFactory.getLog( MessengerManager.class );
    
    /** The singleton MessengerManager used by the static get() method */
    private static MessengerManager singleton;
    
    /** A map where the key = name and value = messenger */
    private Map messengers = new Hashtable();

    
    public MessengerManager() {
    }
    
    
    /** Uses the default configuration mechanism this method will return 
      * the Messenger for the given name. The Messenger.xml file will be searched
      * on the classpath  
      */
    public static Messenger get( String name ) throws JMSException {
        return getInstance().getMessenger( name );
    }
    

 =======================================================================
 ==src/java/org/apache/commons/messenger/MessengerServlet.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 *
 * $Id: MessengerServlet.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.TextMessage;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/** <p><code>MessengerServlet</code> is a simple servlet that
 * dispatches the current HTTP GET to a JMS connection to a receiveNoWait() call
 * or a HTTP POST to send() message.</p>
 *
 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 * @version $Revision: 155459 $
 */
public class MessengerServlet extends HttpServlet {

    private static final String KEY_MESSENGER = "messenger";
    private static final String KEY_DESTINATION= "destination";
    
    /** Holds value of property messenger. */
    private Messenger messenger;
    
    /** Holds value of property destination. */
    private Destination destination;
    
    public MessengerServlet() {
    }
    
    public void init() throws ServletException {
        try {
            String name = getRequiredInitParmeter( KEY_MESSENGER, "Name of the Messenger to use for this servlet" );
            String subject = getRequiredInitParmeter( KEY_DESTINATION, "Destination to be used for this servlet" );

 =======================================================================
 ==src/java/org/apache/commons/messenger/MessengerSession.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: MessengerSession.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;

import java.util.HashMap;
import java.util.Map;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.QueueRequestor;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.Topic;
import javax.jms.TopicRequestor;
import javax.jms.TopicSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/** <p><code>MessengerSession</code> represents all the local information for a single thread.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class MessengerSession {

    private static final Log log = LogFactory.getLog(MessengerSupport.class);

    /** @todo should have ack mode for sending and consuming */


    /** the JMS Session for this thread */
    private Session session;

    /** the JMS Listener (async subscription) Session for this thread */
    private Session listenerSession;

    /** the MessageConsumer for this threads reply to destination */
    private MessageConsumer replyToConsumer;


 =======================================================================
 ==src/java/org/apache/commons/messenger/MessengerSupport.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 *
 * $Id: MessengerSupport.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.ConnectionConsumer;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueBrowser;
import javax.jms.QueueConnection;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.ServerSessionPool;
import javax.jms.Session;
import javax.jms.StreamMessage;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/** <p><code>MessengerSupport</code> is an abstract base class which implements
  * most of the functionality of Messenger. Derivations need to specify the
  * connection and session creation and the pooling strategy.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>

 =======================================================================
 ==src/java/org/apache/commons/messenger/package.html
 =======================================================================
 <html>
<head>
</head>
<body>

  <p>The main Messenger interface, a simple facade for working with JMS, together with all 
  the default implementation classes and additional factory classes.</p>
  
</body>
</html>

 =======================================================================
 ==src/java/org/apache/commons/messenger/SessionFactory.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: SessionFactory.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;

import java.util.Properties;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageListener;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.ServerSessionPool;
import javax.jms.Session;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/** <p><code>SessionFactory</code> is a Factory of JMS Session objects.
  * It can be configured with a JMS Connection object to use or can use 
  * a JMS ConnectionFactory instance to create the JMS Connection lazily</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class SessionFactory {

    /** Logger */
    private static final Log log = LogFactory.getLog(SessionFactory.class);

    /** The JMS connection used to create JMS sessions */
    private Connection connection;

    /** The JMS ConnectionFactory used to create JMS Connection instances */
    private ConnectionFactory connectionFactory;

    /** JMS acknowlege mode used on each session */
    private int acknowlegeMode = Session.AUTO_ACKNOWLEDGE;

    /** whether JMS sessions should be transacted */
    private boolean transacted;

 =======================================================================
 ==src/java/org/apache/commons/messenger/task/ConsumerTask.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: ConsumerTask.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger.task;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.TextMessage;

import org.apache.commons.messenger.Messenger;
import org.apache.commons.messenger.MessengerManager;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;

/** 
 * <p><code>ConsumerTask</code> is an Ant task which will 
 * publish all of the given text files as a JMS Text Message
 * using a given JMS Connection (Messenger) and a Destination
 *
 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 * @version $Revision: 155459 $
 */
public class ConsumerTask extends Task {

    private Messenger messenger;
    private String messengerName;
    private Destination destination;
    private String subject;
    private MessengerManager messengerManager;    

    /** the number of messages to receive */
    private int count;

    /** the output directory */
    private File dir = new File(".");    
    
    // Properties
    //-------------------------------------------------------------------------

 =======================================================================
 ==src/java/org/apache/commons/messenger/task/package.html
 =======================================================================
 <html>
<head>
</head>
<body>

  <p>A collection of Ant tasks for working with JMS.</p>
  
</body>
</html>

 =======================================================================
 ==src/java/org/apache/commons/messenger/task/ProducerTask.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: ProducerTask.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger.task;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.Iterator;
import java.util.Vector;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.TextMessage;

import org.apache.commons.messenger.Messenger;
import org.apache.commons.messenger.MessengerManager;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.FileSet;

/** 
 * <p><code>ProducerTask</code> is an Ant task which will 
 * publish all of the given text files as a JMS Text Message
 * using a given JMS Connection (Messenger) and a Destination
 *
 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 * @version $Revision: 155459 $
 */
public class ProducerTask extends Task {

    private Vector filesets = new Vector();
    private Messenger messenger;
    private String messengerName;
    private Destination destination;
    private String subject;
    private MessengerManager messengerManager;   
    private File file; 

    /** Holds value of property sleep. */
    private long sleep;

 =======================================================================
 ==src/java/org/apache/commons/messenger/tool/Caller.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: Caller.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger.tool;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.TextMessage;

import org.apache.commons.messenger.MessengerManager;

/** <p><code>Caller</code> is a sample program that 
  * sends a message to a destination and waits for a response.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class Caller extends Producer {

    public static void main(String[] args) {
        try {
            Caller client = new Caller();
            client.run( args );
        }
        catch (JMSException e) {
            System.out.println( "Caught: " + e );
            Exception linked = e.getLinkedException();
            if ( linked != null ) {
                System.out.println( "Underlying exception: " + linked );
                linked.printStackTrace();
            }
            else {
                e.printStackTrace();
            }
        }

 =======================================================================
 ==src/java/org/apache/commons/messenger/tool/Consumer.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: Consumer.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger.tool;

import java.io.FileWriter;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.TextMessage;

import org.apache.commons.messenger.Messenger;
import org.apache.commons.messenger.MessengerManager;

/** <p><code>Consumer</code> is a sample program that 
  * consumes a single message and either writes it to 
  * either stanard output or a named file.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class Consumer {

    private Messenger messenger;

    public static void main(String[] args) {
        try {
            Consumer client = new Consumer();
            client.run( args );
        }
        catch (JMSException e) {
            System.out.println( "Caught: " + e );
            Exception linked = e.getLinkedException();
            if ( linked != null ) {
                System.out.println( "Underlying exception: " + linked );
                linked.printStackTrace();
            }
            else {
                e.printStackTrace();
            }

 =======================================================================
 ==src/java/org/apache/commons/messenger/tool/package.html
 =======================================================================
 <html>
<head>
</head>
<body>

  <p>A collection of tools for working with Messenger.</p>
  
</body>
</html>

 =======================================================================
 ==src/java/org/apache/commons/messenger/tool/Producer.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: Producer.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger.tool;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.TextMessage;

import org.apache.commons.messenger.Messenger;
import org.apache.commons.messenger.MessengerManager;

/** <p><code>Producer</code> is a sample program that 
  * creates messages and sends them to a given destination which
  * could either be a queue or a topc.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class Producer {

    protected Messenger messenger;

    public static void main(String[] args) {
        try {
            Producer client = new Producer();
            client.run( args );
        }
        catch (JMSException e) {
            System.out.println( "Caught: " + e );
            Exception linked = e.getLinkedException();
            if ( linked != null ) {
                System.out.println( "Underlying exception: " + linked );
                linked.printStackTrace();
            }
            else {
                e.printStackTrace();

 =======================================================================
 ==src/java/org/apache/commons/messenger/tool/StopWatchMessageListener.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: StopWatchMessageListener.java 155459 2005-02-26 13:24:44Z dirkv $
 */

package org.apache.commons.messenger.tool;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * A simple StopWatch Message Listener for wrapping another MessageListener
 * to determine its performance.
 *
 * @author  James Strachan
 */
public class StopWatchMessageListener implements MessageListener {

    /** The Log to which logging calls will be made. */
    private Log log = LogFactory.getLog( StopWatchMessageListener.class );
    
    /** the underlying MessageListener */
    private MessageListener messageListener;

    /** the number of messages processed */
    private int count;
        
    /** the message group size */
    private int groupSize = 1000;
        
    /** the time that the batch started processing */
    private long startTime;
    
    public StopWatchMessageListener() {
    }
    
    public StopWatchMessageListener(MessageListener messageListener) {
        this.messageListener = messageListener;
    }
    

 =======================================================================
 ==src/java/org/apache/commons/messenger/XACapable.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: XACapable.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;

import javax.transaction.Transaction;

/** 
 * <p><code>XACapable</code> is an object (typically a MessageListener in this context)
 * which can be part of an XA transaction.
 * This just means that this object has a way of providing XA resources.</p>
 *
 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 * @version $Revision: 155459 $
 */
public interface XACapable {

	/**
	 * This method is called to enlist any XA resources the given object 
	 * has to be part of the XA transaction.
	 * 
	 * @param transaction the transaction to enlist to 
	 */	
	public void enlistResources(Transaction transaction) throws Exception;

	/**
	 * This method is called to delist any XA resources the given object 
	 * has previously enlisted to this XA transaction.
	 * 
	 * @param transaction the transaction to delist resources from
	 * @param flag is the flag used by JTA when delisting resources.
	 * It is either XAResource.TMSUCCESS, XAResource.TMSUSPEND, or XAResource.TMFAIL
	 */	
	public void delistResources(Transaction transaction, int flag) throws Exception;
}


 =======================================================================
 ==src/java/org/apache/commons/messenger/XACapableAdapter.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: XACapableAdapter.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;

import javax.jms.Session;
import javax.jms.XASession;
import javax.transaction.Transaction;
import javax.transaction.xa.XAResource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/** 
 * <p><code>XACapableAdapter</code> is an adapter that implements
 * XACapable for a given Messenger 
 * </p>
 *
 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 * @version $Revision: 155459 $
 */
public class XACapableAdapter implements XACapable {

    /** Logger */
    private static final Log log = LogFactory.getLog(XACapableAdapter.class);
    
	private Messenger messenger;
	
	public XACapableAdapter(Messenger messenger) {
		this.messenger = messenger;
	}
    
    // XACapable interface
    //-------------------------------------------------------------------------
        
	public void enlistResources(Transaction transaction) throws Exception {
		XAResource resource = getXAResource();
		if (resource != null) {
			transaction.enlistResource(resource);
		}
	}

	public void delistResources(Transaction transaction, int flag) throws Exception {
		XAResource resource = getXAResource();

 =======================================================================
 ==src/java/org/apache/commons/messenger/XAMessenger.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 *
 * $Id: XAMessenger.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;

import javax.jms.Session;
import javax.jms.XASession;
import javax.transaction.Transaction;
import javax.transaction.xa.XAResource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/** <p><code>XAMessenger</code> is a default implementation of
 * Messenger which can also support XA transactions by enlisting and delisting
 * XAResources.
 * This is implemented as a seperate Messenger implementation to avoid the core
 * Messenger having a dependency on JTA.
 * .</p>
 *
 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 * @version $Revision: 155459 $
 */
public class XAMessenger extends DefaultMessenger implements XACapable {
    
    /** Logger */
    private static final Log log = LogFactory.getLog(XAMessenger.class);
    
    public XAMessenger() {
    }
    
    // XACapable interface
    //-------------------------------------------------------------------------
        
	public void enlistResources(Transaction transaction) throws Exception {
		XAResource resource = getXAResource();
		if (resource != null) {
			transaction.enlistResource(resource);
		}
	}

	public void delistResources(Transaction transaction, int flag) throws Exception {
		XAResource resource = getXAResource();
		if (resource != null) {

 =======================================================================
 ==src/test/org/apache/commons/messenger/LockTest.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: LockTest.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;

import javax.jms.JMSException;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import junit.textui.TestRunner;

/** Test harness for the Lock class
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class LockTest extends TestCase {

    public static Test suite() {
        return new TestSuite(LockTest.class);
    }

    public static void main(String[] args) {
        TestRunner.run(suite());
    }

    public LockTest(String testName) {
        super(testName);
    }

    public void testNormalLockOperation() throws Exception {
        Lock lock = new Lock();
		assertFalse("should not have the lock yet", lock.hasLock());
		
        lock.acquire();
        assertTrue("have lock", lock.hasLock());

        lock.release();
        assertFalse("have released the lock", lock.hasLock());

        try {
            lock.release();
            fail("Should have thrown an exception");

 =======================================================================
 ==src/test/org/apache/commons/messenger/LoggingMDO.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: LoggingMDO.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;

import javax.jms.Message;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.messagelet.MessengerMDO;

/** 
 * <p><code>LoggingMDO</code> is a simple MDO which
 * logs the fact that it consumed a message.</p>
 *
 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 * @version $Revision: 155459 $
 */
public class LoggingMDO extends MessengerMDO {

    /** Logger to which logging messages will go */
    private static final Log log = LogFactory.getLog(LoggingMDO.class);
    
    public void onMessage(Message message) {
        log.info( "Received message: " + message );
        
        System.out.println( "Received message: " + message );
    }
}

 =======================================================================
 ==src/test/org/apache/commons/messenger/TestAll.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: TestAll.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/** Entry point for all JUnit tests.
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
 */
public class TestAll extends TestCase {
    public TestAll(String testName) {
        super(testName);
    }

    public static Test suite() {
        TestSuite suite = new TestSuite();
        suite.addTest(TestMessenger.suite());
        return suite;
    }

    public static void main(String args[]) {
        String[] testCaseName = { TestAll.class.getName() };
        junit.textui.TestRunner.main(testCaseName);
    }
}

 =======================================================================
 ==src/test/org/apache/commons/messenger/TestMessenger.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: TestMessenger.java 155459 2005-02-26 13:24:44Z dirkv $
 */
package org.apache.commons.messenger;

import java.util.ArrayList;
import java.util.List;

import javax.jms.Destination;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import junit.textui.TestRunner;

/** Test harness for Messenger
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class TestMessenger extends TestCase {

    boolean useAsyncStuff = true;

    protected static boolean verbose = true;
    protected List failures = new ArrayList();

    protected String topicName = getClass().getName() + ".Topic";
    protected String queueName = getClass().getName() + ".Queue";

    protected String topicMessageText = "This is the text of a topic message";
    protected String queueMessageText = "This is the text of a queue message";

    protected long waitTime = 2 * 1000;

    protected volatile boolean receivedQueueMessage;
    protected volatile boolean receivedTopicMessage;

    public static Test suite() {
        return new TestSuite(TestMessenger.class);
    }

 =======================================================================
 ==src/webapp/conf/subscriptions.xml
 =======================================================================
 <?xml version="1.0" encoding="UTF-8"?>
<subscriptions>
  <subscription connection="queue" subject="jms/Queue">
    <listener className="EchoMDO"/>
  </subscription>
  
  <subscription connection="queue" subject="echo.servlet">
    <servlet>/jms/echoServlet</servlet>
  </subscription>
  
  <subscription connection="queue" subject="echo.messagelet">
    <servlet>/jms/echoMessagelet</servlet>
  </subscription>
  
  <subscription connection="queue" subject="echo.jsp">
    <servlet>/jms/time.jsp?a=1&amp;b=2</servlet>
  </subscription>
  
  <subscription connection="queue" subject="foo.input">

    <bridge outputConnection="queue" outputSubject="foo.output"/>

  </subscription>

  
</subscriptions>

 =======================================================================
 ==src/webapp/conf/web.xml
 =======================================================================
 <?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE web-app 
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 
    "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

  <display-name>Messenger example web app</display-name>

  <description>This web application demonstrates the use of Messenger, MessageDrivenObjects and Messagelets</description>

  <servlet>
    <servlet-name>managerServlet</servlet-name>
    <servlet-class>org.apache.commons.messagelet.ManagerServlet</servlet-class>
    <init-param>
      <param-name>connections</param-name>
      <param-value>/WEB-INF/Messenger.xml</param-value>
    </init-param> 
    <init-param>
      <param-name>subscriptions</param-name>
      <param-value>/WEB-INF/subscriptions.xml</param-value>
    </init-param> 
    <load-on-startup>1</load-on-startup> 
  </servlet>

  <servlet>
    <servlet-name>echoMessagelet</servlet-name>
    <servlet-class>EchoMessagelet</servlet-class>
    <load-on-startup>1</load-on-startup> 
  </servlet>

  <servlet>
    <servlet-name>echoServlet</servlet-name>
    <servlet-class>EchoServlet</servlet-class>
    <load-on-startup>1</load-on-startup> 
  </servlet>


  <servlet-mapping>
    <servlet-name>echoMessagelet</servlet-name>
    <url-pattern>/jms/echoMessagelet</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>echoServlet</servlet-name>
    <url-pattern>/jms/echoServlet</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>

 =======================================================================
 ==src/webapp/jms/time.jsp
 =======================================================================
 <echo>
  <time><%= new java.util.Date() %></time>
  <a><%= request.getParameter( "a" )%></a>
  <b><%= request.getParameter( "b" )%></b>

  <message><%= request.getAttribute( "message" )%></message>
</echo>

 =======================================================================
 ==src/webapp/src/EchoMDO.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: EchoMDO.java 155459 2005-02-26 13:24:44Z dirkv $
 */

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import org.apache.commons.messagelet.MessengerMDO;
import org.apache.commons.messenger.Messenger;

/** <p><code>EchoMDO</code> is a simple echo MDO which
  * replies with a piece of text.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class EchoMDO extends MessengerMDO {
    
    public void onMessage(Message message) {
        Destination destination = null;
        try {
            destination = message.getJMSReplyTo();
        }
        catch (JMSException e) {
            log("Could not find replyTo Destination for message: " + message, e);
            return;
        }
        if (destination == null) {
            log("No replyTo Destination for message: " + message);
            return;
        }
        
        Messenger messenger = getMessenger();
        String text = "Received: " + message;
        
        try {
            Message reply = messenger.createTextMessage(text);
            messenger.send(destination, reply);
        }
        catch (Exception e) {
            log("Could not send reply", e);
        }
    }
}

 =======================================================================
 ==src/webapp/src/EchoMessagelet.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: EchoMessagelet.java 155459 2005-02-26 13:24:44Z dirkv $
 */

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.servlet.ServletException;

import org.apache.commons.messagelet.Messagelet;
import org.apache.commons.messagelet.MessageletRequest;
import org.apache.commons.messagelet.MessageletResponse;

//import org.apache.commons.messenger.Messenger;

/** <p><code>EchoMessagelet</code> is an example
  * Messagelet which is a JMS specific servlet allowing access
  * to the usual Servlet APIs as well as the JMS message properties.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class EchoMessagelet extends Messagelet {

    public void service( MessageletRequest request, MessageletResponse response ) throws JMSException, IOException, ServletException {
        Message message = request.getMessage();
        
        PrintWriter writer = response.getWriter();
        
        writer.print( "Received message: " );
        writer.print( message.getJMSMessageID() );
        writer.print( " at: " );
        writer.print( new Date() );
        writer.println();
        
        // output the current request
        BufferedReader reader = request.getReader();
        for ( String line; (line = reader.readLine()) != null; ) {
            writer.println( line );

 =======================================================================
 ==src/webapp/src/EchoServlet.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: EchoServlet.java 155459 2005-02-26 13:24:44Z dirkv $
 */

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/** <p><code>EchoServlet</code> is a simple echo generic
  * servlet that can be used to process HTTP or JMS requests
  * based purely in the input and output streams and use of
  * servlet attributes.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class EchoServlet extends GenericServlet {

    public void service( ServletRequest request, ServletResponse response ) throws IOException, ServletException {
        PrintWriter writer = response.getWriter();
        
        writer.print( "Received request at: " );
        writer.print( new Date() );
        writer.println();
        
        // output the current request
        BufferedReader reader = request.getReader();
        for ( String line; (line = reader.readLine()) != null; ) {
            writer.println( line );
        }
    }
}

 =======================================================================
 ==src/webapp/web/default.css
 =======================================================================
 body {
  margin: 2em 1em 2em 70px;
  font-family: sans-serif;
  color: black;
  background: white;
  background-position: top left;
  background-attachment: fixed;
  background-repeat: no-repeat;
}

th, td { /* ns 4 */
  font-family: sans-serif;
}

h1, h2, h3, h4, h5, h6 { text-align: left }
h1, h2, h3, h4, h5 { color: #005A9C }
h1 { font: 170% sans-serif }
h2 { font: 140% sans-serif }
h3 { font: 120% sans-serif }
h4 { font: bold 100% sans-serif }
h5 { font: italic 100% sans-serif }
h6 { font: small-caps 100% sans-serif }

.hide { display: none }

div.head { margin-bottom: 1em }
div.head h1 { margin-top: 2em; clear: both }
div.head table { margin-left: 2em; margin-top: 2em }
div.head img { color: white; border: none } /* remove border from top image */

p.copyright { font-size: small }
p.copyright small { font-size: small }

@media screen {  /* hide from IE3 */
a:hover { background: #ffa } 
}

dt, dd { margin-top: 0; margin-bottom: 0 } /* opera 3.50 */
dt { font-weight: bold }

pre, code { font-family: monospace } /* navigator 4 requires this */

ul.toc {
  list-style: disc;		/* Mac NS has problem with 'none' */
  list-style: none;
}

@media aural {  
  h1, h2, h3 { stress: 20; richness: 90 }
  .hide { speak: none }

 =======================================================================
 ==src/webapp/web/index.jsp
 =======================================================================
 <!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html lang="en">
<!-- $Id: index.jsp 155459 2005-02-26 13:24:44Z dirkv $ -->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Messenger Sample WebApp</title>
<link rel="stylesheet" href="default.css" type="text/css">
</head>
<body>

<h1>Messenger Sample WebApp</h1>

<p>Welcome to the sample web application for the Messenger project.
This web application will hopefully demonstrate the use of the following technologies
</p>

<ul>
<li><b>Messenger</b>, the easy to use JMS framework
</li>
<li><b>MDOs</b>, Message Driven Objects which are like 
  the Message Driven Beans part of the EJB specification but are more lightweight and run inside 
  any servlet engine, such as <a href="http://jakarta.apache.org/tomcat/index.html">Tomcat 4.0</a>.
</li>
<li><b>Messagelets</b>, Message Driven Servlets. 
  These allow standard Servlet technology to be used to process JMS messages.
</li>
</ul>

<hr />

<p>For more details please see the Jakarta <a href="http://jakarta.apache.org/commons/messenger.html">Messenger</a> project</p>

</body>
</html>


 =======================================================================
 ==src/webapp/web/jms/time.jsp
 =======================================================================
 <echo>
  <time><%= new java.util.Date() %></time>
  <a><%= request.getParameter( "a" )%></a>
  <b><%= request.getParameter( "b" )%></b>

  <message><%= request.getAttribute( "message" )%></message>
</echo>

 =======================================================================
 ==src/webapp/WEB-INF/src/EchoMDO.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: EchoMDO.java 155459 2005-02-26 13:24:44Z dirkv $
 */

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import org.apache.commons.messagelet.MessengerMDO;
import org.apache.commons.messenger.Messenger;

/** <p><code>EchoMDO</code> is a simple echo MDO which
  * replies with a piece of text.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class EchoMDO extends MessengerMDO {
    
    public void onMessage(Message message) {
        Destination destination = null;
        try {
            destination = message.getJMSReplyTo();
        }
        catch (JMSException e) {
            log("Could not find replyTo Destination for message: " + message, e);
            return;
        }
        if (destination == null) {
            log("No replyTo Destination for message: " + message);
            return;
        }
        
        Messenger messenger = getMessenger();
        String text = "Received: " + message;
        
        try {
            Message reply = messenger.createTextMessage(text);
            messenger.send(destination, reply);
        }
        catch (Exception e) {
            log("Could not send reply", e);
        }
    }
}

 =======================================================================
 ==src/webapp/WEB-INF/src/EchoMessagelet.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: EchoMessagelet.java 155459 2005-02-26 13:24:44Z dirkv $
 */

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.servlet.ServletException;

import org.apache.commons.messagelet.Messagelet;
import org.apache.commons.messagelet.MessageletRequest;
import org.apache.commons.messagelet.MessageletResponse;

//import org.apache.commons.messenger.Messenger;

/** <p><code>EchoMessagelet</code> is an example
  * Messagelet which is a JMS specific servlet allowing access
  * to the usual Servlet APIs as well as the JMS message properties.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class EchoMessagelet extends Messagelet {

    public void service( MessageletRequest request, MessageletResponse response ) throws JMSException, IOException, ServletException {
        Message message = request.getMessage();
        
        PrintWriter writer = response.getWriter();
        
        writer.print( "Received message: " );
        writer.print( message.getJMSMessageID() );
        writer.print( " at: " );
        writer.print( new Date() );
        writer.println();
        
        // output the current request
        BufferedReader reader = request.getReader();
        for ( String line; (line = reader.readLine()) != null; ) {
            writer.println( line );

 =======================================================================
 ==src/webapp/WEB-INF/src/EchoServlet.java
 =======================================================================
 /*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 * 
 * $Id: EchoServlet.java 155459 2005-02-26 13:24:44Z dirkv $
 */

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/** <p><code>EchoServlet</code> is a simple echo generic
  * servlet that can be used to process HTTP or JMS requests
  * based purely in the input and output streams and use of
  * servlet attributes.</p>
  *
  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
  * @version $Revision: 155459 $
  */
public class EchoServlet extends GenericServlet {

    public void service( ServletRequest request, ServletResponse response ) throws IOException, ServletException {
        PrintWriter writer = response.getWriter();
        
        writer.print( "Received request at: " );
        writer.print( new Date() );
        writer.println();
        
        // output the current request
        BufferedReader reader = request.getReader();
        for ( String line; (line = reader.readLine()) != null; ) {
            writer.println( line );
        }
    }
}

 =======================================================================
 ==src/webapp/WEB-INF/subscriptions.xml
 =======================================================================
 <?xml version="1.0" encoding="UTF-8"?>
<subscriptions>
  <subscription connection="queue" subject="jms/Queue">
    <listener className="EchoMDO"/>
  </subscription>
  
  <subscription connection="queue" subject="echo.servlet">
    <servlet>/jms/echoServlet</servlet>
  </subscription>
  
  <subscription connection="queue" subject="echo.messagelet">
    <servlet>/jms/echoMessagelet</servlet>
  </subscription>
  
  <subscription connection="queue" subject="echo.jsp">
    <servlet>/jms/time.jsp?a=1&amp;b=2</servlet>
  </subscription>
  
  <subscription connection="queue" subject="foo.input">

    <bridge outputConnection="queue" outputSubject="foo.output"/>

  </subscription>

  
</subscriptions>

 =======================================================================
 ==src/webapp/WEB-INF/web.xml
 =======================================================================
 <?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE web-app 
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 
    "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

  <display-name>Messenger example web app</display-name>

  <description>This web application demonstrates the use of Messenger, MessageDrivenObjects and Messagelets</description>

  <servlet>
    <servlet-name>managerServlet</servlet-name>
    <servlet-class>org.apache.commons.messagelet.ManagerServlet</servlet-class>
    <init-param>
      <param-name>connections</param-name>
      <param-value>/WEB-INF/Messenger.xml</param-value>
    </init-param> 
    <init-param>
      <param-name>subscriptions</param-name>
      <param-value>/WEB-INF/subscriptions.xml</param-value>
    </init-param> 
    <load-on-startup>1</load-on-startup> 
  </servlet>

  <servlet>
    <servlet-name>echoMessagelet</servlet-name>
    <servlet-class>EchoMessagelet</servlet-class>
    <load-on-startup>1</load-on-startup> 
  </servlet>

  <servlet>
    <servlet-name>echoServlet</servlet-name>
    <servlet-class>EchoServlet</servlet-class>
    <load-on-startup>1</load-on-startup> 
  </servlet>


  <servlet-mapping>
    <servlet-name>echoMessagelet</servlet-name>
    <url-pattern>/jms/echoMessagelet</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>echoServlet</servlet-name>
    <url-pattern>/jms/echoServlet</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>

 =======================================================================
 ==TODO.txt
 =======================================================================
 Project To Do List
==================

* document the messenger.xml and subscription.xml configuration files

* create a receive Ant task

* consider a BeanUtils Converter to allow Strings to be converted into Destinations or Messengers?

* add an option to the producer task to allow the messenger.xml to be specified

* Allow the replyTo destination and Messenger to be overridden 
  in the XML deployment configuration for Messagelets and Servlets.

* provide a <sender> element in the subscriber XML document which will
  then act as a very simple router. e.g. 

  <subscribe connection="foo" destination="incoming">
    <send connection="bar" destination="outgoing"/>
  </subscribe>

* file based JMS test harness for testing JMS networks? Firing in batches of
  messages to certain JMS connections, via a test agent, then outputtting messages
  to some directory, allowing JUnit style testing.

* write JMSServlet such that
  HTTP GET -> Messenger.receive();
  HTTP POST -> Messenger.send();

* consider Messenger based appender for log4j.

* a Messenger based JAXM provider, allowing SOAP messages to be sent over JMS.


 =======================================================================
 ==xdocs/index.xml
 =======================================================================
 <?xml version="1.0"?>

<document>

 <properties>
  <title>Overview</title>
  <author email="jstrachan@apache.org">James Strachan</author>
 </properties>

<body>

<section name="Messenger Introduction">

<p>
  <b>Messenger</b> is a JMS (Java Message Service) framework
  which makes it very easy to use JMS in Web Service and Web Application environments.
</p>

<p>
  Messenger implements session pooling (which can be quite hard to do with JMS) which makes JMS
  very easy to work with. Also Messenger hides much of the complexity of JMS behind 
  a simple facade API, the 
  <a href="apidocs/org/apache/commons/messenger/Messenger.html">Messenger</a> interface. 
</p>

<p>
  In addition Messenger provides an XML deployment 
  configuration file to avoid having to litter your code with complex deployment 
  configuration details in your application code. 
</p>

<p>
  Messenger also provides a Messagelet Engine which is a JMS based container 
  that can be deployed in any Servlet Engine to process JMS messages
  via MessageListeners, Message Driven Objects, Servlets or JSP.
</p>

</section>

<section name="Example Config">

<p> 
  Here is an example <i>Messenger.xml</i> deployment configuration file.
</p>

<source><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<manager>

  <!-- this example Messenger XML config file should work with J2EE SDK -->