diff options
author | wjaniszewski <wjaniszewski@13f79535-47bb-0310-9956-ffa450edef68> | 2009-04-16 18:01:41 +0000 |
---|---|---|
committer | wjaniszewski <wjaniszewski@13f79535-47bb-0310-9956-ffa450edef68> | 2009-04-16 18:01:41 +0000 |
commit | ca64a758cac9b5bd066eda16d569f1a0e3952c9e (patch) | |
tree | 75ab46a42e06450187bc6757474a4c0539ef974a /branches/sca-java-1.x/modules | |
parent | c86f42066a6a005d52f534694aecd6fdc1692217 (diff) |
Added support for Erlang Atoms
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@765708 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to '')
12 files changed, 393 insertions, 52 deletions
diff --git a/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/ErlangInvoker.java b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/ErlangInvoker.java index 6750e292d9..2fe9ae38b9 100644 --- a/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/ErlangInvoker.java +++ b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/ErlangInvoker.java @@ -19,12 +19,14 @@ package org.apache.tuscany.sca.binding.erlang.impl;
+import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.tuscany.sca.binding.erlang.ErlangBinding;
import org.apache.tuscany.sca.binding.erlang.impl.exceptions.ErlangException;
import org.apache.tuscany.sca.binding.erlang.impl.types.TypeHelpersProxy;
+import org.apache.tuscany.sca.interfacedef.java.JavaOperation;
import org.apache.tuscany.sca.invocation.Invoker;
import org.apache.tuscany.sca.invocation.Message;
@@ -81,9 +83,13 @@ public class ErlangInvoker implements Invoker { }
tmpMbox = node.createMbox();
Object[] args = msg.getBody();
+ Method jmethod = ((JavaOperation) msg.getOperation())
+ .getJavaMethod();
// create and send msg with self pid in the beginning
- OtpErlangObject[] argsArray = { tmpMbox.self(),
- TypeHelpersProxy.toErlang(args) };
+ OtpErlangObject[] argsArray = {
+ tmpMbox.self(),
+ TypeHelpersProxy.toErlang(args, jmethod
+ .getParameterAnnotations()) };
OtpErlangObject otpArgs = new OtpErlangTuple(argsArray);
tmpMbox.send(msg.getOperation().getName(), binding.getNode(),
otpArgs);
@@ -96,7 +102,8 @@ public class ErlangInvoker implements Invoker { }
OtpErlangObject result = resultMsg.getMsg();
msg.setBody(TypeHelpersProxy.toJava(result, msg.getOperation()
- .getOutputType().getPhysical()));
+ .getOutputType().getPhysical(), jmethod
+ .getAnnotations()));
}
} catch (InterruptedException e) {
// TODO: externalize message?
@@ -129,8 +136,10 @@ public class ErlangInvoker implements Invoker { }
other = new OtpPeer(binding.getNode());
connection = self.connect(other);
- OtpErlangList params = TypeHelpersProxy
- .toErlangAsList((Object[]) msg.getBody());
+ Method jmethod = ((JavaOperation) msg.getOperation())
+ .getJavaMethod();
+ OtpErlangList params = TypeHelpersProxy.toErlangAsList(msg
+ .getBody(), jmethod.getParameterAnnotations());
OtpErlangTuple message = MessageHelper.rpcMessage(self.pid(), self
.createRef(), binding.getModule(), msg.getOperation()
.getName(), params);
@@ -152,8 +161,10 @@ public class ErlangInvoker implements Invoker { reportProblem(msg, e);
msg.setBody(null);
} else if (msg.getOperation().getOutputType() != null) {
+ jmethod.getAnnotations();
msg.setBody(TypeHelpersProxy.toJava(result, msg.getOperation()
- .getOutputType().getPhysical()));
+ .getOutputType().getPhysical(), jmethod
+ .getAnnotations()));
}
} catch (OtpAuthException e) {
// TODO: externalize message?
diff --git a/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/ServiceExecutor.java b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/ServiceExecutor.java index e42b93c313..26b772f5e3 100644 --- a/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/ServiceExecutor.java +++ b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/ServiceExecutor.java @@ -20,7 +20,9 @@ package org.apache.tuscany.sca.binding.erlang.impl; import java.io.IOException; +import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.List; import java.util.Map; import java.util.logging.Level; @@ -30,6 +32,7 @@ import org.apache.tuscany.sca.binding.erlang.ErlangBinding; import org.apache.tuscany.sca.binding.erlang.impl.types.TypeHelpersProxy; import org.apache.tuscany.sca.interfacedef.DataType; import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaOperation; import org.apache.tuscany.sca.runtime.RuntimeComponentService; import com.ericsson.otp.erlang.OtpAuthException; @@ -104,6 +107,7 @@ public class ServiceExecutor implements Runnable { argsList = new OtpErlangList(args); } if (!nodeElement.getBinding().getModule().equals(module)) { + // module not found // TODO: externalize message? OtpErlangObject errorMsg = MessageHelper.functionUndefMessage( module, function, argsList, @@ -111,6 +115,7 @@ public class ServiceExecutor implements Runnable { sendMessage(connection, senderPid, senderRef, MessageHelper.ATOM_BADRPC, errorMsg); } else { + // module found, looking for operation RuntimeComponentService service = nodeElement.getService(); ErlangBinding binding = nodeElement.getBinding(); List<Operation> operations = service.getInterfaceContract() @@ -123,6 +128,7 @@ public class ServiceExecutor implements Runnable { } } if (operation != null) { + // operation found List<DataType> iTypes = operation.getInputType() .getLogical(); Class<?>[] forClasses = new Class<?>[iTypes.size()]; @@ -130,22 +136,35 @@ public class ServiceExecutor implements Runnable { forClasses[i] = iTypes.get(i).getPhysical(); } try { + // invoke operation + Method jmethod = ((JavaOperation) operation) + .getJavaMethod(); Object result = service.getRuntimeWire(binding, service.getInterfaceContract()).invoke( operation, TypeHelpersProxy.toJavaFromList(argsList, - forClasses)); + forClasses, jmethod + .getParameterAnnotations())); OtpErlangObject response = null; + + // send reply if (operation.getOutputType() != null && operation.getOutputType().getPhysical() .isArray()) { - response = TypeHelpersProxy.toErlangAsList(result); + // output type is array + Annotation[][] outNotes = new Annotation[][] { jmethod + .getAnnotations() }; + response = TypeHelpersProxy.toErlangAsList(result, + outNotes); } else if (operation.getOutputType() == null) { + // output type is void, create empty reply Object[] arrArg = new Object[] {}; - response = TypeHelpersProxy.toErlang(arrArg); + response = TypeHelpersProxy.toErlang(arrArg, + new Annotation[0][0]); } else { - Object[] arrArg = new Object[] { result }; - response = TypeHelpersProxy.toErlang(arrArg); + // output type is not void and not array + response = TypeHelpersProxy.toErlang(result, + jmethod.getAnnotations()); } sendMessage(connection, senderPid, senderRef, null, response); @@ -156,6 +175,7 @@ public class ServiceExecutor implements Runnable { IllegalArgumentException.class)) || e.getClass().equals( TypeMismatchException.class)) { + // wrong params // TODO: externalize message? OtpErlangObject errorMsg = MessageHelper .functionUndefMessage(module, function, @@ -164,10 +184,12 @@ public class ServiceExecutor implements Runnable { sendMessage(connection, senderPid, senderRef, MessageHelper.ATOM_BADRPC, errorMsg); } else { + // unexpected error throw e; } } } else { + // operation not found // TODO: externalize message? OtpErlangObject errorMsg = MessageHelper .functionUndefMessage(module, function, argsList, @@ -177,6 +199,7 @@ public class ServiceExecutor implements Runnable { } } } catch (ClassCastException e) { + // invalid request // TODO: externalize message? try { logger @@ -189,6 +212,7 @@ public class ServiceExecutor implements Runnable { } catch (OtpErlangDecodeException e1) { } } catch (Exception e) { + // unknown error try { sendMessage(connection, senderPid, senderRef, MessageHelper.ATOM_ERROR, new OtpErlangString( @@ -224,10 +248,12 @@ public class ServiceExecutor implements Runnable { msgNoSender = msg.getMsg(); } } catch (Exception e) { + // TODO: check when this exception can occur e.printStackTrace(); } if (operations == null) { + // operation name not found // TODO: externalize message? // NOTE: I assume in Erlang sender doesn't get confirmation so // no message will be send @@ -235,7 +261,9 @@ public class ServiceExecutor implements Runnable { + "' received message addressed to non exising mbox: " + msg.getRecipientName()); } else { + // find proper operation for received parameters for (Operation operation : operations) { + Method method = ((JavaOperation) operation).getJavaMethod(); List<DataType> iTypes = operation.getInputType().getLogical(); Class<?>[] forClasses = new Class<?>[iTypes.size()]; for (int i = 0; i < iTypes.size(); i++) { @@ -243,7 +271,7 @@ public class ServiceExecutor implements Runnable { } try { args = TypeHelpersProxy.toJavaAsArgs(msgNoSender, - forClasses); + forClasses, method.getParameterAnnotations()); matchedOperation = operation; break; } catch (Exception e) { @@ -252,22 +280,33 @@ public class ServiceExecutor implements Runnable { } } if (matchedOperation != null) { + // operation found, invoke it try { + Method jmethod = ((JavaOperation) matchedOperation) + .getJavaMethod(); Object result = nodeElement.getService().getRuntimeWire( nodeElement.getBinding()).invoke(matchedOperation, args); OtpErlangObject response = null; + + // create and send send reply if (matchedOperation.getOutputType() != null && matchedOperation.getOutputType().getPhysical() .isArray()) { - response = TypeHelpersProxy.toErlangAsList(result); + // result type is array + Annotation[][] outNotes = new Annotation[][] { jmethod + .getAnnotations() }; + response = TypeHelpersProxy.toErlangAsList(result, + outNotes); } else if (matchedOperation.getOutputType() != null) { - Object[] arrArg = new Object[] { result }; - response = TypeHelpersProxy.toErlang(arrArg); + // result type is not array and not void + response = TypeHelpersProxy.toErlang(result, jmethod + .getAnnotations()); } if (response != null && senderPid != null) { connection.send(senderPid, response); } else if (response != null && senderPid == null) { + // couldn't send reply - sender pid unavailable // TODO: externalize message? // TODO: do we need to send this reply? logger @@ -288,13 +327,13 @@ public class ServiceExecutor implements Runnable { new OtpErlangString( "Operation name found in SCA component, but parameters types didn't match.")); } catch (IOException e1) { - // TODO Auto-generated catch block e1.printStackTrace(); } } else { + // unknown/unhandled error + // TODO: decide what to do with this exception e.printStackTrace(); } - // } catch (IOException e) { } catch (Exception e) { // FIXME: log this problem? use linking feature? send error? e.printStackTrace(); @@ -319,6 +358,7 @@ public class ServiceExecutor implements Runnable { } else { msg = connection.receiveMsg(); } + // check if request is message or RPC if (msg.getRecipientName().equals(MessageHelper.RPC_MBOX) && !nodeElement.getBinding().isMbox()) { handleRpc(msg); diff --git a/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/types/AnnotatedListTypeHelper.java b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/types/AnnotatedListTypeHelper.java new file mode 100644 index 0000000000..154f0c27fc --- /dev/null +++ b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/types/AnnotatedListTypeHelper.java @@ -0,0 +1,71 @@ +/* + * 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.tuscany.sca.binding.erlang.impl.types; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.List; + +import com.ericsson.otp.erlang.OtpErlangList; +import com.ericsson.otp.erlang.OtpErlangObject; + +/** + * @version $Rev$ $Date$ + */ +public class AnnotatedListTypeHelper implements TypeHelper { + + private Annotation[] notes; + + public AnnotatedListTypeHelper(Annotation[] notes) { + this.notes = notes; + } + + public OtpErlangObject toErlang(Object object) { + int i = 0; + List<OtpErlangObject> elements = new ArrayList<OtpErlangObject>(); + while (true) { + try { + elements.add(TypeHelpersProxy.toErlang(Array.get(object, i), + notes)); + i++; + } catch (ArrayIndexOutOfBoundsException e) { + // expected + break; + } + } + return new OtpErlangList(elements.toArray(new OtpErlangObject[elements + .size()])); + } + + public Object toJava(OtpErlangObject object, Class<?> forClass) + throws Exception { + OtpErlangList erlangList = (OtpErlangList) object; + Object result = Array.newInstance(forClass.getComponentType(), + erlangList.arity()); + for (int i = 0; i < erlangList.arity(); i++) { + Array.set(result, i, TypeHelpersProxy.toJava(erlangList + .elementAt(i), forClass.getComponentType(), + new Annotation[0])); + } + return result; + } + +} diff --git a/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/types/AtomTypeHelper.java b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/types/AtomTypeHelper.java new file mode 100644 index 0000000000..94285c66bf --- /dev/null +++ b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/types/AtomTypeHelper.java @@ -0,0 +1,39 @@ +/* + * 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.tuscany.sca.binding.erlang.impl.types; + +import com.ericsson.otp.erlang.OtpErlangAtom; +import com.ericsson.otp.erlang.OtpErlangObject; + +/** + * @version $Rev$ $Date$ + */ +public class AtomTypeHelper implements TypeHelper { + + public OtpErlangObject toErlang(Object object) { + return new OtpErlangAtom((String) object); + } + + public Object toJava(OtpErlangObject object, Class<?> forClass) + throws Exception { + return ((OtpErlangAtom) object).atomValue(); + } + +} diff --git a/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/types/ListTypeHelper.java b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/types/ListTypeHelper.java index adac10bcef..7bb62d4cf8 100644 --- a/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/types/ListTypeHelper.java +++ b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/types/ListTypeHelper.java @@ -19,6 +19,7 @@ package org.apache.tuscany.sca.binding.erlang.impl.types; +import java.lang.annotation.Annotation; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.List; @@ -36,9 +37,8 @@ public class ListTypeHelper implements TypeHelper { List<OtpErlangObject> elements = new ArrayList<OtpErlangObject>(); while (true) { try { - Object arrElement = Array.get(object, i); - Object[] args = new Object[] { arrElement }; - elements.add(TypeHelpersProxy.toErlang(args)); + elements.add(TypeHelpersProxy.toErlang(Array.get(object, i), + new Annotation[0])); i++; } catch (ArrayIndexOutOfBoundsException e) { // expected @@ -56,7 +56,8 @@ public class ListTypeHelper implements TypeHelper { erlangList.arity()); for (int i = 0; i < erlangList.arity(); i++) { Array.set(result, i, TypeHelpersProxy.toJava(erlangList - .elementAt(i), forClass.getComponentType())); + .elementAt(i), forClass.getComponentType(), + new Annotation[0])); } return result; } diff --git a/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/types/TupleTypeHelper.java b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/types/TupleTypeHelper.java index 474459b9dc..64ea57f836 100644 --- a/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/types/TupleTypeHelper.java +++ b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/types/TupleTypeHelper.java @@ -36,16 +36,15 @@ public class TupleTypeHelper implements TypeHelper { List<OtpErlangObject> tupleMembers = new ArrayList<OtpErlangObject>(); Field[] fields = forClass.getFields(); for (int i = 0; i < fields.length; i++) { - Object[] args = null; try { - args = new Object[] { fields[i].get(object) }; + OtpErlangObject member = TypeHelpersProxy.toErlang(fields[i] + .get(object), fields[i].getAnnotations()); + tupleMembers.add(member); } catch (IllegalArgumentException e) { // no problem should occur here } catch (IllegalAccessException e) { // and here } - OtpErlangObject member = TypeHelpersProxy.toErlang(args); - tupleMembers.add(member); } OtpErlangObject result = new OtpErlangTuple(tupleMembers .toArray(new OtpErlangObject[tupleMembers.size()])); @@ -61,7 +60,7 @@ public class TupleTypeHelper implements TypeHelper { for (int i = 0; i < tuple.arity(); i++) { OtpErlangObject tupleMember = tuple.elementAt(i); Object javaMember = TypeHelpersProxy.toJava(tupleMember, fields[i] - .getType()); + .getType(), fields[i].getAnnotations()); fields[i].setAccessible(true); fields[i].set(result, javaMember); } diff --git a/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/types/TypeHelpersProxy.java b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/types/TypeHelpersProxy.java index cbfd93796f..380abb852b 100644 --- a/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/types/TypeHelpersProxy.java +++ b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/impl/types/TypeHelpersProxy.java @@ -19,6 +19,7 @@ package org.apache.tuscany.sca.binding.erlang.impl.types;
+import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;
@@ -26,6 +27,7 @@ import java.util.List; import java.util.Map;
import org.apache.tuscany.sca.binding.erlang.impl.TypeMismatchException;
+import org.apache.tuscany.sca.binding.erlang.meta.ErlangAtom;
import com.ericsson.otp.erlang.OtpErlangList;
import com.ericsson.otp.erlang.OtpErlangObject;
@@ -60,13 +62,34 @@ public class TypeHelpersProxy { primitiveTypes.put(Float.class, primitiveTypes.get(float.class));
primitiveTypes.put(Double.class, primitiveTypes.get(double.class));
primitiveTypes.put(byte[].class, new BinaryTypeHelper());
+ primitiveTypes.put(ErlangAtom.class, new AtomTypeHelper());
}
- private static TypeHelper getTypeHelper(Class<?> forClass) {
- TypeHelper typeHelper = primitiveTypes.get(forClass);
+ private static TypeHelper getTypeHelper(Class<?> forClass,
+ Annotation[] notes) {
+ TypeHelper typeHelper = null;
+ // check for special types marked by annotations
+ for (int i = 0; i < notes.length; i++) {
+ typeHelper = primitiveTypes.get(notes[i].annotationType());
+ if (typeHelper != null) {
+ // annotation found, check if it points to array
+ // FIXME: check if annotation points to proper type
+ // ie. ErlangAtom -> String. If not, then log? exception?
+ if (forClass.isArray()) {
+ typeHelper = new AnnotatedListTypeHelper(notes);
+ }
+ break;
+ }
+ }
+ // check for standard types
+ if (typeHelper == null) {
+ typeHelper = primitiveTypes.get(forClass);
+ }
+ // check for arrays
if (typeHelper == null && forClass.isArray()) {
typeHelper = new ListTypeHelper();
}
+ // others would be tuples
if (typeHelper == null) {
typeHelper = new TupleTypeHelper();
}
@@ -74,13 +97,26 @@ public class TypeHelpersProxy { }
/**
+ * Converts single Java object into Erlang
+ *
+ * @param object
+ * @param notes
+ * @return
+ */
+ public static OtpErlangObject toErlang(Object object, Annotation[] notes) {
+ TypeHelper helper = getTypeHelper(object.getClass(), notes);
+ return helper.toErlang(object);
+ }
+
+ /**
* Converts Java objects arrays to Erlang: 1. single object (if array arity
* == 1) or 2. tuple (if array arity > 1)
*
* @param objects
* @return
*/
- public static OtpErlangObject toErlang(Object[] objects) {
+ public static OtpErlangObject toErlang(Object[] objects,
+ Annotation[][] notes) {
OtpErlangObject result = null;
if (objects != null) {
TypeHelper helper = null;
@@ -89,13 +125,13 @@ public class TypeHelpersProxy { result = new OtpErlangList();
break;
case 1:
- helper = getTypeHelper(objects[0].getClass());
+ helper = getTypeHelper(objects[0].getClass(), notes[0]);
result = helper.toErlang(objects[0]);
break;
default:
OtpErlangObject[] erlObjects = new OtpErlangObject[objects.length];
for (int i = 0; i < objects.length; i++) {
- helper = getTypeHelper(objects[i].getClass());
+ helper = getTypeHelper(objects[i].getClass(), notes[i]);
erlObjects[i] = helper.toErlang(objects[i]);
}
result = new OtpErlangTuple(erlObjects);
@@ -111,15 +147,24 @@ public class TypeHelpersProxy { * @param array
* @return
*/
- public static OtpErlangList toErlangAsList(Object array) {
+ public static OtpErlangList toErlangAsList(Object array,
+ Annotation[][] notes) {
OtpErlangList result = null;
if (array != null) {
List<OtpErlangObject> attrsList = new ArrayList<OtpErlangObject>();
int i = 0;
while (true) {
try {
+ // FIXME: if notes.length == 1 then its used to annotate
+ // array. Clean up.
+ Annotation[] currNotes = null;
+ if (notes.length == 1) {
+ currNotes = notes[0];
+ } else {
+ currNotes = notes[i];
+ }
TypeHelper helper = getTypeHelper(Array.get(array, i)
- .getClass());
+ .getClass(), currNotes);
attrsList.add(helper.toErlang(Array.get(array, i)));
i++;
} catch (ArrayIndexOutOfBoundsException e) {
@@ -142,10 +187,10 @@ public class TypeHelpersProxy { * @return
* @throws Exception
*/
- public static Object toJava(OtpErlangObject object, Class<?> forClass)
- throws Exception {
+ public static Object toJava(OtpErlangObject object, Class<?> forClass,
+ Annotation[] notes) throws Exception {
try {
- TypeHelper helper = getTypeHelper(forClass);
+ TypeHelper helper = getTypeHelper(forClass, notes);
return helper.toJava(object, forClass);
} catch (ClassCastException e) {
throw new TypeMismatchException(forClass, object.getClass());
@@ -161,11 +206,11 @@ public class TypeHelpersProxy { * @throws Exception
*/
public static Object[] toJavaFromList(OtpErlangList objects,
- Class<?>[] forClass) throws Exception {
+ Class<?>[] forClass, Annotation[][] notes) throws Exception {
Object[] result = new Object[objects.arity()];
try {
for (int i = 0; i < objects.arity(); i++) {
- TypeHelper helper = getTypeHelper(forClass[i]);
+ TypeHelper helper = getTypeHelper(forClass[i], notes[i]);
result[i] = helper.toJava(objects.elementAt(i), forClass[i]);
}
} catch (Exception e) {
@@ -187,7 +232,7 @@ public class TypeHelpersProxy { * @throws Exception
*/
public static Object[] toJavaAsArgs(OtpErlangObject objects,
- Class<?>[] forClass) throws Exception {
+ Class<?>[] forClass, Annotation[][] notes) throws Exception {
OtpErlangObject[] args = null;
// normalize input
if (objects.getClass().equals(OtpErlangTuple.class)) {
@@ -202,7 +247,7 @@ public class TypeHelpersProxy { Object[] result = new Object[args.length];
try {
for (int i = 0; i < args.length; i++) {
- TypeHelper helper = getTypeHelper(forClass[i]);
+ TypeHelper helper = getTypeHelper(forClass[i], notes[i]);
result[i] = helper.toJava(args[i], forClass[i]);
}
} catch (Exception e) {
diff --git a/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/meta/ErlangAtom.java b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/meta/ErlangAtom.java new file mode 100644 index 0000000000..48037eaa1c --- /dev/null +++ b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/main/java/org/apache/tuscany/sca/binding/erlang/meta/ErlangAtom.java @@ -0,0 +1,28 @@ +/* + * 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.tuscany.sca.binding.erlang.meta; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface ErlangAtom { + +} diff --git a/branches/sca-java-1.x/modules/binding-erlang-runtime/src/test/java/org/apache/tuscany/sca/binding/erlang/testing/AtomTuple.java b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/test/java/org/apache/tuscany/sca/binding/erlang/testing/AtomTuple.java new file mode 100644 index 0000000000..f0930295a7 --- /dev/null +++ b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/test/java/org/apache/tuscany/sca/binding/erlang/testing/AtomTuple.java @@ -0,0 +1,30 @@ +/* + * 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.tuscany.sca.binding.erlang.testing; + +import org.apache.tuscany.sca.binding.erlang.meta.ErlangAtom; + +public class AtomTuple { + + @ErlangAtom + public String field1; + public int field2; + +} diff --git a/branches/sca-java-1.x/modules/binding-erlang-runtime/src/test/java/org/apache/tuscany/sca/binding/erlang/testing/MboxInterface.java b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/test/java/org/apache/tuscany/sca/binding/erlang/testing/MboxInterface.java index 74ec613018..8f950d54f7 100644 --- a/branches/sca-java-1.x/modules/binding-erlang-runtime/src/test/java/org/apache/tuscany/sca/binding/erlang/testing/MboxInterface.java +++ b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/test/java/org/apache/tuscany/sca/binding/erlang/testing/MboxInterface.java @@ -19,6 +19,8 @@ package org.apache.tuscany.sca.binding.erlang.testing; +import org.apache.tuscany.sca.binding.erlang.meta.ErlangAtom; + /** * @version $Rev$ $Date$ */ @@ -49,7 +51,15 @@ public interface MboxInterface { String[] sendArgs(String[] arg) throws Exception; String[][] sendArgs(String[][] arg); - + byte[] sendArgs(byte[] arg); - + + @ErlangAtom + String[] sendArgs(@ErlangAtom String arg1, AtomTuple arg2); + + @ErlangAtom + String[][] sendArgs(@ErlangAtom String[][] arg1, int arg2); + + void sendArgs(); + } diff --git a/branches/sca-java-1.x/modules/binding-erlang-runtime/src/test/java/org/apache/tuscany/sca/binding/erlang/testing/MboxListener.java b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/test/java/org/apache/tuscany/sca/binding/erlang/testing/MboxListener.java index fe643fcff6..0cab5c0b0e 100644 --- a/branches/sca-java-1.x/modules/binding-erlang-runtime/src/test/java/org/apache/tuscany/sca/binding/erlang/testing/MboxListener.java +++ b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/test/java/org/apache/tuscany/sca/binding/erlang/testing/MboxListener.java @@ -19,6 +19,8 @@ package org.apache.tuscany.sca.binding.erlang.testing; +import java.lang.annotation.Annotation; + import org.apache.tuscany.sca.binding.erlang.impl.types.TypeHelpersProxy; import com.ericsson.otp.erlang.OtpErlangObject; @@ -53,14 +55,16 @@ public class MboxListener implements Runnable { Thread.sleep(duration); OtpErlangPid senderPid = null; if (response != null) { - Object[] args = new Object[1]; - args[0] = response; - if (msg.getMsg().getClass().equals(OtpErlangTuple.class) && ((OtpErlangTuple) msg.getMsg()).elementAt(0).getClass().equals(OtpErlangPid.class)) { - senderPid = (OtpErlangPid) ((OtpErlangTuple) msg.getMsg()).elementAt(0); + if (msg.getMsg().getClass().equals(OtpErlangTuple.class) + && ((OtpErlangTuple) msg.getMsg()).elementAt(0) + .getClass().equals(OtpErlangPid.class)) { + senderPid = (OtpErlangPid) ((OtpErlangTuple) msg.getMsg()) + .elementAt(0); } else { senderPid = msg.getSenderPid(); } - mbox.send(senderPid, TypeHelpersProxy.toErlang(args)); + mbox.send(senderPid, TypeHelpersProxy.toErlang(response, + new Annotation[0])); } } catch (Exception e) { e.printStackTrace(); @@ -84,9 +88,9 @@ public class MboxListener implements Runnable { } } } - return msg.getMsg(); + return ((OtpErlangTuple) msg.getMsg()).elementAt(1); } catch (Exception e) { - + e.printStackTrace(); } return null; } diff --git a/branches/sca-java-1.x/modules/binding-erlang-runtime/src/test/java/org/apache/tuscany/sca/binding/erlang/testing/ReferenceServiceTestCase.java b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/test/java/org/apache/tuscany/sca/binding/erlang/testing/ReferenceServiceTestCase.java index 3e0a60725e..0c80df7a04 100644 --- a/branches/sca-java-1.x/modules/binding-erlang-runtime/src/test/java/org/apache/tuscany/sca/binding/erlang/testing/ReferenceServiceTestCase.java +++ b/branches/sca-java-1.x/modules/binding-erlang-runtime/src/test/java/org/apache/tuscany/sca/binding/erlang/testing/ReferenceServiceTestCase.java @@ -32,6 +32,7 @@ import org.apache.tuscany.sca.host.embedded.SCADomain; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; @@ -292,6 +293,11 @@ public class ReferenceServiceTestCase { String testString = "TupleString"; int testInt = 10; mboxReference.sendArgs(testInt, testString); + // FIXME: + // without following sleep an exception occurs: + // com.ericsson.otp.erlang.OtpErlangDecodeException: Cannot read from + // input stream + Thread.sleep(100); assertEquals(testInt, ((OtpErlangLong) ((OtpErlangTuple) mboxListener .getMsg()).elementAt(0)).longValue()); assertEquals(testString, @@ -412,6 +418,52 @@ public class ReferenceServiceTestCase { } /** + * Tests passing Erlang atoms. It provides cases for annotating result + * types, parameters and fields in java classes - tuples. + * + * @throws Exception + */ + @Test(timeout = 1000) + public void testAtoms() throws Exception { + AtomTuple arg2 = new AtomTuple(); + arg2.field1 = "test"; + String arg1 = "First arg"; + String[] strResult = { "Hello", "World" }; + MboxListener mboxListener = new MboxListener(serMbox, strResult); + Thread mboxThread = new Thread(mboxListener); + mboxThread.start(); + String[] testResult = mboxReference.sendArgs(arg1, arg2); + assertEquals(strResult[0], testResult[0]); + assertEquals(strResult[1], testResult[1]); + + assertEquals(arg1, ((OtpErlangAtom) ((OtpErlangTuple) mboxListener + .getMsg()).elementAt(0)).atomValue()); + + assertEquals( + arg2.field1, + ((OtpErlangAtom) ((OtpErlangTuple) ((OtpErlangTuple) mboxListener + .getMsg()).elementAt(1)).elementAt(0)).atomValue()); + + // test multi dimensional arrays + String[][] arg = { { "this", "is" }, { "a" }, { "test" } }; + mboxListener = new MboxListener(serMbox, arg); + mboxThread = new Thread(mboxListener); + mboxThread.start(); + String[][] multiDimRes = mboxReference.sendArgs(arg, 1); + for (int i = 0; i < arg.length; i++) { + for (int j = 0; j < arg[i].length; j++) { + assertEquals(arg[i][j], multiDimRes[i][j]); + assertEquals( + arg[i][j], + ((OtpErlangAtom) ((OtpErlangList) ((OtpErlangList) ((OtpErlangTuple) mboxListener + .getMsg()).elementAt(0)).elementAt(i)) + .elementAt(j)).atomValue()); + } + } + + } + + /** * Tests mismatched interface * * @throws Exception @@ -644,14 +696,16 @@ public class ReferenceServiceTestCase { OtpErlangObject[] argsWithSender = new OtpErlangObject[2]; argsWithSender[0] = refMbox.self(); argsWithSender[1] = tuple; - refMbox.send("sayHello", "RPCServerMbox", new OtpErlangTuple(argsWithSender)); + refMbox.send("sayHello", "RPCServerMbox", new OtpErlangTuple( + argsWithSender)); OtpErlangString result = (OtpErlangString) refMbox.receiveMsg() .getMsg(); assertEquals("Hello world !", result.stringValue()); } - + /** * Tests receiving reply without sending self PID + * * @throws Exception */ @Test(timeout = 1000) @@ -698,7 +752,8 @@ public class ReferenceServiceTestCase { OtpErlangObject[] withSender = new OtpErlangObject[2]; withSender[0] = refMbox.self(); withSender[1] = args; - refMbox.send("passComplexArgs", "RPCServerMbox", new OtpErlangTuple(withSender)); + refMbox.send("passComplexArgs", "RPCServerMbox", new OtpErlangTuple( + withSender)); OtpErlangObject result = refMbox.receiveMsg().getMsg(); assertEquals(arg1, ((OtpErlangLong) ((OtpErlangTuple) ((OtpErlangTuple) result) @@ -831,4 +886,12 @@ public class ReferenceServiceTestCase { cookieModuleReference.sayHellos(); } + @Test(timeout = 1000) + @Ignore("Nothing to test yet") + public void testMboxNoArgs() throws Exception { + // FIXME: decide what to do while invoking mbox reference with no params + // exception? log? + mboxReference.sendArgs(); + } + } |