package omq.server; import java.io.IOException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import omq.Remote; import omq.common.broker.Broker; import omq.common.util.ParameterQueue; import org.apache.log4j.Logger; /** * A RemoteObject when it's started will be waiting for requests and will invoke * them. When a RemoteObject is started it listens two queues, the first one has * the same name as its reference and the second one is its multiqueue -this * name can be set using a property, be aware to use a name not used by another * object!!!-. * * @author Sergi Toda * */ public abstract class RemoteObject implements Remote { private static final long serialVersionUID = -1778953938739846450L; private static final Logger logger = Logger.getLogger(RemoteObject.class.getName()); private String reference; private String UID; private Properties env; private transient Broker broker; private transient RemoteThreadPool pool; private transient Map>> params; private static final Map> primitiveClasses = new HashMap>(); static { primitiveClasses.put("byte", Byte.class); primitiveClasses.put("short", Short.class); primitiveClasses.put("char", Character.class); primitiveClasses.put("int", Integer.class); primitiveClasses.put("long", Long.class); primitiveClasses.put("float", Float.class); primitiveClasses.put("double", Double.class); } /** * This method starts a remoteObject. * * @param reference * - broker's binding referece * @param broker * - broker that binds this remoteObject * @param env * - properties of this remoteObject * @throws Exception */ public void startRemoteObject(String reference, Broker broker, Properties env) throws Exception { this.broker = broker; this.reference = reference; this.env = env; this.params = new HashMap>>(); for (Method m : this.getClass().getMethods()) { List> list = new ArrayList>(); for (Class clazz : m.getParameterTypes()) { list.add(clazz); } this.params.put(m.getName(), list); } // Get pool information int minPoolThreads = Integer.parseInt(env.getProperty(ParameterQueue.MIN_POOL_THREADS, "1")); int maxPoolThreads = Integer.parseInt(env.getProperty(ParameterQueue.MAX_POOL_THREADS, "1")); long refresh = Long.parseLong(env.getProperty(ParameterQueue.POOL_REFRESH_TIME, "60000")); long keepAliveTime = Long.parseLong(env.getProperty(ParameterQueue.KEEP_ALIVE_TIME, "30000")); int maxMessagesPerThread = Integer.parseInt(env.getProperty(ParameterQueue.MAX_MESSAGES_PER_THREAD, "5")); // Create the pool & start it pool = new RemoteThreadPool(minPoolThreads, maxPoolThreads, refresh, keepAliveTime, maxMessagesPerThread, this, broker); pool.start(); } public void startRemoteObject(String reference, String UID, Broker broker, Properties env) throws Exception { this.UID = UID; startRemoteObject(reference, broker, env); } @Override public String getRef() { return reference; } /** * This method kills all the threads waiting for requests * * @throws IOException * - If an operation failed. */ public void kill() throws IOException { logger.info("Killing objectmq: " + this.getRef()); pool.kill(); } /** * This method invokes the method specified by methodName and arguments * * @param methodName * @param arguments * @return result * @throws Exception */ public Object invokeMethod(String methodName, Object[] arguments) throws Exception { // Get the specific method identified by methodName and its arguments Method method = loadMethod(methodName, arguments); return method.invoke(this, arguments); } /** * This method loads the method specified by methodName and args * * @param methodName * @param args * @return method * @throws NoSuchMethodException * - If the method cannot be found */ private Method loadMethod(String methodName, Object[] args) throws NoSuchMethodException { Method m = null; // Obtain the class reference Class clazz = this.getClass(); Class[] argArray = null; if (args != null) { argArray = new Class[args.length]; for (int i = 0; i < args.length; i++) { argArray[i] = args[i].getClass(); } } try { m = clazz.getMethod(methodName, argArray); } catch (NoSuchMethodException nsm) { m = loadMethodWithPrimitives(methodName, argArray); } return m; } /** * This method loads a method which uses primitives as arguments * * @param methodName * - name of the method wanted to invoke * @param argArray * - arguments * @return method * @throws NoSuchMethodException * - If the method cannot be found */ private Method loadMethodWithPrimitives(String methodName, Class[] argArray) throws NoSuchMethodException { if (argArray != null) { Method[] methods = this.getClass().getMethods(); int length = argArray.length; for (Method method : methods) { String name = method.getName(); int argsLength = method.getParameterTypes().length; if (name.equals(methodName) && length == argsLength) { // This array can have primitive types inside Class[] params = method.getParameterTypes(); boolean found = true; for (int i = 0; i < length; i++) { if (params[i].isPrimitive()) { Class paramWrapper = primitiveClasses.get(params[i].getName()); if (!paramWrapper.equals(argArray[i])) { found = false; break; } } } if (found) { return method; } } } } throw new NoSuchMethodException(methodName); } public List> getParams(String methodName) { return params.get(methodName); } public Broker getBroker() { return broker; } public RemoteThreadPool getPool() { return pool; } public Properties getEnv() { return env; } public String getUID() { return UID; } public void setUID(String uID) { UID = uID; } }