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 }