Home | History | Annotate | Download | only in rmi
      1 /*
      2  * Copyright (c) 2009-2010 jMonkeyEngine
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are
      7  * met:
      8  *
      9  * * Redistributions of source code must retain the above copyright
     10  *   notice, this list of conditions and the following disclaimer.
     11  *
     12  * * Redistributions in binary form must reproduce the above copyright
     13  *   notice, this list of conditions and the following disclaimer in the
     14  *   documentation and/or other materials provided with the distribution.
     15  *
     16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
     17  *   may be used to endorse or promote products derived from this software
     18  *   without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 package com.jme3.network.rmi;
     34 
     35 import com.jme3.network.HostedConnection;
     36 import java.lang.reflect.InvocationHandler;
     37 import java.lang.reflect.Method;
     38 import java.util.ArrayList;
     39 import java.util.HashMap;
     40 
     41 /**
     42  * Contains various meta-data about an RMI interface.
     43  *
     44  * @author Kirill Vainer
     45  */
     46 public class RemoteObject implements InvocationHandler {
     47 
     48     /**
     49      * Object ID
     50      */
     51     short objectId;
     52 
     53     /**
     54      * Contains {@link MethodDef method definitions} for all exposed
     55      * RMI methods in the remote RMI interface.
     56      */
     57     MethodDef[] methodDefs;
     58 
     59     /**
     60      * Maps from methods locally retrieved from the RMI interface to
     61      * a method ID.
     62      */
     63     HashMap<Method, Integer> methodMap = new HashMap<Method, Integer>();
     64 
     65     /**
     66      * The {@link ObjectStore} which stores this RMI interface.
     67      */
     68     ObjectStore store;
     69 
     70     /**
     71      * The client who exposed the RMI interface, or null if the server
     72      * exposed it.
     73      */
     74     HostedConnection client;
     75 
     76     public RemoteObject(ObjectStore store, HostedConnection client){
     77         this.store = store;
     78         this.client = client;
     79     }
     80 
     81     private boolean methodEquals(MethodDef methodDef, Method method){
     82         Class<?>[] interfaceTypes = method.getParameterTypes();
     83         Class<?>[] defTypes       = methodDef.paramTypes;
     84 
     85         if (interfaceTypes.length == defTypes.length){
     86             for (int i = 0; i < interfaceTypes.length; i++){
     87                 if (!defTypes[i].isAssignableFrom(interfaceTypes[i])){
     88                     return false;
     89                 }
     90             }
     91             return true;
     92         }
     93         return false;
     94     }
     95 
     96     /**
     97      * Generates mappings from the given interface into the remote RMI
     98      * interface's implementation.
     99      *
    100      * @param interfaceClass The interface class to use.
    101      */
    102     public void loadMethods(Class<?> interfaceClass){
    103         HashMap<String, ArrayList<Method>> nameToMethods
    104                 = new HashMap<String, ArrayList<Method>>();
    105 
    106         for (Method method : interfaceClass.getDeclaredMethods()){
    107             ArrayList<Method> list = nameToMethods.get(method.getName());
    108             if (list == null){
    109                 list = new ArrayList<Method>();
    110                 nameToMethods.put(method.getName(), list);
    111             }
    112             list.add(method);
    113         }
    114 
    115         mapping_search: for (int i = 0; i < methodDefs.length; i++){
    116             MethodDef methodDef = methodDefs[i];
    117             ArrayList<Method> methods = nameToMethods.get(methodDef.name);
    118             if (methods == null)
    119                 continue;
    120 
    121             for (Method method : methods){
    122                 if (methodEquals(methodDef, method)){
    123                     methodMap.put(method, i);
    124                     continue mapping_search;
    125                 }
    126             }
    127         }
    128     }
    129 
    130     /**
    131      * Callback from InvocationHandler.
    132      */
    133     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    134         return store.invokeRemoteMethod(this, method, args);
    135     }
    136 
    137 }
    138