00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 package org.objectweb.proactive.core.component.collectiveitfs;
00032
00033 import java.io.Serializable;
00034 import java.lang.annotation.Annotation;
00035 import java.lang.reflect.Method;
00036 import java.lang.reflect.ParameterizedType;
00037 import java.lang.reflect.Type;
00038
00039 import org.objectweb.fractal.api.Interface;
00040 import org.objectweb.proactive.core.component.exceptions.ParameterDispatchException;
00041 import org.objectweb.proactive.core.component.type.annotations.multicast.ClassDispatchMetadata;
00042 import org.objectweb.proactive.core.component.type.annotations.multicast.MethodDispatchMetadata;
00043 import org.objectweb.proactive.core.component.type.annotations.multicast.ParamDispatch;
00044 import org.objectweb.proactive.core.component.type.annotations.multicast.ParamDispatchMetadata;
00045 import org.objectweb.proactive.core.component.type.annotations.multicast.ParamDispatchMode;
00046
00058 public class MulticastBindingChecker implements Serializable {
00059
00071 public static Method searchMatchingMethod(Method clientSideMethod, Method[] serverSideMethods, boolean serverItfIsGathercast, Interface serverSideItf) throws ParameterDispatchException, NoSuchMethodException {
00072 Method result = null;
00073 Type clientSideReturnType = clientSideMethod.getGenericReturnType();
00074 Type[] clientSideParametersTypes = clientSideMethod.getGenericParameterTypes();
00075 Class[] clientSideExceptionTypes = clientSideMethod.getExceptionTypes();
00076 ParamDispatch[] paramDispatchModes = getDispatchModes(clientSideMethod);
00077
00078
00079 serverSideMethodsLoop:
00080 for (Method serverSideMethod : serverSideMethods) {
00081 if (serverItfIsGathercast) {
00082
00083 Type[] genericParamTypes = serverSideMethod.getGenericParameterTypes();
00084 Class[] correspondingParamTypes = new Class[genericParamTypes.length];
00085 for (int i = 0; i < genericParamTypes.length; i++) {
00086 ParameterizedType t = (ParameterizedType)genericParamTypes[i];
00087 correspondingParamTypes[i] = (Class)t.getActualTypeArguments()[0];
00088 }
00089 serverSideMethod = serverSideItf.getClass().getMethod(serverSideMethod.getName(), correspondingParamTypes);
00090 }
00091
00092 if (! serverSideMethod.getName().equals(clientSideMethod.getName())) {
00093 continue serverSideMethodsLoop;
00094 }
00095
00096
00097 if (!(clientSideReturnType == Void.TYPE)) {
00098 Type cType = ((ParameterizedType) clientSideMethod.getGenericReturnType()).getActualTypeArguments()[0];
00099 Class clientSideReturnTypeArgument = null;
00100 if (cType instanceof ParameterizedType) {
00101 clientSideReturnTypeArgument = (Class)((ParameterizedType)cType).getRawType();
00102 } else {
00103 clientSideReturnTypeArgument = (Class) cType;
00104 }
00105 if (!(clientSideReturnTypeArgument.isAssignableFrom(
00106 serverSideMethod.getReturnType()))) {
00107 continue serverSideMethodsLoop;
00108 }
00109 } else {
00110 if (!(serverSideMethod.getReturnType() == Void.TYPE)) {
00111 continue serverSideMethodsLoop;
00112 }
00113 }
00114
00115
00116 Type[] serverSideParametersTypes = serverSideMethod.getGenericParameterTypes();
00117
00118 for (int i=0; i<serverSideMethod.getGenericParameterTypes().length; i++) {
00119 if (!(paramDispatchModes[i].match(clientSideParametersTypes[i], serverSideParametersTypes[i]))) {
00120 continue serverSideMethodsLoop;
00121 }
00122 }
00123
00124
00125 Class[] serverSideExceptionTypes = serverSideMethod.getExceptionTypes();
00126 for (Class clientExceptionType : clientSideExceptionTypes) {
00127 boolean match = false;
00128 for (Class serverExceptionType : serverSideExceptionTypes) {
00129 if (clientExceptionType.isAssignableFrom(serverExceptionType)) {
00130 match = true;
00131 break;
00132 }
00133 }
00134 if (!match) {
00135 throw new NoSuchMethodException("found a matching method in server interface for " + clientSideMethod.toGenericString() + " but the types of thrown exceptions do not match");
00136 }
00137 }
00138
00139 if (result != null) {
00140 throw new NoSuchMethodException("cannot find matching method for " + clientSideMethod.toGenericString() + " because there are several matches in the server interface ");
00141 } else {
00142 result = serverSideMethod;
00143 }
00144
00145 }
00146
00147 if (result == null) {
00148 throw new NoSuchMethodException("cannot find matching method for " + clientSideMethod.toGenericString());
00149 }
00150
00151 return result;
00152 }
00153
00160 public static ParamDispatch getParamDispatchMode(ParamDispatchMetadata a)
00161 throws ParameterDispatchException {
00162 ParamDispatch mode = null;
00163 if (a == null) {
00164 return ParamDispatchMode.BROADCAST;
00165 }
00166
00167 mode = a.mode();
00168
00169 if (mode.equals(ParamDispatchMode.CUSTOM)) {
00170 try {
00171 mode = (ParamDispatch) ((ParamDispatchMetadata) a).customMode().newInstance();
00172 } catch (InstantiationException e) {
00173 throw new ParameterDispatchException(
00174 "custom annotation refers to a class containing the dispatch algorithm, but this class that cannot be instantiated : " +
00175 ((ParamDispatchMetadata) a).customMode(),
00176 e);
00177 } catch (IllegalAccessException e) {
00178 throw new ParameterDispatchException(
00179 "custom annotation refers to a class containing the dispatch algorithm, but this class that cannot be instantiated : " +
00180 ((ParamDispatchMetadata) a).customMode(),
00181 e);
00182 }
00183 }
00184
00185 return mode;
00186 }
00187
00194 public static ParamDispatch[] getDispatchModes(Method matchingMethodInClientInterface) throws ParameterDispatchException {
00195 ParamDispatch[] result = new ParamDispatch[matchingMethodInClientInterface.getParameterTypes().length];
00196
00197 Annotation[] classAnnotations = matchingMethodInClientInterface.getDeclaringClass()
00198 .getAnnotations();
00199 Annotation[] methodAnnotations = matchingMethodInClientInterface.getAnnotations();
00200 Annotation[][] paramsAnnotations = matchingMethodInClientInterface.getParameterAnnotations();
00201
00202
00203 for (Annotation annotation : classAnnotations) {
00204 if (ClassDispatchMetadata.class.isAssignableFrom(annotation.annotationType())) {
00205 for (int i = 0; i < matchingMethodInClientInterface.getParameterTypes().length;
00206 i++) {
00207 result[i] = getParamDispatchMode(((ClassDispatchMetadata) annotation).mode());
00208 if (result[i] == null) {
00209 result[i] = ParamDispatchMode.BROADCAST;
00210 }
00211 }
00212 return result;
00213 }
00214 }
00215
00216
00217 for (Annotation annotation : methodAnnotations) {
00218 if (MethodDispatchMetadata.class.isAssignableFrom(annotation.annotationType())) {
00219 for (int i = 0; i < matchingMethodInClientInterface.getParameterTypes().length;
00220 i++) {
00221 result[i] = getParamDispatchMode(((MethodDispatchMetadata) annotation).mode());
00222 if (result[i] == null) {
00223 result[i] = ParamDispatchMode.BROADCAST;
00224 }
00225 }
00226 return result;
00227 }
00228 }
00229
00230
00231 for (int i = 0; i < matchingMethodInClientInterface.getParameterTypes().length; i++) {
00232 Annotation[] currentParamAnnotations = paramsAnnotations[i];
00233 for (int j = 0; j < currentParamAnnotations.length; j++) {
00234 if ((currentParamAnnotations[j] != null) &&
00235 ParamDispatchMetadata.class.isAssignableFrom(
00236 currentParamAnnotations[j].annotationType())) {
00237 result[i] = getParamDispatchMode((ParamDispatchMetadata) currentParamAnnotations[j]);
00238 if (result[i] == null) {
00239 result[i] = ParamDispatchMode.BROADCAST;
00240 }
00241 }
00242 }
00243 if (result[i] == null) {
00244 result[i] = ParamDispatchMode.BROADCAST;
00245 }
00246
00247 }
00248
00249 return result;
00250 }
00251 }