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