You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by kp...@apache.org on 2015/07/09 05:31:08 UTC

qpid-interop-test git commit: QPIDIT-1: Intial commit of qpid-jms shim

Repository: qpid-interop-test
Updated Branches:
  refs/heads/master 6d0d60388 -> 77eba676f


QPIDIT-1: Intial commit of qpid-jms shim


Project: http://git-wip-us.apache.org/repos/asf/qpid-interop-test/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-interop-test/commit/77eba676
Tree: http://git-wip-us.apache.org/repos/asf/qpid-interop-test/tree/77eba676
Diff: http://git-wip-us.apache.org/repos/asf/qpid-interop-test/diff/77eba676

Branch: refs/heads/master
Commit: 77eba676f7653c3bdb1ea44d1e1c6cb81f47a932
Parents: 6d0d603
Author: Kim van der Riet <kp...@apache.org>
Authored: Wed Jul 8 23:29:14 2015 -0400
Committer: Kim van der Riet <kp...@apache.org>
Committed: Wed Jul 8 23:29:14 2015 -0400

----------------------------------------------------------------------
 jars/README                                     |   3 +
 jars/slf4j-nop-1.5.6.jar                        | Bin 0 -> 5283 bytes
 shims/qpid-jms/java-build.sh                    |  13 +
 shims/qpid-jms/java-clean.sh                    |   5 +
 .../interop_test/shim/ProtonJmsReceiver.java    | 269 +++++++++++++++++++
 .../qpid/interop_test/shim/ProtonJmsSender.java | 258 ++++++++++++++++++
 shims/qpid-proton-python/src/proton-python-send |   2 +-
 .../types/simple_type_tests.py                  | 117 +++++---
 8 files changed, 625 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/77eba676/jars/README
----------------------------------------------------------------------
diff --git a/jars/README b/jars/README
new file mode 100644
index 0000000..4aea73f
--- /dev/null
+++ b/jars/README
@@ -0,0 +1,3 @@
+This directory is a temporary landing place for jars that need to be included
+in the java CLASSPATH. Once this project has been Maven-ized, it is expected
+that this will be handled automatically by Maven and this dir will go away.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/77eba676/jars/slf4j-nop-1.5.6.jar
----------------------------------------------------------------------
diff --git a/jars/slf4j-nop-1.5.6.jar b/jars/slf4j-nop-1.5.6.jar
new file mode 100644
index 0000000..71fda42
Binary files /dev/null and b/jars/slf4j-nop-1.5.6.jar differ

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/77eba676/shims/qpid-jms/java-build.sh
----------------------------------------------------------------------
diff --git a/shims/qpid-jms/java-build.sh b/shims/qpid-jms/java-build.sh
new file mode 100755
index 0000000..78f5bfa
--- /dev/null
+++ b/shims/qpid-jms/java-build.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# JARS
+JMS_API=${HOME}/.m2/repository/org/apache/geronimo/specs/geronimo-jms_1.1_spec/1.1.1/geronimo-jms_1.1_spec-1.1.1.jar:${HOME}/.m2/repository/org/apache/qpid/qpid-jms-client/0.4.0-SNAPSHOT/qpid-jms-client-0.4.0-SNAPSHOT.jar
+CLASSPATH=${JMS_API}
+
+BASEPATH=org/apache/qpid/interop_test/shim
+SRCPATH=src/main/java/${BASEPATH}
+TARGETPATH=target
+
+mkdir -p ${TARGETPATH}/classes
+javac -cp ${CLASSPATH} -d ${TARGETPATH}/classes ${SRCPATH}/ProtonJmsSender.java ${SRCPATH}/ProtonJmsReceiver.java
+jar -cf ${TARGETPATH}/qpid-jms-shim.jar -C ${TARGETPATH}/classes ${BASEPATH}/ProtonJmsSender.class -C ${TARGETPATH}/classes ${BASEPATH}/ProtonJmsSender\$1.class -C ${TARGETPATH}/classes ${BASEPATH}/ProtonJmsSender\$MyExceptionListener.class -C ${TARGETPATH}/classes ${BASEPATH}/ProtonJmsReceiver.class -C ${TARGETPATH}/classes ${BASEPATH}/ProtonJmsReceiver\$1.class -C ${TARGETPATH}/classes ${BASEPATH}/ProtonJmsReceiver\$MyExceptionListener.class

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/77eba676/shims/qpid-jms/java-clean.sh
----------------------------------------------------------------------
diff --git a/shims/qpid-jms/java-clean.sh b/shims/qpid-jms/java-clean.sh
new file mode 100755
index 0000000..7fc8be1
--- /dev/null
+++ b/shims/qpid-jms/java-clean.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+TARGETPATH=target
+
+rm -rf ${TARGETPATH}/*.jar ${TARGETPATH}/classes/*

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/77eba676/shims/qpid-jms/src/main/java/org/apache/qpid/interop_test/shim/ProtonJmsReceiver.java
----------------------------------------------------------------------
diff --git a/shims/qpid-jms/src/main/java/org/apache/qpid/interop_test/shim/ProtonJmsReceiver.java b/shims/qpid-jms/src/main/java/org/apache/qpid/interop_test/shim/ProtonJmsReceiver.java
new file mode 100644
index 0000000..4710025
--- /dev/null
+++ b/shims/qpid-jms/src/main/java/org/apache/qpid/interop_test/shim/ProtonJmsReceiver.java
@@ -0,0 +1,269 @@
+/**
+ * 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.interop_test.shim;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+import java.util.Vector;
+import javax.jms.BytesMessage;
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.ExceptionListener;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.ObjectMessage;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import org.apache.qpid.jms.JmsConnectionFactory;
+
+public class ProtonJmsReceiver {
+    private static final String USER = "guest";
+    private static final String PASSWORD = "guest";
+    private static final int TIMEOUT = 1000;
+    private static final String[] SUPPORTED_AMQP_TYPES = {"null",
+													      "boolean",
+													      "ubyte",
+													      "ushort",
+													      "uint",
+													      "ulong",
+													      "byte",
+													      "short",
+													      "int",
+													      "long",
+													      "float",
+													      "double",
+													      "decimal32",
+													      "decimal64",
+													      "decimal128",
+													      "char",
+													      "timestamp",
+													      "uuid",
+													      "binary",
+													      "string",
+													      "symbol",
+													      "list",
+													      "map",
+													      "array"};
+
+    public static void main(String[] args) throws Exception {
+    	if (args.length < 4) {
+    		System.out.println("ProtonJmsReceiver: Insufficient number of arguments");
+    		System.out.println("ProtonJmsReceiver: Expected arguments: broker_address, queue_name, amqp_type, num_test_values");
+    		System.exit(1);
+    	}
+    	String brokerAddress = "amqp://" + args[0];
+    	String queueName = args[1];
+    	String amqpType = args[2];
+    	int numTestValues = Integer.parseInt(args[3]);
+    	Connection connection = null;
+
+        try {
+        	ConnectionFactory factory = (ConnectionFactory)new JmsConnectionFactory(brokerAddress);
+
+            connection = factory.createConnection(USER, PASSWORD);
+            connection.setExceptionListener(new MyExceptionListener());
+            connection.start();
+
+            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+            
+            Queue queue = session.createQueue(queueName);
+
+            MessageConsumer messageConsumer = session.createConsumer(queue);
+            
+            Vector<String> outList = new Vector<String>();
+            outList.add(amqpType);
+            if (isSupportedAmqpType(amqpType)) {
+                int actualCount = 0;
+                Message message = null;
+                for (int i = 1; i <= numTestValues; i++, actualCount++) {
+        			message = messageConsumer.receive(TIMEOUT);
+        			if (message == null)
+        				break;
+            		switch (amqpType) {
+            		case "null":
+            			long bodyLength = ((BytesMessage)message).getBodyLength();
+            			if (bodyLength == 0L) {
+            				outList.add("None");
+            			} else {
+            				throw new Exception("ProtonJmsReceiver: JMS BytesMessage size error: Expected 0 bytes, read " + bodyLength);
+            			}
+            			break;
+            		case "boolean":
+            			String bs = String.valueOf(((BytesMessage)message).readBoolean());
+            			outList.add(Character.toUpperCase(bs.charAt(0)) + bs.substring(1));
+            			break;
+            		case "ubyte":
+            			byte byteValue = ((BytesMessage)message).readByte();
+            			short ubyteValue = (short)(byteValue & 0xff);
+            			outList.add(String.valueOf(ubyteValue));
+            			break;
+            		case "ushort":
+            		{
+            			byte[] byteArray = new byte[2];
+            			int numBytes = ((BytesMessage)message).readBytes(byteArray);
+            			if (numBytes != 2) {
+            				// TODO: numBytes == -1 means no more bytes in stream - add error message for this case?
+            				throw new Exception("ProtonJmsReceiver: JMS BytesMessage size error: Exptected 2 bytes, read " + numBytes);
+            			}
+            			int ushortValue = 0;
+            			for (int j=0; j<byteArray.length; j++) {
+            				ushortValue = (ushortValue << 8) + (byteArray[j] & 0xff);
+            			}
+            			outList.add(String.valueOf(ushortValue));
+            			break;
+            		}
+            		case "uint":
+            		{
+            			byte[] byteArray = new byte[4];
+            			int numBytes = ((BytesMessage)message).readBytes(byteArray);
+            			if (numBytes != 4) {
+            				// TODO: numBytes == -1 means no more bytes in stream - add error message for this case?
+            				throw new Exception("ProtonJmsReceiver: JMS BytesMessage size error: Exptected 4 bytes, read " + numBytes);
+            			}
+            			long uintValue = 0;
+            			for (int j=0; j<byteArray.length; j++) {
+            				uintValue = (uintValue << 8) + (byteArray[j] & 0xff);
+            			}
+            			outList.add(String.valueOf(uintValue));
+            			break;
+            		}
+            		case "ulong":
+            		case "timestamp":
+            		{
+            			// TODO: Tidy this ugliness up - perhaps use of vector<byte>?
+            			byte[] byteArray = new byte[8];
+            			int numBytes = ((BytesMessage)message).readBytes(byteArray);
+            			if (numBytes != 8) {
+            				// TODO: numBytes == -1 means no more bytes in stream - add error message for this case?
+            				throw new Exception("ProtonJmsReceiver: JMS BytesMessage size error: Exptected 8 bytes, read " + numBytes);
+            			}
+            			// TODO: shortcut in use here - this byte array should go through a Java type that can represent this as a number - such as BigInteger.
+            			outList.add(String.format("0x%02x%02x%02x%02x%02x%02x%02x%02x", byteArray[0], byteArray[1],
+            					byteArray[2], byteArray[3], byteArray[4], byteArray[5], byteArray[6], byteArray[7]));
+            			break;
+            		}
+            		case "byte":
+            			outList.add(String.valueOf(((BytesMessage)message).readByte()));
+            			break;
+            		case "short":
+            			outList.add(String.valueOf(((BytesMessage)message).readShort()));
+            			break;
+            		case "int":
+            			outList.add(String.valueOf(((BytesMessage)message).readInt()));
+            			break;
+            		case "long":
+            			outList.add(String.valueOf(((BytesMessage)message).readLong()));
+            			break;
+            		case "float":
+            			float f = ((BytesMessage)message).readFloat();
+            			int i0 = Float.floatToRawIntBits(f);
+            			outList.add(String.format("0x%8s", Integer.toHexString(i0)).replace(' ', '0'));
+            			break;
+            		case "double":
+            			double d = ((BytesMessage)message).readDouble();
+            			long l = Double.doubleToRawLongBits(d);
+            			outList.add(String.format("0x%16s", Long.toHexString(l)).replace(' ', '0'));
+            			break;
+            		case "decimal32":
+            			BigDecimal bd32 = (BigDecimal)((ObjectMessage)message).getObject();
+            			outList.add(bd32.toString());
+            			break;
+            		case "decimal64":
+            			BigDecimal bd64 = (BigDecimal)((ObjectMessage)message).getObject();
+            			outList.add(bd64.toString());
+            			break;
+            		case "decimal128":
+            			BigDecimal bd128 = (BigDecimal)((ObjectMessage)message).getObject();
+            			outList.add(bd128.toString());
+            			break;
+            		case "char":
+            			outList.add(String.format("%c", ((BytesMessage)message).readChar()));
+            			break;
+            		case "uuid":
+            			UUID uuid = (UUID)((ObjectMessage)message).getObject();
+            			outList.add(uuid.toString());
+            			break;
+            		case "binary":
+            			BytesMessage bm = (BytesMessage)message;
+            			int msgLen = (int)bm.getBodyLength();
+            			byte[] ba = new byte[msgLen];
+            			if (bm.readBytes(ba) == msgLen) {
+            				outList.add(new String(ba));
+            			} else {
+            				// TODO: Raise exception or error here: size mismatch
+            			}
+            			break;
+            		case "string":
+            			outList.add(((TextMessage)message).getText());
+            			break;
+            		case "symbol":
+            			outList.add(((BytesMessage)message).readUTF());
+            			break;
+            		case "list":
+            			break;
+            		case "map":
+            			break;
+            		case "array":
+            			break;
+            		default:
+            			// Internal error, should never happen if SUPPORTED_AMQP_TYPES matches this case stmt
+            			connection.close();
+            			throw new Exception("ProtonJmsReceiver: Internal error: unsupported AMQP type \"" + amqpType + "\"");
+            		}
+                }
+            } else {
+            	System.out.println("ERROR: ProtonJmsReceiver: AMQP type \"" + amqpType + "\" is not supported");
+            	connection.close();
+            	System.exit(1);
+            }
+
+            connection.close();
+
+            // No exception, print results
+            for (int i=0; i<outList.size(); i++) {
+            	System.out.println(outList.get(i));
+            }
+        } catch (Exception exp) {
+        	if (connection != null)
+        		connection.close();
+            System.out.println("Caught exception, exiting.");
+            exp.printStackTrace(System.out);
+            System.exit(1);
+        }
+    }
+    
+    protected static boolean isSupportedAmqpType(String amqpType) {
+    	for (String supportedAmqpType: SUPPORTED_AMQP_TYPES) {
+    		if (amqpType.equals(supportedAmqpType))
+    			return true;
+    	}
+    	return false;
+    }
+
+    private static class MyExceptionListener implements ExceptionListener {
+        @Override
+        public void onException(JMSException exception) {
+            System.out.println("Connection ExceptionListener fired, exiting.");
+            exception.printStackTrace(System.out);
+            System.exit(1);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/77eba676/shims/qpid-jms/src/main/java/org/apache/qpid/interop_test/shim/ProtonJmsSender.java
----------------------------------------------------------------------
diff --git a/shims/qpid-jms/src/main/java/org/apache/qpid/interop_test/shim/ProtonJmsSender.java b/shims/qpid-jms/src/main/java/org/apache/qpid/interop_test/shim/ProtonJmsSender.java
new file mode 100644
index 0000000..3507fbd
--- /dev/null
+++ b/shims/qpid-jms/src/main/java/org/apache/qpid/interop_test/shim/ProtonJmsSender.java
@@ -0,0 +1,258 @@
+/**
+ * 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.interop_test.shim;
+
+import java.math.BigDecimal; 
+import java.math.BigInteger; 
+import java.math.MathContext; 
+import java.util.Arrays;
+import java.util.UUID;
+import javax.jms.BytesMessage;
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.DeliveryMode;
+import javax.jms.ExceptionListener;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageProducer;
+import javax.jms.ObjectMessage;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import org.apache.qpid.jms.JmsConnectionFactory;
+
+public class ProtonJmsSender {
+    private static final String USER = "guest";
+    private static final String PASSWORD = "guest";
+    private static final String[] SUPPORTED_AMQP_TYPES = {"null",
+    	                                                  "boolean",
+    	                                                  "ubyte",
+    	                                                  "ushort",
+    	                                                  "uint",
+    	                                                  "ulong",
+    	                                                  "byte",
+    	                                                  "short",
+    	                                                  "int",
+    	                                                  "long",
+    	                                                  "float",
+    	                                                  "double",
+    	                                                  "decimal32",
+    	                                                  "decimal64",
+    	                                                  "decimal128",
+    	                                                  "char",
+    	                                                  "timestamp",
+    	                                                  "uuid",
+    	                                                  "binary",
+    	                                                  "string",
+    	                                                  "symbol",
+    	                                                  "list",
+    	                                                  "map",
+    	                                                  "array"};
+
+    public static void main(String[] args) throws Exception {
+    	if (args.length < 4) {
+    		System.out.println("ProtonJmsSender: Insufficient number of arguments");
+    		System.out.println("ProtonJmsSender: Expected arguments: broker_address, queue_name, amqp_type, test_val, test_val, ...");
+    		System.exit(1);
+    	}
+    	String brokerAddress = "amqp://" + args[0];
+    	String queueName = args[1];
+    	String amqpType = args[2];
+    	String[] testValueList = Arrays.copyOfRange(args, 3, args.length); // Use remaining args as test values
+    	
+        try {
+        	ConnectionFactory factory = (ConnectionFactory)new JmsConnectionFactory(brokerAddress);
+
+            Connection connection = factory.createConnection();
+            connection.setExceptionListener(new MyExceptionListener());
+            connection.start();
+
+            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+            
+            Queue queue = session.createQueue(queueName);
+
+            MessageProducer messageProducer = session.createProducer(queue);
+
+            if (isSupportedAmqpType(amqpType)) {
+            	Message message = null;
+            	for (String testValueStr : testValueList) {
+            		switch (amqpType) {
+            		case "null":
+            			message = session.createBytesMessage();
+            			break;
+            		case "boolean":
+            			message = session.createBytesMessage();
+            			((BytesMessage)message).writeBoolean(Boolean.parseBoolean(testValueStr));
+            			break;
+            		case "ubyte":
+            		{
+            			byte testValue = (byte)Short.parseShort(testValueStr);
+            			message = session.createBytesMessage();
+            			((BytesMessage)message).writeByte(testValue);
+            			break;
+            		}
+            		case "ushort":
+            		{
+            			int testValue = Integer.parseInt(testValueStr);
+            			byte[] byteArray = new byte[2];
+            			byteArray[0] = (byte)(testValue >> 8);
+            			byteArray[1] = (byte)(testValue);
+            			message = session.createBytesMessage();
+            			((BytesMessage)message).writeBytes(byteArray);
+            			break;
+            		}
+            		case "uint":
+            		{
+            			long testValue = Long.parseLong(testValueStr);
+            			byte[] byteArray = new byte[4];
+            			byteArray[0] = (byte)(testValue >> 24);
+            			byteArray[1] = (byte)(testValue >> 16);
+            			byteArray[2] = (byte)(testValue >> 8);
+            			byteArray[3] = (byte)(testValue);
+            			message = session.createBytesMessage();
+            			((BytesMessage)message).writeBytes(byteArray);
+            			break;
+            		}
+            		case "ulong":
+            		{
+            			// TODO: Tidy this ugliness up - perhaps use of vector<byte>?
+            			BigInteger testValue = new BigInteger(testValueStr);
+            			byte[] bigIntArray =  testValue.toByteArray(); // may be 1 to 9 bytes depending on number
+            			byte[] byteArray = {0, 0, 0, 0, 0, 0, 0, 0};
+            			int effectiveBigIntArrayLen = bigIntArray.length > 8 ? 8 : bigIntArray.length; // Cap length at 8
+            			int bigIntArrayOffs = bigIntArray.length > 8 ? bigIntArray.length - 8 : 0; // Offset when length > 8
+            			for (int i=0; i<bigIntArray.length && i < 8; i++)
+            				byteArray[8 - effectiveBigIntArrayLen + i] = bigIntArray[bigIntArrayOffs + i];
+            			message = session.createBytesMessage();
+            			((BytesMessage)message).writeBytes(byteArray);
+            			break;
+            		}
+            		case "byte":
+            			message = session.createBytesMessage();
+            			((BytesMessage)message).writeByte(Byte.parseByte(testValueStr));
+            			break;
+            		case "short":
+            			message = session.createBytesMessage();
+            			((BytesMessage)message).writeShort(Short.parseShort(testValueStr));
+            			break;
+            		case "int":
+            			message = session.createBytesMessage();
+            			((BytesMessage)message).writeInt(Integer.parseInt(testValueStr));
+            			break;
+            		case "long":
+            		case "timestamp":
+            			message = session.createBytesMessage();
+            			((BytesMessage)message).writeLong(Long.parseLong(testValueStr));
+            			break;
+            		case "float":
+            			Long i = Long.parseLong(testValueStr.substring(2), 16);
+            			message = session.createBytesMessage();
+            			((BytesMessage)message).writeFloat(Float.intBitsToFloat(i.intValue()));
+            			break;
+            		case "double":
+            			Long l1 = Long.parseLong(testValueStr.substring(2, 3), 16) << 60;
+            			Long l2 = Long.parseLong(testValueStr.substring(3), 16);
+            			message = session.createBytesMessage();
+            			((BytesMessage)message).writeDouble(Double.longBitsToDouble(l1 | l2));
+            			break;
+            		case "decimal32":
+            			BigDecimal bd32 = new BigDecimal(testValueStr, MathContext.DECIMAL32);
+            			message = session.createObjectMessage();
+            			((ObjectMessage)message).setObject(bd32);
+            			break;
+            		case "decimal64":
+            			BigDecimal bd64 = new BigDecimal(testValueStr, MathContext.DECIMAL64);
+            			message = session.createObjectMessage();
+            			((ObjectMessage)message).setObject(bd64);
+            			break;
+            		case "decimal128":
+            			BigDecimal bd128 = new BigDecimal(testValueStr, MathContext.DECIMAL128);
+            			message = session.createObjectMessage();
+            			((ObjectMessage)message).setObject(bd128);
+            			break;
+            		case "char":
+            			char c = 0;
+            			if (testValueStr.length() == 1) // Single char
+            				c = testValueStr.charAt(0);
+            			else if (testValueStr.length() == 6) // unicode format
+            				c = (char)Integer.parseInt(testValueStr, 16);
+            			message = session.createBytesMessage();
+            			((BytesMessage)message).writeChar(c);
+            			break;
+            		case "uuid":
+            			UUID uuid = UUID.fromString(testValueStr);
+            			message = session.createObjectMessage();
+            			((ObjectMessage)message).setObject(uuid);
+            			break;
+            		case "binary":
+            			message = session.createBytesMessage();
+            			byte[] byteArray = testValueStr.getBytes();
+            			((BytesMessage)message).writeBytes(byteArray, 0, byteArray.length);
+            			break;
+            		case "string":
+            			message = session.createTextMessage(testValueStr);
+            			break;
+            		case "symbol":
+            			message = session.createBytesMessage();
+            			((BytesMessage)message).writeUTF(testValueStr);
+            			break;
+            		case "list":
+            			break;
+            		case "map":
+            			break;
+            		case "array":
+            			break;
+            		default:
+            			// Internal error, should never happen if SUPPORTED_AMQP_TYPES matches this case stmt
+            			connection.close();
+            			throw new Exception("ProtonJmsSender: Internal error: unsupported AMQP type \"" + amqpType + "\"");
+            		}
+            		messageProducer.send(message, DeliveryMode.NON_PERSISTENT, Message.DEFAULT_PRIORITY, Message.DEFAULT_TIME_TO_LIVE);
+            	}
+            } else {
+            	System.out.println("ERROR: ProtonJmsSender: AMQP type \"" + amqpType + "\" is not supported");
+            	connection.close();
+            	System.exit(1);
+            }
+            
+            connection.close();
+        } catch (Exception exp) {
+            System.out.println("Caught exception, exiting.");
+            exp.printStackTrace(System.out);
+            System.exit(1);
+        }
+    }
+    
+    protected static boolean isSupportedAmqpType(String amqpType) {
+    	for (String supportedAmqpType: SUPPORTED_AMQP_TYPES) {
+    		if (amqpType.equals(supportedAmqpType))
+    			return true;
+    	}
+    	return false;
+    }
+
+    private static class MyExceptionListener implements ExceptionListener {
+        @Override
+        public void onException(JMSException exception) {
+            System.out.println("Connection ExceptionListener fired, exiting.");
+            exception.printStackTrace(System.out);
+            System.exit(1);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/77eba676/shims/qpid-proton-python/src/proton-python-send
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/proton-python-send b/shims/qpid-proton-python/src/proton-python-send
index 2b8703d..eb1c52c 100755
--- a/shims/qpid-proton-python/src/proton-python-send
+++ b/shims/qpid-proton-python/src/proton-python-send
@@ -88,7 +88,7 @@ class Sender(MessagingHandler):
         elif self.amqp_type == 'decimal64':
             return Message(id=(self.sent+1), body=decimal64(literal_eval(test_value)))
         elif self.amqp_type == 'decimal128':
-            return Message(id=(self.sent+1), body=decimal128(test_value.decode('hex')))
+            return Message(id=(self.sent+1), body=decimal128(literal_eval(test_value)))
         elif self.amqp_type == 'char':
             return Message(id=(self.sent+1), body=char(test_value))
         elif self.amqp_type == 'timestamp':

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/77eba676/src/py/qpid-interop-test/types/simple_type_tests.py
----------------------------------------------------------------------
diff --git a/src/py/qpid-interop-test/types/simple_type_tests.py b/src/py/qpid-interop-test/types/simple_type_tests.py
index 2e3fc20..48e1195 100755
--- a/src/py/qpid-interop-test/types/simple_type_tests.py
+++ b/src/py/qpid-interop-test/types/simple_type_tests.py
@@ -28,16 +28,15 @@ import unittest
 
 from ast import literal_eval
 from itertools import product
-from os import getenv
+from os import getenv, path
 from proton import char, int32, symbol, timestamp, ulong
 from shim_utils import StrToObj
-from subprocess import check_output
+from subprocess import check_output, CalledProcessError
 from time import mktime, time
 from uuid import UUID, uuid4
 
 QPID_INTEROP_TEST_HOME = getenv('QPID_INTEROP_TEST_HOME') # TODO - propose a sensible default when installation details are worked out
 
-
 class SimpleTypeTestError(StandardError):
     """
     Error class for use in simpe AMQP type tests
@@ -58,7 +57,7 @@ class AmqpPrimitiveTypes(object):
         'ushort': [0x0, 0x7fff, 0x8000, 0xffff],
         'uint': [0x0, 0x7fffffff, 0x80000000, 0xffffffff],
         'ulong': [0x0, 0x01, 0xff, 0x100, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff],
-        'byte': [0x0, 0x7f, 0x80, 0xff],
+        'byte': [-0x80, -0x01, 0x0, 0x7f],
         'short': [-0x8000, -0x1, 0x0, 0x7fff],
         'int': [-0x80000000, -0x1, 0x0, 0x7fffffff],
         'long': [-0x8000000000000000, -0x81, -0x80, -0x01, 0x0, 0x7f, 0x80, 0x7fffffffffffffff],
@@ -78,8 +77,8 @@ class AmqpPrimitiveTypes(object):
                   '0xff7fffff', # Largest negative normalized number
                   '0x7f800000', # +Infinity
                   '0xff800000', # -Infinity
-                  '0x7fffffff', # +NaN 
-                  '0xffffffff'], # -NaN 
+                  '0x7fc00000', # +NaN 
+                  '0xffc00000'], # -NaN 
         'double': ['0x0000000000000000', # 0.0
                    '0x8000000000000000', # -0.0
                    '0x400921fb54442eea', # pi (3.14159265359) positive decimal
@@ -94,32 +93,30 @@ class AmqpPrimitiveTypes(object):
                    '0xffefffffffffffff', # Largest negative normalized number
                    '0x7ff0000000000000', # +Infinity
                    '0xfff0000000000000', # -Infinity
-                   '0x7fffffffffffffff', # +NaN
-                   '0xffffffffffffffff'], # -NaN
-        'decimal32': [0, 100, -1000],#,
-        'decimal64': [0, 100, -1000],#,
-        #'decimal128': [b'00000000000000000000000000000000',
-        #               b'00000000000000000000000000000100',
-        #               b'0102030405060708090a0b0c0d0e0f00'],
-        #'char': [u'a', u'Z', u'0', u'\x01', u'\x7f'], #TODO: Char value \x00 causes problems in check_output(), find another solution
+                   '0x7ff8000000000000', # +NaN
+                   '0xfff8000000000000'], # -NaN
+        'decimal32': [0, 100, -1000.001, 3.14159, 1.234e+56],
+        'decimal64': [0, 100, -1000.001, 3.14159, 1.234e+56],
+#        'decimal128': [0, 100, -1000.001, 3.14159, 1.234e+56], # Hangs python shim, ok in jms shim
+#        'char': [u'a', u'Z', u'\u0001', u'\u007f'],            # Hangs python shim, ok in jms shim
         # timestamp must be in milliseconds since the unix epoch
         'timestamp': [0, int(mktime((2000, 1, 1, 0, 0, 0, 5, 1, 0))*1000), int(time()*1000)],
         'uuid': [UUID(int=0x0), UUID('00010203-0405-0607-0809-0a0b0c0d0e0f'), uuid4()],
-        'binary': [bytes(), bytes(12345), b'Hello, world!', b'\x01\x02\x03\x04\x05\xff',
-                   b'The quick brown fox jumped over the lazy cow 0123456789' * 1000],
+        'binary': [bytes(), bytes(12345), b'Hello, world!', b'\x01\x02\x03\x04\x05abcde\x80\x81\xfe\xff'],
+                   #b'The quick brown fox jumped over the lazy dog 0123456789.' * 1000],
         # strings must be unicode to comply with AMQP spec
         'string': [u'', u'Hello, world!', u'"Hello, world!"', u"Charlie's peach",
-                   u'The quick brown fox jumped over the lazy cow 0123456789' * 1000],
+                   u'The quick brown fox jumped over the lazy dog 0123456789.' * 1000],
         'symbol': ['', 'myDomain.123', 'domain.0123456789.' * 1000],
-        'list': [[],
-                 [1, -2, 3.14],
-                 [u'a', u'b', u'c'],
-                 [ulong(12345), timestamp(int(time()*1000)), int32(-25), uuid4(), symbol('a.b.c')],
-                 [[], None, [1,2,3], {1:'one', 2:'two', 3:'three', 4:True, 5:False, 6:None}, True, False, char(u'5')],
-                 [[],[[],[[],[],[]],[]],[]],
-                 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] * 1000],
-        'map': [{}, {1:u'one', 2:u'two'}, {None:None, 1:1, '2':'2', True:False, False:True}]#,
-        #'array': [[], [1,2,3], ['Hello', 'world']]
+#        'list': [[],
+#                 [1, -2, 3.14],
+#                 [u'a', u'b', u'c'],
+#                 [ulong(12345), timestamp(int(time()*1000)), int32(-25), uuid4(), symbol('a.b.c')],
+#                 [[], None, [1,2,3], {1:'one', 2:'two', 3:'three', 4:True, 5:False, 6:None}, True, False, char(u'5')],
+#                 [[],[[],[[],[],[]],[]],[]],
+#                 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] * 1000]#,
+        #'map': [{}, {1:u'one', 2:u'two'}, {None:None, 1:1, '2':'2', True:False, False:True}]#, # TODO: Bug in handling maps
+        #'array': [[], [1,2,3], ['Hello', 'world']] # TODO: Not yet implemented
         }
 
     @staticmethod
@@ -198,24 +195,31 @@ class Shim(object):
     Abstract shim class, parent of all shims.
     """
     NAME = None
-    ENV = []
-    SHIM_LOC = None
     SEND = None
     RECEIVE = None
+    USE_SHELL = False
 
     def send(self, broker_addr, queue_name, amqp_type, test_value_list):
         """
         Send the values of type amqp_type in test_value_list to queue queue_name. Return output (if any) from stdout.
         """
-        arg_list = [self.SEND, broker_addr, queue_name, amqp_type]
+        arg_list = []
+        arg_list.extend(self.SEND)
+        arg_list.extend([broker_addr, queue_name, amqp_type])
         for test_value in test_value_list:
             if amqp_type == 'string' or amqp_type == 'char' or amqp_type == 'float' or amqp_type == 'double':
                 arg_list.append(test_value) # Not using str() on strings preserves the unicode prefix u'...'
             else:
                 arg_list.append(str(test_value))
-        #print
-        #print '>>>', arg_list
-        return check_output(arg_list)
+        try:
+            #print
+            #print '>>>', arg_list
+            return check_output(arg_list, shell=self.USE_SHELL)
+        except CalledProcessError as e:
+            return str(e) + '\n\nOutput:\n' + e.output
+        except Exception as e:
+            return str(e)
+        
 
     def receive(self, broker_addr, queue_name, amqp_type, num_test_values):
         """
@@ -223,10 +227,15 @@ class Shim(object):
         from stdout is the AMQP type, then the rest is assumed to be the returned test value list. Otherwise error
         output is assumed.
         """
+        output = ''
         try:
-            arg_list = [self.RECEIVE, broker_addr, queue_name, amqp_type, str(num_test_values)]
+            arg_list = []
+            arg_list.extend(self.RECEIVE)
+            arg_list.extend([broker_addr, queue_name, amqp_type, str(num_test_values)])
+            #print
             #print '>>>', arg_list
             output = check_output(arg_list)
+            #print '<<<', output
             str_tvl = output.split('\n')[0:-1] # remove trailing \n
             if str_tvl[0] == amqp_type:
                 received_test_value_list = []
@@ -244,6 +253,7 @@ class Shim(object):
                        amqp_type == 'long' or \
                        amqp_type == 'decimal32' or \
                        amqp_type == 'decimal64' or \
+                       amqp_type == 'decimal128' or \
                        amqp_type == 'timestamp':
                         received_test_value_list.append(literal_eval(stv))
                     # Non-string types not using literal_evel
@@ -254,7 +264,6 @@ class Shim(object):
                     # String  and float types used as-is
                     elif amqp_type == 'float' or \
                          amqp_type == 'double' or \
-                         amqp_type == 'decimal128' or \
                          amqp_type == 'char' or \
                          amqp_type == 'string' or \
                          amqp_type == 'symbol':
@@ -267,8 +276,10 @@ class Shim(object):
                 return received_test_value_list
             else:
                 return output # return error string
+        except CalledProcessError as e:
+            return str(e) + '\n\n' + e.output
         except Exception as e:
-            return str(e) + '\n' + output
+            return str(e)
 
 
 class ProtonPythonShim(Shim):
@@ -276,9 +287,9 @@ class ProtonPythonShim(Shim):
     Shim for qpid-proton Python client
     """
     NAME = 'ProtonPython'
-    SHIM_LOC = QPID_INTEROP_TEST_HOME + '/shims/qpid-proton-python/src/'
-    SEND = SHIM_LOC + 'proton-python-send'
-    RECEIVE = SHIM_LOC + 'proton-python-receive'
+    SHIM_LOC = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-python', 'src')
+    SEND = [path.join(SHIM_LOC, 'proton-python-send')]
+    RECEIVE = [path.join(SHIM_LOC, 'proton-python-receive')]
 
 
 class QpidJmsShim(Shim):
@@ -286,9 +297,29 @@ class QpidJmsShim(Shim):
     Shim for qpid-jms JMS client
     """
     NAME = 'QpidJms'
-    SHIM_LOC = '/shims/qpid-jms/src/main/java/'
-    SEND = SHIM_LOC + 'org/apache/qpid/qpid-interop-test/shim/ProtonJmsReceiver'
-    RECEIVE = SHIM_LOC + 'org/apache/qpid/qpid-interop-test/shim/ProtonJmsReceiver'
+    
+    # Installed qpid versions
+    QPID_JMS_VER = '0.4.0-SNAPSHOT'
+    QPID_PROTON_J_VER = '0.10-SNAPSHOT'
+    
+    # Classpath components
+    QPID_INTEROP_TEST_SHIM_JAR = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-jms', 'target', 'qpid-jms-shim.jar')
+    MAVEN_REPO_PATH = path.join(getenv('HOME'), '.m2', 'repository')
+    JMS_API_JAR = path.join(MAVEN_REPO_PATH, 'org', 'apache', 'geronimo', 'specs', 'geronimo-jms_1.1_spec', '1.1.1',
+                            'geronimo-jms_1.1_spec-1.1.1.jar')
+    JMS_IMPL_JAR = path.join(MAVEN_REPO_PATH, 'org', 'apache', 'qpid', 'qpid-jms-client', QPID_JMS_VER,
+                             'qpid-jms-client-' + QPID_JMS_VER + '.jar')
+    LOGGER_API_JAR = path.join(MAVEN_REPO_PATH, 'org', 'slf4j', 'slf4j-api', '1.5.6', 'slf4j-api-1.5.6.jar')
+    LOGGER_IMPL_JAR = path.join(QPID_INTEROP_TEST_HOME, 'jars', 'slf4j-nop-1.5.6.jar')
+    PROTON_J_JAR = path.join(MAVEN_REPO_PATH, 'org', 'apache', 'qpid', 'proton-j', QPID_PROTON_J_VER,
+                             'proton-j-' + QPID_PROTON_J_VER + '.jar')
+    NETTY_JAR = path.join(MAVEN_REPO_PATH, 'io', 'netty', 'netty-all', '4.0.17.Final', 'netty-all-4.0.17.Final.jar')
+    
+    CLASSPATH = ':'.join([QPID_INTEROP_TEST_SHIM_JAR, JMS_API_JAR, JMS_IMPL_JAR, LOGGER_API_JAR, LOGGER_IMPL_JAR, PROTON_J_JAR, NETTY_JAR])
+    JAVA_HOME = getenv('JAVA_HOME', '/usr/bin') # Default only works in Linux
+    JAVA_EXEC = path.join(JAVA_HOME, 'java')
+    SEND = [JAVA_EXEC, '-cp', CLASSPATH, 'org.apache.qpid.interop_test.shim.ProtonJmsSender']
+    RECEIVE = [JAVA_EXEC, '-cp', CLASSPATH, 'org.apache.qpid.interop_test.shim.ProtonJmsReceiver']
 
     
 # SHIM_MAP contains an instance of each client language shim that is to be tested as a part of this test. For
@@ -297,6 +328,10 @@ class QpidJmsShim(Shim):
 #
 # As new shims are added, add them into this map to have them included in the test cases.
 SHIM_MAP = {ProtonPythonShim.NAME: ProtonPythonShim()}
+#SHIM_MAP = {QpidJmsShim.NAME: QpidJmsShim()}
+#SHIM_MAP = {ProtonPythonShim.NAME: ProtonPythonShim(),
+#            QpidJmsShim.NAME: QpidJmsShim()
+#            }
 
 
 class TestOptions(object):


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