You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by cs...@apache.org on 2014/01/29 10:04:06 UTC

git commit: KARAF-2741 Refactorings for error and connection handling

Updated Branches:
  refs/heads/master 2d705cfa9 -> 47d745dfd


KARAF-2741 Refactorings for error and connection handling


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

Branch: refs/heads/master
Commit: 47d745dfd46a15f0ba40665f5d99f387a34dc6b6
Parents: 2d705cf
Author: Christian Schneider <ch...@die-schneider.net>
Authored: Wed Jan 29 10:03:46 2014 +0100
Committer: Christian Schneider <ch...@die-schneider.net>
Committed: Wed Jan 29 10:03:46 2014 +0100

----------------------------------------------------------------------
 jms/command/pom.xml                             |   4 +
 .../apache/karaf/jms/command/BrowseCommand.java |  11 +-
 .../karaf/jms/command/ConsumeCommand.java       |  12 +-
 .../apache/karaf/jms/command/CountCommand.java  |  15 +-
 .../apache/karaf/jms/command/CreateCommand.java |  10 +-
 .../apache/karaf/jms/command/InfoCommand.java   |  17 +-
 .../karaf/jms/command/JmsCommandSupport.java    |   2 -
 .../command/JmsConnectionCommandSupport.java    |  36 ++
 .../apache/karaf/jms/command/MoveCommand.java   |  12 +-
 .../apache/karaf/jms/command/QueuesCommand.java |  13 +-
 .../apache/karaf/jms/command/SendCommand.java   |  11 +-
 .../apache/karaf/jms/command/TopicsCommand.java |  13 +-
 .../java/org/apache/karaf/jms/JmsMessage.java   |   1 -
 .../apache/karaf/jms/internal/JmsCallback.java  |  25 +
 .../karaf/jms/internal/JmsServiceImpl.java      | 474 +++++++------------
 .../apache/karaf/jms/internal/JmsTemplate.java  |  97 ++++
 .../apache/karaf/jms/internal/TemplateUtil.java |  87 ++++
 17 files changed, 434 insertions(+), 406 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/47d745df/jms/command/pom.xml
----------------------------------------------------------------------
diff --git a/jms/command/pom.xml b/jms/command/pom.xml
index 3415841..be28def 100644
--- a/jms/command/pom.xml
+++ b/jms/command/pom.xml
@@ -39,6 +39,10 @@
 
     <dependencies>
         <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.apache.karaf.jms</groupId>
             <artifactId>org.apache.karaf.jms.core</artifactId>
         </dependency>

http://git-wip-us.apache.org/repos/asf/karaf/blob/47d745df/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
index cadd132..c99374a 100644
--- 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
@@ -25,10 +25,7 @@ import org.apache.karaf.shell.table.ShellTable;
 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;
+public class BrowseCommand extends JmsConnectionCommandSupport {
 
     @Argument(index = 1, name = "queue", description = "The JMS queue to browse", required = true, multiValued = false)
     String queue;
@@ -36,12 +33,6 @@ public class BrowseCommand extends JmsCommandSupport {
     @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";
-
     @Option(name = "-v", aliases = { "--verbose" }, description = "Display JMS properties", required = false, multiValued = false)
     boolean verbose = false;
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/47d745df/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
index 8ee992c..d7c732d 100644
--- 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
@@ -21,10 +21,8 @@ import org.apache.karaf.shell.commands.Command;
 import org.apache.karaf.shell.commands.Option;
 
 @Command(scope = "jms", name = "consume", description = "Consume messages from a JMS queue.")
-public class ConsumeCommand extends JmsCommandSupport {
+public class ConsumeCommand extends JmsConnectionCommandSupport {
 
-    @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;
@@ -32,16 +30,8 @@ public class ConsumeCommand extends JmsCommandSupport {
     @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/47d745df/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
index 7d8ad9c..016d6cd 100644
--- 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
@@ -18,31 +18,18 @@ package org.apache.karaf.jms.command;
 
 import org.apache.karaf.shell.commands.Argument;
 import org.apache.karaf.shell.commands.Command;
-import org.apache.karaf.shell.commands.Option;
 import org.apache.karaf.shell.table.ShellTable;
 
 @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;
+public class CountCommand extends JmsConnectionCommandSupport {
 
     @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 {
         ShellTable table = new ShellTable();
-
         table.column("Messages Count");
-
         table.addRow().addContent(getJmsService().count(connectionFactory, queue, username, password));
-
         table.print(System.out);
         return null;
     }

http://git-wip-us.apache.org/repos/asf/karaf/blob/47d745df/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
index 62f19de..9e029f5 100644
--- 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
@@ -26,12 +26,12 @@ 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;
+    @Option(name = "-t", aliases = { "--type" }, description = "The JMS connection factory type (ActiveMQ or WebsphereMQ)", required = false, multiValued = false)
+    String type = "ActiveMQ";
 
+    @Option(name = "--url", description = "URL of the JMS broker. For WebsphereMQ type, the URL is hostname/port/queuemanager/channel", required = false, multiValued = false)
+    String url = "tcp://localhost:61616";
+    
     public Object doExecute() throws Exception {
         getJmsService().create(name, type, url);
         return null;

http://git-wip-us.apache.org/repos/asf/karaf/blob/47d745df/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
index 9d7ee22..8b25130 100644
--- 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
@@ -16,24 +16,13 @@
  */
 package org.apache.karaf.jms.command;
 
-import org.apache.karaf.shell.commands.Argument;
+import java.util.Map;
+
 import org.apache.karaf.shell.commands.Command;
-import org.apache.karaf.shell.commands.Option;
 import org.apache.karaf.shell.table.ShellTable;
 
-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";
+public class InfoCommand extends JmsConnectionCommandSupport {
 
     public Object doExecute() throws Exception {
         ShellTable table = new ShellTable();

http://git-wip-us.apache.org/repos/asf/karaf/blob/47d745df/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
index 7d8eb11..86b99a7 100644
--- 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
@@ -23,8 +23,6 @@ public abstract class JmsCommandSupport extends OsgiCommandSupport {
 
     private JmsService jmsService;
 
-    public abstract Object doExecute() throws Exception;
-
     public JmsService getJmsService() {
         return jmsService;
     }

http://git-wip-us.apache.org/repos/asf/karaf/blob/47d745df/jms/command/src/main/java/org/apache/karaf/jms/command/JmsConnectionCommandSupport.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/JmsConnectionCommandSupport.java b/jms/command/src/main/java/org/apache/karaf/jms/command/JmsConnectionCommandSupport.java
new file mode 100644
index 0000000..00f0a95
--- /dev/null
+++ b/jms/command/src/main/java/org/apache/karaf/jms/command/JmsConnectionCommandSupport.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.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Option;
+
+/**
+ * For commands that need a connection factory and authentication information 
+ */
+public abstract class JmsConnectionCommandSupport 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";
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/47d745df/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
index 7e08188..f1bc85b 100644
--- 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
@@ -21,11 +21,7 @@ import org.apache.karaf.shell.commands.Command;
 import org.apache.karaf.shell.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;
-
+public class MoveCommand extends JmsConnectionCommandSupport {
     @Argument(index = 1, name = "source", description = "The source JMS queue", required = true, multiValued = false)
     String source;
 
@@ -35,12 +31,6 @@ public class MoveCommand extends JmsCommandSupport {
     @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/47d745df/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
index 91aff83..8ae4cab 100644
--- 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
@@ -16,22 +16,11 @@
  */
 package org.apache.karaf.jms.command;
 
-import org.apache.karaf.shell.commands.Argument;
 import org.apache.karaf.shell.commands.Command;
-import org.apache.karaf.shell.commands.Option;
 import org.apache.karaf.shell.table.ShellTable;
 
 @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 class QueuesCommand extends JmsConnectionCommandSupport {
 
     public Object doExecute() throws Exception {
         ShellTable table = new ShellTable();

http://git-wip-us.apache.org/repos/asf/karaf/blob/47d745df/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
index 758881d..792de7f 100644
--- 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
@@ -21,10 +21,7 @@ import org.apache.karaf.shell.commands.Command;
 import org.apache.karaf.shell.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;
+public class SendCommand extends JmsConnectionCommandSupport {
 
     @Argument(index = 1, name = "queue", description = "The JMS queue name", required = true, multiValued = false)
     String queue;
@@ -35,12 +32,6 @@ public class SendCommand extends JmsCommandSupport {
     @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/47d745df/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
index 8993fa8..bd27dcf 100644
--- 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
@@ -16,22 +16,11 @@
  */
 package org.apache.karaf.jms.command;
 
-import org.apache.karaf.shell.commands.Argument;
 import org.apache.karaf.shell.commands.Command;
-import org.apache.karaf.shell.commands.Option;
 import org.apache.karaf.shell.table.ShellTable;
 
 @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 class TopicsCommand extends JmsConnectionCommandSupport {
 
     public Object doExecute() throws Exception {
         ShellTable table = new ShellTable();

http://git-wip-us.apache.org/repos/asf/karaf/blob/47d745df/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
index c159193..a85af10 100644
--- a/jms/core/src/main/java/org/apache/karaf/jms/JmsMessage.java
+++ b/jms/core/src/main/java/org/apache/karaf/jms/JmsMessage.java
@@ -18,7 +18,6 @@ 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;

http://git-wip-us.apache.org/repos/asf/karaf/blob/47d745df/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsCallback.java
----------------------------------------------------------------------
diff --git a/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsCallback.java b/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsCallback.java
new file mode 100644
index 0000000..2e24819
--- /dev/null
+++ b/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsCallback.java
@@ -0,0 +1,25 @@
+/*
+ * 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 javax.jms.Connection;
+import javax.jms.JMSException;
+import javax.jms.Session;
+
+public interface JmsCallback<E> {
+    public E doInSession(Connection connection, Session session) throws JMSException;
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/47d745df/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
index c3430ba..e4b5fc0 100644
--- 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
@@ -28,6 +28,7 @@ import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
 
 import javax.jms.*;
+
 import java.io.*;
 import java.lang.IllegalStateException;
 import java.util.*;
@@ -38,6 +39,12 @@ import java.util.*;
 public class JmsServiceImpl implements JmsService {
 
     private BundleContext bundleContext;
+    private File deployFolder;
+    
+    public JmsServiceImpl() {
+        File karafBase = new File(System.getProperty("karaf.base"));
+        deployFolder = new File(karafBase, "deploy");
+    }
 
     @Override
     public void create(String name, String type, String url) throws Exception {
@@ -45,43 +52,45 @@ public class JmsServiceImpl implements JmsService {
             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");
+        File outFile = getConnectionFactoryFile(name);
+        String template;
+        HashMap<String, String> properties = new HashMap<String, String>();
+        properties.put("name", name);
 
         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);
+            properties.put("url", url);
+            template = "connectionfactory-activemq.xml";
         } 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);
+            
+            properties.put("host", splitted[0]);
+            properties.put("port", splitted[1]);
+            properties.put("queuemanager", splitted[2]);
+            properties.put("channel", splitted[3]);
+            template = "connectionfactory-webspheremq.xml";
         }
+        TemplateUtil.createFromTemplate(outFile, template, properties);
+    }
+
+    private File getConnectionFactoryFile(String name) {
+        return new File(deployFolder, "connectionfactory-" + name + ".xml");
     }
 
     @Override
     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");
+        File connectionFactoryFile = getConnectionFactoryFile(name);
         if (!connectionFactoryFile.exists()) {
             throw new IllegalStateException("The JMS connection factory file " + connectionFactoryFile.getPath() + " doesn't exist");
         }
         connectionFactoryFile.delete();
     }
 
+    @SuppressWarnings("rawtypes")
     @Override
     public List<String> connectionFactories() throws Exception {
         List<String> connectionFactories = new ArrayList<String>();
@@ -102,9 +111,6 @@ public class JmsServiceImpl implements JmsService {
 
     @Override
     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() {
 
             @Override
@@ -118,327 +124,187 @@ public class JmsServiceImpl implements JmsService {
 
     @Override
     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;
-    }
+        JmsTemplate jmsTemplate = new JmsTemplate(bundleContext, connectionFactory, username, password);
+        return jmsTemplate.execute(new JmsCallback<Map<String, String>>() {
 
-    @Override
-    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);
-            }
-        }
+            @Override
+            public Map<String, String> doInSession(Connection connection, Session session)
+                throws JMSException {
+                ConnectionMetaData metaData = connection.getMetaData();
+                Map<String, String> map = new HashMap<String, String>();
+                map.put("product", metaData.getJMSProviderName());
+                map.put("version", metaData.getProviderVersion());
+                return map;
+            }
+            
+        });
     }
 
     @Override
-    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 int count(String connectionFactory, final String destination, String username, String password) throws Exception {
+        JmsTemplate jmsTemplate = new JmsTemplate(bundleContext, connectionFactory, username, password);
+        return jmsTemplate.execute(new JmsCallback<Integer>() {
 
-    @Override
-    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());
+            @SuppressWarnings("unchecked")
+            @Override
+            public Integer doInSession(Connection connection, Session session) throws JMSException {
+                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 (connection != null) {
-                connection.close();
-            }
-            if (reference != null) {
-                bundleContext.ungetService(reference);
-            }
-        }
-        return topics;
+            
+        });
     }
 
-    @Override
-    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);
-            }
+    private DestinationSource getDestinationSource(Connection connection) throws JMSException {
+        if (connection instanceof PooledConnection) {
+            connection = ((PooledConnection) connection).getConnection();
+        }
+        if (connection instanceof ActiveMQConnection) {
+            return ((ActiveMQConnection) connection).getDestinationSource();
+        } else {
+            return null;
         }
-        return messages;
     }
-
+    
     @Override
-    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 List<String> queues(String connectionFactory, String username, String password) {
+        JmsTemplate jmsTemplate = new JmsTemplate(bundleContext, connectionFactory, username, password);
+        return jmsTemplate.execute(new JmsCallback<List<String>>() {
+
+            @Override
+            public List<String> doInSession(Connection connection, Session session) throws JMSException {
+                List<String> queues = new ArrayList<String>();
+                DestinationSource destinationSource = getDestinationSource(connection);
+                if (destinationSource != null) {
+                    Set<ActiveMQQueue> activeMQQueues = destinationSource.getQueues();
+                    for (ActiveMQQueue activeMQQueue : activeMQQueues) {
+                        queues.add(activeMQQueue.getQueueName());
+                    }
+                }
+                return queues;
             }
-        }
+        });
     }
 
     @Override
-    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++;
+    public List<String> topics(String connectionFactory, String username, String password) {
+        JmsTemplate jmsTemplate = new JmsTemplate(bundleContext, connectionFactory, username, password);
+        return jmsTemplate.execute(new JmsCallback<List<String>>() {
+
+            @Override
+            public List<String> doInSession(Connection connection, Session session) throws JMSException {
+                DestinationSource destinationSource = getDestinationSource(connection);
+                List<String> topics = new ArrayList<String>();
+                if (destinationSource != null) {
+                    Set<ActiveMQTopic> activeMQTopics = destinationSource.getTopics();
+                    for (ActiveMQTopic activeMQTopic : activeMQTopics) {
+                        topics.add(activeMQTopic.getTopicName());
+                    }
                 }
-            } while (message != null);
-        } finally {
-            if (session != null) {
-                session.close();
-            }
-            if (connection != null) {
-                connection.close();
-            }
-            if (reference != null) {
-                bundleContext.ungetService(reference);
+                return topics;
             }
-        }
-        return count;
+        });
     }
 
     @Override
-    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++;
+    public List<JmsMessage> browse(String connectionFactory, final String queue, final String filter, String username, String password) {
+        JmsTemplate jmsTemplate = new JmsTemplate(bundleContext, connectionFactory, username, password);
+        return jmsTemplate.execute(new JmsCallback<List<JmsMessage>>() {
+
+            @SuppressWarnings("unchecked")
+            @Override
+            public List<JmsMessage> doInSession(Connection connection, Session session) throws JMSException {
+                List<JmsMessage> messages = new ArrayList<JmsMessage>();
+                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));
                 }
-            } while (message != null);
-            session.commit();
-        } finally {
-            if (session != null) {
-                session.close();
+                browser.close();
+                return messages;
             }
-            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];
-    }
+    @Override
+    public void send(String connectionFactory, final String queue, final String body, final String replyTo, String username, String password) {
+        JmsTemplate jmsTemplate = new JmsTemplate(bundleContext, connectionFactory, username, password);
+        jmsTemplate.execute(new JmsCallback<Void>() {
 
-    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);
+            @Override
+            public Void doInSession(Connection connection, Session session) throws JMSException {
+                Message message = session.createTextMessage(body);
+                if (replyTo != null) {
+                    message.setJMSReplyTo(session.createQueue(replyTo));
                 }
-            } finally {
-                safeClose(is);
+                MessageProducer producer = session.createProducer(session.createQueue(queue));
+                producer.send(message);
+                producer.close();
+                return null;
             }
-        } 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
-        }
-    }
+    @Override
+    public int consume(String connectionFactory, final String queue, final String selector, String username, String password) throws Exception {
+        JmsTemplate jmsTemplate = new JmsTemplate(bundleContext, connectionFactory, username, password);
+        return jmsTemplate.execute(new JmsCallback<Integer>() {
 
-    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;
+            @Override
+            public Integer doInSession(Connection connection, Session session) throws JMSException {
+                int count = 0;
+                MessageConsumer consumer = session.createConsumer(session.createQueue(queue), selector);
+                Message message;
+                do {
+                    message = consumer.receiveNoWait();
+                    if (message != null) {
+                        count++;
+                    }
+                } while (message != null);
+                return count;
             }
-        }
-        return line;
+            
+        });
     }
 
-    public BundleContext getBundleContext() {
-        return bundleContext;
+    @Override
+    public int move(String connectionFactory, final String sourceQueue, final String targetQueue, final String selector, String username, String password) {
+        JmsTemplate jmsTemplate = new JmsTemplate(bundleContext, connectionFactory, username, password);
+        return jmsTemplate.execute(new JmsCallback<Integer>() {
+            
+            @Override
+            public Integer doInSession(Connection connection, Session session) throws JMSException {
+                int count = 0;
+                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);
+                consumer.close();
+                return count;
+            }
+            
+        });
     }
 
     public void setBundleContext(BundleContext bundleContext) {
         this.bundleContext = bundleContext;
     }
 
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/47d745df/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsTemplate.java
----------------------------------------------------------------------
diff --git a/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsTemplate.java b/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsTemplate.java
new file mode 100644
index 0000000..9206632
--- /dev/null
+++ b/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsTemplate.java
@@ -0,0 +1,97 @@
+/*
+ * 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 javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.jms.Session;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+public class JmsTemplate {
+    private BundleContext bc;
+    private String connectionFactoryName;
+    private String username;
+    private String password;
+
+    public JmsTemplate(BundleContext bc, String connectionFactoryName, String username, String password) {
+        this.bc = bc;
+        this.connectionFactoryName = connectionFactoryName;
+        this.username = username;
+        this.password = password;
+    }
+
+    @SuppressWarnings({
+        "rawtypes", "unchecked"
+    })
+    public <E> E execute(JmsCallback<E> callback) {
+        ServiceReference reference = null;
+        Connection connection = null;
+        Session session = null;
+        try {
+            reference = this.lookupConnectionFactory(connectionFactoryName);
+            ConnectionFactory cf = (ConnectionFactory) bc.getService(reference);
+            connection = cf.createConnection(username, password);
+            connection.start();
+            session = connection.createSession(true, Session.SESSION_TRANSACTED);
+            E result = callback.doInSession(connection, session);
+            session.commit();
+            return result;
+        } catch (Exception e) {
+            try {
+                if (session != null) {
+                    session.rollback();
+                }
+            } catch (JMSException e1) {
+                // Ignore 
+            }
+            throw new RuntimeException(e.getMessage(), e);
+        } finally {
+            if (session != null) {
+                try {
+                    session.close();
+                } catch (JMSException e) {
+                    // Ignore
+                }
+            }
+            if (connection != null) {
+                try {
+                    connection.close();
+                } catch (JMSException e) {
+                    // Ignore
+                }
+            }
+            if (reference != null) {
+                bc.ungetService(reference);
+            }
+        }
+    }
+    
+    @SuppressWarnings("rawtypes")
+    private ServiceReference lookupConnectionFactory(String name) throws Exception {
+        ServiceReference[] references = bc.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];
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/47d745df/jms/core/src/main/java/org/apache/karaf/jms/internal/TemplateUtil.java
----------------------------------------------------------------------
diff --git a/jms/core/src/main/java/org/apache/karaf/jms/internal/TemplateUtil.java b/jms/core/src/main/java/org/apache/karaf/jms/internal/TemplateUtil.java
new file mode 100644
index 0000000..bb9cb75
--- /dev/null
+++ b/jms/core/src/main/java/org/apache/karaf/jms/internal/TemplateUtil.java
@@ -0,0 +1,87 @@
+/*
+ * 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 java.io.Closeable;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Scanner;
+
+public class TemplateUtil {
+    private TemplateUtil() {
+    }
+
+    public static void createFromTemplate(File outFile, String resource, HashMap<String, String> properties) {
+        if (outFile.exists()) {
+            throw new IllegalArgumentException("File " + outFile.getPath()
+                                               + " already exists. Remove it if you wish to recreate it.");
+        }
+        InputStream is = TemplateUtil.class.getResourceAsStream(resource);
+        if (is == null) {
+            throw new IllegalArgumentException("Resource " + resource + " doesn't exist");
+        }
+        PrintStream out = null;
+        Scanner scanner = null;
+        try {
+            // read it line at a time so that we can use the platform line ending when we write it out
+            out = new PrintStream(new FileOutputStream(outFile));
+            scanner = new Scanner(is);
+
+            while (scanner.hasNextLine()) {
+                String line = scanner.nextLine();
+                line = filter(line, properties);
+                out.println(line);
+            }
+        } catch (FileNotFoundException e) {
+            throw new RuntimeException("Can not create " + outFile, e);
+        } finally {
+            safeClose(scanner);
+            safeClose(out);
+            safeClose(is);
+        }
+    }
+
+    private static String filter(String line, HashMap<String, String> props) {
+        for (Map.Entry<String, String> entry : props.entrySet()) {
+            String key = "${" + entry.getKey() + "}";
+            int p1 = line.indexOf(key);
+            if (p1 >= 0) {
+                String l1 = line.substring(0, p1);
+                String l2 = line.substring(p1 + key.length());
+                line = l1 + entry.getValue() + l2;
+            }
+        }
+        return line;
+    }
+
+    private static void safeClose(Closeable cl) {
+        if (cl == null) {
+            return;
+        }
+        try {
+            cl.close();
+        } catch (Throwable ignore) {
+            // nothing to do
+        }
+    }
+
+}