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.controller;
00032 
00033 import java.io.Serializable;
00034 import java.lang.reflect.Method;
00035 import java.util.ArrayList;
00036 import java.util.Arrays;
00037 import java.util.HashMap;
00038 import java.util.Iterator;
00039 import java.util.List;
00040 import java.util.Map;
00041 import java.util.Vector;
00042 
00043 import org.apache.log4j.Logger;
00044 import org.objectweb.fractal.api.Component;
00045 import org.objectweb.fractal.api.NoSuchInterfaceException;
00046 import org.objectweb.fractal.api.control.IllegalBindingException;
00047 import org.objectweb.fractal.api.factory.InstantiationException;
00048 import org.objectweb.fractal.api.type.ComponentType;
00049 import org.objectweb.fractal.api.type.InterfaceType;
00050 import org.objectweb.fractal.api.type.TypeFactory;
00051 import org.objectweb.fractal.util.Fractal;
00052 import org.objectweb.proactive.core.ProActiveRuntimeException;
00053 import org.objectweb.proactive.core.component.Constants;
00054 import org.objectweb.proactive.core.component.ProActiveInterface;
00055 import org.objectweb.proactive.core.component.collectiveitfs.MulticastBindingChecker;
00056 import org.objectweb.proactive.core.component.exceptions.ParameterDispatchException;
00057 import org.objectweb.proactive.core.component.group.ProxyForComponentInterfaceGroup;
00058 import org.objectweb.proactive.core.component.type.ProActiveInterfaceType;
00059 import org.objectweb.proactive.core.component.type.ProActiveTypeFactoryImpl;
00060 import org.objectweb.proactive.core.component.type.annotations.multicast.ParamDispatch;
00061 import org.objectweb.proactive.core.group.Group;
00062 import org.objectweb.proactive.core.group.ProActiveComponentGroup;
00063 import org.objectweb.proactive.core.group.ProActiveGroup;
00064 import org.objectweb.proactive.core.mop.ClassNotReifiableException;
00065 import org.objectweb.proactive.core.mop.MethodCall;
00066 import org.objectweb.proactive.core.mop.Proxy;
00067 import org.objectweb.proactive.core.mop.StubObject;
00068 import org.objectweb.proactive.core.util.SerializableMethod;
00069 import org.objectweb.proactive.core.util.log.Loggers;
00070 import org.objectweb.proactive.core.util.log.ProActiveLogger;
00071 
00072 
00073 public class MulticastControllerImpl
00074     extends AbstractProActiveController implements MulticastController,
00075         Serializable {
00076     private static Logger logger = ProActiveLogger.getLogger(Loggers.COMPONENTS_CONTROLLERS);
00077     private static Logger multicastLogger = ProActiveLogger.getLogger(Loggers.COMPONENTS_MULTICAST);
00078     private Map<String, ProActiveInterface> multicastItfs = new HashMap<String, ProActiveInterface>();
00079     private Map clientSideProxies = new HashMap();
00080     private Map<String, Map<SerializableMethod, SerializableMethod>> matchingMethods = new HashMap<String, Map<SerializableMethod, SerializableMethod>>();
00081 
00082     
00083 
00084     public MulticastControllerImpl(Component owner) {
00085         super(owner);
00086     }
00087 
00088     public void init() {
00089         
00090         InterfaceType[] itfTypes = ((ComponentType) owner.getFcType()).getFcInterfaceTypes();
00091         for (int i = 0; i < itfTypes.length; i++) {
00092             ProActiveInterfaceType type = (ProActiveInterfaceType) itfTypes[i];
00093             if (type.isFcMulticastItf()) {
00094                 try {
00095                     addClientSideProxy(type.getFcItfName(),
00096                         (ProActiveInterface) owner.getFcInterface(
00097                             type.getFcItfName()));
00098                 } catch (NoSuchInterfaceException e) {
00099                     throw new ProActiveRuntimeException(e);
00100                 }
00101             }
00102         }
00103         List<InterfaceType> interfaceTypes = Arrays.asList(((ComponentType) owner.getFcType()).getFcInterfaceTypes());
00104         Iterator<InterfaceType> it = interfaceTypes.iterator();
00105 
00106         while (it.hasNext()) {
00107             
00108             addManagedInterface((ProActiveInterfaceType) it.next());
00109         }
00110     }
00111 
00119     public void ensureCompatibility(ProActiveInterfaceType clientSideItfType,
00120         ProActiveInterface serverSideItf) throws IllegalBindingException {
00121         try {
00122             ProActiveInterfaceType serverSideItfType = (ProActiveInterfaceType) serverSideItf.getFcItfType();
00123             Class clientSideItfClass;
00124             clientSideItfClass = Class.forName(clientSideItfType.getFcItfSignature());
00125             Class serverSideItfClass = Class.forName(serverSideItfType.getFcItfSignature());
00126 
00127             Method[] clientSideItfMethods = clientSideItfClass.getMethods();
00128             Method[] serverSideItfMethods = serverSideItfClass.getMethods();
00129 
00130             if (clientSideItfMethods.length != serverSideItfMethods.length) {
00131                 throw new IllegalBindingException(
00132                     "incompatible binding between client interface " +
00133                     clientSideItfType.getFcItfName() + " (" +
00134                     clientSideItfType.getFcItfSignature() +
00135                     ")  and server interface " +
00136                     serverSideItfType.getFcItfName() + " (" +
00137                     serverSideItfType.getFcItfSignature() +
00138                     ") : there is not the same number of methods (including those inherited) in both interfaces !");
00139             }
00140 
00141             Map<SerializableMethod, SerializableMethod> matchingMethodsForThisItf =
00142                 new HashMap<SerializableMethod, SerializableMethod>(clientSideItfMethods.length);
00143 
00144             for (Method method : clientSideItfMethods) {
00145                 Method serverSideMatchingMethod = searchMatchingMethod(method,
00146                         serverSideItfMethods,
00147                         clientSideItfType.isFcMulticastItf(),
00148                         serverSideItfType.isFcGathercastItf(), serverSideItf);
00149                 if (serverSideMatchingMethod == null) {
00150                     throw new IllegalBindingException(
00151                         "binding incompatibility between " +
00152                         clientSideItfType.getFcItfName() + " and " +
00153                         serverSideItfType.getFcItfName() +
00154                         " : cannot find matching method");
00155                 }
00156                 matchingMethodsForThisItf.put(new SerializableMethod(method),
00157                     new SerializableMethod(serverSideMatchingMethod));
00158             }
00159 
00160             matchingMethods.put(clientSideItfType.getFcItfName(),
00161                 matchingMethodsForThisItf);
00162         } catch (ClassNotFoundException e) {
00163             throw new IllegalBindingException(
00164                 "cannot find class corresponding to given signature " +
00165                 e.getMessage());
00166         }
00167     }
00168 
00169 
00170     
00171 
00172 
00173     protected Method searchMatchingMethod(Method clientSideMethod,
00174         Method[] serverSideMethods, boolean clientItfIsMulticast,
00175         boolean serverItfIsGathercast, ProActiveInterface serverSideItf) {
00176         try {
00177             return MulticastBindingChecker.searchMatchingMethod(clientSideMethod,
00178                 serverSideMethods, serverItfIsGathercast, serverSideItf);
00179         } catch (ParameterDispatchException e) {
00180             e.printStackTrace();
00181             return null;
00182         } catch (NoSuchMethodException e) {
00183             e.printStackTrace();
00184             return null;
00185         }
00186     }
00187 
00188     protected void setControllerItfType() {
00189         try {
00190             setItfType(ProActiveTypeFactoryImpl.instance()
00191                                                .createFcItfType(Constants.MULTICAST_CONTROLLER,
00192                     MulticastController.class.getName(), TypeFactory.SERVER,
00193                     TypeFactory.MANDATORY, TypeFactory.SINGLE));
00194         } catch (InstantiationException e) {
00195             throw new ProActiveRuntimeException(
00196                 "cannot create controller type for controller " +
00197                 this.getClass().getName());
00198         }
00199     }
00200 
00201     private boolean addManagedInterface(ProActiveInterfaceType itfType) {
00202         if (!itfType.isFcMulticastItf()) {
00203             return false;
00204         }
00205         if (multicastItfs.containsKey(itfType.getFcItfName())) {
00206             
00207             
00208             return false;
00209         }
00210 
00211         try {
00212             ProActiveInterface multicastItf = (ProActiveInterface) owner.getFcInterface(itfType.getFcItfName());
00213 
00214             if (itfType.isFcMulticastItf()) {
00215                 multicastItfs.put(itfType.getFcItfName(), multicastItf);
00216             } else {
00217                 
00218                 
00219                 return false;
00220             }
00221         } catch (NoSuchInterfaceException e) {
00222             e.printStackTrace();
00223             return false;
00224         }
00225 
00226         return true;
00227     }
00228 
00229     
00230 
00231 
00232     public void bindFcMulticast(String clientItfName,
00233         ProActiveInterface serverItf) {
00234         init();
00235         if (logger.isDebugEnabled()) {
00236             try {
00237                 if (!ProActiveGroup.isGroup(serverItf.getFcItfOwner())) {
00238                     logger.debug("multicast binding : " + clientItfName +
00239                         " to : " +
00240                         Fractal.getNameController(serverItf.getFcItfOwner())
00241                                .getFcName() + "." + serverItf.getFcItfName());
00242                 }
00243             } catch (NoSuchInterfaceException e) {
00244                 e.printStackTrace();
00245             }
00246         }
00247         if (multicastItfs.containsKey(clientItfName)) {
00248             bindFc(clientItfName, serverItf);
00249         }
00250     }
00251 
00252     
00253 
00254 
00255     public void unbindFcMulticast(String clientItfName,
00256         ProActiveInterface serverItf) {
00257         if (multicastItfs.containsKey(clientItfName)) {
00258             if (ProActiveGroup.getGroup(multicastItfs.get(clientItfName))
00259                                   .remove(serverItf)) {
00260                 logger.debug(
00261                     "removed connected interface from multicast interface : " +
00262                     clientItfName);
00263             } else {
00264                 logger.error(
00265                     "cannot remove connected interface from multicast interface : " +
00266                     clientItfName);
00267             }
00268         }
00269     }
00270 
00271     
00272 
00273 
00274     public ProxyForComponentInterfaceGroup lookupFcMulticast(
00275         String clientItfName) {
00276         if (multicastItfs.containsKey(clientItfName)) {
00277             return (ProxyForComponentInterfaceGroup) ((ProActiveInterface) multicastItfs.get(clientItfName)
00278                                                                                         .getFcItfImpl()).getProxy();
00279         } else {
00280             return null;
00281         }
00282     }
00283 
00284     public Map<MethodCall, Integer> generateMethodCallsForMulticastDelegatee(
00285         MethodCall mc, ProxyForComponentInterfaceGroup delegatee)
00286         throws ParameterDispatchException {
00287         
00288         Object[] clientSideEffectiveArguments = mc.getEffectiveArguments();
00289 
00290         ProActiveInterfaceType itfType = (ProActiveInterfaceType) multicastItfs.get(mc.getComponentMetadata()
00291                                                                                       .getComponentInterfaceName())
00292                                                                                .getFcItfType();
00293 
00294         Method matchingMethodInClientInterface; 
00295 
00296         try {
00297             matchingMethodInClientInterface = Class.forName(itfType.getFcItfSignature())
00298                                                    .getMethod(mc.getReifiedMethod()
00299                                                                 .getName(),
00300                     mc.getReifiedMethod().getParameterTypes());
00301         } catch (Exception e) {
00302             e.printStackTrace();
00303             throw new ParameterDispatchException(e.fillInStackTrace());
00304         }
00305 
00306         Class[] clientSideParamTypes = matchingMethodInClientInterface.getParameterTypes();
00307         ParamDispatch[] clientSideParamDispatchModes = MulticastBindingChecker.getDispatchModes(matchingMethodInClientInterface);
00308 
00309         List<List<Object>> dispatchedParameters = new ArrayList<List<Object>>();
00310 
00311         int expectedMethodCallsNb = 0;
00312 
00313         
00314         Vector<Integer> dispatchSizes = new Vector<Integer>();
00315 
00316         for (int i = 0; i < clientSideParamTypes.length; i++) {
00317             dispatchSizes.addElement(clientSideParamDispatchModes[i].expectedDispatchSize(
00318                     clientSideEffectiveArguments[i], delegatee.size()));
00319         }
00320 
00321         if (dispatchSizes.size() > 0) {
00322             
00323             expectedMethodCallsNb = dispatchSizes.get(0);
00324 
00325             for (int i = 1; i < dispatchSizes.size(); i++) {
00326                 if (dispatchSizes.get(i).intValue() != expectedMethodCallsNb) {
00327                     throw new ParameterDispatchException(
00328                         "cannot generate invocation for multicast interface " +
00329                         itfType.getFcItfName() +
00330                         "because the specified distribution of parameters is incorrect in method " +
00331                         matchingMethodInClientInterface.getName());
00332                 }
00333             }
00334         } else {
00335             
00336             expectedMethodCallsNb = delegatee.size();
00337         }
00338 
00339         
00340         for (int i = 0; i < clientSideParamTypes.length; i++) {
00341             List<Object> dispatchedParameter = clientSideParamDispatchModes[i].dispatch(clientSideEffectiveArguments[i],
00342                     delegatee.size());
00343             dispatchedParameters.add(dispatchedParameter);
00344         }
00345 
00346         Map<MethodCall, Integer> result = new HashMap<MethodCall, Integer>(expectedMethodCallsNb);
00347 
00348         
00349         try {
00350 
00351 
00352 
00353 
00354 
00355             Method matchingMethodInServerInterface = matchingMethods.get(mc.getComponentMetadata()
00356                                                                            .getComponentInterfaceName())
00357                                                                     .get(new SerializableMethod(
00358                         mc.getReifiedMethod())).getMethod();
00359 
00360             
00361             
00362             for (int generatedMethodCallIndex = 0;
00363                     generatedMethodCallIndex < expectedMethodCallsNb;
00364                     generatedMethodCallIndex++) {
00365                 Object[] individualEffectiveArguments = new Object[matchingMethodInServerInterface.getParameterTypes().length];
00366 
00367                 for (int parameterIndex = 0;
00368                         parameterIndex < individualEffectiveArguments.length;
00369                         parameterIndex++) {
00370                     individualEffectiveArguments[parameterIndex] = dispatchedParameters.get(parameterIndex)
00371                                                                                        .get(generatedMethodCallIndex); 
00372                 }
00373 
00374                 result.put(new MethodCall(matchingMethodInServerInterface, mc.getGenericTypesMapping(), 
00375                         individualEffectiveArguments, mc.getExceptionContext()),
00376                     generatedMethodCallIndex % delegatee.size());
00377                 
00378             }
00379         } catch (SecurityException e) {
00380             
00381             e.printStackTrace();
00382         }
00383 
00384         return result;
00385     }
00386 
00387     private void bindFc(String clientItfName, ProActiveInterface serverItf) {
00388         try {
00389             ProxyForComponentInterfaceGroup clientSideProxy = (ProxyForComponentInterfaceGroup) clientSideProxies.get(clientItfName);
00390 
00391             if (clientSideProxy.getDelegatee() == null) {
00392                 ProActiveInterface groupItf = ProActiveComponentGroup.newComponentInterfaceGroup((ProActiveInterfaceType) serverItf.getFcItfType(),
00393                         owner);
00394                 ProxyForComponentInterfaceGroup proxy = (ProxyForComponentInterfaceGroup) ((StubObject) groupItf).getProxy();
00395                 clientSideProxy.setDelegatee(proxy);
00396             }
00397 
00398             ((Group) clientSideProxy.getDelegatee()).add(serverItf);
00399         } catch (ClassNotReifiableException e) {
00400             
00401             e.printStackTrace();
00402         } catch (ClassNotFoundException e) {
00403             
00404             e.printStackTrace();
00405         }
00406     }
00407 
00408     private boolean hasClientSideProxy(String itfName) {
00409         return clientSideProxies.containsKey(itfName);
00410     }
00411 
00412     private void addClientSideProxy(String itfName, ProActiveInterface itf) {
00413         Proxy proxy = ((ProActiveInterface) itf.getFcItfImpl()).getProxy();
00414 
00415         if (!(proxy instanceof Group)) {
00416             throw new ProActiveRuntimeException(
00417                 "client side proxies for multicast interfaces must be Group instances");
00418         }
00419 
00420         clientSideProxies.put(itfName, proxy);
00421     }
00422 }