You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by jb...@apache.org on 2014/01/18 15:32:38 UTC

[1/2] [KARAF-2642] Merge jms feature

Updated Branches:
  refs/heads/karaf-2.x 36761d5d5 -> 9de0903e8


http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsServiceImpl.java
----------------------------------------------------------------------
diff --git a/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsServiceImpl.java b/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsServiceImpl.java
new file mode 100644
index 0000000..4d3caf3
--- /dev/null
+++ b/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsServiceImpl.java
@@ -0,0 +1,430 @@
+/*
+ * 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.karaf.jms.internal;
+
+import org.apache.activemq.ActiveMQConnection;
+import org.apache.activemq.advisory.DestinationSource;
+import org.apache.activemq.command.ActiveMQQueue;
+import org.apache.activemq.command.ActiveMQTopic;
+import org.apache.activemq.pool.PooledConnection;
+import org.apache.karaf.jms.JmsMessage;
+import org.apache.karaf.jms.JmsService;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+import javax.jms.*;
+import java.io.*;
+import java.lang.IllegalStateException;
+import java.util.*;
+
+/**
+ * Default implementation of the JMS Service.
+ */
+public class JmsServiceImpl implements JmsService {
+
+    private BundleContext bundleContext;
+
+    public void create(String name, String type, String url) throws Exception {
+        if (!type.equalsIgnoreCase("activemq") && !type.equalsIgnoreCase("webspheremq")) {
+            throw new IllegalArgumentException("JMS connection factory type not known");
+        }
+
+        File karafBase = new File(System.getProperty("karaf.base"));
+        File deployFolder = new File(karafBase, "deploy");
+        File  outFile = new File(deployFolder, "connectionfactory-" + name + ".xml");
+
+        if (type.equalsIgnoreCase("activemq")) {
+            // activemq
+            HashMap<String, String> properties = new HashMap<String, String>();
+            properties.put("${name}", name);
+            properties.put("${url}", url);
+            copyDataSourceFile(outFile, "connectionfactory-activemq.xml", properties);
+        } else {
+            // webspheremq
+            String[] splitted = url.split("/");
+            if (splitted.length != 4) {
+                throw new IllegalStateException("WebsphereMQ URI should be in the following format: host/port/queuemanager/channel");
+            }
+            HashMap<String, String> properties = new HashMap<String, String>();
+            properties.put("${name}", name);
+            properties.put("${host}", splitted[0]);
+            properties.put("${port}", splitted[1]);
+            properties.put("${queuemanager}", splitted[2]);
+            properties.put("${channel}", splitted[3]);
+            copyDataSourceFile(outFile, "connectionfactory-webspheremq.xml", properties);
+        }
+    }
+
+    public void delete(String name) throws Exception {
+        File karafBase = new File(System.getProperty("karaf.base"));
+        File deployFolder = new File(karafBase, "deploy");
+        File connectionFactoryFile = new File(deployFolder, "connectionfactory-" + name + ".xml");
+        if (!connectionFactoryFile.exists()) {
+            throw new IllegalStateException("The JMS connection factory file " + connectionFactoryFile.getPath() + " doesn't exist");
+        }
+        connectionFactoryFile.delete();
+    }
+
+    public List<String> connectionFactories() throws Exception {
+        List<String> connectionFactories = new ArrayList<String>();
+        ServiceReference[] references = bundleContext.getServiceReferences(ConnectionFactory.class.getName(), null);
+        if (references != null) {
+            for (ServiceReference reference : references) {
+                if (reference.getProperty("osgi.jndi.service.name") != null) {
+                    connectionFactories.add((String) reference.getProperty("osgi.jndi.service.name"));
+                } else if (reference.getProperty("name") != null) {
+                    connectionFactories.add((String) reference.getProperty("name"));
+                } else {
+                    connectionFactories.add(reference.getProperty(Constants.SERVICE_ID).toString());
+                }
+            }
+        }
+        return connectionFactories;
+    }
+
+    public List<String> connectionFactoryFileNames() throws Exception {
+        File karafBase = new File(System.getProperty("karaf.base"));
+        File deployFolder = new File(karafBase, "deploy");
+
+        String[] connectionFactoryFileNames = deployFolder.list(new FilenameFilter() {
+            public boolean accept(File dir, String name) {
+                return name.startsWith("connectionfactory-") && name.endsWith(".xml");
+            }
+        });
+
+        return Arrays.asList(connectionFactoryFileNames);
+    }
+
+    public Map<String, String> info(String connectionFactory, String username, String password) throws Exception {
+        Map<String, String> map = new HashMap<String, String>();
+        ServiceReference reference = this.lookupConnectionFactory(connectionFactory);
+        Connection connection = null;
+        try {
+            ConnectionFactory cf = (ConnectionFactory) bundleContext.getService(reference);
+            connection = cf.createConnection(username, password);
+            connection.start();
+            ConnectionMetaData metaData = connection.getMetaData();
+            map.put("product", metaData.getJMSProviderName());
+            map.put("version", metaData.getProviderVersion());
+        } finally {
+            if (connection != null) {
+                connection.close();
+            }
+            if (reference != null) {
+                bundleContext.ungetService(reference);
+            }
+        }
+        return map;
+    }
+
+    public int count(String connectionFactory, String destination, String username, String password) throws Exception {
+        ServiceReference reference = this.lookupConnectionFactory(connectionFactory);
+        Connection connection = null;
+        Session session = null;
+        try {
+            ConnectionFactory cf = (ConnectionFactory) bundleContext.getService(reference);
+            connection = cf.createConnection(username, password);
+            connection.start();
+            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+            QueueBrowser browser = session.createBrowser(session.createQueue(destination));
+            Enumeration<Message> enumeration = browser.getEnumeration();
+            int count = 0;
+            while (enumeration.hasMoreElements()) {
+                enumeration.nextElement();
+                count++;
+            }
+            browser.close();
+            return count;
+        } finally {
+            if (session != null) {
+                session.close();
+            }
+            if (connection != null) {
+                connection.close();
+            }
+            if (reference != null) {
+                bundleContext.ungetService(reference);
+            }
+        }
+    }
+
+    public List<String> queues(String connectionFactory, String username, String password) throws Exception {
+        List<String> queues = new ArrayList<String>();
+        ServiceReference reference = this.lookupConnectionFactory(connectionFactory);
+        Connection connection = null;
+        try {
+            ConnectionFactory cf = (ConnectionFactory) bundleContext.getService(reference);
+            connection = cf.createConnection(username, password);
+            connection.start();
+            if (connection instanceof PooledConnection) {
+                connection = ((PooledConnection) connection).getConnection();
+            }
+            if (connection instanceof ActiveMQConnection) {
+                DestinationSource destinationSource = ((ActiveMQConnection) connection).getDestinationSource();
+                Set<ActiveMQQueue> activeMQQueues = destinationSource.getQueues();
+                for (ActiveMQQueue activeMQQueue : activeMQQueues) {
+                    queues.add(activeMQQueue.getQueueName());
+                }
+            }
+        } finally {
+            if (connection != null) {
+                connection.close();
+            }
+            if (reference != null) {
+                bundleContext.ungetService(reference);
+            }
+        }
+        return queues;
+    }
+
+    public List<String> topics(String connectionFactory, String username, String password) throws Exception {
+        List<String> topics = new ArrayList<String>();
+        ServiceReference reference = this.lookupConnectionFactory(connectionFactory);
+        Connection connection = null;
+        try {
+            ConnectionFactory cf = (ConnectionFactory) bundleContext.getService(reference);
+            connection = cf.createConnection(username, password);
+            connection.start();
+            if (connection instanceof PooledConnection) {
+                connection = ((PooledConnection) connection).getConnection();
+            }
+            if (connection instanceof ActiveMQConnection) {
+                DestinationSource destinationSource = ((ActiveMQConnection) connection).getDestinationSource();
+                Set<ActiveMQTopic> activeMQTopics = destinationSource.getTopics();
+                for (ActiveMQTopic activeMQTopic : activeMQTopics) {
+                    topics.add(activeMQTopic.getTopicName());
+                }
+            }
+        } finally {
+            if (connection != null) {
+                connection.close();
+            }
+            if (reference != null) {
+                bundleContext.ungetService(reference);
+            }
+        }
+        return topics;
+    }
+
+    public List<JmsMessage> browse(String connectionFactory, String queue, String filter, String username, String password) throws Exception {
+        List<JmsMessage> messages = new ArrayList<JmsMessage>();
+        ServiceReference reference = this.lookupConnectionFactory(connectionFactory);
+        Connection connection = null;
+        Session session = null;
+        try {
+            ConnectionFactory cf = (ConnectionFactory) bundleContext.getService(reference);
+            connection = cf.createConnection(username, password);
+            connection.start();
+            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+            QueueBrowser browser = session.createBrowser(session.createQueue(queue), filter);
+            Enumeration<Message> enumeration = browser.getEnumeration();
+            while (enumeration.hasMoreElements()) {
+                Message message = enumeration.nextElement();
+
+                messages.add(new JmsMessage(message));
+            }
+            browser.close();
+        } finally {
+            if (session != null) {
+                session.close();
+            }
+            if (connection != null) {
+                connection.close();
+            }
+            if (reference != null) {
+                bundleContext.ungetService(reference);
+            }
+        }
+        return messages;
+    }
+
+    public void send(String connectionFactory, String queue, String body, String replyTo, String username, String password) throws Exception {
+        ServiceReference reference = this.lookupConnectionFactory(connectionFactory);
+        Connection connection = null;
+        Session session = null;
+        try {
+            ConnectionFactory cf = (ConnectionFactory) bundleContext.getService(reference);
+            connection = cf.createConnection(username, password);
+            connection.start();
+            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+            Message message = session.createTextMessage(body);
+            if (replyTo != null) {
+                message.setJMSReplyTo(session.createQueue(replyTo));
+            }
+            MessageProducer producer = session.createProducer(session.createQueue(queue));
+            producer.send(message);
+            producer.close();
+        } finally {
+            if (session != null) {
+                session.close();
+            }
+            if (connection != null) {
+                connection.close();
+            }
+            if (reference != null) {
+                bundleContext.ungetService(reference);
+            }
+        }
+    }
+
+    public int consume(String connectionFactory, String queue, String selector, String username, String password) throws Exception {
+        int count = 0;
+        ServiceReference reference = this.lookupConnectionFactory(connectionFactory);
+        Connection connection = null;
+        Session session = null;
+        try {
+            ConnectionFactory cf = (ConnectionFactory) bundleContext.getService(reference);
+            connection = cf.createConnection(username, password);
+            connection.start();
+            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+            MessageConsumer consumer = session.createConsumer(session.createQueue(queue), selector);
+            Message message;
+            do {
+                message = consumer.receiveNoWait();
+                if (message != null) {
+                    count++;
+                }
+            } while (message != null);
+        } finally {
+            if (session != null) {
+                session.close();
+            }
+            if (connection != null) {
+                connection.close();
+            }
+            if (reference != null) {
+                bundleContext.ungetService(reference);
+            }
+        }
+        return count;
+    }
+
+    public int move(String connectionFactory, String sourceQueue, String targetQueue, String selector, String username, String password) throws Exception {
+        int count = 0;
+        ServiceReference reference = this.lookupConnectionFactory(connectionFactory);
+        Connection connection = null;
+        Session session = null;
+        try {
+            ConnectionFactory cf = (ConnectionFactory) bundleContext.getService(reference);
+            connection = cf.createConnection(username, password);
+            connection.start();
+            session = connection.createSession(true, Session.SESSION_TRANSACTED);
+            MessageConsumer consumer = session.createConsumer(session.createQueue(sourceQueue), selector);
+            Message message;
+            do {
+                message = consumer.receiveNoWait();
+                if (message != null) {
+                    MessageProducer producer = session.createProducer(session.createQueue(targetQueue));
+                    producer.send(message);
+                    count++;
+                }
+            } while (message != null);
+            session.commit();
+        } finally {
+            if (session != null) {
+                session.close();
+            }
+            if (connection != null) {
+                connection.close();
+            }
+            if (reference != null) {
+                bundleContext.ungetService(reference);
+            }
+        }
+        return count;
+    }
+
+    private ServiceReference lookupConnectionFactory(String name) throws Exception {
+        ServiceReference[] references = bundleContext.getServiceReferences(ConnectionFactory.class.getName(), "(|(osgi.jndi.service.name=" + name + ")(name=" + name + ")(service.id=" + name + "))");
+        if (references == null || references.length == 0) {
+            throw new IllegalArgumentException("No JMS connection factory found for " + name);
+        }
+        if (references.length > 1) {
+            throw new IllegalArgumentException("Multiple JMS connection factories found for " + name);
+        }
+        return references[0];
+    }
+
+    private void copyDataSourceFile(File outFile, String resource, HashMap<String, String> properties) throws Exception {
+        if (!outFile.exists()) {
+            InputStream is = JmsServiceImpl.class.getResourceAsStream(resource);
+            if (is == null) {
+                throw new IllegalArgumentException("Resource " + resource + " doesn't exist");
+            }
+            try {
+                // read it line at a time so that we can use the platform line ending when we write it out
+                PrintStream out = new PrintStream(new FileOutputStream(outFile));
+                try {
+                    Scanner scanner = new Scanner(is);
+                    while (scanner.hasNextLine()) {
+                        String line = scanner.nextLine();
+                        line = filter(line, properties);
+                        out.println(line);
+                    }
+                } finally {
+                    safeClose(out);
+                }
+            } finally {
+                safeClose(is);
+            }
+        } else {
+            throw new IllegalArgumentException("File " + outFile.getPath() + " already exists. Remove it if you wish to recreate it.");
+        }
+    }
+
+    private void safeClose(InputStream is) throws IOException {
+        if (is == null)
+            return;
+        try {
+            is.close();
+        } catch (Throwable ignore) {
+            // nothing to do
+        }
+    }
+
+    private void safeClose(OutputStream is) throws IOException {
+        if (is == null)
+            return;
+        try {
+            is.close();
+        } catch (Throwable ignore) {
+            // nothing to do
+        }
+    }
+
+    private String filter(String line, HashMap<String, String> props) {
+        for (Map.Entry<String, String> i : props.entrySet()) {
+            int p1 = line.indexOf(i.getKey());
+            if (p1 >= 0) {
+                String l1 = line.substring(0, p1);
+                String l2 = line.substring(p1 + i.getKey().length());
+                line = l1 + i.getValue() + l2;
+            }
+        }
+        return line;
+    }
+
+    public BundleContext getBundleContext() {
+        return bundleContext;
+    }
+
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/core/src/main/resources/OSGI-INF/blueprint/jms-core.xml
----------------------------------------------------------------------
diff --git a/jms/core/src/main/resources/OSGI-INF/blueprint/jms-core.xml b/jms/core/src/main/resources/OSGI-INF/blueprint/jms-core.xml
new file mode 100644
index 0000000..27b8500
--- /dev/null
+++ b/jms/core/src/main/resources/OSGI-INF/blueprint/jms-core.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+        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.
+    -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+    <bean id="jmsService" class="org.apache.karaf.jms.internal.JmsServiceImpl">
+        <property name="bundleContext" ref="blueprintBundleContext"/>
+    </bean>
+
+    <service ref="jmsService" interface="org.apache.karaf.jms.JmsService" />
+
+    <!-- Management -->
+    <bean id="jmsMBeanImpl" class="org.apache.karaf.jms.internal.JmsMBeanImpl">
+        <property name="jmsService" ref="jmsService"/>
+    </bean>
+
+    <reference id="mbeanServer" interface="javax.management.MBeanServer">
+        <reference-listener ref="mbeanRegister" bind-method="registerMBeanServer" unbind-method="unregisterMBeanServer" />
+    </reference>
+
+    <bean id="mbeanRegister" class="org.apache.karaf.management.MBeanRegistrer" init-method="init"  destroy-method="destroy">
+        <property name="mbeans">
+            <map>
+                <entry value="org.apache.karaf:type=jms,name=${karaf.name}" key-ref="jmsMBeanImpl" />
+            </map>
+        </property>
+    </bean>
+
+</blueprint>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/jms/core/src/main/resources/OSGI-INF/bundle.info b/jms/core/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..1aeb646
--- /dev/null
+++ b/jms/core/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,18 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+This bundle is the core implementation of the JMS service support.
+
+The JMS service allows you to create connection factories, and send/browse/consume messages.
+
+h1. See also
+
+JMS - section of the Karaf User Guide

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/core/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-activemq.xml
----------------------------------------------------------------------
diff --git a/jms/core/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-activemq.xml b/jms/core/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-activemq.xml
new file mode 100644
index 0000000..0201989
--- /dev/null
+++ b/jms/core/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-activemq.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+    <bean id="activemqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
+        <property name="brokerURL" value="${url}" />
+    </bean>
+
+    <bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory">
+        <property name="maxConnections" value="8" />
+        <property name="connectionFactory" ref="activemqConnectionFactory" />
+    </bean>
+
+    <bean id="resourceManager" class="org.apache.activemq.pool.ActiveMQResourceManager" init-method="recoverResource">
+        <property name="transactionManager" ref="transactionManager" />
+        <property name="connectionFactory" ref="activemqConnectionFactory" />
+        <property name="resourceName" value="activemq.localhost" />
+    </bean>
+
+    <reference id="transactionManager" interface="javax.transaction.TransactionManager" />
+
+    <service ref="pooledConnectionFactory" interface="javax.jms.ConnectionFactory">
+        <service-properties>
+            <entry key="name" value="${name}" />
+            <entry key="osgi.jndi.service.name" value="jms/${name}" />
+        </service-properties>
+    </service>
+
+</blueprint>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/core/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-webspheremq.xml
----------------------------------------------------------------------
diff --git a/jms/core/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-webspheremq.xml b/jms/core/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-webspheremq.xml
new file mode 100644
index 0000000..4650237
--- /dev/null
+++ b/jms/core/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-webspheremq.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+    <bean id="wmqConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
+        <property name="transportType" value="1" />
+        <property name="hostName" value="${hostname}" />
+        <property name="port" value="${port}" />
+        <property name="queueManager" value="${queuemanager}" />
+        <property name="channel" value="${channel}" />
+        <property name="useConnectionPooling" value="true" />
+    </bean>
+
+    <service ref="wmqConnectionFactory" interface="javax.jms.ConnectionFactory">
+        <service-properties>
+            <entry key="name" value="${name}"/>
+            <entry key="osgi.jndi.service.name" value="jms/${name}"/>
+        </service-properties>
+    </service>
+
+</blueprint>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/pom.xml
----------------------------------------------------------------------
diff --git a/jms/pom.xml b/jms/pom.xml
new file mode 100644
index 0000000..0afb54d
--- /dev/null
+++ b/jms/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <!--
+
+        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.
+    -->
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.karaf</groupId>
+        <artifactId>karaf</artifactId>
+        <version>2.4.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <groupId>org.apache.karaf.jms</groupId>
+    <artifactId>jms</artifactId>
+    <packaging>pom</packaging>
+    <name>Apache Karaf :: JMS</name>
+
+    <modules>
+        <module>core</module>
+        <module>command</module>
+    </modules>
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 8876807..7b3efdf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -47,6 +47,7 @@
         <module>management</module>
         <module>jndi</module>
         <module>jdbc</module>
+        <module>jms</module>
         <module>webconsole</module>
         <module>exception</module>
         <module>assemblies</module>
@@ -483,6 +484,16 @@
                 <version>${project.version}</version>
             </dependency>
             <dependency>
+                <groupId>org.apache.karaf.jms</groupId>
+                <artifactId>org.apache.karaf.jms.core</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.karaf.jms</groupId>
+                <artifactId>org.apache.karaf.jms.command</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
                 <groupId>org.apache.karaf.webconsole</groupId>
                 <artifactId>org.apache.karaf.webconsole.admin</artifactId>
                 <version>${project.version}</version>
@@ -940,6 +951,11 @@
             </dependency>
             <dependency>
                 <groupId>org.apache.geronimo.specs</groupId>
+                <artifactId>geronimo-jms_1.1_spec</artifactId>
+                <version>${geronimo.jms-spec.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.geronimo.specs</groupId>
                 <artifactId>geronimo-servlet_3.0_spec</artifactId>
                 <version>${geronimo.servlet.version}</version>
             </dependency>


[2/2] git commit: [KARAF-2642] Merge jms feature

Posted by jb...@apache.org.
[KARAF-2642] Merge jms feature


Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/9de0903e
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/9de0903e
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/9de0903e

Branch: refs/heads/karaf-2.x
Commit: 9de0903e8f4cb1c51bec65df1e0b9c325a6caeeb
Parents: 36761d5
Author: Jean-Baptiste Onofré <jb...@apache.org>
Authored: Sat Jan 18 15:31:54 2014 +0100
Committer: Jean-Baptiste Onofré <jb...@apache.org>
Committed: Sat Jan 18 15:31:54 2014 +0100

----------------------------------------------------------------------
 .../enterprise/src/main/resources/features.xml  |   8 +
 jms/command/NOTICE                              |  71 +++
 jms/command/pom.xml                             |  92 ++++
 .../apache/karaf/jms/command/BrowseCommand.java |  70 +++
 .../jms/command/ConnectionFactoriesCommand.java |  38 ++
 .../karaf/jms/command/ConsumeCommand.java       |  48 +++
 .../apache/karaf/jms/command/CountCommand.java  |  47 ++
 .../apache/karaf/jms/command/CreateCommand.java |  40 ++
 .../apache/karaf/jms/command/DeleteCommand.java |  33 ++
 .../apache/karaf/jms/command/InfoCommand.java   |  51 +++
 .../karaf/jms/command/JmsCommandSupport.java    |  36 ++
 .../apache/karaf/jms/command/MoveCommand.java   |  49 +++
 .../apache/karaf/jms/command/QueuesCommand.java |  46 ++
 .../apache/karaf/jms/command/SendCommand.java   |  49 +++
 .../apache/karaf/jms/command/TopicsCommand.java |  46 ++
 .../ConnectionFactoriesFileNameCompleter.java   |  52 +++
 .../ConnectionFactoriesNameCompleter.java       |  52 +++
 .../OSGI-INF/blueprint/jms-command.xml          | 123 ++++++
 .../src/main/resources/OSGI-INF/bundle.info     |  29 ++
 jms/core/NOTICE                                 |  71 +++
 jms/core/pom.xml                                | 100 +++++
 .../java/org/apache/karaf/jms/JmsMBean.java     | 153 +++++++
 .../java/org/apache/karaf/jms/JmsMessage.java   | 165 +++++++
 .../java/org/apache/karaf/jms/JmsService.java   | 159 +++++++
 .../apache/karaf/jms/internal/JmsMBeanImpl.java | 150 +++++++
 .../karaf/jms/internal/JmsServiceImpl.java      | 430 +++++++++++++++++++
 .../resources/OSGI-INF/blueprint/jms-core.xml   |  43 ++
 .../src/main/resources/OSGI-INF/bundle.info     |  18 +
 .../jms/internal/connectionfactory-activemq.xml |  28 ++
 .../internal/connectionfactory-webspheremq.xml  |  20 +
 jms/pom.xml                                     |  41 ++
 pom.xml                                         |  16 +
 32 files changed, 2374 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/assemblies/features/enterprise/src/main/resources/features.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/enterprise/src/main/resources/features.xml b/assemblies/features/enterprise/src/main/resources/features.xml
index fc6d7ee..d687d76 100644
--- a/assemblies/features/enterprise/src/main/resources/features.xml
+++ b/assemblies/features/enterprise/src/main/resources/features.xml
@@ -166,6 +166,14 @@
         <bundle>mvn:org.apache.karaf.jdbc/org.apache.karaf.jdbc.command/${project.version}</bundle>
     </feature>
 
+    <feature name="jms" description="JMS service and commands" version="${project.version}" resolver="(obr)">
+        <details>JMS support provinding service, commands, and MBean.</details>
+        <feature>transaction</feature>
+        <bundle>mvn:org.apache.geronimo.specs/geronimo-jms_1.1_spec/${geronimo.jms-spec.version}</bundle>
+        <bundle>mvn:org.apache.karaf.jms/org.apache.karaf.jms.core/${project.version}</bundle>
+        <bundle>mvn:org.apache.karaf.jms/org.apache.karaf.jms.command/${project.version}</bundle>
+    </feature>
+
     <feature name="openwebbeans" description="Apache OpenWebBeans CDI container support" version="${openwebbeans.version}" resolver="(obr)">
         <details>Add support of Apache OpenWebBeans CDI container.</details>
         <feature>http</feature>

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/command/NOTICE
----------------------------------------------------------------------
diff --git a/jms/command/NOTICE b/jms/command/NOTICE
new file mode 100644
index 0000000..de8d101
--- /dev/null
+++ b/jms/command/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2013 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/command/pom.xml
----------------------------------------------------------------------
diff --git a/jms/command/pom.xml b/jms/command/pom.xml
new file mode 100644
index 0000000..c3f2415
--- /dev/null
+++ b/jms/command/pom.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <!--
+
+        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.
+    -->
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.karaf.jms</groupId>
+        <artifactId>jms</artifactId>
+        <version>2.4.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>org.apache.karaf.jms.command</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: JMS :: Command</name>
+    <description>This bundle provides shell commands to manipulate the JMS server.</description>
+
+    <properties>
+        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.karaf.jms</groupId>
+            <artifactId>org.apache.karaf.jms.core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.gogo.runtime</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.console</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/*.info</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Import-Package>
+                            org.apache.felix.service.command,
+                            org.apache.felix.gogo.commands,
+                            org.apache.karaf.shell.console,
+                            *
+                        </Import-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/command/src/main/java/org/apache/karaf/jms/command/BrowseCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/BrowseCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/BrowseCommand.java
new file mode 100644
index 0000000..4572b99
--- /dev/null
+++ b/jms/command/src/main/java/org/apache/karaf/jms/command/BrowseCommand.java
@@ -0,0 +1,70 @@
+/*
+ * 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.karaf.jms.command;
+
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.Option;
+import org.apache.karaf.jms.JmsMessage;
+
+import java.util.List;
+
+@Command(scope = "jms", name = "browse", description = "Browse a JMS queue")
+public class BrowseCommand extends JmsCommandSupport {
+
+    @Argument(index = 0, name = "connectionFactory", description = "The JMS connection factory name", required = true, multiValued = false)
+    String connectionFactory;
+
+    @Argument(index = 1, name = "queue", description = "The JMS queue to browse", required = true, multiValued = false)
+    String queue;
+
+    @Option(name = "-s", aliases = { "--selector" }, description = "The selector to select the messages to browse", required = false, multiValued = false)
+    String selector;
+
+    @Option(name = "-u", aliases = { "--username" }, description = "Username to connect to the JMS broker", required = false, multiValued = false)
+    String username = "karaf";
+
+    @Option(name = "-p", aliases = { "--password" }, description = "Password to connect to the JMS broker", required = false, multiValued = false)
+    String password = "karaf";
+
+    private final static String JMS_QUEUE_FORMAT = "%15s %40% %5s %10s %10s %10s %10s %10s %10s %10s %10s %10s";
+
+    public Object doExecute() throws Exception {
+
+        System.out.println(String.format(JMS_QUEUE_FORMAT, "ID", "Content", "Charset", "Type", "Correlation", "Delivery", "Destination", "Expiration", "Priority", "Redelivered", "ReplyTo", "Timestamp"));
+
+        List<JmsMessage> messages = getJmsService().browse(connectionFactory, queue, selector, username, password);
+        for (JmsMessage message : messages) {
+            System.out.println(String.format(JMS_QUEUE_FORMAT,
+                    message.getMessageId(),
+                    message.getContent(),
+                    message.getCharset(),
+                    message.getType(),
+                    message.getCorrelationID(),
+                    message.getDeliveryMode(),
+                    message.getDestination(),
+                    message.getExpiration(),
+                    message.getPriority(),
+                    message.isRedelivered(),
+                    message.getReplyTo(),
+                    message.getTimestamp()));
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/command/src/main/java/org/apache/karaf/jms/command/ConnectionFactoriesCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/ConnectionFactoriesCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/ConnectionFactoriesCommand.java
new file mode 100644
index 0000000..c60d875
--- /dev/null
+++ b/jms/command/src/main/java/org/apache/karaf/jms/command/ConnectionFactoriesCommand.java
@@ -0,0 +1,38 @@
+/*
+ * 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.karaf.jms.command;
+
+import org.apache.felix.gogo.commands.Command;
+
+import java.util.List;
+
+@Command(scope = "jms", name = "connectionfactories", description = "List the JMS connection factories")
+public class ConnectionFactoriesCommand extends JmsCommandSupport {
+
+    public Object doExecute() throws Exception {
+
+        System.out.println("JMS Connection Factory");
+
+        List<String> connectionFactories = getJmsService().connectionFactories();
+        for (String connectionFactory : connectionFactories) {
+            System.out.println(connectionFactory);
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/command/src/main/java/org/apache/karaf/jms/command/ConsumeCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/ConsumeCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/ConsumeCommand.java
new file mode 100644
index 0000000..2109be6
--- /dev/null
+++ b/jms/command/src/main/java/org/apache/karaf/jms/command/ConsumeCommand.java
@@ -0,0 +1,48 @@
+/*
+ * 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.karaf.jms.command;
+
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.Option;
+
+@Command(scope = "jms", name = "consume", description = "Consume messages from a JMS queue.")
+public class ConsumeCommand extends JmsCommandSupport {
+
+    @Argument(index = 0, name = "connectionFactory", description = "The JMS connection factory name", required = true, multiValued = false)
+    String connectionFactory;
+
+    @Argument(index = 1, name = "queue", description = "The JMS queue where to consume messages", required = true, multiValued = false)
+    String queue;
+
+    @Option(name = "-s", aliases = { "--selector" }, description = "The selector to use to select the messages to consume", required = false, multiValued = false)
+    String selector;
+
+    @Option(name = "-u", aliases = { "--username" }, description = "Username to connect to the JMS broker", required = false, multiValued = false)
+    String username = "karaf";
+
+    @Option(name = "-p", aliases = { "--password" }, description = "Password to connect to the JMS broker", required = false, multiValued = false)
+    String password = "karaf";
+
+    public Object doExecute() throws Exception {
+
+        System.out.println(getJmsService().consume(connectionFactory, queue, selector, username, password) + " message(s) consumed");
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/command/src/main/java/org/apache/karaf/jms/command/CountCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/CountCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/CountCommand.java
new file mode 100644
index 0000000..48c5fa1
--- /dev/null
+++ b/jms/command/src/main/java/org/apache/karaf/jms/command/CountCommand.java
@@ -0,0 +1,47 @@
+/*
+ * 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.karaf.jms.command;
+
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.Option;
+
+@Command(scope = "jms", name = "count", description = "Count the number of messages on a JMS queue.")
+public class CountCommand extends JmsCommandSupport {
+
+    @Argument(index = 0, name = "connectionFactory", description = "The JMS connection factory name", required = true, multiValued = false)
+    String connectionFactory;
+
+    @Argument(index = 1, name = "queue", description = "The JMS queue name", required = true, multiValued = false)
+    String queue;
+
+    @Option(name = "-u", aliases = { "--username" }, description = "Username to connect to the JMS broker", required = false, multiValued = false)
+    String username = "karaf";
+
+    @Option(name = "-p", aliases = { "--password" }, description = "Password to connect to the JMS broker", required = false, multiValued = false)
+    String password = "karaf";
+
+    public Object doExecute() throws Exception {
+
+        System.out.println("Messages Count");
+
+        System.out.println(getJmsService().count(connectionFactory, queue, username, password));
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/command/src/main/java/org/apache/karaf/jms/command/CreateCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/CreateCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/CreateCommand.java
new file mode 100644
index 0000000..5c00466
--- /dev/null
+++ b/jms/command/src/main/java/org/apache/karaf/jms/command/CreateCommand.java
@@ -0,0 +1,40 @@
+/*
+ * 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.karaf.jms.command;
+
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.Option;
+
+@Command(scope = "jms", name = "create", description = "Create a JMS connection factory.")
+public class CreateCommand extends JmsCommandSupport {
+
+    @Argument(index = 0, name = "name", description = "The JMS connection factory name", required = true, multiValued = false)
+    String name;
+
+    @Option(name = "-t", aliases = { "--type" }, description = "The JMS connection factory type (ActiveMQ or WebsphereMQ)", required = true, multiValued = false)
+    String type;
+
+    @Option(name = "-u", aliases = { "--url" }, description = "The JMS URL. NB: for WebsphereMQ type, the URL is hostname/port/queuemanager/channel", required = true, multiValued = false)
+    String url;
+
+    public Object doExecute() throws Exception {
+        getJmsService().create(name, type, url);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/command/src/main/java/org/apache/karaf/jms/command/DeleteCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/DeleteCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/DeleteCommand.java
new file mode 100644
index 0000000..0df9c15
--- /dev/null
+++ b/jms/command/src/main/java/org/apache/karaf/jms/command/DeleteCommand.java
@@ -0,0 +1,33 @@
+/*
+ * 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.karaf.jms.command;
+
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+
+@Command(scope = "jms", name = "delete", description = "Delete a JMS connection factory")
+public class DeleteCommand extends JmsCommandSupport {
+
+    @Argument(index = 0, name = "name", description = "The JMS connection factory name", required = true, multiValued = false)
+    String name;
+
+    public Object doExecute() throws Exception {
+        getJmsService().delete(name);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/command/src/main/java/org/apache/karaf/jms/command/InfoCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/InfoCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/InfoCommand.java
new file mode 100644
index 0000000..929ca1b
--- /dev/null
+++ b/jms/command/src/main/java/org/apache/karaf/jms/command/InfoCommand.java
@@ -0,0 +1,51 @@
+/*
+ * 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.karaf.jms.command;
+
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.Option;
+
+import java.util.Map;
+
+@Command(scope = "jms", name = "info", description = "Provides details about a JMS connection factory.")
+public class InfoCommand extends JmsCommandSupport {
+
+    @Argument(index = 0, name = "connectionFactory", description = "The JMS connection factory name", required = true, multiValued = false)
+    String connectionFactory;
+
+    @Option(name = "-u", aliases = { "--username" }, description = "Username to connect to the JMS broker", required = false, multiValued = false)
+    String username = "karaf";
+
+    @Option(name = "-p", aliases = { "--password" }, description = "Password to connect to the JMS broker", required = false, multiValued = false)
+    String password = "karaf";
+
+    private final static String PROPERTIES_FORMAT = "%20s %20s";
+
+    public Object doExecute() throws Exception {
+
+        System.out.println(String.format(PROPERTIES_FORMAT, "Property", "Value"));
+
+        Map<String, String> info = getJmsService().info(connectionFactory, username, password);
+        for (String key : info.keySet()) {
+            System.out.println(String.format(PROPERTIES_FORMAT, key, info.get(key)));
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/command/src/main/java/org/apache/karaf/jms/command/JmsCommandSupport.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/JmsCommandSupport.java b/jms/command/src/main/java/org/apache/karaf/jms/command/JmsCommandSupport.java
new file mode 100644
index 0000000..7d8eb11
--- /dev/null
+++ b/jms/command/src/main/java/org/apache/karaf/jms/command/JmsCommandSupport.java
@@ -0,0 +1,36 @@
+/*
+ * 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.karaf.jms.command;
+
+import org.apache.karaf.jms.JmsService;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+
+public abstract class JmsCommandSupport extends OsgiCommandSupport {
+
+    private JmsService jmsService;
+
+    public abstract Object doExecute() throws Exception;
+
+    public JmsService getJmsService() {
+        return jmsService;
+    }
+
+    public void setJmsService(JmsService jmsService) {
+        this.jmsService = jmsService;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/command/src/main/java/org/apache/karaf/jms/command/MoveCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/MoveCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/MoveCommand.java
new file mode 100644
index 0000000..cd0389b
--- /dev/null
+++ b/jms/command/src/main/java/org/apache/karaf/jms/command/MoveCommand.java
@@ -0,0 +1,49 @@
+/*
+ * 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.karaf.jms.command;
+
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.Option;
+
+@Command(scope = "jms", name = "move", description = "Move messages from one JMS queue to another one.")
+public class MoveCommand extends JmsCommandSupport {
+
+    @Argument(index = 0, name = "connectionFactory", description = "The JMS connection factory name", required = true, multiValued = false)
+    String connectionFactory;
+
+    @Argument(index = 1, name = "source", description = "The source JMS queue", required = true, multiValued = false)
+    String source;
+
+    @Argument(index = 2, name = "destination", description = "The destination JMS queue", required = true, multiValued = false)
+    String destination;
+
+    @Option(name = "-s", aliases = { "--selector" }, description = "Selector to move only some messages", required = false, multiValued = false)
+    String selector;
+
+    @Option(name = "-u", aliases = { "--username" }, description = "Username to connect to the JMS broker", required = false, multiValued = false)
+    String username = "karaf";
+
+    @Option(name = "-p", aliases = { "--password" }, description = "Password to connect to the JMS broker", required = false, multiValued = false)
+    String password = "karaf";
+
+    public Object doExecute() throws Exception {
+        System.out.println(getJmsService().move(connectionFactory, source, destination, selector, username, password) + " message(s) moved");
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/command/src/main/java/org/apache/karaf/jms/command/QueuesCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/QueuesCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/QueuesCommand.java
new file mode 100644
index 0000000..5a269a5
--- /dev/null
+++ b/jms/command/src/main/java/org/apache/karaf/jms/command/QueuesCommand.java
@@ -0,0 +1,46 @@
+/*
+ * 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.karaf.jms.command;
+
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.Option;
+
+@Command(scope = "jms", name = "queues", description = "List the JMS queues.")
+public class QueuesCommand extends JmsCommandSupport {
+
+    @Argument(index = 0, name = "connectionFactory", description= "The JMS connection factory name", required = true, multiValued = false)
+    String connectionFactory;
+
+    @Option(name = "-u", aliases = { "--username" }, description = "Username to connect to the JMS broker", required = false, multiValued = false)
+    String username = "karaf";
+
+    @Option(name = "-p", aliases = { "--password" }, description = "Password to connect to the JMS broker", required = false, multiValued = false)
+    String password = "karaf";
+
+    public Object doExecute() throws Exception {
+
+        System.out.println("JMS Queues");
+
+        for (String queue : getJmsService().queues(connectionFactory, username, password)) {
+            System.out.println(queue);
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/command/src/main/java/org/apache/karaf/jms/command/SendCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/SendCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/SendCommand.java
new file mode 100644
index 0000000..34e25d4
--- /dev/null
+++ b/jms/command/src/main/java/org/apache/karaf/jms/command/SendCommand.java
@@ -0,0 +1,49 @@
+/*
+ * 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.karaf.jms.command;
+
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.Option;
+
+@Command(scope = "jms", name = "send", description = "Send a message to ")
+public class SendCommand extends JmsCommandSupport {
+
+    @Argument(index = 0, name = "connectionFactory", description = "The JMS connection factory name", required = true, multiValued = false)
+    String connectionFactory;
+
+    @Argument(index = 1, name = "queue", description = "The JMS queue name", required = true, multiValued = false)
+    String queue;
+
+    @Argument(index = 2, name = "message", description = "The JMS message content", required = true, multiValued = false)
+    String message;
+
+    @Option(name = "-r", aliases = { "--replyTo" }, description = "Set the message ReplyTo", required = false, multiValued = false)
+    String replyTo;
+
+    @Option(name = "-u", aliases = { "--username" }, description = "Username to connect to the JMS broker", required = false, multiValued = false)
+    String username = "karaf";
+
+    @Option(name = "-p", aliases = { "--password" }, description = "Password to connect to the JMS broker", required = false, multiValued = false)
+    String password = "karaf";
+
+    public Object doExecute() throws Exception {
+        getJmsService().send(connectionFactory, queue, message, replyTo, username, password);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/command/src/main/java/org/apache/karaf/jms/command/TopicsCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/TopicsCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/TopicsCommand.java
new file mode 100644
index 0000000..e9edcfe
--- /dev/null
+++ b/jms/command/src/main/java/org/apache/karaf/jms/command/TopicsCommand.java
@@ -0,0 +1,46 @@
+/*
+ * 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.karaf.jms.command;
+
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.Option;
+
+@Command(scope = "jms", name = "topics", description = "List the JMS topics.")
+public class TopicsCommand extends JmsCommandSupport {
+
+    @Argument(index = 0, name = "connectionFactory", description = "The JMS connection factory name", required = true, multiValued = false)
+    String connectionFactory;
+
+    @Option(name = "-u", aliases = { "--username" }, description = "Username to connect to the JMS broker", required = false, multiValued = false)
+    String username = "karaf";
+
+    @Option(name = "-p", aliases = { "--password" }, description = "Password to connect to the JMS broker", required = false, multiValued = false)
+    String password = "karaf";
+
+    public Object doExecute() throws Exception {
+
+        System.out.println("JMS Topics");
+
+        for (String topic : getJmsService().topics(connectionFactory, username, password)) {
+            System.out.println(topic);
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/command/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesFileNameCompleter.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesFileNameCompleter.java b/jms/command/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesFileNameCompleter.java
new file mode 100644
index 0000000..ae4293f
--- /dev/null
+++ b/jms/command/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesFileNameCompleter.java
@@ -0,0 +1,52 @@
+/*
+ * 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.karaf.jms.command.completers;
+
+import org.apache.karaf.jms.JmsService;
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+
+import java.util.List;
+
+/**
+ * Completer on the JMS connection factory file names.
+ */
+public class ConnectionFactoriesFileNameCompleter implements Completer {
+
+    private JmsService jmsService;
+
+    public int complete(String buffer, int cursor, List<String> candidates) {
+        StringsCompleter delegate = new StringsCompleter();
+        try {
+            for (String connectionFactory : jmsService.connectionFactoryFileNames()) {
+                delegate.getStrings().add(connectionFactory.replace("connectionfactory-", "").replace(".xml", ""));
+            }
+        } catch (Exception e) {
+            // nothing to do
+        }
+        return delegate.complete(buffer, cursor, candidates);
+    }
+
+    public JmsService getJmsService() {
+        return jmsService;
+    }
+
+    public void setJmsService(JmsService jmsService) {
+        this.jmsService = jmsService;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/command/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesNameCompleter.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesNameCompleter.java b/jms/command/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesNameCompleter.java
new file mode 100644
index 0000000..865ef41
--- /dev/null
+++ b/jms/command/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesNameCompleter.java
@@ -0,0 +1,52 @@
+/*
+ * 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.karaf.jms.command.completers;
+
+import org.apache.karaf.jms.JmsService;
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+
+import java.util.List;
+
+/**
+ * Completer on the JMS connection factories name.
+ */
+public class ConnectionFactoriesNameCompleter implements Completer {
+
+    private JmsService jmsService;
+
+    public int complete(String buffer, int cursor, List<String> candidates) {
+        StringsCompleter delegate = new StringsCompleter();
+        try {
+            for (String connectionFactory : jmsService.connectionFactories()) {
+                delegate.getStrings().add(connectionFactory);
+            }
+        } catch (Exception e) {
+            // nothing to do
+        }
+        return delegate.complete(buffer, cursor, candidates);
+    }
+
+    public JmsService getJmsService() {
+        return jmsService;
+    }
+
+    public void setJmsService(JmsService jmsService) {
+        this.jmsService = jmsService;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/command/src/main/resources/OSGI-INF/blueprint/jms-command.xml
----------------------------------------------------------------------
diff --git a/jms/command/src/main/resources/OSGI-INF/blueprint/jms-command.xml b/jms/command/src/main/resources/OSGI-INF/blueprint/jms-command.xml
new file mode 100644
index 0000000..83ee1dc
--- /dev/null
+++ b/jms/command/src/main/resources/OSGI-INF/blueprint/jms-command.xml
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+        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.
+    -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" default-activation="lazy">
+
+    <reference id="jmsService" interface="org.apache.karaf.jms.JmsService"/>
+
+    <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+        <command name="jms/browse">
+            <action class="org.apache.karaf.jms.command.BrowseCommand">
+                <property name="jmsService" ref="jmsService"/>
+            </action>
+            <completers>
+                <ref component-id="connectionFactoriesNameCompleter"/>
+                <null/>
+            </completers>
+        </command>
+        <command name="jms/connectionfactories">
+            <action class="org.apache.karaf.jms.command.ConnectionFactoriesCommand">
+                <property name="jmsService" ref="jmsService"/>
+            </action>
+        </command>
+        <command name="jms/consume">
+            <action class="org.apache.karaf.jms.command.ConsumeCommand">
+                <property name="jmsService" ref="jmsService"/>
+            </action>
+            <completers>
+                <ref component-id="connectionFactoriesNameCompleter"/>
+                <null/>
+            </completers>
+        </command>
+        <command name="jms/count">
+            <action class="org.apache.karaf.jms.command.CountCommand">
+                <property name="jmsService" ref="jmsService"/>
+            </action>
+            <completers>
+                <ref component-id="connectionFactoriesNameCompleter"/>
+                <null/>
+            </completers>
+        </command>
+        <command name="jms/create">
+            <action class="org.apache.karaf.jms.command.CreateCommand">
+                <property name="jmsService" ref="jmsService"/>
+            </action>
+        </command>
+        <command name="jms/delete">
+            <action class="org.apache.karaf.jms.command.DeleteCommand">
+                <property name="jmsService" ref="jmsService"/>
+            </action>
+            <completers>
+                <ref component-id="connectionFactoriesFileNameCompleter"/>
+                <null/>
+            </completers>
+        </command>
+        <command name="jms/info">
+            <action class="org.apache.karaf.jms.command.InfoCommand">
+                <property name="jmsService" ref="jmsService"/>
+            </action>
+            <completers>
+                <ref component-id="connectionFactoriesNameCompleter"/>
+                <null/>
+            </completers>
+        </command>
+        <command name="jms/move">
+            <action class="org.apache.karaf.jms.command.MoveCommand">
+                <property name="jmsService" ref="jmsService"/>
+            </action>
+            <completers>
+                <ref component-id="connectionFactoriesNameCompleter"/>
+                <null/>
+            </completers>
+        </command>
+        <command name="jms/queues">
+            <action class="org.apache.karaf.jms.command.QueuesCommand">
+                <property name="jmsService" ref="jmsService"/>
+            </action>
+            <completers>
+                <ref component-id="connectionFactoriesNameCompleter"/>
+                <null/>
+            </completers>
+        </command>
+        <command name="jms/send">
+            <action class="org.apache.karaf.jms.command.SendCommand">
+                <property name="jmsService" ref="jmsService"/>
+            </action>
+            <completers>
+                <ref component-id="connectionFactoriesNameCompleter"/>
+                <null/>
+            </completers>
+        </command>
+        <command name="jms/topics">
+            <action class="org.apache.karaf.jms.command.TopicsCommand">
+                <property name="jmsService" ref="jmsService"/>
+            </action>
+            <completers>
+                <ref component-id="connectionFactoriesNameCompleter"/>
+                <null/>
+            </completers>
+        </command>
+    </command-bundle>
+
+    <bean id="connectionFactoriesNameCompleter" class="org.apache.karaf.jms.command.completers.ConnectionFactoriesNameCompleter">
+        <property name="jmsService" ref="jmsService"/>
+    </bean>
+    <bean id="connectionFactoriesFileNameCompleter" class="org.apache.karaf.jms.command.completers.ConnectionFactoriesFileNameCompleter">
+        <property name="jmsService" ref="jmsService"/>
+    </bean>
+
+</blueprint>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/command/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/jms/command/src/main/resources/OSGI-INF/bundle.info b/jms/command/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..8b83f13
--- /dev/null
+++ b/jms/command/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,29 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+This bundle provides the shell commands to manipulate the JMS service.
+
+The following commands are available:
+
+* jms:create
+* jms:delete
+* jms:connectionfactories
+* jms:info
+* jms:count
+* jms:queues
+* jms:topics
+* jms:send
+* jms:consume
+* jms:move
+
+h1. See also
+
+JMS - section of the Karaf User Guide
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/core/NOTICE
----------------------------------------------------------------------
diff --git a/jms/core/NOTICE b/jms/core/NOTICE
new file mode 100644
index 0000000..de8d101
--- /dev/null
+++ b/jms/core/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2013 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/core/pom.xml
----------------------------------------------------------------------
diff --git a/jms/core/pom.xml b/jms/core/pom.xml
new file mode 100644
index 0000000..4b6f2b0
--- /dev/null
+++ b/jms/core/pom.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <!--
+
+        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.
+    -->
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.karaf.jms</groupId>
+        <artifactId>jms</artifactId>
+        <version>2.4.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>org.apache.karaf.jms.core</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: JMS :: Core</name>
+    <description>This bundle provides core implementation of the JMS service.</description>
+
+    <properties>
+        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-jms_1.1_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.activemq</groupId>
+            <artifactId>activemq-pool</artifactId>
+            <version>5.9.0</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/*.info</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.karaf.jms
+                        </Export-Package>
+                        <Import-Package>
+                            javax.management,
+                            javax.management.loading,
+                            org.apache.karaf.management;version=${project.version},
+                            org.apache.activemq*;resolution:=optional,
+                            *
+                        </Import-Package>
+                        <Private-Package>
+                            org.apache.karaf.jms.internal
+                        </Private-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/core/src/main/java/org/apache/karaf/jms/JmsMBean.java
----------------------------------------------------------------------
diff --git a/jms/core/src/main/java/org/apache/karaf/jms/JmsMBean.java b/jms/core/src/main/java/org/apache/karaf/jms/JmsMBean.java
new file mode 100644
index 0000000..8540b86
--- /dev/null
+++ b/jms/core/src/main/java/org/apache/karaf/jms/JmsMBean.java
@@ -0,0 +1,153 @@
+/*
+ * 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.karaf.jms;
+
+import javax.management.MBeanException;
+import javax.management.openmbean.TabularData;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * JMS MBean.
+ */
+public interface JmsMBean {
+
+    /**
+     * List the JMS connection factories.
+     *
+     * @return the list of the JMS connection factories name.
+     * @throws MBeanException
+     */
+    List<String> getConnectionfactories() throws MBeanException;
+
+    /**
+     * Create a JMS connection factory.
+     *
+     * @param name the JMS connection factory name.
+     * @param type the JMS connection factory type (ActiveMQ or WebsphereMQ).
+     * @param url the JMS connection factory URL. NB: when type is WebsphereMQ, the URL has the format host/port/queuemanager/channel.
+     * @throws MBeanException
+     */
+    void create(String name, String type, String url) throws MBeanException;
+
+    /**
+     * Delete a JMS connection factory.
+     *
+     * @param name the JMS connection factory name.
+     * @throws MBeanException
+     */
+    void delete(String name) throws MBeanException;
+
+    /**
+     * Get details about a JMS connection factory.
+     *
+     * @param connectionFactory the JMS connection factory name.
+     * @param username optional username to connect to the JMS broker.
+     * @param password optional password to connect to the JMS broker.
+     * @return a map (property/value) containing details.
+     * @throws MBeanException
+     */
+    Map<String, String> info(String connectionFactory, String username, String password) throws MBeanException;
+
+    /**
+     * Count the messages on a given JMS queue.
+     *
+     * @param connectionFactory the JMS connection factory name.
+     * @param queue the JMS queue name.
+     * @param username optional username to connect to the JMS broker.
+     * @param password optional password to connect to the JMS broker.
+     * @return
+     * @throws MBeanException
+     */
+    int count(String connectionFactory, String queue, String username, String password) throws MBeanException;
+
+    /**
+     * List the JMS queues.
+     *
+     * @param connectionFactory the JMS connection factory name.
+     * @param username optional username to connect to the JMS broker.
+     * @param password optional password to connect to the JMS broker.
+     * @return the list of JMS queues.
+     * @throws MBeanException
+     */
+    List<String> queues(String connectionFactory, String username, String password) throws MBeanException;
+
+    /**
+     * List the JMS topics.
+     *
+     * @param connectionFactory the JMS connection factory name.
+     * @param username optional username to connect to the JMS broker.
+     * @param password optional password to connect to the JMS broker.
+     * @return the list of JMS topics.
+     * @throws MBeanException
+     */
+    List<String> topics(String connectionFactory, String username, String password) throws MBeanException;
+
+    /**
+     * Browse the messages in a JMS queue.
+     *
+     * @param connectionFactory the JMS connection factory name.
+     * @param queue the JMS queue name.
+     * @param selector a selector to use to browse only certain messages.
+     * @param username optional username to connect to the JMS broker.
+     * @param password optional password to connect to the JMS broker.
+     * @return a tabular data with messages details.
+     * @throws MBeanException
+     */
+    TabularData browse(String connectionFactory, String queue, String selector, String username, String password) throws MBeanException;
+
+    /**
+     * Send a JMS message to given queue.
+     *
+     * @param connectionFactory the JMS connection factory name.
+     * @param queue the JMS queue name.
+     * @param content the message content.
+     * @param replyTo the message ReplyTo.
+     * @param username optional username to connect to the JMS broker.
+     * @param password optional password to connect to the JMS broker.
+     * @throws MBeanException
+     */
+    void send(String connectionFactory, String queue, String content, String replyTo, String username, String password) throws MBeanException;
+
+    /**
+     * Consume JMS messages from a given queue.
+     *
+     * @param connectionFactory the JMS connection factory name.
+     * @param queue the JMS queue name.
+     * @param selector a selector to use to consume only certain messages.
+     * @param username optional username to connect to the JMS broker.
+     * @param password optional password to connect to the JMS broker.
+     * @return the number of messages consumed.
+     * @throws MBeanException
+     */
+    int consume(String connectionFactory, String queue, String selector, String username, String password) throws MBeanException;
+
+    /**
+     * Move JMS messages from one queue to another.
+     *
+     * @param connectionFactory the JMS connection factory name.
+     * @param source the source JMS queue name.
+     * @param destination the destination JMS queue name.
+     * @param selector a selector to move only certain messages.
+     * @param username optional username to connect to the JMS broker.
+     * @param password optional password to connect to the JMS broker.
+     * @return the number of messages moved.
+     * @throws MBeanException
+     */
+    int move(String connectionFactory, String source, String destination, String selector, String username, String password) throws MBeanException;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/core/src/main/java/org/apache/karaf/jms/JmsMessage.java
----------------------------------------------------------------------
diff --git a/jms/core/src/main/java/org/apache/karaf/jms/JmsMessage.java b/jms/core/src/main/java/org/apache/karaf/jms/JmsMessage.java
new file mode 100644
index 0000000..c159193
--- /dev/null
+++ b/jms/core/src/main/java/org/apache/karaf/jms/JmsMessage.java
@@ -0,0 +1,165 @@
+/*
+ * 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.karaf.jms;
+
+import javax.jms.*;
+import java.io.UnsupportedEncodingException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Describe a JMS message is more human readable way.
+ */
+public class JmsMessage {
+
+    private Map<String, Object> properties = new HashMap<String, Object>();
+
+    private String content;
+    private String charset = "UTF-8";
+    private String correlationID;
+    private String deliveryMode;
+    private String destination;
+    private String expiration;
+    private String messageId;
+    private int priority;
+    private boolean redelivered;
+    private String replyTo;
+    private String timestamp;
+    private String type;
+
+    public JmsMessage(Message message) {
+        try {
+            initFromMessage(message);
+        } catch (JMSException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    public void initFromMessage(Message message) throws JMSException {
+        @SuppressWarnings("unchecked")
+        Enumeration<String> names = message.getPropertyNames();
+        while (names.hasMoreElements()) {
+            String key = names.nextElement();
+            Object value = message.getObjectProperty(key);
+            properties.put(key, value);
+        }
+
+        correlationID = message.getJMSCorrelationID();
+        if (message.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT) {
+            deliveryMode = "Non Persistent";
+        } else {
+            deliveryMode = "Persistent";
+        }
+        Destination destinationDest = message.getJMSDestination();
+        if (destinationDest != null) {
+            destination = destinationDest.toString();
+        }
+        if (message.getJMSExpiration() > 0) {
+            expiration = new Date(message.getJMSExpiration()).toString();
+        } else {
+            expiration = "Never";
+        }
+        messageId = message.getJMSMessageID();
+        priority = message.getJMSPriority();
+        redelivered = message.getJMSRedelivered();
+        Destination replyToDest = message.getJMSReplyTo();
+        if (replyToDest != null) {
+            replyTo = replyToDest.toString();
+        }
+        if (message.getJMSTimestamp() > 0) {
+            timestamp = new Date(message.getJMSTimestamp()).toString();
+        } else {
+            timestamp = "";
+        }
+        type = message.getJMSType();
+        content = getMessageContent(message);
+    }
+
+
+    private String getMessageContent(Message message) throws JMSException {
+        if (message instanceof TextMessage) {
+            return ((TextMessage) message).getText();
+        } else if (message instanceof BytesMessage) {
+            BytesMessage bMessage = (BytesMessage) message;
+            long length = bMessage.getBodyLength();
+            byte[] content = new byte[(int) length];
+            bMessage.readBytes(content);
+            try {
+                return new String(content, charset);
+            } catch (UnsupportedEncodingException e) {
+                throw new RuntimeException(e.getMessage(), e);
+            }
+        }
+        return "";
+    }
+
+    public Map<String, Object> getProperties() {
+        return properties;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public String getCharset() {
+        return charset;
+    }
+
+    public String getCorrelationID() {
+        return correlationID;
+    }
+
+    public String getDeliveryMode() {
+        return deliveryMode;
+    }
+
+    public String getDestination() {
+        return destination;
+    }
+
+    public String getExpiration() {
+        return expiration;
+    }
+
+    public String getMessageId() {
+        return messageId;
+    }
+
+    public int getPriority() {
+        return priority;
+    }
+
+    public boolean isRedelivered() {
+        return redelivered;
+    }
+
+    public String getReplyTo() {
+        return replyTo;
+    }
+
+    public String getTimestamp() {
+        return timestamp;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/core/src/main/java/org/apache/karaf/jms/JmsService.java
----------------------------------------------------------------------
diff --git a/jms/core/src/main/java/org/apache/karaf/jms/JmsService.java b/jms/core/src/main/java/org/apache/karaf/jms/JmsService.java
new file mode 100644
index 0000000..8aa970f
--- /dev/null
+++ b/jms/core/src/main/java/org/apache/karaf/jms/JmsService.java
@@ -0,0 +1,159 @@
+/*
+ * 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.karaf.jms;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * JMS Service.
+ */
+public interface JmsService {
+
+    /**
+     * List the JMS connection factories.
+     *
+     * @return the list of JMS connection factory names.
+     * @throws Exception
+     */
+    List<String> connectionFactories() throws Exception;
+
+    /**
+     * List the JMS connecion factories file names.
+     *
+     * @return the list of JMS connection factory file names.
+     * @throws Exception
+     */
+    List<String> connectionFactoryFileNames() throws Exception;
+
+    /**
+     * Create a new JMS connection factory.
+     *
+     * @param name the JMS connection factory name.
+     * @param type the JMS connection factory type (ActiveMQ, WebsphereMQ, ...).
+     * @param url the JMS URL to use.
+     * @throws Exception
+     */
+    void create(String name, String type, String url) throws Exception;
+
+    /**
+     * Delete a JMS connection factory.
+     *
+     * @param name the JMS connection factory name.
+     * @throws Exception
+     */
+    void delete(String name) throws Exception;
+
+    /**
+     * Get details about a given JMS connection factory.
+     *
+     * @param connectionFactory the JMS connection factory name.
+     * @param username optional username to connect to the JMS broker.
+     * @param password optional password to connect to the JMS broker.
+     * @return a map (property/value) containing details.
+     * @throws Exception
+     */
+    Map<String, String> info(String connectionFactory, String username, String password) throws Exception;
+
+    /**
+     * Count the number of messages in a JMS queue.
+     *
+     * @param connectionFactory the JMS connection factory name.
+     * @param queue the queue name.
+     * @param username optional username to connect to the JMS broker.
+     * @param password optional password to connect to the JMS broker.
+     * @return the number of messages in a JMS queue.
+     * @throws Exception
+     */
+    int count(String connectionFactory, String queue, String username, String password) throws Exception;
+
+    /**
+     * List the queues.
+     *
+     * @param connectionFactory the JMS connection factory name.
+     * @param username optional username to connect to the JMS broker.
+     * @param password optional password to connect to the JMS broker.
+     * @return the list of queues.
+     * @throws Exception
+     */
+    List<String> queues(String connectionFactory, String username, String password) throws Exception;
+
+    /**
+     * List the topics.
+     *
+     * @param connectionFactory the JMS connection factory name.
+     * @param username optional username to connect to the JMS broker.
+     * @param password optional password to connect to the JMS broker.
+     * @return the list of topics.
+     * @throws Exception
+     */
+    List<String> topics(String connectionFactory, String username, String password) throws Exception;
+
+    /**
+     * Browse a destination.
+     *
+     * @param connectionFactory the JMS connection factory name.
+     * @param queue the queue name.
+     * @param selector the selector.
+     * @param username optional username to connect to the JMS broker.
+     * @param password optional password to connect to the JMS broker.
+     * @return the list of messages.
+     * @throws Exception
+     */
+    List<JmsMessage> browse(String connectionFactory, String queue, String selector, String username, String password) throws Exception;
+
+    /**
+     * Send a message on the given queue.
+     *
+     * @param connectionFactory the JMS connection factory name.
+     * @param queue the queue name.
+     * @param body the message body.
+     * @param replyTo the message replyTo header.
+     * @param username optional username to connect to the JMS broker.
+     * @param password optional password to connect to the JMS broker.
+     * @throws Exception
+     */
+    void send(String connectionFactory, String queue, String body, String replyTo, String username, String password) throws Exception;
+
+    /**
+     * Consume messages from a given destination.
+     *
+     * @param connectionFactory the JMS connection factory name.
+     * @param queue the queue name.
+     * @param selector the messages selector.
+     * @param username optional username to connect to the JMS broker.
+     * @param password optional password to connect to the JMS broker.
+     * @return the number of messages consumed.
+     * @throws Exception
+     */
+    int consume(String connectionFactory, String queue, String selector, String username, String password) throws Exception;
+
+    /**
+     * Move messages from a destination to another.
+     *
+     * @param connectionFactory the JMS connection factory name.
+     * @param sourceQueue the source queue.
+     * @param targetQueue the target queue.
+     * @param selector the messages selector on the source queue.
+     * @param username optional username to connect to the JMS broker.
+     * @param password optional password to connect to the JMS broker.
+     * @return the number of messages moved.
+     * @throws Exception
+     */
+    int move(String connectionFactory, String sourceQueue, String targetQueue, String selector, String username, String password) throws Exception;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/9de0903e/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsMBeanImpl.java
----------------------------------------------------------------------
diff --git a/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsMBeanImpl.java b/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsMBeanImpl.java
new file mode 100644
index 0000000..511b690
--- /dev/null
+++ b/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsMBeanImpl.java
@@ -0,0 +1,150 @@
+/*
+ * 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.karaf.jms.internal;
+
+import org.apache.karaf.jms.JmsMBean;
+import org.apache.karaf.jms.JmsMessage;
+import org.apache.karaf.jms.JmsService;
+
+import javax.management.MBeanException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+import javax.management.openmbean.*;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Default implementation of the JMS MBean.
+ */
+public class JmsMBeanImpl extends StandardMBean implements JmsMBean {
+
+    private JmsService jmsService;
+
+    public JmsMBeanImpl() throws NotCompliantMBeanException {
+        super(JmsMBean.class);
+    }
+
+    public List<String> getConnectionfactories() throws MBeanException {
+        try {
+            return jmsService.connectionFactories();
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    public void create(String name, String type, String url) throws MBeanException {
+        try {
+            jmsService.create(name, type, url);
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    public void delete(String name) throws MBeanException {
+        try {
+            jmsService.delete(name);
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    public Map<String, String> info(String connectionFactory, String username, String password) throws MBeanException {
+        try {
+            return jmsService.info(connectionFactory, username, password);
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    public int count(String connectionFactory, String queue, String username, String password) throws MBeanException {
+        try {
+            return jmsService.count(connectionFactory, queue, username, password);
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    public List<String> queues(String connectionFactory, String username, String password) throws MBeanException {
+        try {
+            return jmsService.queues(connectionFactory, username, password);
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    public List<String> topics(String connectionFactory, String username, String password) throws MBeanException {
+        try {
+            return jmsService.topics(connectionFactory, username, password);
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    public void send(String connectionFactory, String queue, String content, String replyTo, String username, String password) throws MBeanException {
+        try {
+            jmsService.send(connectionFactory, queue, content, replyTo, username, password);
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    public int consume(String connectionFactory, String queue, String selector, String username, String password) throws MBeanException {
+        try {
+            return jmsService.consume(connectionFactory, queue, selector, username, password);
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    public int move(String connectionFactory, String source, String destination, String selector, String username, String password) throws MBeanException {
+        try {
+            return jmsService.move(connectionFactory, source, destination, selector, username, password);
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    public TabularData browse(String connectionFactory, String queue, String selector, String username, String password) throws MBeanException {
+        try {
+            CompositeType type = new CompositeType("message", "JMS Message",
+                    new String[]{ "id", "content", "charset", "type", "correlation", "delivery", "destination", "expiration", "priority", "redelivered", "replyto", "timestamp" },
+                    new String[]{ "Message ID", "Content", "Charset", "Type", "Correlation ID", "Delivery Mode", "Destination", "Expiration Date", "Priority", "Redelivered", "Reply-To", "Timestamp" },
+                    new OpenType[]{ SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.INTEGER, SimpleType.BOOLEAN, SimpleType.STRING, SimpleType.STRING });
+            TabularType tableType = new TabularType("messages", "JMS Messages", type, new String[]{ "id" });
+            TabularData table = new TabularDataSupport(tableType);
+            for (JmsMessage message : getJmsService().browse(connectionFactory, queue, selector, username, password)) {
+                CompositeData data = new CompositeDataSupport(type,
+                        new String[]{ "id", "content", "charset", "type", "correlation", "delivery", "destination", "expiration", "priority", "redelivered", "replyto", "timestamp" },
+                        new Object[]{ message.getMessageId(), message.getContent(), message.getCharset(), message.getType(), message.getCorrelationID(), message.getDeliveryMode(), message.getDestination(), message.getExpiration(), message.getPriority(), message.isRedelivered(), message.getReplyTo(), message.getTimestamp() }
+                        );
+                table.put(data);
+            }
+            return table;
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    public JmsService getJmsService() {
+        return jmsService;
+    }
+
+    public void setJmsService(JmsService jmsService) {
+        this.jmsService = jmsService;
+    }
+
+}