You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by bs...@apache.org on 2017/12/13 19:17:18 UTC

[48/51] [partial] activemq-web git commit: Initial commit

http://git-wip-us.apache.org/repos/asf/activemq-web/blob/c5128cb5/MessageListenerServlet.java
----------------------------------------------------------------------
diff --git a/MessageListenerServlet.java b/MessageListenerServlet.java
new file mode 100644
index 0000000..cb4cc3c
--- /dev/null
+++ b/MessageListenerServlet.java
@@ -0,0 +1,541 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.web;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.ObjectMessage;
+import javax.jms.TextMessage;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.apache.activemq.MessageAvailableConsumer;
+import org.eclipse.jetty.continuation.Continuation;
+import org.eclipse.jetty.continuation.ContinuationListener;
+import org.eclipse.jetty.continuation.ContinuationSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A servlet for sending and receiving messages to/from JMS destinations using
+ * HTTP POST for sending and HTTP GET for receiving. <p/> You can specify the
+ * destination and whether it is a topic or queue via configuration details on
+ * the servlet or as request parameters. <p/> For reading messages you can
+ * specify a readTimeout parameter to determine how long the servlet should
+ * block for. The servlet can be configured with the following init parameters:
+ * <dl>
+ * <dt>defaultReadTimeout</dt>
+ * <dd>The default time in ms to wait for messages. May be overridden by a
+ * request using the 'timeout' parameter</dd>
+ * <dt>maximumReadTimeout</dt>
+ * <dd>The maximum value a request may specify for the 'timeout' parameter</dd>
+ * <dt>maximumMessages</dt>
+ * <dd>maximum messages to send per response</dd>
+ * <dt></dt>
+ * <dd></dd>
+ * </dl>
+ *
+ *
+ */
+@SuppressWarnings("serial")
+public class MessageListenerServlet extends MessageServletSupport {
+    private static final Logger LOG = LoggerFactory.getLogger(MessageListenerServlet.class);
+
+    private final String readTimeoutParameter = "timeout";
+    private long defaultReadTimeout = -1;
+    private long maximumReadTimeout = 25000;
+    private int maximumMessages = 100;
+    private final Timer clientCleanupTimer = new Timer("ActiveMQ Ajax Client Cleanup Timer", true);
+    private final HashMap<String,AjaxWebClient> ajaxWebClients = new HashMap<String,AjaxWebClient>();
+
+    @Override
+    public void init() throws ServletException {
+        ServletConfig servletConfig = getServletConfig();
+        String name = servletConfig.getInitParameter("defaultReadTimeout");
+        if (name != null) {
+            defaultReadTimeout = asLong(name);
+        }
+        name = servletConfig.getInitParameter("maximumReadTimeout");
+        if (name != null) {
+            maximumReadTimeout = asLong(name);
+        }
+        name = servletConfig.getInitParameter("maximumMessages");
+        if (name != null) {
+            maximumMessages = (int)asLong(name);
+        }
+        clientCleanupTimer.schedule( new ClientCleaner(), 5000, 60000 );
+    }
+
+    /**
+     * Sends a message to a destination or manage subscriptions. If the the
+     * content type of the POST is
+     * <code>application/x-www-form-urlencoded</code>, then the form
+     * parameters "destination", "message" and "type" are used to pass a message
+     * or a subscription. If multiple messages or subscriptions are passed in a
+     * single post, then additional parameters are shortened to "dN", "mN" and
+     * "tN" where N is an index starting from 1. The type is either "send",
+     * "listen" or "unlisten". For send types, the message is the text of the
+     * TextMessage, otherwise it is the ID to be used for the subscription. If
+     * the content type is not <code>application/x-www-form-urlencoded</code>,
+     * then the body of the post is sent as the message to a destination that is
+     * derived from a query parameter, the URL or the default destination.
+     *
+     * @param request
+     * @param response
+     * @throws ServletException
+     * @throws IOException
+     */
+    @Override
+    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+        // lets turn the HTTP post into a JMS Message
+        AjaxWebClient client = getAjaxWebClient( request );
+        String messageIds = "";
+
+        synchronized (client) {
+
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("POST client=" + client + " session=" + request.getSession().getId() + " clientId="+ request.getParameter("clientId") + " info=" + request.getPathInfo() + " contentType=" + request.getContentType());
+                // dump(request.getParameterMap());
+            }
+
+            int messages = 0;
+
+            // loop until no more messages
+            while (true) {
+                // Get the message parameters. Multiple messages are encoded
+                // with more compact parameter names.
+                String destinationName = request.getParameter(messages == 0 ? "destination" : ("d" + messages));
+
+                if (destinationName == null) {
+                    destinationName = request.getHeader("destination");
+                }
+
+                String message = request.getParameter(messages == 0 ? "message" : ("m" + messages));
+                String type = request.getParameter(messages == 0 ? "type" : ("t" + messages));
+
+                if (destinationName == null || message == null || type == null) {
+                    break;
+                }
+
+                try {
+                    Destination destination = getDestination(client, request, destinationName);
+
+                    if (LOG.isDebugEnabled()) {
+                        LOG.debug(messages + " destination=" + destinationName + " message=" + message + " type=" + type);
+                        LOG.debug(destination + " is a " + destination.getClass().getName());
+                    }
+
+                    messages++;
+
+                    if ("listen".equals(type)) {
+                        AjaxListener listener = client.getListener();
+                        Map<MessageAvailableConsumer, String> consumerIdMap = client.getIdMap();
+                        Map<MessageAvailableConsumer, String> consumerDestinationNameMap = client.getDestinationNameMap();
+                        client.closeConsumer(destination); // drop any existing
+                        // consumer.
+                        MessageAvailableConsumer consumer = (MessageAvailableConsumer)client.getConsumer(destination, request.getHeader(WebClient.selectorName));
+
+                        consumer.setAvailableListener(listener);
+                        consumerIdMap.put(consumer, message);
+                        consumerDestinationNameMap.put(consumer, destinationName);
+                        if (LOG.isDebugEnabled()) {
+                            LOG.debug("Subscribed: " + consumer + " to " + destination + " id=" + message);
+                        }
+                    } else if ("unlisten".equals(type)) {
+                        Map<MessageAvailableConsumer, String> consumerIdMap = client.getIdMap();
+                        Map<MessageAvailableConsumer, String> consumerDestinationNameMap = client.getDestinationNameMap();
+                        MessageAvailableConsumer consumer = (MessageAvailableConsumer)client.getConsumer(destination, request.getHeader(WebClient.selectorName));
+
+                        consumer.setAvailableListener(null);
+                        consumerIdMap.remove(consumer);
+                        consumerDestinationNameMap.remove(consumer);
+                        client.closeConsumer(destination);
+                        if (LOG.isDebugEnabled()) {
+                            LOG.debug("Unsubscribed: " + consumer);
+                        }
+                    } else if ("send".equals(type)) {
+                        TextMessage text = client.getSession().createTextMessage(message);
+                        appendParametersToMessage(request, text);
+
+                        client.send(destination, text);
+                        messageIds += text.getJMSMessageID() + "\n";
+                        if (LOG.isDebugEnabled()) {
+                            LOG.debug("Sent " + message + " to " + destination);
+                        }
+                    } else {
+                        LOG.warn("unknown type " + type);
+                    }
+
+                } catch (JMSException e) {
+                    LOG.warn("jms", e);
+                }
+            }
+        }
+
+        if ("true".equals(request.getParameter("poll"))) {
+            try {
+                // TODO return message IDs
+                doMessages(client, request, response);
+            } catch (JMSException e) {
+                throw new ServletException("JMS problem: " + e, e);
+            }
+        } else {
+            // handle simple POST of a message
+            if (request.getContentLength() != 0 && (request.getContentType() == null || !request.getContentType().toLowerCase().startsWith("application/x-www-form-urlencoded"))) {
+                try {
+                    Destination destination = getDestination(client, request);
+                    String body = getPostedMessageBody(request);
+                    TextMessage message = client.getSession().createTextMessage(body);
+                    appendParametersToMessage(request, message);
+
+                    client.send(destination, message);
+                    if (LOG.isDebugEnabled()) {
+                        LOG.debug("Sent to destination: " + destination + " body: " + body);
+                    }
+                    messageIds += message.getJMSMessageID() + "\n";
+                } catch (JMSException e) {
+                    throw new ServletException(e);
+                }
+            }
+
+            response.setContentType("text/plain");
+            response.setHeader("Cache-Control", "no-cache");
+            response.getWriter().print(messageIds);
+        }
+    }
+
+    /**
+     * Supports a HTTP DELETE to be equivlanent of consuming a singe message
+     * from a queue
+     */
+    @Override
+    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+        try {
+            AjaxWebClient client = getAjaxWebClient(request);
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("GET client=" + client + " session=" + request.getSession().getId() + " clientId="+ request.getParameter("clientId") + " uri=" + request.getRequestURI() + " query=" + request.getQueryString());
+            }
+
+            doMessages(client, request, response);
+        } catch (JMSException e) {
+            throw new ServletException("JMS problem: " + e, e);
+        }
+    }
+
+    /**
+     * Reads a message from a destination up to some specific timeout period
+     *
+     * @param client The webclient
+     * @param request
+     * @param response
+     * @throws ServletException
+     * @throws IOException
+     */
+    protected void doMessages(AjaxWebClient client, HttpServletRequest request, HttpServletResponse response) throws JMSException, IOException {
+
+        int messages = 0;
+        // This is a poll for any messages
+
+        long timeout = getReadTimeout(request);
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("doMessage timeout=" + timeout);
+        }
+
+        // this is non-null if we're resuming the continuation.
+        // attributes set in AjaxListener
+        UndeliveredAjaxMessage undelivered_message = null;
+        Message message = null;
+        undelivered_message = (UndeliveredAjaxMessage)request.getAttribute("undelivered_message");
+        if( undelivered_message != null ) {
+            message = undelivered_message.getMessage();
+        }
+
+        synchronized (client) {
+
+            List<MessageConsumer> consumers = client.getConsumers();
+            MessageAvailableConsumer consumer = null;
+            if( undelivered_message != null ) {
+                consumer = (MessageAvailableConsumer)undelivered_message.getConsumer();
+            }
+
+            if (message == null) {
+                // Look for a message that is ready to go
+                for (int i = 0; message == null && i < consumers.size(); i++) {
+                    consumer = (MessageAvailableConsumer)consumers.get(i);
+                    if (consumer.getAvailableListener() == null) {
+                        continue;
+                    }
+
+                    // Look for any available messages
+                    message = consumer.receive(10);
+                    if (LOG.isDebugEnabled()) {
+                        LOG.debug("received " + message + " from " + consumer);
+                    }
+                }
+            }
+
+            // prepare the response
+            response.setContentType("text/xml");
+            response.setHeader("Cache-Control", "no-cache");
+
+            if (message == null && client.getListener().getUndeliveredMessages().size() == 0) {
+                Continuation continuation = ContinuationSupport.getContinuation(request);
+
+                // Add a listener to the continuation to make sure it actually
+                // will expire (seems like a bug in Jetty Servlet 3 continuations,
+                // see https://issues.apache.org/jira/browse/AMQ-3447
+                continuation.addContinuationListener(new ContinuationListener() {
+                    @Override
+                    public void onTimeout(Continuation cont) {
+                        if (LOG.isDebugEnabled()) {
+                            LOG.debug("Continuation " + cont.toString() + " expired.");
+                        }
+                    }
+
+                    @Override
+                    public void onComplete(Continuation cont) {
+                        if (LOG.isDebugEnabled()) {
+                           LOG.debug("Continuation " + cont.toString() + " completed.");
+                        }
+                    }
+                });
+
+                if (continuation.isExpired()) {
+                    response.setStatus(HttpServletResponse.SC_OK);
+                    StringWriter swriter = new StringWriter();
+                    PrintWriter writer = new PrintWriter(swriter);
+                    writer.println("<ajax-response>");
+                    writer.print("</ajax-response>");
+
+                    writer.flush();
+                    String m = swriter.toString();
+                    response.getWriter().println(m);
+
+                    return;
+                }
+
+                continuation.setTimeout(timeout);
+                continuation.suspend();
+                LOG.debug( "Suspending continuation " + continuation );
+
+                // Fetch the listeners
+                AjaxListener listener = client.getListener();
+                listener.access();
+
+                // register this continuation with our listener.
+                listener.setContinuation(continuation);
+
+                return;
+            }
+
+            StringWriter swriter = new StringWriter();
+            PrintWriter writer = new PrintWriter(swriter);
+
+            Map<MessageAvailableConsumer, String> consumerIdMap = client.getIdMap();
+            Map<MessageAvailableConsumer, String> consumerDestinationNameMap = client.getDestinationNameMap();
+            response.setStatus(HttpServletResponse.SC_OK);
+            writer.println("<ajax-response>");
+
+            // Send any message we already have
+            if (message != null) {
+                String id = consumerIdMap.get(consumer);
+                String destinationName = consumerDestinationNameMap.get(consumer);
+                LOG.debug( "sending pre-existing message" );
+                writeMessageResponse(writer, message, id, destinationName);
+
+                messages++;
+            }
+
+            // send messages buffered while continuation was unavailable.
+            LinkedList<UndeliveredAjaxMessage> undeliveredMessages = ((AjaxListener)consumer.getAvailableListener()).getUndeliveredMessages();
+            LOG.debug("Send " + undeliveredMessages.size() + " unconsumed messages");
+            synchronized( undeliveredMessages ) {
+                for (Iterator<UndeliveredAjaxMessage> it = undeliveredMessages.iterator(); it.hasNext();) {
+                    messages++;
+                    UndeliveredAjaxMessage undelivered = it.next();
+                    Message msg = undelivered.getMessage();
+                    consumer = (MessageAvailableConsumer)undelivered.getConsumer();
+                    String id = consumerIdMap.get(consumer);
+                    String destinationName = consumerDestinationNameMap.get(consumer);
+                    LOG.debug( "sending undelivered/buffered messages" );
+                    LOG.debug( "msg:" +msg+ ", id:" +id+ ", destinationName:" +destinationName);
+                    writeMessageResponse(writer, msg, id, destinationName);
+                    it.remove();
+                    if (messages >= maximumMessages) {
+                        break;
+                    }
+                }
+            }
+
+            // Send the rest of the messages
+            for (int i = 0; i < consumers.size() && messages < maximumMessages; i++) {
+                consumer = (MessageAvailableConsumer)consumers.get(i);
+                if (consumer.getAvailableListener() == null) {
+                    continue;
+                }
+
+                // Look for any available messages
+                while (messages < maximumMessages) {
+                    message = consumer.receiveNoWait();
+                    if (message == null) {
+                        break;
+                    }
+                    messages++;
+                    String id = consumerIdMap.get(consumer);
+                    String destinationName = consumerDestinationNameMap.get(consumer);
+                    LOG.debug( "sending final available messages" );
+                    writeMessageResponse(writer, message, id, destinationName);
+                }
+            }
+
+            writer.print("</ajax-response>");
+
+            writer.flush();
+            String m = swriter.toString();
+            response.getWriter().println(m);
+        }
+    }
+
+    protected void writeMessageResponse(PrintWriter writer, Message message, String id, String destinationName) throws JMSException, IOException {
+        writer.print("<response id='");
+        writer.print(id);
+        writer.print("'");
+        if (destinationName != null) {
+            writer.print(" destination='" + destinationName + "' ");
+        }
+        writer.print(">");
+        if (message instanceof TextMessage) {
+            TextMessage textMsg = (TextMessage)message;
+            String txt = textMsg.getText();
+            if (txt != null) {
+                if (txt.startsWith("<?")) {
+                    txt = txt.substring(txt.indexOf("?>") + 2);
+                }
+                writer.print(txt);
+            }
+        } else if (message instanceof ObjectMessage) {
+            ObjectMessage objectMsg = (ObjectMessage)message;
+            Object object = objectMsg.getObject();
+            if (object != null) {
+                writer.print(object.toString());
+            }
+        }
+        writer.println("</response>");
+    }
+
+    /*
+     * Return the AjaxWebClient for this session+clientId.
+     * Create one if it does not already exist.
+     */
+    protected AjaxWebClient getAjaxWebClient( HttpServletRequest request ) {
+        HttpSession session = request.getSession(true);
+
+        String clientId = request.getParameter( "clientId" );
+        // if user doesn't supply a 'clientId', we'll just use a default.
+        if( clientId == null ) {
+            clientId = "defaultAjaxWebClient";
+        }
+        String sessionKey = session.getId() + '-' + clientId;
+
+        AjaxWebClient client = null;
+        synchronized (ajaxWebClients) {
+            client = ajaxWebClients.get( sessionKey );
+            // create a new AjaxWebClient if one does not already exist for this sessionKey.
+            if( client == null ) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug( "creating new AjaxWebClient in "+sessionKey );
+                }
+                client = new AjaxWebClient( request, maximumReadTimeout );
+                ajaxWebClients.put( sessionKey, client );
+            }
+            client.updateLastAccessed();
+        }
+        return client;
+    }
+
+    /**
+     * @return the timeout value for read requests which is always >= 0 and <=
+     *         maximumReadTimeout to avoid DoS attacks
+     */
+    protected long getReadTimeout(HttpServletRequest request) {
+        long answer = defaultReadTimeout;
+
+        String name = request.getParameter(readTimeoutParameter);
+        if (name != null) {
+            answer = asLong(name);
+        }
+        if (answer < 0 || answer > maximumReadTimeout) {
+            answer = maximumReadTimeout;
+        }
+        return answer;
+    }
+
+    /*
+     * an instance of this class runs every minute (started in init), to clean up old web clients & free resources.
+     */
+    private class ClientCleaner extends TimerTask {
+        @Override
+        public void run() {
+            if( LOG.isDebugEnabled() ) {
+                LOG.debug( "Cleaning up expired web clients." );
+            }
+
+            synchronized( ajaxWebClients ) {
+                Iterator<Map.Entry<String, AjaxWebClient>> it = ajaxWebClients.entrySet().iterator();
+                while ( it.hasNext() ) {
+                    Map.Entry<String,AjaxWebClient> e = it.next();
+                    String key = e.getKey();
+                    AjaxWebClient val = e.getValue();
+                    if ( LOG.isDebugEnabled() ) {
+                        LOG.debug( "AjaxWebClient " + key + " last accessed " + val.getMillisSinceLastAccessed()/1000 + " seconds ago." );
+                    }
+                    // close an expired client and remove it from the ajaxWebClients hash.
+                    if( val.closeIfExpired() ) {
+                        if ( LOG.isDebugEnabled() ) {
+                            LOG.debug( "Removing expired AjaxWebClient " + key );
+                        }
+                        it.remove();
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public void destroy() {
+        // make sure we cancel the timer
+        clientCleanupTimer.cancel();
+        super.destroy();
+    }
+}

http://git-wip-us.apache.org/repos/asf/activemq-web/blob/c5128cb5/NOTICE.txt
----------------------------------------------------------------------
diff --git a/NOTICE.txt b/NOTICE.txt
new file mode 100644
index 0000000..27628f9
--- /dev/null
+++ b/NOTICE.txt
@@ -0,0 +1,21 @@
+=========================================================================
+==  NOTICE file corresponding to the section 4 d of                    ==
+==  the Apache License, Version 2.0,                                   ==
+==  in this case for the Apache ActiveMQ distribution.                 ==
+=========================================================================
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+=========================================================================
+==  Doxygen Automake Macro Notice                                      ==
+=========================================================================
+
+This product includes software developed by the Oren Ben-Kiki
+http://ben-kiki.org/oren/doxample/
+
+=========================================================================
+==  ZLib Compression / Decompression Library Notice                    ==
+=========================================================================
+This product includes software developed by the Jean-loup Gailly and Mark Adler
+http://www.zlib.net/

http://git-wip-us.apache.org/repos/asf/activemq-web/blob/c5128cb5/NonPersistentMsgs.graffle
----------------------------------------------------------------------
diff --git a/NonPersistentMsgs.graffle b/NonPersistentMsgs.graffle
new file mode 100644
index 0000000..3e7572e
Binary files /dev/null and b/NonPersistentMsgs.graffle differ

http://git-wip-us.apache.org/repos/asf/activemq-web/blob/c5128cb5/NonPersistentMsgs.png
----------------------------------------------------------------------
diff --git a/NonPersistentMsgs.png b/NonPersistentMsgs.png
new file mode 100644
index 0000000..9cbe7b0
Binary files /dev/null and b/NonPersistentMsgs.png differ

http://git-wip-us.apache.org/repos/asf/activemq-web/blob/c5128cb5/README.txt
----------------------------------------------------------------------
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..7436a7a
--- /dev/null
+++ b/README.txt
@@ -0,0 +1 @@
+For more information on using XSD with ActiveMQ see http://activemq.apache.org/xml-reference.html

http://git-wip-us.apache.org/repos/asf/activemq-web/blob/c5128cb5/RELEASE_NOTES.txt
----------------------------------------------------------------------
diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt
new file mode 100644
index 0000000..136ff4f
--- /dev/null
+++ b/RELEASE_NOTES.txt
@@ -0,0 +1,1019 @@
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.8.0                               ==
+=========================================================================
+
+Bug
+
+    [AMQCPP-483] - 3.7.0 does not compile with gcc-4.4.7 on CentOS-6
+    [AMQCPP-484] - Can't connect via Stomp to Apollo broker - ActiveMq-Cpp version: 3.7.0
+    [AMQCPP-485] - APR-Util header include missed in latest release.
+    [AMQCPP-487] - CMS FailoverTransport Leaks Socket Descriptors
+    [AMQCPP-488] - closing a connection stalled in start because of failover should stop the transport safely.
+    [AMQCPP-489] - Compilation Error Fix for Sun Studio under Solaris 10
+    [AMQCPP-490] - Exception lifetime confusion can cause the application to crash
+    [AMQCPP-491] - Connection didn't switch to the slave broker when the master broker is down
+    [AMQCPP-494] - Commiting a session with a deleted consumer causes access violation
+    [AMQCPP-497] - Compilation of 3.7.0 fails for Linux systems (Redhat 5.8 and SuSE SLES 10)
+    [AMQCPP-498] - Client doesn't work on Linux Red Hat 6.4 systems, fails when setting thread priority
+    [AMQCPP-501] - Consumers remain active after being deleted
+    [AMQCPP-505] - For SSL connections ensure the SNI field is set.
+    [AMQCPP-506] - Exception "attempt to unlock read lock, not locked by current thread" when doing
+                   performance testing
+
+New Feature
+
+    [AMQCPP-502] - Can't send to temporary queues created by name
+
+Task
+
+    [AMQCPP-507] - Add new Visual Studio 2010 Project files
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.7.1                               ==
+=========================================================================
+
+Bug
+
+    [AMQCPP-483] - 3.7.0 does not compile with gcc-4.4.7 on CentOS-6
+    [AMQCPP-484] - Can't connect via Stomp to Apollo broker - ActiveMq-Cpp version: 3.7.0
+    [AMQCPP-485] - APR-Util header include missed in latest release.
+    [AMQCPP-487] - CMS FailoverTransport Leaks Socket Descriptors
+    [AMQCPP-488] - closing a connection stalled in start because of failover should stop
+                   the transport safely.
+    [AMQCPP-489] - Fix for Sun Studio
+    [AMQCPP-490] - Exception lifetime confusion can cause the application to crash
+    [AMQCPP-491] - Connection didn't switch to the slave broker when the master broker is down
+    [AMQCPP-494] - Commiting a session with a deleted consumer causes access violation
+    [AMQCPP-497] - Compilation of 3.7.0 fails for Linux systems (Redhat 5.8 and SuSE SLES 10)
+    [AMQCPP-498] - Client doesn't work on Linux Red Hat 6.4 systems, fails when setting thread priority
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.7.0                               ==
+=========================================================================
+
+Bug
+
+    [AMQCPP-470] - ConnectionStateTracker needs to enforce message cache size restrictions
+    [AMQCPP-474] - On closing a connection, ActiveMQ raises the exception: StlMap modified
+                   outside this iterator
+    [AMQCPP-475] - Fix for Atomics Helper for Solaris 10
+    [AMQCPP-476] - Reading of Stomp Frame with content length may throw exception
+    [AMQCPP-482] - Message.getCMSMessageID() returns an empty string after send
+
+Improvement
+
+    [AMQCPP-469] - Remove linkage to APR-Util
+    [AMQCPP-471] - Add support for Optimize Acknowledge
+    [AMQCPP-472] - Add support for Non-Blocking redelivery.
+    [AMQCPP-473] - Add some additional configuration options for URI support
+
+New Feature
+
+    [AMQCPP-367] - failover: receiving duplicate messages after a broker restart
+    [AMQCPP-479] - Add support for priority backups to failover transport.
+    [AMQCPP-480] - Add complete support for Update Cluster clients and rebalancing
+                   to Failover Transport.
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.6.0                               ==
+=========================================================================
+
+Bug
+
+    [AMQCPP-449] - activemq::library::ActiveMQCPP::shutdownLibrary(); causing runtime exception
+    [AMQCPP-450] - Win32 Thread Handle Leak
+    [AMQCPP-451] - The number of CMS threads increases when we restart the message broker repeatedly
+    [AMQCPP-454] - Found pure function call error in CMS
+    [AMQCPP-455] - Found an access violation in CMS when creating a new connection
+    [AMQCPP-456] - Add ability to set updateURIsSupported for failover transport
+    [AMQCPP-459] - Found an access violation in NodePool::ReturNode(Node* node)
+    [AMQCPP-460] - Access Violation
+    [AMQCPP-461] - Create Thread objects that aren't started can leak their suspended thread on destroy.
+    [AMQCPP-464] - Deadlock during normal task termination
+    [AMQCPP-465] - Periodic access violation originating from Openwire::unmarshal
+    [AMQCPP-466] - Segmentation Fault in Temporary Queue consumer (incorrect Exception construction)
+
+Improvement
+
+    [AMQCPP-457] - Refactor Transports layer for more control over started / stopped state during initialization
+    [AMQCPP-467] - Improve the CMSException types thrown from errors sent back from the broker.
+
+New Feature
+
+    [AMQCPP-463] - Add support for priority backups to the FailoverTransport
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.5.0                               ==
+=========================================================================
+
+Bug
+
+    [AMQCPP-369] - dynamic library segfaults on load under Mac OS/X
+    [AMQCPP-370] - pkg-config does not properly indicate static dependencies
+    [AMQCPP-371] - bytesmessages's size doubled If Message body compression enabled
+    [AMQCPP-373] - AMQ_CATCH_RETHROW upcasts the re-thrown exception
+    [AMQCPP-374] - BaseDataStreamMarshaller::tightUnmarshalByteArray crashes
+    [AMQCPP-375] - decaf::lang::Long::to{Hex,Binary,Octal}String problems
+    [AMQCPP-376] - Deadlock in IOTransport when network of brokers restart and failover is used.
+    [AMQCPP-382] - Spurious error messages printed by consumer when no messages available to consumer
+    [AMQCPP-384] - Failover and prefetch=0 can result in hung consumers if the MessagePull command is lost
+    [AMQCPP-385] - Compilation errors with Sun Studio 12 / libCstd
+    [AMQCPP-387] - Credentials are not propagated correctly when passed through the ActiveMQConnectionFactory constructor in the CPP client API (However, it works correctly when passed through the createConnection method)
+    [AMQCPP-389] - activemq-cpp build fails with gcc 4.7
+    [AMQCPP-391] - Potential hang on connect if wireformatinfo response is not received before timeout and failover transport is in use.
+    [AMQCPP-392] - Class Priority Queue defines constant in non-spec complaint manner
+    [AMQCPP-393] - TimeToLive feature makes some messages disappear
+    [AMQCPP-402] - Fix ConnectionStateTracker processMessageAck
+    [AMQCPP-405] - CMS sender thread hangs after restarting broker
+    [AMQCPP-406] - TcpTransport can leak memory if the connect method fails midway through
+    [AMQCPP-407] - Application crashes after stopping message broker
+    [AMQCPP-410] - prefetchSize=0 is ignored when set via PrefetchPolicy
+    [AMQCPP-414] - Remove bundled zlib and using external library
+    [AMQCPP-415] - compiler flags with HPUX 11_31 aCC A.06.26
+    [AMQCPP-416] - help wrong for configure
+    [AMQCPP-417] - decaf/lang/System.cpp error with HPUX aCC
+    [AMQCPP-418] - HPUX aCC compiler const char[] to initialize char*
+    [AMQCPP-419] - Missing dependency on apr/apr-util in pkg-config and config files
+    [AMQCPP-420] - The same fix should have been applied to SSLTransportFactory.cpp
+    [AMQCPP-424] - Cannot clone() and then update properties of the newly cloned message
+    [AMQCPP-426] - Connection setClientID doesn't catch and convert all exceptions to CMSException
+    [AMQCPP-429] - Response correlator can let a future into its mapping after its been closed causing a hang
+    [AMQCPP-430] - CMS crashes in decaf::internal::util::concurrent::MutexImpl::destroy
+    [AMQCPP-431] - Memory leak possible in OpenWireFormat and BaseDataStreamMarshaller when connection drops during read.
+    [AMQCPP-432] - Possible Segfault on Connection close during a failover cycle
+    [AMQCPP-433] - Message::getCMSCorrelationID() returns different value from Java's Message.getJMSCorrelationID()
+    [AMQCPP-437] - ActiveMQ crashes on subscribing one listener on several topics with a same session.
+    [AMQCPP-441] - Incorrect propagation of AMQ-2489 to CMS/C++ (causes performance degradation) in r833769.
+    [AMQCPP-443] - Configure adding invalid option
+    [AMQCPP-445] - Prefetch_size = 0 and failover: consumer blocked in receive() when broker restarts
+
+Improvement
+
+    [AMQCPP-383] - Implement the Session recover method.
+    [AMQCPP-386] - Run-time Setting of Destination Prefix
+    [AMQCPP-395] - Add advisory message monitoring for Temp Destination create / destory
+    [AMQCPP-396] - Add method reset() to the cms::StreamMessage interface.
+    [AMQCPP-397] - Add utility class for working with Advisory Topics
+    [AMQCPP-398] - Add support for transforming cms::Message and cms::Destination from non activemq client implementations.
+    [AMQCPP-399] - Add support for closing Session consumers with active transaction
+    [AMQCPP-400] - Add new accessor in CMS Message types to get the type of a Property value or MapMessage value
+    [AMQCPP-401] - Add get and set methods for ObjectMessage that grants access to the payload as bytes.
+    [AMQCPP-435] - Support doing non-blocking sends that uses an async callback that gets notified when the send has been received by the broker
+    [AMQCPP-436] - Add MessageAvailableListener to CMS API
+
+New Feature
+
+    [AMQCPP-160] - Add MessageTransformer
+    [AMQCPP-411] - Add new get method in StreamMessage to allow for checking the type of the next value
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.4.5                               ==
+=========================================================================
+
+Bug
+
+    [AMQCPP-426] - Connection setClientID doesn't catch and convert all exceptions to CMSException
+    [AMQCPP-429] - Response correlator can let a future into its mapping after its been closed causing a hang
+    [AMQCPP-430] - CMS crashes in decaf::internal::util::concurrent::MutexImpl::destroy
+    [AMQCPP-431] - Memory leak possible in OpenWireFormat and BaseDataStreamMarshaller when connection
+                   drops during read.
+    [AMQCPP-432] - Possible Segfault on Connection close during a failover cycle
+    [AMQCPP-433] - Message::getCMSCorrelationID() returns different value from Java's Message.
+                   getJMSCorrelationID()
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.4.4                               ==
+=========================================================================
+
+Bug
+
+    [AMQCPP-404] - compilation errors on Windows because of Unicode set in project file
+    [AMQCPP-407] - Application crashes after stopping message broker
+    [AMQCPP-408] - CMS opens a large number of threads
+    [AMQCPP-410] - prefetchSize=0 is ignored when set via PrefetchPolicy
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.4.3                               ==
+=========================================================================
+
+Bug
+
+    [AMQCPP-402] - Fix ConnectionStateTracker processMessageAck
+    [AMQCPP-403] - Possible for memory to leak when using transacted producer with failover
+    [AMQCPP-406] - TcpTransport can leak memory if the connect method fails midway through
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.4.2                               ==
+=========================================================================
+
+Bug
+
+    [AMQCPP-387] - Credentials are not propagated correctly when passed through the
+                   ActiveMQConnectionFactory constructor in the CPP client API (However,
+                   it works correctly when passed through the createConnection method)
+    [AMQCPP-391] - Potential hang on connect if wireformatinfo response is not received
+                   before timeout and failover transport is in use.
+    [AMQCPP-392] - Class Priority Queue defines constant in non-spec complaint manner
+    [AMQCPP-393] - TimeToLive feature makes some messages disappear
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.4.1                               ==
+=========================================================================
+
+Bug
+
+    [AMQCPP-369] - dynamic library segfaults on load under Mac OS/X
+    [AMQCPP-370] - pkg-config does not properly indicate static dependencies
+    [AMQCPP-371] - bytesmessages's size doubled If Message body compression enabled
+    [AMQCPP-373] - AMQ_CATCH_RETHROW upcasts the re-thrown exception
+    [AMQCPP-374] - BaseDataStreamMarshaller::tightUnmarshalByteArray crashes
+    [AMQCPP-382] - Spurious error messages printed by consumer when no messages
+                   available to consumer
+
+Improvement
+
+    [AMQCPP-383] - Implement the Session recover method.
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.4.0                               ==
+=========================================================================
+
+Bug:
+
+    * [AMQCPP-363] - failover: consumer does not always restart properly after reconnect
+    * [AMQCPP-365] - 3.3.0 - compiler errors in Windows
+    * [AMQCPP-366] - createConnection() fails if given an ip address
+
+Improvement
+
+    * [AMQCPP-362] - Make Session and MessageConsumer both Startable and Stoppable in the CMS API
+    * [AMQCPP-364] - Dont perform two phase consumer recover when openwire version is not six or higher
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.3.0                               ==
+=========================================================================
+
+Bug
+
+    * [AMQCPP-294] - RemoveInfo Segmentation Fault
+    * [AMQCPP-298] - Example code crashes in 3.2.0 on MacOSX
+    * [AMQCPP-301] - Unmarshal of an empty byte array in a MapMessage
+                     segfaults on Windows
+    * [AMQCPP-302] - Compilation issue with older GCC versions in
+                     MessageCompressionTest.cpp
+    * [AMQCPP-312] - exception when bytearray is 0 length
+    * [AMQCPP-314] - Starting app with Com using cms destroys connection of
+                     other app. New problem with recent lib version
+    * [AMQCPP-315] - Advisory messages do not work with multiple listeners
+    * [AMQCPP-316] - Unable to receive any messages after re-starting message broker
+    * [AMQCPP-317] - activemq-cpp 3.2.2 will not work with activemq 5.4.0 broker using Stomp
+    * [AMQCPP-318] - Missing preprocessor definitions in Release SSL profile can cause the build to fail
+    * [AMQCPP-323] - The OnException method of registered Exception listener is not called
+                     when broker is stopped.
+    * [AMQCPP-328] - crash found in activemqcpp when turning broker offline
+    * [AMQCPP-330] - Unable to reinitialize ActiveMQ CMS library and then open a session
+    * [AMQCPP-331] - Small typo in TcpTransportFactory.cpp
+    * [AMQCPP-335] - redeliveryPolicy: rollback always loops
+    * [AMQCPP-345] - Can't connect via Stomp to Apollo broker
+    * [AMQCPP-347] - SEGFAULT on ssl connections with certificates
+    * [AMQCPP-350] - URI Query params are sometimes missed when creating Connections and Transports.
+    * [AMQCPP-351] - Using incorrect peer list in failover transport
+    * [AMQCPP-352] - FailoverTransportFactory doesn't work correctly with more than two composite uris
+    * [AMQCPP-353] - BaseDataStreamMarshaller::readAsciiString crashes
+    * [AMQCPP-355] - Transactional consumer using MessageListener freezes on commit
+    * [AMQCPP-356] - Auto-Acknowledge consumer using MessageListener freezes on destructor
+    * [AMQCPP-358] - FailoverTransport can peg CPU when connection attempts exceeds max and its
+                     waiting to be closed
+    * [AMQCPP-359] - ActiveMQBytesMessage should throw IndexOutOfBoundsException is array length
+                     is negative for readBytes method
+
+Improvement
+
+    * [AMQCPP-284] - Generate Openwire 6 commands and marshalers to keep pace with the AMQ 5.4 broker.
+    * [AMQCPP-300] - Add new method to CMS MapMessage - "isEmpty"
+    * [AMQCPP-305] - Add option to set the level of Compressiion for Message Body Compression
+    * [AMQCPP-307] - Port Update of Connection URI from AMQ to AMQCPP
+    * [AMQCPP-308] - Update Redelivery policy to better handle initial redelivery delay processing.
+    * [AMQCPP-310] - Add support for Message Priority Dispatching to CMS
+    * [AMQCPP-319] - Add equals method to the CMS Destination interface to allow opaque compare of
+                     Destination instances.
+    * [AMQCPP-329] - Add the ability to participate in XA Transactions
+    * [AMQCPP-348] - Allow unverified SSL peer
+
+Wish
+
+    * [AMQCPP-309] - pkg-config library version mismatch
+    * [AMQCPP-334] - pkg-config output incorrect
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.2.4                               ==
+=========================================================================
+
+This release is a bugfix release that addresses a couple issues found since
+the release of v3.2.3
+
+bug:
+
+    * [AMQCPP-316] - Unable to receive any messages after re-starting message broker
+    * [AMQCPP-317] - activemq-cpp 3.2.2 will not work with activemq 5.4.0 broker
+                     using Stomp
+    * [AMQCPP-322] - Found memory leaks in ActiveMQCPP
+    * [AMQCPP-323] - The OnException method of registered Exception listener is not
+                     called when broker is stopped.
+    * [AMQCPP-324] - Destination options are ignored
+    * [AMQCPP-331] - Small typo in TcpTransportFactory.cpp
+    * [AMQCPP-332] - First send after we restart broker seems to always get a CmsException
+    * [AMQCPP-335] - redeliveryPolicy: rollback always loops
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.2.3                               ==
+=========================================================================
+
+This release is a bugfix release that addresses a couple issues found since
+the release of v3.2.2
+
+Bug
+
+    * [AMQCPP-312] - exception when bytearray is 0 length
+    * [AMQCPP-314] - Starting app with Com using cms destroys connection of
+                     other app. New problem with recent lib version
+    * [AMQCPP-315] - Advisory messages do not work with multiple listeners
+
+Wish
+
+    * [AMQCPP-309] - pkg-config library version mismatch
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.2.2                               ==
+=========================================================================
+
+This release is a bugfix release that addresses a couple issues found since
+the release of v3.2.1
+
+Bug
+
+    * [AMQCPP-301] - Unmarshal of an empty byte array in a MapMessage segfaults on Windows
+    * [AMQCPP-302] - Compilation issue with older GCC versions in MessageCompressionTest.cpp
+    * [AMQCPP-303] - SEGFAULT on startup (before main)
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.2.1                               ==
+=========================================================================
+
+This release is a bugfix release that addresses a couple issues for Windows
+users.
+
+Bug
+
+    * [AMQCPP-295] - Build Error on windows machines due to missing/wrong ifdef
+    * [AMQCPP-296] - vs2008 project files are missing in the download-package
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.2.0                               ==
+=========================================================================
+
+This is a major release featuring many new feature, performance improvements,
+bugfixes and tests.  The major new feature in this release is support for SSL
+using the popular OpenSSL library.  Also in this release Message body compression
+and a working QueueBrowser.
+
+Bug
+
+    * [AMQCPP-275] - Thread::UncaughtExceptionHandler missing virtual destructor
+    * [AMQCPP-280] - Missing call to pthread_detach on linux causes temporary resource leak.
+    * [AMQCPP-281] - Memory Leak in Pointer class Constructor when dynamic cast fails.
+    * [AMQCPP-285] - If brokerURI is ipv4 format(127.0.0.1), createConnection will throw decaf::lang::exceptions::NumberFormatException.
+    * [AMQCPP-288] - ResourceLifecycleManager needs to be thread-safe
+    * [AMQCPP-290] - Authentication error leads to pure virtual call/kaboom in CMS 3.1.1
+    * [AMQCPP-292] - transacted sessions over shared failover connection throws exceptions
+    * [AMQCPP-295] - Build Error on windows machines due to missing/wrong ifdef
+
+Improvement
+
+    * [AMQCPP-261] - Handle Multibyte Strings or Strings encoded in Charsets other than US-ASCII
+    * [AMQCPP-274] - Refactor Commands toString methods and Logging Transport to make debugging easier
+    * [AMQCPP-283] - Update Visual Studio projects to VS2008 format.
+    * [AMQCPP-287] - Implement Message Body Compression that works with Java and .NET clients
+    * [AMQCPP-293] - Add configuration options to ActiveMQConnectionFactory class
+
+New Feature
+
+    * [AMQCPP-129] - Implement QueueBrowser
+    * [AMQCPP-140] - Add SSL transport
+    * [AMQCPP-147] - Add Optimized Acknowledge support to the CPP client
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.1.3                               ==
+=========================================================================
+
+This release is a minor patch release that resolves an issue on Windows
+that could result in a thread deadlocking while a join operation was in
+progress.
+
+Bug
+
+    * [AMQCPP-277] - Freeze when creating multiple Consumers
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.1.2                               ==
+=========================================================================
+
+This release is a minor patch release that resolves a few memory leaks and
+other small bugs found since the 3.1.1 release.  The changes in this release
+should not break compatibility with the previous version.
+
+Bug
+
+    * [AMQCPP-273] - Segmentation violation after pure virtual method called in
+                     tempdest_advisory_producer example
+    * [AMQCPP-290] - Authentication error leads to pure virtual call/kaboom in CMS 3.1.1
+    * [AMQCPP-291] - Crash on sending a message with length = 0
+    * [AMQCPP-292] - transacted sessions over shared failover connection throws exceptions
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.1.1                               ==
+=========================================================================
+
+This release is a minor patch release that resolves a few memory leaks and
+other small bugs found since the 3.1.0 release.  The changes in this release
+should not break compatibility with the previous version.
+
+Bug
+
+    * [AMQCPP-273] - Segmentation violation after pure virtual method called
+                     in tempdest_advisory_producer example
+    * [AMQCPP-275] - Thread::UncaughtExceptionHandler missing virtual destructor
+    * [AMQCPP-280] - Missing call to pthread_detach on linux causes temporary
+                     resource leak.
+    * [AMQCPP-281] - Memory Leak in Pointer class Constructor when dynamic cast fails.
+    * [AMQCPP-285] - If brokerURI is ipv4 format(127.0.0.1), createConnection will
+                     throw decaf::lang::exceptions::NumberFormatException.
+    * [AMQCPP-286] - Memory leak when adding connection.sendTimeout=3000 to a
+                     failover transport
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.1.0                               ==
+=========================================================================
+
+This is a new Major release of ActiveMQ-CPP.  Many new features have been added
+and several bugs have been fixed.  The client now has an connection Inactivity
+Monitor which allows it to more quickly detect when a TCP connection has been
+broken.  The Threading code has been rewritten to improve performance and lower
+memory usage, and there have been several other performance improvements added
+throughout the code-base.
+
+Bug
+
+    * [AMQCPP-256] - Transaction has not been started exceptions on the broker with
+                     parallel transacted sessions
+    * [AMQCPP-257] - Segfault on session or connection cleanup
+    * [AMQCPP-260] - Wrong exception propogated from Transport close methods
+    * [AMQCPP-262] - exception message in checkWriteOnlyBody is wrong
+    * [AMQCPP-263] - Use of in-class static const variables in cms/DeliveryMode.h results
+                     in crash while linking with --no-undefined option
+    * [AMQCPP-266] - Client Ack is not applied across the session
+    * [AMQCPP-267] - ResponseCorrelator::request() exception safety concern
+    * [AMQCPP-268] - Unspecified exception can be thrown from
+                     decaf::io::ByteArrayOutputStream::write( const unsigned char* buffer,
+                     std::size_t offset, std::size_t len )
+    * [AMQCPP-270] - Broker exception on message Ack,
+    * [AMQCPP-271] - Connection shutdown crashes if the server went down
+    * [AMQCPP-272] - MessageProducer is not throwing correct exceptions when called with
+                     invalid arguments.
+
+Improvement
+
+    * [AMQCPP-240] - Add the Individual Ack type to the CMS API and support of it in the
+                     ActiveMQConsumer code.
+    * [AMQCPP-250] - Implement an Inactivity Monotir Transport filter for use on Transport
+                     that are used by the Failover Transport
+    * [AMQCPP-253] - Problems with compiler aCC on HPUX
+    * [AMQCPP-254] - Update client to add support for Openwire 4 and 5.
+    * [AMQCPP-258] - Allow clients to attach a TransportListener to an ActiveMQConnection
+    * [AMQCPP-264] - Added what() to CMSException
+    * [AMQCPP-265] - The C++ ActiveMQ StreamMessage and the Java ActiveMQ StreamMessage are
+                     not compatible.
+    * [AMQCPP-269] - Update CMS API to include the proper exceptions in the Message interfaces
+                     throw declarations
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.0.1                               ==
+=========================================================================
+
+This is a bugfix build that corrects a few issues that have been found since
+the 3.0 release, mainly in the area of Failover.
+
+Bug
+
+    * [AMQCPP-246] - Failover transport doesn't detect network failures
+    * [AMQCPP-247] - Exception thrown while using failover and Transacted sessions.
+    * [AMQCPP-248] - Failover Transport can deadlock when the connection fails
+                     during restore of previous state.
+    * [AMQCPP-249] - activemq/core/ActiveMQSession.cpp fails to compile on Solaris 10
+                     with Sun Studio Compiler
+    * [AMQCPP-252] - Can't set Producer Window Size from connection URI
+
+Improvement
+
+    * [AMQCPP-245] - Add docs to README file regarding the use of APR from MacPorts
+    * [AMQCPP-251] - default to use failover:tcp://localhost:8080 by default so we use
+                     reconnection out of the box
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 3.0                                 ==
+=========================================================================
+
+The 3.0 release represents a major reworking of the ActiveMQ-CPP code, many internal
+changes have been made to enhance stability and improve performance.  The major new
+feature in this release is the addition of the Failover Transport.
+
+Bug
+
+    * [AMQCPP-205] - CmsTemplate testBasics test can hang
+    * [AMQCPP-209] - Transaction Integration Tests for both Stomp and Openwire fail randomly
+    * [AMQCPP-218] - CMSException is not getting caught by base class std::exception.
+    * [AMQCPP-219] - Compilation errors in main/decaf/net on Solaris 10 with SunStudio 12
+    * [AMQCPP-220] - Memory leak in activemq-cpp
+    * [AMQCPP-223] - Message delivered async do not have their read only properties set properly.
+    * [AMQCPP-224] - Configure accept wrong versions of apr-util
+    * [AMQCPP-227] - Mutex class allows for double free in APR pools under certain circumstances
+    * [AMQCPP-232] - OpenWire encode and decode UTF8 incorrect
+    * [AMQCPP-234] - URI class helpers are missing the DLLExport Macro
+    * [AMQCPP-235] - UTF8 length marshaling bug in openwire readString and writeString.
+    * [AMQCPP-236] - maxInactivityDuration of Wire-Format is not supported by ActiveMQ-CPP2.2.5
+    * [AMQCPP-243] - Error when acknowledging messages that are sent to Virtual Topic subscribers
+
+Improvement
+
+    * [AMQCPP-100] - Implement a Failover Transport
+    * [AMQCPP-233] - Update Windows Builds Files to use ENV vars to find dependencies
+    * [AMQCPP-237] - Create 64bit configurations in the VC2005 build projects
+    * [AMQCPP-244] - Provide the configure script in the distribution
+
+New Feature
+
+    * [AMQCPP-153] - Additional decaf classes to support SSL
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 2.2.6                               ==
+=========================================================================
+
+This is another bugfix release in the 2.2.x series.  This release address a few issues
+related to String marshaling and unmarshaling, we can now encode ASCII values greater
+than 127 into modified UTF-8 along with any embedded Nulls in the string.  The URI option
+for setting Max inactivity duration now works properly as well.
+
+Bug
+
+    * [AMQCPP-232] - OpenWire encode and decode UTF8 incorrect
+    * [AMQCPP-234] - URI class helpers are missing the DLLExport Macro
+    * [AMQCPP-235] - UTF8 length marshalling bug in openwire readString and writeString.
+    * [AMQCPP-236] - maxInactivityDuration of Wire-Format is not supported by ActiveMQ-CPP2.2.5
+
+Improvement
+
+    * [AMQCPP-233] - Update Windows Builds Files to use ENV vars to find dependancies
+    * [AMQCPP-237] - Create 64bit configurations in the VC2005 build projects
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 2.2.5                               ==
+=========================================================================
+
+This is a minor release which mainly resolves a few small bugs that have
+been identified since the 2.2.4 release.  Also a few more fixes to improve
+compatibility with the Sun compiler has been added.  One big improvement
+in this release is that the Message's are now delivered with the read-only
+state consistently set correctly.
+
+Bug
+
+    * [AMQCPP-223] - Message delivered async do not have their read only properties set properly.
+    * [AMQCPP-224] - Configure accept wrong versions of apr-util
+    * [AMQCPP-225] - configure.ac does not work correctly on Solaris with SunStudio Compiler
+    * [AMQCPP-227] - Mutex class allows for double free in APR pools under certain circumstances
+    * [AMQCPP-230] - BlockByteArrayInputStream read method is not thread safe
+
+Improvement
+
+    * [AMQCPP-229] - Session createTopic and createQueue don't provide clear error when an empty
+                     Destination is given
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 2.2.4                               ==
+=========================================================================
+
+This is a minor release which mainly resolves a few memory leak issues that
+have been identified since the 2.2.3 release.  Also a small fix to improve
+compatibility with the Sun compiler has been added.
+
+Bug
+
+    * [AMQCPP-219] - Compilation errors in main/decaf/net on Solaris 10 with SunStudio 12
+    * [AMQCPP-220] - Memory leak in activemq-cpp
+
+Improvement
+
+    * [AMQCPP-222] - Potential memory leak in OpenWire Commands
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 2.2.3                               ==
+=========================================================================
+
+This is a minor release that contains bugfixes that were found since the
+2.2.2 release.  This version adds support for responding to KeepAlive
+requests from the broker, and it now properly sets JMSX properties on both
+stomp and openwire commands.  Users can now delete destinations using the
+deleteDestination function in ActiveMQConnection.
+
+Bug
+
+    * [AMQCPP-158] - libtool release and version-info arguments need to be set correctly
+    * [AMQCPP-184] - TransportFilter::fire() crashes after accessing a dangling pointer during exception in ActiveMQConnectionFactory::createConnection()
+    * [AMQCPP-193] - If activeMQ blocks due to reaching memory limit during a transaction, the last message sent is posted to the queue after the rollback occurs and persists
+    * [AMQCPP-210] - ActiveMQ-CPP on Mac OS X and iPhone OS link error
+    * [AMQCPP-213] - JMSXGroupID works with Stomp, not OpenWire.
+
+Improvement
+
+    * [AMQCPP-183] - Add a note about using LIBTOOLIZE environment variable when building on MacOS X
+    * [AMQCPP-208] - Update Openwire Command and Marshaler generator
+    * [AMQCPP-211] - Add support for responding to the KeepAliveInfo message from the Broker to Openwire
+
+New Feature
+
+    * [AMQCPP-169] - Add a new Broker managment interface in ActiveMQ Core.
+
+Task
+
+    * [AMQCPP-212] - Add more examples to the CPP Client
+
+Wish
+
+    * [AMQCPP-176] - Work around Visual Studio .NET 2003 covariant return issues
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 2.2.2                               ==
+=========================================================================
+
+This is a minor release that contains bugfixes that were found since the
+2.2.1 release.  Also in this release the there have been several memory leak
+fixes and threading issues resolved.  The connection URI options have
+changed to reflect improved asynchronous message send capabilities as well,
+see the wiki for the new configuration option documentation.  This version
+of the library now requires APR 1.3 or higher to compile.
+
+Sub-task
+
+    * [AMQCPP-202] - Occasional Deadlocks when Integration tests are run in a
+                     long loop on CentOS and REHL.
+    * [AMQCPP-203] - Segmentation Fault in Integration tests occurs occasionally.
+
+Bug
+
+    * [AMQCPP-197] - include file activemq/exceptions/ExceptionDefines.h missing
+    * [AMQCPP-198] - File activemq/exceptions/ActiveMQException.h isn't installed
+                     during make install
+    * [AMQCPP-199] - Segmentation fault at decaf/net/SocketInputStream.cpp (line 108)
+    * [AMQCPP-200] - activemq-cpp-2.2.1 test fails for
+                     decaf::io::ByteArrayInputStreamTest::testConstructor (segmentation fault)
+
+Improvement
+
+    * [AMQCPP-196] - Make the openwire connecter handle sending messages sync or async
+                     based on rules and settings
+    * [AMQCPP-206] - Fix warnings generated when compiling the library on Windows.
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 2.2.1                               ==
+=========================================================================
+
+This is a minor release that contains bugfixes that were found since the
+2.2 release.
+
+Sub-task
+
+    * [AMQCPP-189] - the message producer core dump during sending lots of messages
+
+Bug
+
+    * [AMQCPP-165] - Core Dump on reconnect/open queue
+    * [AMQCPP-184] - TransportFilter::fire() crashes after accessing a dangling
+                     pointer during exception in ActiveMQConnectionFactory::createConnection()
+    * [AMQCPP-185] - Some CmsTemplate headers missing from headers section in Makefile.am
+    * [AMQCPP-188] - ActiveMQ message consumer waiting for receive to complete is not closing...
+    * [AMQCPP-190] - setStringProperty() max length
+    * [AMQCPP-191] - autogen.sh fails to create configure : doxygen-related
+    * [AMQCPP-194] - Potential Deadlock in OpenwireConnector on exception from transport
+    * [AMQCPP-195] - Message stuck in queue when using transactional sessions
+
+Improvement
+
+    * [AMQCPP-179] - Add support for the openwire 3.0 commands
+    * [AMQCPP-192] - Add getCause to the CMS and Decaf exception interfaces
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 2.2                                 ==
+=========================================================================
+
+This release has seen a large restructuring of the codebase to separate
+out to platform code into a new package called decaf.  We are now making
+use of the APR and APR-Util libraries for platform independence.  Also
+many new tests and bug fixes have made their way into this release.
+
+Sub-task
+
+    * [AMQCPP-164] - Math functions don't all exist on the windows platform
+
+Bug
+
+    * [AMQCPP-136] - Some IO Stream classes don't honor the stream interface contract
+    * [AMQCPP-155] - Problem changing from "AUTO_ACKNOWLEDGE" to "SESSION_TRANSACTED"
+    * [AMQCPP-157] - Interoperability issues between C++ and .NET
+    * [AMQCPP-158] - libtool release and version-info arguments need to be set correctly
+    * [AMQCPP-159] - autogen.sh fails to create configure
+    * [AMQCPP-161] - CMS does not support prefetchSize=0 correctly
+    * [AMQCPP-163] - Durable Subscriber test fails consistantly on linux and windows
+    * [AMQCPP-165] - Core Dump on reconnect/open queue
+    * [AMQCPP-166] - MapMessage does not send mapped fields
+    * [AMQCPP-167] - Client has memory leaks when used in an MFC application
+    * [AMQCPP-170] - SEGV in activemq::connector::openwire::OpenWireConnector::createProducer
+    * [AMQCPP-173] - C++ Client has memory leaks
+    * [AMQCPP-174] - Deadlock on transacted session
+    * [AMQCPP-178] - Core dump in ActiveMQException::buildMessage
+    * [AMQCPP-181] - Failed unit tests in 2.2 RC1
+    * [AMQCPP-182] - Compile with GCC 4.3.0 fails
+
+Improvement
+
+    * [AMQCPP-103] - Pull out generic libraries from activemq-cpp namespace
+    * [AMQCPP-138] - Streams classes do not honor their Interface Contracts
+    * [AMQCPP-151] - Add a static create method to CMS ConnectionFactory
+    * [AMQCPP-168] - Create a connection can block for up to 4 mins under Linux when TCP socket connect() times out
+    * [AMQCPP-172] - Add support for MAP_TYPE and LIST_TYPE to the PrimitiveMap implementation
+    * [AMQCPP-177] - Defines for static linking with APR on Windows
+
+New Feature
+
+    * [AMQCPP-148] - Add support for embedding environment variables in connection URI
+    * [AMQCPP-152] - Create a CmsTemplate class
+
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 2.1.3                               ==
+=========================================================================
+
+This release adds support for building the library and tests, etc on the
+Solaris platform using the Sun Compiler in Sun Studio 11.
+
+Improvement
+
+    * [AMQCPP-154] - Improve build compatibility (Solaris)
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 2.1.2                               ==
+=========================================================================
+
+This release adds support for building the library and tests, etc on the
+Solaris platform using the Sun Compiler in Sun Studio 11.
+
+Improvement
+
+    * [AMQCPP-154] - Improve build compatibility (Solaris)
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 2.1.1                               ==
+=========================================================================
+
+== Overview ==
+
+This version includes several bugfixes, as well as some new examples.  Also
+a lot of work has been done on performance and memory leaks and stability.
+
+NOTE: Compatable with ActiveMQ Broker version >= 4.0
+
+Bug
+
+    * [AMQCPP-111] - Unable to ./configure under Suse Linux 64 bit
+    * [AMQCPP-137] - Exception in ResponseCorrelator::onCommand()
+    * [AMQCPP-141] - ActiveMQTextMessage::getText() causes an index out of bounds assertion failure if trying to read a 0 length text message
+    * [AMQCPP-142] - BufferedOutputStream flush called after BufferedOutputStream close resulting in unhandled exceptions
+    * [AMQCPP-144] - Decaf library build fails on OS X
+    * [AMQCPP-145] - Compiler error concerning TRANSACTION_ROLLBACK
+    * [AMQCPP-149] - Client crash when receiving message with empty string property from java
+    * [AMQCPP-150] - ActiveMQ-CPP consumer client hanging after receiving 32767 messages.
+
+Improvement
+
+    * [AMQCPP-99] - Incorporate APR for generation of GUIDs
+    * [AMQCPP-124] - Provide a ConnectionMetaData interface in CMS
+    * [AMQCPP-139] - Improvements for the Openwire Commands Generated Code
+    * [AMQCPP-143] - declara BytesMessage::readXXX() methods as 'const'
+    * [AMQCPP-146] - Refactor sequence id generation in the connectors
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 2.1                               ==
+=========================================================================
+
+== Overview ==
+
+This version includes several bugfixes, as well as some new features.  Also
+a lot of work has been done on performance and memory leaks.  One new feature that
+has been highly anticipated is that we now build both shared and static libraries.
+
+NOTE: Compatable with ActiveMQ Broker version >= 4.0.2
+
+== Issues Resolved ==
+
+Bug
+
+    * [AMQCPP-104] - Enabling async send prevents program from terminating properly on Windows
+    * [AMQCPP-119] - getClientID segfaults is called after connection has been closed
+    * [AMQCPP-120] - Possible memory leak in StompConnector
+    * [AMQCPP-121] - Possible memory leak in activemq::transport::IOTransport::run
+    * [AMQCPP-122] - Crash on Windows when rapidly creating and destroying connections
+    * [AMQCPP-126] - closing ressources after an IOException crashes the app
+    * [AMQCPP-128] - Transacted session crashes or loses messages
+    * [AMQCPP-131] - StompConnector doesn't rethrow UnsupportedOperationException
+    * [AMQCPP-132] - Unsubscribe of durable subscription fails
+    * [AMQCPP-133] - Receive of plain Message with Openwire returns null
+    * [AMQCPP-134] - Compiler warnings have returned for tests on gcc
+
+Improvement
+
+    * [AMQCPP-65] - Refactor transport creation
+    * [AMQCPP-66] - Refactor the Async send to happen in an Async Transport instead of in ActiveMQSession
+    * [AMQCPP-108] - Make stomp connector more generic
+    * [AMQCPP-110] - Create activemqcpp-openwire-generator build in our pom.xml, move code to src/main/java
+    * [AMQCPP-116] - quick improvements to CMS example code
+    * [AMQCPP-118] - Provide a way to allocate and free with the same allocator
+    * [AMQCPP-123] - Link error when trying to link another shared library against AMQCPP on 64-bit Linux
+    * [AMQCPP-127] - ResponseCorrelator doesn't have a way to set max timeot from the properties uri.
+    * [AMQCPP-130] - Enhance the DummyTransport and rename it to MockTransport
+
+New Feature
+
+    * [AMQCPP-125] - Decaf: Random
+
+Task
+
+    * [AMQCPP-106] - reorganize subversion
+    * [AMQCPP-115] - Change build to create dynamic libraries
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 2.0.1                               ==
+=========================================================================
+
+== Overview ==
+
+This version is a bug fix release for issues that were found in the 2.0 release
+
+NOTE: Compatable with ActiveMQ Broker version >= 4.0.2
+
+== Issues Resolved ==
+
+Bug
+
+    * [AMQCPP-105] - Openwire ActiveMQMessage sets Persistant flag incorrectly
+    * [AMQCPP-107] - SocketInputStream::read() doesn't check for EINTR error
+    * [AMQCPP-109] - Exception when acknowledging null messages, originating from the receipt of an ObjectMessage
+    * [AMQCPP-112] - Openwire Experiation Integration tests fail when fixed to actually use Openwire
+
+Improvement
+
+    * [AMQCPP-101] - Add the Ability to set the TcpNoDelay flag of a TCP Socket
+    * [AMQCPP-102] - Create a Tag for CMS
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 2.0                                 ==
+=========================================================================
+
+== Overview ==
+
+This version is a major release containing new features and bug fixes.
+
+    * Full OpenWire v2 support!
+    * You can switch between openwire and stomp via the connection URL
+    * Temporary destinations when using OpenWire
+    * Added support for asynchronous send
+    * Fixed client acknowledge
+    * Resolved some memory leaks
+    * Sessions are now single threaded
+
+NOTE: Compatable with ActiveMQ Broker version >= 4.0.2
+
+== Issues Resolved ==
+
+Bug
+
+    * [AMQCPP-38] - Async error on broker when running integration tests
+    * [AMQCPP-44] - Reason for socket errors not reported correctly on Windows
+    * [AMQCPP-46] - ActiveMQConnection doesn't propagate exception listener to underlying connector
+    * [AMQCPP-51] - Autoconf is not properly setting CXXFLAGS on Linux
+    * [AMQCPP-52] - Valgrind reports memory leaks when running PrimitiveMapTest
+    * [AMQCPP-53] - Declaration of extern int errno after including errno.h doesn't compile
+    * [AMQCPP-54] - Build broken due to autoconf problem?
+    * [AMQCPP-55] - Need close() to propagate to child resources
+    * [AMQCPP-56] - GCC warnings and possible SocketFactory bug on 64-bit Linux
+    * [AMQCPP-58] - Possible memory leak when reestablishing connection
+    * [AMQCPP-59] - Exception is thrown when destroying consumer after connection failure
+    * [AMQCPP-60] - message information is lost from stomp message to jms
+    * [AMQCPP-61] - CMSException::what returns c_str of temporary std::string
+    * [AMQCPP-62] - Broken CLIENT_ACKNOWLEDGE
+    * [AMQCPP-64] - Inconsistency in topic names when creating topics
+    * [AMQCPP-75] - setCMSReplyTo with null destination segfaults when using Openwire wire format
+    * [AMQCPP-76] - Integer property not propagated when using Openwire
+    * [AMQCPP-77] - Inconsistency when getting string property between Stomp and Openwire
+    * [AMQCPP-78] - session tries to destroy already destroyed temporary queue
+    * [AMQCPP-80] - sending with explicit message id hangs
+    * [AMQCPP-81] - openwire consumer never receives messages already in queue
+    * [AMQCPP-83] - Integration tests fail for openwire
+    * [AMQCPP-85] - activemq/util/Character.h not being installed by automake
+    * [AMQCPP-86] - Valgrind reports memory leaks in unit tests
+    * [AMQCPP-87] - ActiveMQConnectionFactory creates only one unique clientId
+    * [AMQCPP-90] - Openwire Session doesn't run its MessageListeners from a single thread
+    * [AMQCPP-91] - A few more Openwire memory leaks
+    * [AMQCPP-92] - memory leak in openwire session info
+
+Improvement
+
+    * [AMQCPP-40] - A few stray unix and sun defines
+    * [AMQCPP-47] - MapMessage getters should be const
+    * [AMQCPP-48] - Fix compilation with Visual Studio .NET 2003
+    * [AMQCPP-49] - Add -W -Wall compile options
+    * [AMQCPP-50] - Derive cms::CMSException from std::exception
+    * [AMQCPP-57] - Typo in names of delivery modes
+    * [AMQCPP-79] - allow createProducer to accept null destination
+    * [AMQCPP-89] - Case of cms::Message getter and setter names are not consistent with case of JMS Message getter and setter names
+    * [AMQCPP-94] - StompConnector should use Long::toString instead of Integer::toString
+
+New Feature
+
+    * [AMQCPP-30] - Add support to activemq-cpp to support the openwire protocol
+    * [AMQCPP-63] - asynchronous send
+
+Task
+
+    * [AMQCPP-82] - Make openwire the default protocol
+    * [AMQCPP-84] - add unit/integration tests
+    * [AMQCPP-88] - Remove setCMSMessageId from CMS API
+    * [AMQCPP-95] - Perform Memory Leak testing on 2.0 codebase
+
+
+=========================================================================
+==  Release Notes for ActiveMQ CPP 1.1                                 ==
+=========================================================================
+
+== Overview ==
+
+This version fixes several bugs and adds a few new features.
+
+    * Updated interface for cms::BytesMessage - more JMS-like.
+    * Updated the MessageProducer interface to add multiple versions of the send method
+    * Fixed several memory leaks
+    * Now run on linux, win32, OS X, and Solaris
+    * Persistence is fixed
+    * Fixed deadlocks when closing a connection
+    * Fixed message expiration
+
+NOTE: Compatable with ActiveMQ Broker version >= 4.0.2
+
+== Issues Resolved ==
+
+Bug
+
+    * [AMQCPP-3] - Receiving a BytesMessage sent from Java using CMS listener causes exception thrown in class BufferedInputStream
+    * [AMQCPP-14] - CMSExpiration not handled properly in ActiveMQProducer
+    * [AMQCPP-18] - ActiveMQConnection.close() causes app to crash
+    * [AMQCPP-20] - Deadlock when in stomp connector close
+    * [AMQCPP-22] - Use common name for ActiveMQ C++ library on Windows and Linux
+    * [AMQCPP-23] - active-cpp persistent problem
+    * [AMQCPP-25] - Bus error on Solaris OS from DataInput and DataOutput streams
+    * [AMQCPP-26] - Memory leaks reported by Rational Purify when running unit tests
+    * [AMQCPP-27] - Issues reported by Valgrind when running unit tests
+    * [AMQCPP-28] - Purify and Valgrind warnings when running integration tests
+    * [AMQCPP-29] - Projects in MSVC build building on top of one another
+    * [AMQCPP-35] - Stomp content-length header not being set on BytesMessage
+    * [AMQCPP-39] - Some AMQCPP includes not installed when doing make install on Linux
+    * [AMQCPP-41] - Byte swap on float and double truncates values
+    * [AMQCPP-43] - Crash when getting string property that doesn't exist
+
+Improvement
+
+    * [AMQCPP-16] - CMS API needs updates to more closely follow JMS API
+    * [AMQCPP-33] - Integration tests crash if broker isn't running
+    * [AMQCPP-36] - Cleanup whitespace and member function definitions in header files
+    * [AMQCPP-42] - A few more strict aliasing warnings
+
+New Feature
+
+    * [AMQCPP-15] - Add other versions of send method to CMS MessageProducer
+    * [AMQCPP-37] - readUTF and writeUTF for BytesMessage
+
+Task
+
+    * [AMQCPP-45] - Update configure.ac with release version
+
+Wish
+
+    * [AMQCPP-31] - Consider giving the unix #define a more unique name
+    * [AMQCPP-32] - Stomp messages don't preserve property types: please document this behaviour

http://git-wip-us.apache.org/repos/asf/activemq-web/blob/c5128cb5/ReadMe.html
----------------------------------------------------------------------
diff --git a/ReadMe.html b/ReadMe.html
new file mode 100644
index 0000000..34e8c81
--- /dev/null
+++ b/ReadMe.html
@@ -0,0 +1,9 @@
+<html>
+	<body>
+		<h1>Apache ActiveMQ XML Schemas</h1>
+		
+		<p>This site contains all the various versions of the XML Schema Documents for the <a href="http://activemq.apache.org/">Apache ActiveMQ project</a></p>
+		
+		<p>For details of how to use the XML Schema files, particularly with Spring, please see the <a href="http://activemq.apache.org/xml-reference.html">XML Reference</a></p>
+	</body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/activemq-web/blob/c5128cb5/SimpleProducer.java
----------------------------------------------------------------------
diff --git a/SimpleProducer.java b/SimpleProducer.java
new file mode 100644
index 0000000..85061c8
--- /dev/null
+++ b/SimpleProducer.java
@@ -0,0 +1,139 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * The SimpleQueueSender class consists only of a main method,
+ * which sends several messages to a queue.
+ *
+ * Run this program in conjunction with SimpleQueueReceiver.
+ * Specify a queue name on the command line when you run the
+ * program.  By default, the program sends one message.  Specify
+ * a number after the queue name to send that number of messages.
+ */
+package org.apache.activemq.demo;
+
+// START SNIPPET: demo
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A simple polymorphic JMS producer which can work with Queues or Topics which
+ * uses JNDI to lookup the JMS connection factory and destination
+ * 
+ * 
+ */
+public final class SimpleProducer {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SimpleProducer.class);
+
+    private SimpleProducer() {
+    }
+
+    /**
+     * @param args the destination name to send to and optionally, the number of
+     *                messages to send
+     */
+    public static void main(String[] args) {
+        Context jndiContext = null;
+        ConnectionFactory connectionFactory = null;
+        Connection connection = null;
+        Session session = null;
+        Destination destination = null;
+        MessageProducer producer = null;
+        String destinationName = null;
+        final int numMsgs;
+
+        if ((args.length < 1) || (args.length > 2)) {
+            LOG.info("Usage: java SimpleProducer <destination-name> [<number-of-messages>]");
+            System.exit(1);
+        }
+        destinationName = args[0];
+        LOG.info("Destination name is " + destinationName);
+        if (args.length == 2) {
+            numMsgs = (new Integer(args[1])).intValue();
+        } else {
+            numMsgs = 1;
+        }
+
+        /*
+         * Create a JNDI API InitialContext object
+         */
+        try {
+            jndiContext = new InitialContext();
+        } catch (NamingException e) {
+            LOG.info("Could not create JNDI API context: " + e.toString());
+            System.exit(1);
+        }
+
+        /*
+         * Look up connection factory and destination.
+         */
+        try {
+            connectionFactory = (ConnectionFactory)jndiContext.lookup("ConnectionFactory");
+            destination = (Destination)jndiContext.lookup(destinationName);
+        } catch (NamingException e) {
+            LOG.info("JNDI API lookup failed: " + e);
+            System.exit(1);
+        }
+
+        /*
+         * Create connection. Create session from connection; false means
+         * session is not transacted. Create sender and text message. Send
+         * messages, varying text slightly. Send end-of-messages message.
+         * Finally, close connection.
+         */
+        try {
+            connection = connectionFactory.createConnection();
+            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+            producer = session.createProducer(destination);
+            TextMessage message = session.createTextMessage();
+            for (int i = 0; i < numMsgs; i++) {
+                message.setText("This is message " + (i + 1));
+                LOG.info("Sending message: " + message.getText());
+                producer.send(message);
+            }
+
+            /*
+             * Send a non-text control message indicating end of messages.
+             */
+            producer.send(session.createMessage());
+        } catch (JMSException e) {
+            LOG.info("Exception occurred: " + e);
+        } finally {
+            if (connection != null) {
+                try {
+                    connection.close();
+                } catch (JMSException e) {
+                }
+            }
+        }
+    }
+}
+
+// END SNIPPET: demo