1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.googlecode.android_scripting.jsonrpc; 18 19 import java.lang.reflect.Constructor; 20 import java.lang.reflect.Method; 21 import java.util.Collection; 22 import java.util.HashMap; 23 import java.util.Map; 24 25 import com.googlecode.android_scripting.facade.FacadeManager; 26 import com.googlecode.android_scripting.Log; 27 import com.googlecode.android_scripting.rpc.MethodDescriptor; 28 29 public abstract class RpcReceiverManager { 30 31 private final Map<Class<? extends RpcReceiver>, RpcReceiver> mReceivers; 32 33 /** 34 * A map of strings to known RPCs. 35 */ 36 private final Map<String, MethodDescriptor> mKnownRpcs = new HashMap<String, MethodDescriptor>(); 37 RpcReceiverManager(Collection<Class<? extends RpcReceiver>> classList)38 public RpcReceiverManager(Collection<Class<? extends RpcReceiver>> classList) { 39 mReceivers = new HashMap<Class<? extends RpcReceiver>, RpcReceiver>(); 40 for (Class<? extends RpcReceiver> receiverClass : classList) { 41 mReceivers.put(receiverClass, null); 42 Collection<MethodDescriptor> methodList = MethodDescriptor.collectFrom(receiverClass); 43 for (MethodDescriptor m : methodList) { 44 if (mKnownRpcs.containsKey(m.getName())) { 45 // We already know an RPC of the same name. We don't catch this anywhere because 46 // this is a programming error. 47 throw new RuntimeException("An RPC with the name " + m.getName() 48 + " is already known."); 49 } 50 mKnownRpcs.put(m.getName(), m); 51 } 52 } 53 } 54 getRpcReceiverClasses()55 public Collection<Class<? extends RpcReceiver>> getRpcReceiverClasses() { 56 return mReceivers.keySet(); 57 } 58 get(Class<? extends RpcReceiver> clazz)59 private RpcReceiver get(Class<? extends RpcReceiver> clazz) { 60 RpcReceiver object = mReceivers.get(clazz); 61 if (object != null) { 62 return object; 63 } 64 65 Constructor<? extends RpcReceiver> constructor; 66 try { 67 constructor = clazz.getConstructor(FacadeManager.class); 68 object = constructor.newInstance(this); 69 mReceivers.put(clazz, object); 70 } catch (Exception e) { 71 Log.e(e); 72 } 73 74 return object; 75 } 76 getReceiver(Class<T> clazz)77 public <T extends RpcReceiver> T getReceiver(Class<T> clazz) { 78 RpcReceiver receiver = get(clazz); 79 return clazz.cast(receiver); 80 } 81 getMethodDescriptor(String methodName)82 public MethodDescriptor getMethodDescriptor(String methodName) { 83 return mKnownRpcs.get(methodName); 84 } 85 invoke(Class<? extends RpcReceiver> clazz, Method method, Object[] args)86 public Object invoke(Class<? extends RpcReceiver> clazz, Method method, Object[] args) 87 throws Exception { 88 RpcReceiver object = get(clazz); 89 return method.invoke(object, args); 90 } 91 shutdown()92 public void shutdown() { 93 for (RpcReceiver receiver : mReceivers.values()) { 94 try { 95 if (receiver != null) { 96 receiver.shutdown(); 97 } 98 } catch (Exception e) { 99 Log.e("Failed to shut down an RpcReceiver", e); 100 } 101 } 102 } 103 } 104