From 8b6426edb85b07d58c05440a9a1e73c6f509993e Mon Sep 17 00:00:00 2001 From: rtrimana Date: Mon, 10 Oct 2016 10:35:13 -0700 Subject: [PATCH] Adding early version of IoT RMI system; for now: 1) Connects Java to Java; 2) Translates only primitive/basic data types --- iotjava/Makefile | 9 +- iotjava/iotpolicy/IoTCompiler.java | 6 +- iotjava/iotrmi/IoTRMITypes.java | 140 +++++++ iotjava/iotrmi/Java/IoTRMICall.java | 120 ++++++ iotjava/iotrmi/Java/IoTRMIObject.java | 231 +++++++++++ iotjava/iotrmi/Java/IoTRMIUtil.java | 465 +++++++++++++++++++++++ iotjava/iotrmi/Java/IoTSocketClient.java | 133 +++++++ iotjava/iotrmi/Java/IoTSocketServer.java | 146 +++++++ 8 files changed, 1245 insertions(+), 5 deletions(-) create mode 100644 iotjava/iotrmi/IoTRMITypes.java create mode 100644 iotjava/iotrmi/Java/IoTRMICall.java create mode 100644 iotjava/iotrmi/Java/IoTRMIObject.java create mode 100644 iotjava/iotrmi/Java/IoTRMIUtil.java create mode 100644 iotjava/iotrmi/Java/IoTSocketClient.java create mode 100644 iotjava/iotrmi/Java/IoTSocketServer.java diff --git a/iotjava/Makefile b/iotjava/Makefile index 9854cc8..d40d939 100644 --- a/iotjava/Makefile +++ b/iotjava/Makefile @@ -17,10 +17,15 @@ compiler: $(JAVAC) -cp .:$(PARSERJARS) -d $(BIN_DIR) iotpolicy/*.java cp ../config/iotpolicy/*.pol $(BIN_DIR)/iotpolicy/ -PHONY += run -run: +PHONY += run-compiler +run-compiler: cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler camerapolicy.pol camerarequires.pol lightbulbpolicy.pol lightbulbrequires.pol -cplus Cplus -java Java +PHONY += rmi +rmi: + $(JAVAC) -cp . -d $(BIN_DIR) iotrmi/*.java + $(JAVAC) -cp .:../$(BIN_DIR) -d $(BIN_DIR) iotrmi/Java/*.java + PHONY += doc doc: iotruntime iotinstaller $(JAVADOC) -d $(DOCS_DIR) iotpolicy/*.java diff --git a/iotjava/iotpolicy/IoTCompiler.java b/iotjava/iotpolicy/IoTCompiler.java index 79202c4..f4248f2 100644 --- a/iotjava/iotpolicy/IoTCompiler.java +++ b/iotjava/iotpolicy/IoTCompiler.java @@ -664,9 +664,9 @@ public class IoTCompiler { } - /**================================================ - * Helper functions to write stub codes into files - **================================================ + /**================ + * Helper functions + **================ */ boolean newline=true; int tablevel=0; diff --git a/iotjava/iotrmi/IoTRMITypes.java b/iotjava/iotrmi/IoTRMITypes.java new file mode 100644 index 0000000..a0c682f --- /dev/null +++ b/iotjava/iotrmi/IoTRMITypes.java @@ -0,0 +1,140 @@ +package iotrmi; + +/** Class IoTRMITypes is a class that provides type translations. + *

+ * It stores C++ and Java types. + * + * @author Rahmadi Trimananda + * @version 1.0 + * @since 2016-10-03 + */ + +import java.util.HashMap; +import java.util.Map; + +public class IoTRMITypes { + + /** + * Primitive data types in Java + */ + public final static String[] primitivesJava = new String[] { + + "byte", // 1 byte + "Byte", // 1 byte + "short", // 2 bytes + "Short", // 2 bytes + "int", // 4 bytes + "Integer", // 4 bytes + "long", // 8 bytes + "Long", // 8 bytes + "float", // 4 bytes + "Float", // 4 bytes + "double", // 8 bytes + "Double", // 8 bytes + "boolean", // 1 bytes + "Boolean", // 1 bytes + "char", // 2 bytes + "Character", // 2 bytes + "string", // indefinite + "String", // indefinite + "void" // 0 byte + }; + + + /** + * Primitive data types in C++ to map the primitives list + */ + public final static String[] primitivesCplus = new String[] { + + "char", // 1 byte + "char", // 1 byte + "short", // 2 bytes + "short", // 2 bytes + "int", // 4 bytes + "int", // 4 bytes + "long", // 4 bytes + "long", // 4 bytes + "float", // 4 bytes + "float", // 4 bytes + "double", // 8 bytes + "double", // 8 bytes + "bool", // 1 byte + "bool", // 1 byte + "char", // 1 byte + "char", // 1 byte + "string", // indefinite + "string", // indefinite + "void" // 0 byte + }; + + + /** + * Primitive sizes in Java - Long is 8 bytes and char is 2 bytes + */ + public final static Integer[] primitivesJavaSizes = new Integer[] { + + 1, 1, 2, 2, 4, 4, 8, 8, 4, 4, 8, 8, 1, 1, 2, 2, -1, -1, 0 + }; + + + /** + * Primitive sizes in Cplus - Long is 4 bytes and char is 1 byte + */ + public final static Integer[] primitivesCplusSizes = new Integer[] { + + 1, 1, 2, 2, 4, 4, 4, 4, 4, 4, 8, 8, 1, 1, 1, 1, -1, -1, 0 + }; + + + /** + * Non-primitive Java data types + */ + public final static String[] nonPrimitivesJava = new String[] { + + "Set", + "HashSet", + "Map", + "HashMap", + "List", + "ArrayList" + }; + + + /** + * Non-primitive C++ data types + */ + public final static String[] nonPrimitivesCplus = new String[] { + + "set", + "unordered_set", + "map", + "unordered_map", + "list", + "list" + }; + + + /**================ + * Helper functions + **================ + */ + // Inserting array members into a Map object + // that maps arrKey to arrVal objects + public static void arraysToMap(Map map, String[] arrKey, String[] arrVal) { + + for(int i = 0; i < arrKey.length; i++) { + + map.put(arrKey[i], arrVal[i]); + } + } + + // Inserting array members into a Map object + // that maps arrKey to arrVal objects + public static void arraysToMap(Map map, String[] arrKey, Integer[] arrVal) { + + for(int i = 0; i < arrKey.length; i++) { + + map.put(arrKey[i], arrVal[i]); + } + } +} diff --git a/iotjava/iotrmi/Java/IoTRMICall.java b/iotjava/iotrmi/Java/IoTRMICall.java new file mode 100644 index 0000000..9410662 --- /dev/null +++ b/iotjava/iotrmi/Java/IoTRMICall.java @@ -0,0 +1,120 @@ +package iotrmi.Java; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.lang.reflect.Method; + + +/** Class IoTRMICall is a class that serves method calls on stub. + *

+ * A stub will use an object of this class to send the method + * information, e.g. object identifier, method identifier, and + * parameters. + * + * @author Rahmadi Trimananda + * @version 1.0 + * @since 2016-10-04 + */ +public class IoTRMICall { + + /** + * Class Properties + */ + private IoTRMIUtil rmiUtil; + private IoTSocketClient rmiClient; + + + /** + * Constructors + */ + public IoTRMICall(int _port, String _address, int _rev) throws IOException { + + rmiUtil = new IoTRMIUtil(); + rmiClient = new IoTSocketClient(_port, _address, _rev); + } + + + /** + * remoteCall() calls a method remotely by passing in parameters and getting a return Object + */ + public Object remoteCall(String methodSign, String retType, Class[] paramCls, Object[] paramObj) throws IOException { + + // Send method info + byte[] methodBytes = methodToBytes(methodSign, paramCls, paramObj); + rmiClient.sendBytes(methodBytes); + // Receive return value and return it to caller + byte[] retObjBytes = null; + retObjBytes = rmiClient.receiveBytes(retObjBytes); + Object retObj = IoTRMIUtil.getParamObject(retType, retObjBytes); + return retObj; + } + + + /** + * methodToBytes() returns byte representation of a method + */ + public byte[] methodToBytes(String methodSign, Class[] paramCls, Object[] paramObj) { + + // Get method ID in bytes + byte[] methodId = IoTRMIUtil.getHashCodeBytes(methodSign); + + // Get byte arrays and calculate method bytes length + int numbParam = paramObj.length; + int methodLen = IoTRMIUtil.METHOD_ID_LEN; // Initialized to the length of method ID + byte[][] objBytesArr = new byte[numbParam][]; + for (int i=0; i < numbParam; i++) { + // Get byte arrays for the objects + objBytesArr[i] = IoTRMIUtil.getObjectBytes(paramObj[i]); + String clsName = paramCls[i].getSimpleName(); + int paramLen = rmiUtil.getTypeSize(clsName); + if (paramLen == -1) { // indefinite length + methodLen = methodLen + IoTRMIUtil.PARAM_LEN; + } + methodLen = methodLen + objBytesArr[i].length; + } + + // Construct method in byte array + byte[] method = new byte[methodLen]; + int pos = 0; + System.arraycopy(methodId, 0, method, 0, methodId.length); + pos = pos + IoTRMIUtil.METHOD_ID_LEN; + // Second iteration for copying bytes + for (int i=0; i < numbParam; i++) { + + String clsName = paramCls[i].getSimpleName(); + int paramLen = rmiUtil.getTypeSize(clsName); + if (paramLen == -1) { // indefinite length + paramLen = objBytesArr[i].length; + byte[] paramLenBytes = IoTRMIUtil.intToByteArray(paramLen); + System.arraycopy(paramLenBytes, 0, method, pos, IoTRMIUtil.PARAM_LEN); + pos = pos + IoTRMIUtil.PARAM_LEN; + } + System.arraycopy(objBytesArr[i], 0, method, pos, paramLen); + pos = pos + paramLen; + } + + return method; + } + + + public static void main(String[] args) throws Exception { + + int port = 5010; + String address = "localhost"; + int rev = 0; + IoTRMICall rmiCall = new IoTRMICall(port, address, rev); + String sign = "intsetACAndGetA(string,int)"; + String retType = "int"; + System.out.println("Calling function: " + sign); + Object retObj = rmiCall.remoteCall(sign, retType, new Class[] { String.class, int.class }, + new Object[] { "Test param", 1234567 }); + System.out.println("Returned object: " + retObj); + + System.out.println(); + } +} diff --git a/iotjava/iotrmi/Java/IoTRMIObject.java b/iotjava/iotrmi/Java/IoTRMIObject.java new file mode 100644 index 0000000..9f40b82 --- /dev/null +++ b/iotjava/iotrmi/Java/IoTRMIObject.java @@ -0,0 +1,231 @@ +package iotrmi.Java; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.lang.reflect.*; + + +/** Class IoTRMIObject is a class that stores info of an object. + *

+ * It stores object ID, methods, method ID, method's signature + * and parameters. + * This class also receive calls from different objects as they + * ask to execute certain methods remotely. This will have the + * execution result (return value) sent back to + * + * @author Rahmadi Trimananda + * @version 1.0 + * @since 2016-10-03 + */ +public class IoTRMIObject { + + /** + * Class Properties + */ + private Map mapSign2Method; // Map from signature to method + private Map mapHash2Sign; // Map from hashcode(method ID) to signature + private IoTRMIUtil rmiUtil; + private IoTSocketServer rmiServer; + private Object obj; + private Class cls; + private Method[] methods; + + + /** + * Constructors + */ + public IoTRMIObject(String _clsName, int _port) throws + ClassNotFoundException, InstantiationException, + IllegalAccessException, IOException { + + rmiUtil = new IoTRMIUtil(); + cls = Class.forName(_clsName); + obj = cls.newInstance(); + methods = cls.getDeclaredMethods(); + mapSign2Method = new HashMap(); + mapHash2Sign = new HashMap(); + getMethodSignatures(); // Initialize the signature map + getMethodIds(); // Initialize the method ID map + rmiServer = new IoTSocketServer(_port); + rmiServer.connect(); + } + + + /** + * getName() gets class name + */ + public String getName() { + + return cls.getName(); + } + + + /** + * getSignatures() gets method signatures + */ + public Set getSignatures() { + + return mapSign2Method.keySet(); + } + + + /** + * getMethodParamTypes() gets method parameter types + */ + public Class[] getMethodParamTypes(String signature) { + + Method method = mapSign2Method.get(signature); + return method.getParameterTypes(); + } + + + /** + * getMethodRetType() gets method return type + */ + public Class getMethodRetType(String signature) { + + Method method = mapSign2Method.get(signature); + return method.getReturnType(); + } + + + /** + * invokeMethod() invokes a method based on signature and params + */ + public Object invokeMethod(String signature, Object[] params) { + + Method method = mapSign2Method.get(signature); + Object retVal = null; + try { + retVal = method.invoke(obj, params); + } catch (IllegalAccessException | + InvocationTargetException ex) { + ex.printStackTrace(); + throw new Error("IoTRMICall: Error invoking method: " + signature); + } + + return retVal; + } + + + /** + * recvAndInvoke() waits for method transmission and invoke the method + */ + private void recvAndInvoke() throws IOException { + + // Receive method info and invoke + byte[] method = null; + method = rmiServer.receiveBytes(method); + Object retObj = invokeMethod(method); + // Send back return value + byte[] retObjBytes = IoTRMIUtil.getObjectBytes(retObj); + rmiServer.sendBytes(retObjBytes); + } + + + /** + * invokeMethod() invokes a method based on byte array received + *

+ * Basically this is the format of a method in bytes: + * 1) 32-bit value of method ID (hash code) + * 2) m parameters with n-bit value each (m x n-bit) + * For the parameters that don't have definite length, + * we need to extract the length from a preceding 32-bit + * field in front of it. + * + * For primitive objects: + * | 32-bit method ID | m-bit actual data (fixed length) | + * + * For string, arrays, and non-primitive objects: + * | 32-bit method ID | 32-bit length | n-bit actual data | ... + * + */ + public Object invokeMethod(byte[] methodBytes) { + + // Byte scanning position + int pos = 0; + // Get method ID + byte[] methodIdBytes = new byte[IoTRMIUtil.METHOD_ID_LEN]; + System.arraycopy(methodBytes, pos, methodIdBytes, 0, IoTRMIUtil.METHOD_ID_LEN); + pos = pos + IoTRMIUtil.METHOD_ID_LEN; + // Get Method object to handle method + int methodId = IoTRMIUtil.byteArrayToInt(methodIdBytes); + String signature = mapHash2Sign.get(methodId); + Method method = mapSign2Method.get(signature); + // Get class name and then param length + Class[] arrCls = method.getParameterTypes(); + Object[] paramObj = new Object[arrCls.length]; + for (int i=0; i < arrCls.length; i++) { + + String paramType = arrCls[i].getSimpleName(); + int paramSize = rmiUtil.getTypeSize(paramType); + // Get the 32-bit field in the byte array to get the actual + // length (this is a param with indefinite length) + if (paramSize == -1) { + byte[] bytPrmLen = new byte[IoTRMIUtil.PARAM_LEN]; + System.arraycopy(methodBytes, pos, bytPrmLen, 0, IoTRMIUtil.PARAM_LEN); + pos = pos + IoTRMIUtil.PARAM_LEN; + paramSize = IoTRMIUtil.byteArrayToInt(bytPrmLen); + } + byte[] paramBytes = new byte[paramSize]; + System.arraycopy(methodBytes, pos, paramBytes, 0, paramSize); + pos = pos + paramSize; + paramObj[i] = IoTRMIUtil.getParamObject(paramType, paramBytes); + } + Object retObj = null; + try { + retObj = method.invoke(obj, paramObj); + } catch (IllegalAccessException | + InvocationTargetException ex) { + ex.printStackTrace(); + throw new Error("IoTRMICall: Error invoking method: " + signature); + } + + return retObj; + } + + + /**================ + * Helper methods + **================ + */ + /** + * getMethodSignatures() gets methods signatures and store them in the Map + */ + private void getMethodSignatures() { + + for (Method m : methods) { + String sign = rmiUtil.getSignature(m); + //System.out.println("Signature: " + sign); + mapSign2Method.put(sign, m); + } + } + + + /** + * getMethodIds() gets methods identifiers (hash code) and store them in the Map + */ + private void getMethodIds() { + + Set setSignatures = getSignatures(); + for (String sign : setSignatures) { + byte[] hashCode = IoTRMIUtil.getHashCodeBytes(sign); + int methodId = IoTRMIUtil.byteArrayToInt(hashCode); + mapHash2Sign.put(methodId, sign); + } + } + + + public static void main(String[] args) throws Exception { + + int port = 5010; + IoTRMIObject rmiObj = new IoTRMIObject("TestClass", port); + rmiObj.recvAndInvoke(); + } +} diff --git a/iotjava/iotrmi/Java/IoTRMIUtil.java b/iotjava/iotrmi/Java/IoTRMIUtil.java new file mode 100644 index 0000000..df76959 --- /dev/null +++ b/iotjava/iotrmi/Java/IoTRMIUtil.java @@ -0,0 +1,465 @@ +package iotrmi.Java; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.lang.reflect.Method; + +import iotrmi.IoTRMITypes; + +/** Class IoTRMI provides utility services. + *

+ * It provides miscellaneous (data type/value) translations. + * + * @author Rahmadi Trimananda + * @version 1.0 + * @since 2016-10-04 + */ +public class IoTRMIUtil { + + /** + * Class Properties + */ + private Map mapPrimitives; + private Map mapPrimitiveSizesJava; + private Map mapPrimitiveSizesCplus; + private Map mapNonPrimitives; + + /** + * Class Constants + */ + public final static int METHOD_ID_LEN = 4; // 4 bytes = 32 bits + public final static int PARAM_LEN = 4; // 4 bytes = 32 bits (4-byte field that stores the length of the param) + + /** + * Constructors + */ + public IoTRMIUtil() { + + mapPrimitives = new HashMap(); + IoTRMITypes.arraysToMap(mapPrimitives, + IoTRMITypes.primitivesJava, IoTRMITypes.primitivesCplus); + mapPrimitiveSizesJava = new HashMap(); + IoTRMITypes.arraysToMap(mapPrimitiveSizesJava, + IoTRMITypes.primitivesJava, IoTRMITypes.primitivesJavaSizes); + mapPrimitiveSizesCplus = new HashMap(); + IoTRMITypes.arraysToMap(mapPrimitiveSizesCplus, + IoTRMITypes.primitivesCplus, IoTRMITypes.primitivesCplusSizes); + mapNonPrimitives = new HashMap(); + IoTRMITypes.arraysToMap(mapNonPrimitives, + IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitivesCplus); + } + + + /** + * getSignature() gets method signature, i.e. type, identifier, parameters + */ + public String getSignature(Method m) { + + String retType = translateType(m.getReturnType().getSimpleName()); + String signature = retType + + m.getName() + "("; + Class[] clsParam = m.getParameterTypes(); + for (int i = 0; i < clsParam.length; i++) { + String paramType = translateType(clsParam[i].getSimpleName()); + signature = signature + paramType; + if (i < clsParam.length - 1) { + signature = signature + ","; + } + } + signature = signature + ")"; + return signature; + } + + + /** + * getHashCodeBytes() gets hash value (in bytes) from method name + */ + public static byte[] getHashCodeBytes(String string) { + + int hash = string.hashCode(); + byte[] hashBytes = ByteBuffer.allocate(4).putInt(hash).array(); + return hashBytes; + } + + + /**================ + * Helper methods + **================ + */ + /** + * translateType() try to translate a type + *

+ * It returns the original type when fails. + */ + public String translateType(String type) { + + if (mapPrimitives.containsKey(type)) + return mapPrimitives.get(type); + else if (mapNonPrimitives.containsKey(type)) + return mapNonPrimitives.get(type); + else + return type; + } + + + /** + * getTypeSize() gets the size of a type + * + */ + public int getTypeSize(String type) { + + if (mapPrimitiveSizesJava.containsKey(type)) + return mapPrimitiveSizesJava.get(type); + else if (mapPrimitiveSizesCplus.containsKey(type)) + return mapPrimitiveSizesCplus.get(type); + else + return -1; // Size is unknown + } + + + /** + * getParamObject() converts byte array of certain object type into Object + */ + public static Object getParamObject(String type, byte[] paramBytes) { + + Object retObj = null; + if (type.equals("byte") || + type.equals("Byte")) { + retObj = (Object) paramBytes[0]; + } else if ( type.equals("short") || + type.equals("Short")) { + retObj = (Object) byteArrayToShort(paramBytes); + } else if ( type.equals("int") || + type.equals("Integer")) { + retObj = (Object) byteArrayToInt(paramBytes); + } else if ( type.equals("long") || + type.equals("Long")) { + retObj = (Object) byteArrayToLong(paramBytes); + } else if ( type.equals("float") || + type.equals("Float")) { + retObj = (Object) byteArrayToFloat(paramBytes); + } else if ( type.equals("double") || + type.equals("Double")) { + retObj = (Object) byteArrayToDouble(paramBytes); + } else if ( type.equals("boolean") || + type.equals("Boolean")) { + retObj = (Object) byteArrayToBoolean(paramBytes); + } else if ( type.equals("char") || + type.equals("Character")) { + retObj = (Object) byteArrayToChar(paramBytes); + } else if (type.equals("String")) { + retObj = (Object) toString(paramBytes); + } else + throw new Error("IoTRMIUtil: Unrecognizable type: " + type); + + return retObj; + } + + + /** + * getObjectBytes() converts an object into byte array + */ + public static byte[] getObjectBytes(Object obj) { + + byte[] retObjBytes = null; + if (obj instanceof Byte) { + retObjBytes = (byte[]) obj; + } else if (obj instanceof Short) { + retObjBytes = shortToByteArray((short) obj); + } else if (obj instanceof Integer) { + retObjBytes = intToByteArray((int) obj); + } else if (obj instanceof Long) { + retObjBytes = longToByteArray((long) obj); + } else if (obj instanceof Float) { + retObjBytes = floatToByteArray((float) obj); + } else if (obj instanceof Double) { + retObjBytes = doubleToByteArray((double) obj); + } else if (obj instanceof Character) { + retObjBytes = charToByteArray((char) obj); + } else if (obj instanceof Boolean) { + retObjBytes = booleanToByteArray((boolean) obj); + } else if (obj instanceof String) { + retObjBytes = ((String) obj).getBytes(); + } else + throw new Error("IoTRMIUtil: Unrecognizable object: " + obj); + + return retObjBytes; + } + + + /** + * Converters to byte array + */ + // Single variables + public static byte[] shortToByteArray(short s) { + + ByteBuffer bb = ByteBuffer.allocate(2); + bb.putShort(s); + + return bb.array(); + } + + + public static byte[] intToByteArray(int i) { + + ByteBuffer bb = ByteBuffer.allocate(4); + bb.putInt(i); + + return bb.array(); + } + + + public static byte[] longToByteArray(long l) { + + ByteBuffer bb = ByteBuffer.allocate(8); + bb.putLong(l); + + return bb.array(); + } + + + public static byte[] floatToByteArray(float f) { + + ByteBuffer bb = ByteBuffer.allocate(4); + bb.putFloat(f); + + return bb.array(); + } + + + public static byte[] doubleToByteArray(double d) { + + ByteBuffer bb = ByteBuffer.allocate(8); + bb.putDouble(d); + + return bb.array(); + } + + + public static byte[] charToByteArray(char c) { + + ByteBuffer bb = ByteBuffer.allocate(2); + bb.putChar(c); + + return bb.array(); + } + + + public static byte[] booleanToByteArray(boolean b) { + + ByteBuffer bb = ByteBuffer.allocate(1); + if (b) + bb.put((byte)1); + else + bb.put((byte)0); + + return bb.array(); + } + + + // Arrays + public static byte[] arrShortToByteArray(short[] arrShort) { + + ByteBuffer bb = ByteBuffer.allocate(2 * arrShort.length); + for(short s : arrShort) { + bb.putShort(s); + } + + return bb.array(); + } + + + public static byte[] arrIntToByteArray(int[] arrInt) { + + ByteBuffer bb = ByteBuffer.allocate(4 * arrInt.length); + for(int i : arrInt) { + bb.putInt(i); + } + + return bb.array(); + } + + + public static byte[] arrLongToByteArray(long[] arrLong) { + + ByteBuffer bb = ByteBuffer.allocate(8 * arrLong.length); + for(long l : arrLong) { + bb.putLong(l); + } + + return bb.array(); + } + + + public static byte[] arrFloatToByteArray(float[] arrFloat) { + + ByteBuffer bb = ByteBuffer.allocate(4 * arrFloat.length); + for(float f : arrFloat) { + bb.putFloat(f); + } + + return bb.array(); + } + + + public static byte[] arrDoubleToByteArray(double[] arrDouble) { + + ByteBuffer bb = ByteBuffer.allocate(8 * arrDouble.length); + for(double d : arrDouble) { + bb.putDouble(d); + } + + return bb.array(); + } + + + public static byte[] arrCharToByteArray(char[] arrChar) { + + ByteBuffer bb = ByteBuffer.allocate(2 * arrChar.length); + for(char c : arrChar) { + bb.putChar(c); + } + + return bb.array(); + } + + + public static byte[] arrBooleanToByteArray(boolean[] arrBool) { + + ByteBuffer bb = ByteBuffer.allocate(1 * arrBool.length); + for(boolean b : arrBool) { + if (b) + bb.put((byte)1); + else + bb.put((byte)0); + } + + return bb.array(); + } + + + /** + * Converters from byte array + */ + // Single variables + public static short byteArrayToShort(byte[] bytes) { + + return ByteBuffer.wrap(bytes).getShort(); + } + + + public static int byteArrayToInt(byte[] bytes) { + + return ByteBuffer.wrap(bytes).getInt(); + } + + + public static long byteArrayToLong(byte[] bytes) { + + return ByteBuffer.wrap(bytes).getLong(); + } + + + public static float byteArrayToFloat(byte[] bytes) { + + return ByteBuffer.wrap(bytes).getFloat(); + } + + + public static double byteArrayToDouble(byte[] bytes) { + + return ByteBuffer.wrap(bytes).getDouble(); + } + + + public static char byteArrayToChar(byte[] bytes) { + + return ByteBuffer.wrap(bytes).getChar(); + } + + + public static boolean byteArrayToBoolean(byte[] bytes) { + + Byte boolValByte = ByteBuffer.wrap(bytes).get(); + short boolVal = boolValByte.shortValue(); + if (boolVal == 1) + return true; + else + return false; + } + + + public static String toString(byte[] bytes) { + return new String(bytes); + } + + + /** + * toByteArray() gets Object and return its byte array + *

+ * Adapted from http://www.java2s.com/ + * @see + */ + // toByteArray and toObject are taken from: http://tinyurl.com/69h8l7x + public static byte[] toByteArray(Object obj) throws IOException { + + byte[] bytes = null; + ByteArrayOutputStream bos = null; + ObjectOutputStream oos = null; + try { + + bos = new ByteArrayOutputStream(); + oos = new ObjectOutputStream(bos); + oos.writeObject(obj); + oos.flush(); + bytes = bos.toByteArray(); + } finally { + + if (oos != null) { + oos.close(); + } + if (bos != null) { + bos.close(); + } + } + return bytes; + } + + + /** + * toObject() gets byte array and return its Object + *

+ * Adapted from http://www.java2s.com/ + * @see + */ + public static Object toObject(byte[] bytes) throws IOException, ClassNotFoundException { + + Object obj = null; + ByteArrayInputStream bis = null; + ObjectInputStream ois = null; + try { + + bis = new ByteArrayInputStream(bytes); + ois = new ObjectInputStream(bis); + obj = ois.readObject(); + } finally { + + if (bis != null) { + bis.close(); + } + if (ois != null) { + ois.close(); + } + } + return obj; + } +} diff --git a/iotjava/iotrmi/Java/IoTSocketClient.java b/iotjava/iotrmi/Java/IoTSocketClient.java new file mode 100644 index 0000000..3d3e8b7 --- /dev/null +++ b/iotjava/iotrmi/Java/IoTSocketClient.java @@ -0,0 +1,133 @@ +package iotrmi.Java; + +// Java libraries +import java.io.*; +import java.net.*; +import java.awt.*; +import java.util.*; + + +/** Class IoTSocketClient is a communication class + * that provides interfaces to connect to either + * Java or C++ socket endpoint + *

+ * Adapted from Java/C++ socket implementation + * by Keith Vertanen + * @see + * Adapted from Java/C++ socket implementation + * by Keith Vertanen + * @see