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: [email protected] For additional commands, e-mail: [email protected]
