You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ta...@apache.org on 2014/09/23 20:20:38 UTC

[14/27] Initial drop of donated AMQP Client Code.

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/StopWatch.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/StopWatch.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/StopWatch.java
new file mode 100644
index 0000000..72c871d
--- /dev/null
+++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/StopWatch.java
@@ -0,0 +1,79 @@
+/**
+ * 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.qpid.jms.util;
+
+/**
+ * A very simple stop watch.
+ * <p/>
+ * This implementation is not thread safe and can only time one task at any given time.
+ */
+public final class StopWatch {
+
+    private long start;
+    private long stop;
+
+    /**
+     * Starts the stop watch
+     */
+    public StopWatch() {
+        this(true);
+    }
+
+    /**
+     * Creates the stop watch
+     *
+     * @param started whether it should start immediately
+     */
+    public StopWatch(boolean started) {
+        if (started) {
+            restart();
+        }
+    }
+
+    /**
+     * Starts or restarts the stop watch
+     */
+    public void restart() {
+        start = System.currentTimeMillis();
+        stop = 0;
+    }
+
+    /**
+     * Stops the stop watch
+     *
+     * @return the time taken in millis.
+     */
+    public long stop() {
+        stop = System.currentTimeMillis();
+        return taken();
+    }
+
+    /**
+     * Returns the time taken in millis.
+     *
+     * @return time in millis
+     */
+    public long taken() {
+        if (start > 0 && stop > 0) {
+            return stop - start;
+        } else if (start > 0) {
+            return System.currentTimeMillis() - start;
+        } else {
+            return 0;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/ThreadPoolUtils.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/ThreadPoolUtils.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/ThreadPoolUtils.java
new file mode 100644
index 0000000..71ae92e
--- /dev/null
+++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/ThreadPoolUtils.java
@@ -0,0 +1,190 @@
+/**
+ * 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.qpid.jms.util;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Utility methods for working with thread pools {@link ExecutorService}.
+ */
+public final class ThreadPoolUtils {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ThreadPoolUtils.class);
+
+    public static final long DEFAULT_SHUTDOWN_AWAIT_TERMINATION = 10 * 1000L;
+
+    /**
+     * Shutdown the given executor service only (ie not graceful shutdown).
+     *
+     * @see java.util.concurrent.ExecutorService#shutdown()
+     */
+    public static void shutdown(ExecutorService executorService) {
+        doShutdown(executorService, 0);
+    }
+
+    /**
+     * Shutdown now the given executor service aggressively.
+     *
+     * @param executorService
+     *        the executor service to shutdown now
+     * @return list of tasks that never commenced execution
+     * @see java.util.concurrent.ExecutorService#shutdownNow()
+     */
+    public static List<Runnable> shutdownNow(ExecutorService executorService) {
+        if (executorService == null) {
+            return Collections.emptyList();
+        }
+
+        List<Runnable> answer = null;
+        if (!executorService.isShutdown()) {
+            LOG.debug("Forcing shutdown of ExecutorService: {}", executorService);
+            answer = executorService.shutdownNow();
+            if (LOG.isTraceEnabled()) {
+                LOG.trace("Shutdown of ExecutorService: {} is shutdown: {} and terminated: {}.",
+                    new Object[] { executorService, executorService.isShutdown(), executorService.isTerminated() });
+            }
+        }
+
+        return answer;
+    }
+
+    /**
+     * Shutdown the given executor service graceful at first, and then aggressively if the await
+     * termination timeout was hit.
+     * <p/>
+     * This implementation invokes the
+     * {@link #shutdownGraceful(java.util.concurrent.ExecutorService, long)} with a timeout
+     * value of {@link #DEFAULT_SHUTDOWN_AWAIT_TERMINATION} millis.
+     */
+    public static void shutdownGraceful(ExecutorService executorService) {
+        doShutdown(executorService, DEFAULT_SHUTDOWN_AWAIT_TERMINATION);
+    }
+
+    /**
+     * Shutdown the given executor service graceful at first, and then aggressively if the await
+     * termination timeout was hit.
+     * <p/>
+     * Will try to perform an orderly shutdown by giving the running threads time to complete
+     * tasks, before going more aggressively by doing a
+     * {@link #shutdownNow(java.util.concurrent.ExecutorService)} which forces a shutdown. The
+     * parameter <tt>shutdownAwaitTermination</tt> is used as timeout value waiting for orderly
+     * shutdown to complete normally, before going aggressively.
+     *
+     * @param executorService
+     *        the executor service to shutdown
+     * @param shutdownAwaitTermination
+     *        timeout in millis to wait for orderly shutdown
+     */
+    public static void shutdownGraceful(ExecutorService executorService, long shutdownAwaitTermination) {
+        doShutdown(executorService, shutdownAwaitTermination);
+    }
+
+    private static void doShutdown(ExecutorService executorService, long shutdownAwaitTermination) {
+        if (executorService == null) {
+            return;
+        }
+
+        // shutting down a thread pool is a 2 step process. First we try graceful, and if
+        // that fails, then we go more aggressively and try shutting down again. In both
+        // cases we wait at most the given shutdown timeout value given
+        //
+        // total wait could then be 2 x shutdownAwaitTermination, but when we shutdown the
+        // 2nd time we are aggressive and thus we ought to shutdown much faster
+        if (!executorService.isShutdown()) {
+            boolean warned = false;
+            StopWatch watch = new StopWatch();
+
+            LOG.trace("Shutdown of ExecutorService: {} with await termination: {} millis", executorService, shutdownAwaitTermination);
+            executorService.shutdown();
+
+            if (shutdownAwaitTermination > 0) {
+                try {
+                    if (!awaitTermination(executorService, shutdownAwaitTermination)) {
+                        warned = true;
+                        LOG.warn("Forcing shutdown of ExecutorService: {} due first await termination elapsed.", executorService);
+                        executorService.shutdownNow();
+                        // we are now shutting down aggressively, so wait to see
+                        // if we can completely shutdown or not
+                        if (!awaitTermination(executorService, shutdownAwaitTermination)) {
+                            LOG.warn("Cannot completely force shutdown of ExecutorService: {} due second await termination elapsed.", executorService);
+                        }
+                    }
+                } catch (InterruptedException e) {
+                    warned = true;
+                    LOG.warn("Forcing shutdown of ExecutorService: {} due interrupted.", executorService);
+                    // we were interrupted during shutdown, so force shutdown
+                    executorService.shutdownNow();
+                }
+            }
+
+            // if we logged at WARN level, then report at INFO level when we are
+            // complete so the end user can see this in the log
+            if (warned) {
+                LOG.info("Shutdown of ExecutorService: {} is shutdown: {} and terminated: {} took: {}.",
+                    new Object[] { executorService, executorService.isShutdown(), executorService.isTerminated(), TimeUtils.printDuration(watch.taken()) });
+            } else if (LOG.isDebugEnabled()) {
+                LOG.debug("Shutdown of ExecutorService: {} is shutdown: {} and terminated: {} took: {}.",
+                    new Object[] { executorService, executorService.isShutdown(), executorService.isTerminated(), TimeUtils.printDuration(watch.taken()) });
+            }
+        }
+    }
+
+    /**
+     * Awaits the termination of the thread pool.
+     * <p/>
+     * This implementation will log every 2nd second at INFO level that we are waiting, so the
+     * end user can see we are not hanging in case it takes longer time to terminate the pool.
+     *
+     * @param executorService
+     *        the thread pool
+     * @param shutdownAwaitTermination
+     *        time in millis to use as timeout
+     *
+     * @return <tt>true</tt> if the pool is terminated, or <tt>false</tt> if we timed out
+     *
+     * @throws InterruptedException
+     *         is thrown if we are interrupted during the waiting
+     */
+    public static boolean awaitTermination(ExecutorService executorService, long shutdownAwaitTermination) throws InterruptedException {
+
+        if (executorService == null) {
+            return true;
+        }
+
+        // log progress every 5th second so end user is aware of we are shutting down
+        StopWatch watch = new StopWatch();
+        long interval = Math.min(2000, shutdownAwaitTermination);
+        boolean done = false;
+        while (!done && interval > 0) {
+            if (executorService.awaitTermination(interval, TimeUnit.MILLISECONDS)) {
+                done = true;
+            } else {
+                LOG.info("Waited {} for ExecutorService: {} to terminate...", TimeUtils.printDuration(watch.taken()), executorService);
+                // recalculate interval
+                interval = Math.min(2000, shutdownAwaitTermination - watch.taken());
+            }
+        }
+
+        return done;
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/TimeUtils.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/TimeUtils.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/TimeUtils.java
new file mode 100644
index 0000000..979d2f0
--- /dev/null
+++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/TimeUtils.java
@@ -0,0 +1,73 @@
+/**
+ * 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.qpid.jms.util;
+
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
+import java.util.Locale;
+
+/**
+ * Time utils.
+ */
+public final class TimeUtils {
+
+    private TimeUtils() {
+    }
+
+    /**
+     * Prints the duration in a human readable format as X days Y hours Z minutes etc.
+     *
+     * @param uptime
+     *        the uptime in millis
+     * @return the time used for displaying on screen or in logs
+     */
+    public static String printDuration(double uptime) {
+
+        NumberFormat fmtI = new DecimalFormat("###,###", new DecimalFormatSymbols(Locale.ENGLISH));
+        NumberFormat fmtD = new DecimalFormat("###,##0.000", new DecimalFormatSymbols(Locale.ENGLISH));
+
+        uptime /= 1000;
+        if (uptime < 60) {
+            return fmtD.format(uptime) + " seconds";
+        }
+        uptime /= 60;
+        if (uptime < 60) {
+            long minutes = (long) uptime;
+            String s = fmtI.format(minutes) + (minutes > 1 ? " minutes" : " minute");
+            return s;
+        }
+        uptime /= 60;
+        if (uptime < 24) {
+            long hours = (long) uptime;
+            long minutes = (long) ((uptime - hours) * 60);
+            String s = fmtI.format(hours) + (hours > 1 ? " hours" : " hour");
+            if (minutes != 0) {
+                s += " " + fmtI.format(minutes) + (minutes > 1 ? " minutes" : " minute");
+            }
+            return s;
+        }
+        uptime /= 24;
+        long days = (long) uptime;
+        long hours = (long) ((uptime - days) * 24);
+        String s = fmtI.format(days) + (days > 1 ? " days" : " day");
+        if (hours != 0) {
+            s += " " + fmtI.format(hours) + (hours > 1 ? " hours" : " hour");
+        }
+        return s;
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/ToStringSupport.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/ToStringSupport.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/ToStringSupport.java
new file mode 100644
index 0000000..6ed6a3a
--- /dev/null
+++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/ToStringSupport.java
@@ -0,0 +1,125 @@
+/**
+ * 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.qpid.jms.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class ToStringSupport {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ToStringSupport.class);
+
+    private ToStringSupport() {
+    }
+
+    public static String toString(Object target) {
+        return toString(target, Object.class, null);
+    }
+
+    @SuppressWarnings({ "rawtypes" })
+    public static String toString(Object target, Class stopClass) {
+        return toString(target, stopClass, null);
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public static String toString(Object target, Class stopClass, Map<String, Object> overrideFields) {
+        LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>();
+        addFields(target, target.getClass(), stopClass, map);
+        if (overrideFields != null) {
+            for(String key : overrideFields.keySet()) {
+                Object value = overrideFields.get(key);
+                map.put(key, value);
+            }
+
+        }
+        StringBuffer buffer = new StringBuffer(simpleName(target.getClass()));
+        buffer.append(" {");
+        Set<Entry<String, Object>> entrySet = map.entrySet();
+        boolean first = true;
+        for (Map.Entry<String,Object> entry : entrySet) {
+            Object value = entry.getValue();
+            Object key = entry.getKey();
+            if (first) {
+                first = false;
+            } else {
+                buffer.append(", ");
+            }
+            buffer.append(key);
+            buffer.append(" = ");
+
+            appendToString(buffer, key, value);
+        }
+        buffer.append("}");
+        return buffer.toString();
+    }
+
+    protected static void appendToString(StringBuffer buffer, Object key, Object value) {
+        if (key.toString().toLowerCase(Locale.ENGLISH).contains("password")){
+            buffer.append("*****");
+        } else {
+            buffer.append(value);
+        }
+    }
+
+    public static String simpleName(Class<?> clazz) {
+        String name = clazz.getName();
+        int p = name.lastIndexOf(".");
+        if (p >= 0) {
+            name = name.substring(p + 1);
+        }
+        return name;
+    }
+
+    @SuppressWarnings({ "rawtypes" })
+    private static void addFields(Object target, Class startClass, Class<Object> stopClass, LinkedHashMap<String, Object> map) {
+
+        if (startClass != stopClass) {
+            addFields(target, startClass.getSuperclass(), stopClass, map);
+        }
+
+        Field[] fields = startClass.getDeclaredFields();
+        for (Field field : fields) {
+            if (Modifier.isStatic(field.getModifiers()) || Modifier.isTransient(field.getModifiers())
+                || Modifier.isPrivate(field.getModifiers())) {
+                continue;
+            }
+
+            try {
+                field.setAccessible(true);
+                Object o = field.get(target);
+                if (o != null && o.getClass().isArray()) {
+                    try {
+                        o = Arrays.asList((Object[])o);
+                    } catch (Exception e) {
+                    }
+                }
+                map.put(field.getName(), o);
+            } catch (Exception e) {
+                LOG.debug("Error getting field " + field + " on class " + startClass + ". This exception is ignored.", e);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/TypeConversionSupport.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/TypeConversionSupport.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/TypeConversionSupport.java
new file mode 100644
index 0000000..08c378c
--- /dev/null
+++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/TypeConversionSupport.java
@@ -0,0 +1,180 @@
+/**
+ * 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.qpid.jms.util;
+
+import java.util.Date;
+import java.util.HashMap;
+
+import org.apache.qpid.jms.JmsDestination;
+import org.apache.qpid.jms.JmsQueue;
+
+public final class TypeConversionSupport {
+
+    static class ConversionKey {
+        final Class<?> from;
+        final Class<?> to;
+        final int hashCode;
+
+        public ConversionKey(Class<?> from, Class<?> to) {
+            this.from = from;
+            this.to = to;
+            this.hashCode = from.hashCode() ^ (to.hashCode() << 1);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            ConversionKey x = (ConversionKey) o;
+            return x.from == from && x.to == to;
+        }
+
+        @Override
+        public int hashCode() {
+            return hashCode;
+        }
+    }
+
+    interface Converter {
+        Object convert(Object value);
+    }
+
+    private static final HashMap<ConversionKey, Converter> CONVERSION_MAP = new HashMap<ConversionKey, Converter>();
+
+    static {
+        Converter toStringConverter = new Converter() {
+            @Override
+            public Object convert(Object value) {
+                return value.toString();
+            }
+        };
+        CONVERSION_MAP.put(new ConversionKey(Boolean.class, String.class), toStringConverter);
+        CONVERSION_MAP.put(new ConversionKey(Byte.class, String.class), toStringConverter);
+        CONVERSION_MAP.put(new ConversionKey(Short.class, String.class), toStringConverter);
+        CONVERSION_MAP.put(new ConversionKey(Integer.class, String.class), toStringConverter);
+        CONVERSION_MAP.put(new ConversionKey(Long.class, String.class), toStringConverter);
+        CONVERSION_MAP.put(new ConversionKey(Float.class, String.class), toStringConverter);
+        CONVERSION_MAP.put(new ConversionKey(Double.class, String.class), toStringConverter);
+
+        CONVERSION_MAP.put(new ConversionKey(String.class, Boolean.class), new Converter() {
+            @Override
+            public Object convert(Object value) {
+                return Boolean.valueOf((String) value);
+            }
+        });
+        CONVERSION_MAP.put(new ConversionKey(String.class, Byte.class), new Converter() {
+            @Override
+            public Object convert(Object value) {
+                return Byte.valueOf((String) value);
+            }
+        });
+        CONVERSION_MAP.put(new ConversionKey(String.class, Short.class), new Converter() {
+            @Override
+            public Object convert(Object value) {
+                return Short.valueOf((String) value);
+            }
+        });
+        CONVERSION_MAP.put(new ConversionKey(String.class, Integer.class), new Converter() {
+            @Override
+            public Object convert(Object value) {
+                return Integer.valueOf((String) value);
+            }
+        });
+        CONVERSION_MAP.put(new ConversionKey(String.class, Long.class), new Converter() {
+            @Override
+            public Object convert(Object value) {
+                return Long.valueOf((String) value);
+            }
+        });
+        CONVERSION_MAP.put(new ConversionKey(String.class, Float.class), new Converter() {
+            @Override
+            public Object convert(Object value) {
+                return Float.valueOf((String) value);
+            }
+        });
+        CONVERSION_MAP.put(new ConversionKey(String.class, Double.class), new Converter() {
+            @Override
+            public Object convert(Object value) {
+                return Double.valueOf((String) value);
+            }
+        });
+
+        Converter longConverter = new Converter() {
+            @Override
+            public Object convert(Object value) {
+                return Long.valueOf(((Number) value).longValue());
+            }
+        };
+        CONVERSION_MAP.put(new ConversionKey(Byte.class, Long.class), longConverter);
+        CONVERSION_MAP.put(new ConversionKey(Short.class, Long.class), longConverter);
+        CONVERSION_MAP.put(new ConversionKey(Integer.class, Long.class), longConverter);
+        CONVERSION_MAP.put(new ConversionKey(Date.class, Long.class), new Converter() {
+            @Override
+            public Object convert(Object value) {
+                return Long.valueOf(((Date) value).getTime());
+            }
+        });
+
+        Converter intConverter = new Converter() {
+            @Override
+            public Object convert(Object value) {
+                return Integer.valueOf(((Number) value).intValue());
+            }
+        };
+        CONVERSION_MAP.put(new ConversionKey(Byte.class, Integer.class), intConverter);
+        CONVERSION_MAP.put(new ConversionKey(Short.class, Integer.class), intConverter);
+
+        CONVERSION_MAP.put(new ConversionKey(Byte.class, Short.class), new Converter() {
+            @Override
+            public Object convert(Object value) {
+                return Short.valueOf(((Number) value).shortValue());
+            }
+        });
+
+        CONVERSION_MAP.put(new ConversionKey(Float.class, Double.class), new Converter() {
+            @Override
+            public Object convert(Object value) {
+                return new Double(((Number) value).doubleValue());
+            }
+        });
+
+        CONVERSION_MAP.put(new ConversionKey(String.class, JmsDestination.class), new Converter() {
+            @Override
+            public Object convert(Object value) {
+                // TODO - Right now we go right to a Queue, we need to examine the name
+                //        and correctly map to the appropriate destination type.
+                return new JmsQueue(value.toString());
+            }
+        });
+    }
+
+    private TypeConversionSupport() {
+    }
+
+    public static Object convert(Object value, Class<?> clazz) {
+
+        assert value != null && clazz != null;
+
+        if (value.getClass() == clazz) {
+            return value;
+        }
+
+        Converter c = CONVERSION_MAP.get(new ConversionKey(value.getClass(), clazz));
+        if (c == null) {
+            return null;
+        }
+        return c.convert(value);
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/URISupport.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/URISupport.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/URISupport.java
new file mode 100644
index 0000000..0a649f3
--- /dev/null
+++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/URISupport.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.qpid.jms.util;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Provides support methods for dealing with URI values.
+ */
+public class URISupport {
+
+    /**
+     * A composite URI can be split into one or more CompositeData object which each represent
+     * the individual URIs that comprise the composite one.
+     */
+    public static class CompositeData {
+        private String host;
+        private String scheme;
+        private String path;
+        private URI components[];
+        private Map<String, String> parameters;
+        private String fragment;
+
+        public URI[] getComponents() {
+            return components;
+        }
+
+        public String getFragment() {
+            return fragment;
+        }
+
+        public Map<String, String> getParameters() {
+            return parameters;
+        }
+
+        public String getScheme() {
+            return scheme;
+        }
+
+        public String getPath() {
+            return path;
+        }
+
+        public String getHost() {
+            return host;
+        }
+
+        public URI toURI() throws URISyntaxException {
+            StringBuffer sb = new StringBuffer();
+            if (scheme != null) {
+                sb.append(scheme);
+                sb.append(':');
+            }
+
+            if (host != null && host.length() != 0) {
+                sb.append(host);
+            } else {
+                sb.append('(');
+                for (int i = 0; i < components.length; i++) {
+                    if (i != 0) {
+                        sb.append(',');
+                    }
+                    sb.append(components[i].toString());
+                }
+                sb.append(')');
+            }
+
+            if (path != null) {
+                sb.append('/');
+                sb.append(path);
+            }
+            if (!parameters.isEmpty()) {
+                sb.append("?");
+                sb.append(PropertyUtil.createQueryString(parameters));
+            }
+            if (fragment != null) {
+                sb.append("#");
+                sb.append(fragment);
+            }
+            return new URI(sb.toString());
+        }
+    }
+
+    /**
+     * Given a composite URI, parse the individual URI elements contained within that URI and
+     * return a CompsoteData instance that contains the parsed URI values.
+     *
+     * @param uri
+     *        The target URI that should be parsed.
+     *
+     * @return a new CompsiteData instance representing the parsed composite URI.
+     * @throws URISyntaxException
+     */
+    public static CompositeData parseComposite(URI uri) throws URISyntaxException {
+
+        CompositeData rc = new CompositeData();
+        rc.scheme = uri.getScheme();
+        String ssp = PropertyUtil.stripPrefix(uri.getRawSchemeSpecificPart().trim(), "//").trim();
+
+        try {
+            parseComposite(uri, rc, ssp);
+        } catch (Exception e) {
+            throw new URISyntaxException(uri.toString(), e.getMessage());
+        }
+
+        rc.fragment = uri.getFragment();
+        return rc;
+    }
+
+    /**
+     * Given a composite URI and a CompositeData instance and the scheme specific part extracted
+     * from the source URI, parse the composite URI and populate the CompositeData object with
+     * the results. The source URI is used only for logging as the ssp should have already been
+     * extracted from it and passed here.
+     *
+     * @param uri
+     *        The original source URI whose ssp is parsed into the composite data.
+     * @param rc
+     *        The CompsositeData instance that will be populated from the given ssp.
+     * @param ssp
+     *        The scheme specific part from the original string that is a composite or one or
+     *        more URIs.
+     *
+     * @throws URISyntaxException
+     */
+    private static void parseComposite(URI uri, CompositeData rc, String ssp) throws Exception {
+        String componentString;
+        String params;
+
+        if (!checkParenthesis(ssp)) {
+            throw new URISyntaxException(uri.toString(), "Not a matching number of '(' and ')' parenthesis");
+        }
+
+        int p;
+        int initialParen = ssp.indexOf("(");
+        if (initialParen == 0) {
+
+            rc.host = ssp.substring(0, initialParen);
+            p = rc.host.indexOf("/");
+
+            if (p >= 0) {
+                rc.path = rc.host.substring(p);
+                rc.host = rc.host.substring(0, p);
+            }
+
+            p = indexOfParenthesisMatch(ssp, initialParen);
+            componentString = ssp.substring(initialParen + 1, p);
+            params = ssp.substring(p + 1).trim();
+
+        } else {
+            componentString = ssp;
+            params = "";
+        }
+
+        String components[] = splitComponents(componentString);
+        rc.components = new URI[components.length];
+        for (int i = 0; i < components.length; i++) {
+            rc.components[i] = new URI(components[i].trim());
+        }
+
+        p = params.indexOf("?");
+        if (p >= 0) {
+            if (p > 0) {
+                rc.path = PropertyUtil.stripPrefix(params.substring(0, p), "/");
+            }
+            rc.parameters = PropertyUtil.parseQuery(params.substring(p + 1));
+        } else {
+            if (params.length() > 0) {
+                rc.path = PropertyUtil.stripPrefix(params, "/");
+            }
+            rc.parameters = Collections.emptyMap();
+        }
+    }
+
+    /**
+     * Examine a URI and determine if it is a Composite type or not.
+     *
+     * @param uri
+     *        The URI that is to be examined.
+     *
+     * @return true if the given URI is a Composite type.
+     */
+    public static boolean isCompositeURI(URI uri) {
+        String ssp = PropertyUtil.stripPrefix(uri.getRawSchemeSpecificPart().trim(), "//").trim();
+
+        if (ssp.indexOf('(') == 0 && checkParenthesis(ssp)) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Examine the supplied string and ensure that all parends appear as matching pairs.
+     *
+     * @param str
+     *        The target string to examine.
+     *
+     * @return true if the target string has valid parend pairings.
+     */
+    public static boolean checkParenthesis(String str) {
+        boolean result = true;
+        if (str != null) {
+            int open = 0;
+            int closed = 0;
+
+            int i = 0;
+            while ((i = str.indexOf('(', i)) >= 0) {
+                i++;
+                open++;
+            }
+            i = 0;
+            while ((i = str.indexOf(')', i)) >= 0) {
+                i++;
+                closed++;
+            }
+            result = open == closed;
+        }
+        return result;
+    }
+
+    /**
+     * Given a string and a position in that string of an open parend, find the matching close
+     * parend.
+     *
+     * @param str
+     *        The string to be searched for a matching parend.
+     * @param first
+     *        The index in the string of the opening parend whose close value is to be searched.
+     *
+     * @return the index in the string where the closing parend is located.
+     *
+     * @throws URISyntaxException
+     *         if the string does not contain a matching parend.
+     */
+    public static int indexOfParenthesisMatch(String str, int first) throws URISyntaxException {
+        int index = -1;
+
+        if (first < 0 || first > str.length()) {
+            throw new IllegalArgumentException("Invalid position for first parenthesis: " + first);
+        }
+
+        if (str.charAt(first) != '(') {
+            throw new IllegalArgumentException("character at indicated position is not a parenthesis");
+        }
+
+        int depth = 1;
+        char[] array = str.toCharArray();
+        for (index = first + 1; index < array.length; ++index) {
+            char current = array[index];
+            if (current == '(') {
+                depth++;
+            } else if (current == ')') {
+                if (--depth == 0) {
+                    break;
+                }
+            }
+        }
+
+        if (depth != 0) {
+            throw new URISyntaxException(str, "URI did not contain a matching parenthesis.");
+        }
+
+        return index;
+    }
+
+    /**
+     * Given the inner portion of a composite URI, split and return each inner URI as a string
+     * element in a new String array.
+     *
+     * @param str
+     *        The inner URI elements of a composite URI string.
+     *
+     * @return an array containing each inner URI from the composite one.
+     */
+    public static String[] splitComponents(String str) {
+        List<String> l = new ArrayList<String>();
+
+        int last = 0;
+        int depth = 0;
+        char chars[] = str.toCharArray();
+        for (int i = 0; i < chars.length; i++) {
+            switch (chars[i]) {
+                case '(':
+                    depth++;
+                    break;
+                case ')':
+                    depth--;
+                    break;
+                case ',':
+                    if (depth == 0) {
+                        String s = str.substring(last, i);
+                        l.add(s);
+                        last = i + 1;
+                    }
+                    break;
+                default:
+            }
+        }
+
+        String s = str.substring(last);
+        if (s.length() != 0) {
+            l.add(s);
+        }
+
+        String rc[] = new String[l.size()];
+        l.toArray(rc);
+        return rc;
+    }
+
+    /**
+     * Removes any URI query from the given uri and return a new URI that does not contain the
+     * query portion.
+     *
+     * @param uri
+     *        The URI whose query value is to be removed.
+     *
+     * @return a new URI that does not contain a query value.
+     * @throws URISyntaxException
+     */
+    public static URI removeQuery(URI uri) throws URISyntaxException {
+        return PropertyUtil.replaceQuery(uri, (String) null);
+    }
+
+    /**
+     * Given a URI parse and extract any URI query options and return them as a Key / Value
+     * mapping.
+     *
+     * This method differs from the {@link parseQuery} method in that it handles composite URI
+     * types and will extract the URI options from the outermost composite URI.
+     *
+     * @param uri
+     *        The URI whose query should be extracted and processed.
+     *
+     * @return A Mapping of the URI options.
+     * @throws URISyntaxException
+     */
+    public static Map<String, String> parseParameters(URI uri) throws URISyntaxException {
+        if (!isCompositeURI(uri)) {
+            if (uri.getQuery() == null) {
+                return Collections.emptyMap();
+            } else {
+                try {
+                    return PropertyUtil.parseQuery(PropertyUtil.stripPrefix(uri.getQuery(), "?"));
+                } catch (Exception e) {
+                    throw new URISyntaxException(uri.toString(), e.getMessage());
+                }
+            }
+        } else {
+            CompositeData data = URISupport.parseComposite(uri);
+            Map<String, String> parameters = new HashMap<String, String>();
+            parameters.putAll(data.getParameters());
+            if (parameters.isEmpty()) {
+                parameters = Collections.emptyMap();
+            }
+
+            return parameters;
+        }
+    }
+
+    /**
+     * Given a Key / Value mapping create and append a URI query value that represents the
+     * mapped entries, return the newly updated URI that contains the value of the given URI and
+     * the appended query value.
+     *
+     * @param uri
+     *        The source URI that will have the Map entries appended as a URI query value.
+     * @param queryParameters
+     *        The Key / Value mapping that will be transformed into a URI query string.
+     *
+     * @return A new URI value that combines the given URI and the constructed query string.
+     * @throws URISyntaxException
+     */
+    public static URI applyParameters(URI uri, Map<String, String> queryParameters) throws URISyntaxException {
+        return applyParameters(uri, queryParameters, "");
+    }
+
+    /**
+     * Given a Key / Value mapping create and append a URI query value that represents the
+     * mapped entries, return the newly updated URI that contains the value of the given URI and
+     * the appended query value. Each entry in the query string is prefixed by the supplied
+     * optionPrefix string.
+     *
+     * @param uri
+     *        The source URI that will have the Map entries appended as a URI query value.
+     * @param queryParameters
+     *        The Key / Value mapping that will be transformed into a URI query string.
+     * @param optionPrefix
+     *        A string value that when not null or empty is used to prefix each query option
+     *        key.
+     *
+     * @return A new URI value that combines the given URI and the constructed query string.
+     * @throws URISyntaxException
+     */
+    public static URI applyParameters(URI uri, Map<String, String> queryParameters, String optionPrefix) throws URISyntaxException {
+        if (queryParameters != null && !queryParameters.isEmpty()) {
+            StringBuffer newQuery = uri.getRawQuery() != null ? new StringBuffer(uri.getRawQuery()) : new StringBuffer();
+            for (Map.Entry<String, String> param : queryParameters.entrySet()) {
+                if (param.getKey().startsWith(optionPrefix)) {
+                    if (newQuery.length() != 0) {
+                        newQuery.append('&');
+                    }
+                    final String key = param.getKey().substring(optionPrefix.length());
+                    newQuery.append(key).append('=').append(param.getValue());
+                }
+            }
+            uri = PropertyUtil.replaceQuery(uri, newQuery.toString());
+        }
+        return uri;
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/amqp
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/amqp b/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/amqp
new file mode 100644
index 0000000..fe3ecca
--- /dev/null
+++ b/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/amqp
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+class=org.apache.qpid.jms.provider.amqp.AmqpProviderFactory

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/amqp+nio
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/amqp+nio b/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/amqp+nio
new file mode 100644
index 0000000..fe3ecca
--- /dev/null
+++ b/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/amqp+nio
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+class=org.apache.qpid.jms.provider.amqp.AmqpProviderFactory

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/amqp+nio+ssl
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/amqp+nio+ssl b/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/amqp+nio+ssl
new file mode 100644
index 0000000..69cd431
--- /dev/null
+++ b/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/amqp+nio+ssl
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+class=org.apache.qpid.jms.provider.amqp.AmqpSslProviderFactory

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/amqp+ssl
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/amqp+ssl b/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/amqp+ssl
new file mode 100644
index 0000000..69cd431
--- /dev/null
+++ b/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/amqp+ssl
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+class=org.apache.qpid.jms.provider.amqp.AmqpSslProviderFactory

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/amqps
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/amqps b/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/amqps
new file mode 100644
index 0000000..69cd431
--- /dev/null
+++ b/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/amqps
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+class=org.apache.qpid.jms.provider.amqp.AmqpSslProviderFactory

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/failover
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/failover b/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/failover
new file mode 100644
index 0000000..b66f21e
--- /dev/null
+++ b/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/provider/failover
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+class=org.apache.qpid.jms.provider.failover.FailoverProviderFactory

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/sasl/ANONYMOUS
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/sasl/ANONYMOUS b/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/sasl/ANONYMOUS
new file mode 100644
index 0000000..00b9f52
--- /dev/null
+++ b/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/sasl/ANONYMOUS
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+class=org.apache.qpid.jms.sasl.AnonymousMechanismFactory

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/sasl/CRAM-MD5
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/sasl/CRAM-MD5 b/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/sasl/CRAM-MD5
new file mode 100644
index 0000000..fb2d223
--- /dev/null
+++ b/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/sasl/CRAM-MD5
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+class=org.apache.qpid.jms.sasl.CramMD5MechanismFactory

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/sasl/PLAIN
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/sasl/PLAIN b/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/sasl/PLAIN
new file mode 100644
index 0000000..cf06fa1
--- /dev/null
+++ b/qpid-jms-client/src/main/resources/META-INF/services/org/apache/qpid/jms/sasl/PLAIN
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+class=org.apache.qpid.jms.sasl.PlainMechanismFactory

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/ConnectionIntegrationTest.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/ConnectionIntegrationTest.java b/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/ConnectionIntegrationTest.java
new file mode 100644
index 0000000..3a7b6ac
--- /dev/null
+++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/ConnectionIntegrationTest.java
@@ -0,0 +1,66 @@
+/*
+ *
+ * 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.qpid.jms.integration;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionMetaData;
+import javax.jms.Session;
+
+import org.apache.qpid.jms.test.QpidJmsTestCase;
+import org.apache.qpid.jms.test.testpeer.TestAmqpPeer;
+import org.junit.Test;
+
+// TODO find a way to make the test abort immediately if the TestAmqpPeer throws an exception
+public class ConnectionIntegrationTest extends QpidJmsTestCase {
+    private final IntegrationTestFixture testFixture = new IntegrationTestFixture();
+
+    @Test(timeout=10000)
+    public void testCreateAndCloseConnection() throws Exception {
+        try (TestAmqpPeer testPeer = new TestAmqpPeer(IntegrationTestFixture.PORT);) {
+            Connection connection = testFixture.establishConnecton(testPeer);
+            testPeer.expectClose();
+            connection.close();
+        }
+    }
+
+    @Test(timeout=10000)
+    public void testCreateAutoAckSession() throws Exception {
+        try (TestAmqpPeer testPeer = new TestAmqpPeer(IntegrationTestFixture.PORT);) {
+            Connection connection = testFixture.establishConnecton(testPeer);
+            testPeer.expectBegin(true);
+            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+            assertNotNull("Session should not be null", session);
+        }
+    }
+
+    @Test(timeout=5000)
+    public void testConnectionMetaDataVersion() throws Exception {
+        try (TestAmqpPeer testPeer = new TestAmqpPeer(IntegrationTestFixture.PORT);) {
+            Connection connection = testFixture.establishConnecton(testPeer);
+
+            ConnectionMetaData meta = connection.getMetaData();
+            assertTrue("Expected non-zero provider major version", meta.getProviderMajorVersion() != 0);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/IntegrationTestFixture.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/IntegrationTestFixture.java b/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/IntegrationTestFixture.java
new file mode 100644
index 0000000..cf19d67
--- /dev/null
+++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/integration/IntegrationTestFixture.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.qpid.jms.integration;
+
+import static org.junit.Assert.assertNull;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+
+import org.apache.qpid.jms.JmsConnectionFactory;
+import org.apache.qpid.jms.test.testpeer.TestAmqpPeer;
+
+public class IntegrationTestFixture {
+    static final int PORT = 25672;
+
+    Connection establishConnecton(TestAmqpPeer testPeer) throws JMSException {
+        testPeer.expectPlainConnect("guest", "guest", true);
+
+        // Each connection creates a session for managing temporary destinations etc
+        testPeer.expectBegin(true);
+
+        ConnectionFactory factory = new JmsConnectionFactory("amqp://localhost:" + PORT);
+        Connection connection = factory.createConnection("guest", "guest");
+
+        // Set a clientId to provoke the actual AMQP connection process to occur.
+        connection.setClientID("clientName");
+
+        assertNull(testPeer.getThrowable());
+        return connection;
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org