package co.codewizards.cloudstore.ls.core.invoke; import java.beans.PropertyChangeListener; import java.io.Serializable; import java.lang.reflect.Proxy; import co.codewizards.cloudstore.core.Uid; public interface Invoker { /** * Invoke a static method from the {@code LocalServerClient} in the {@code LocalServer} or vice-versa. * <p> * Convenience method delegating to {@link #invokeStatic(String, String, String[], Object...)}. * <p> * See {@link #invoke(Object, String, String[], Object...)} for further details. * @param clazz the class owning the static method to be invoked. Must not be <code>null</code>. * @param methodName the name of the static method to be invoked. Must not be <code>null</code>. * @param arguments the arguments passed to the static method. May be <code>null</code> (if the method does not take any parameters). * @return the result of the method invocation. May be <code>null</code>. * @see #invokeStatic(String, String, String[], Object...) * @see #invoke(Object, String, String[], Object...) */ <T> T invokeStatic(Class<?> clazz, String methodName, Object... arguments); /** * Invoke a static method from the {@code LocalServerClient} in the {@code LocalServer} or vice-versa. * <p> * Convenience method delegating to {@link #invokeStatic(String, String, String[], Object...)}. * <p> * See {@link #invoke(Object, String, String[], Object...)} for further details. * @param className the fully qualified name of the class owning the static method to be invoked. Must not be <code>null</code>. * @param methodName the name of the static method to be invoked. Must not be <code>null</code>. * @param arguments the arguments passed to the static method. May be <code>null</code> (if the method does not take any parameters). * @return the result of the method invocation. May be <code>null</code>. * @see #invokeStatic(String, String, String[], Object...) * @see #invoke(Object, String, String[], Object...) */ <T> T invokeStatic(String className, String methodName, Object... arguments); /** * Invoke a static method from the {@code LocalServerClient} in the {@code LocalServer} or vice-versa. * <p> * Convenience method delegating to {@link #invokeStatic(String, String, String[], Object...)}. * <p> * See {@link #invoke(Object, String, String[], Object...)} for further details. * @param clazz the class owning the static method to be invoked. Must not be <code>null</code>. * @param methodName the name of the static method to be invoked. Must not be <code>null</code>. * @param argumentTypes the argument-types. May be <code>null</code>; then a matching method * will be searched. If there are multiple matching methods, an exception is thrown, though (and the argument-types must be * specified). If {@code argumentTypes} is not <code>null</code>, its {@code length} must match the one of {@code arguments}. * @param arguments the arguments passed to the static method. May be <code>null</code> (if the method does not take any parameters). * @return the result of the method invocation. May be <code>null</code>. * @see #invokeStatic(String, String, String[], Object...) * @see #invoke(Object, String, String[], Object...) */ <T> T invokeStatic(Class<?> clazz, String methodName, Class<?>[] argumentTypes, Object... arguments); /** * Invoke a static method from the {@code LocalServerClient} in the {@code LocalServer} or vice-versa. * <p> * See {@link #invoke(Object, String, String[], Object...)} for further details. * @param className the fully qualified name of the class owning the static method to be invoked. Must not be <code>null</code>. * @param methodName the name of the static method to be invoked. Must not be <code>null</code>. * @param argumentTypeNames the fully qualified names of the argument-types. May be <code>null</code>; then a matching method * will be searched. If there are multiple matching methods, an exception is thrown, though (and the argument-types must be * specified). If {@code argumentTypeNames} is not <code>null</code>, its {@code length} must match the one of {@code arguments}. * @param arguments the arguments passed to the static method. May be <code>null</code> (if the method does not take any parameters). * @return the result of the method invocation. May be <code>null</code>. * @see #invoke(Object, String, String[], Object...) */ <T> T invokeStatic(String className, String methodName, String[] argumentTypeNames, Object... arguments); /** * Invoke a constructor from the {@code LocalServerClient} in the {@code LocalServer} or vice-versa. * <p> * Convenience method delegating to {@link #invokeConstructor(String, String[], Object...)}. * <p> * See {@link #invoke(Object, String, String[], Object...)} for further details. * @param clazz the class to be instantiated. Must not be <code>null</code>. * @param arguments the arguments passed to the constructor. May be <code>null</code> (if the constructor does not take any parameters). * @return the newly created objectRef. Never <code>null</code>. * @see #invokeConstructor(String, String[], Object...) * @see #invoke(Object, String, String[], Object...) */ <T> T invokeConstructor(Class<T> clazz, Object... arguments); /** * Invoke a constructor from the {@code LocalServerClient} in the {@code LocalServer} or vice-versa. * <p> * See {@link #invoke(Object, String, String[], Object...)} for further details. * @param className the fully qualified name of the class to be instantiated. Must not be <code>null</code>. * @param arguments the arguments passed to the constructor. May be <code>null</code> (if the constructor does not take any parameters). * @return the newly created objectRef. Never <code>null</code>. * @see #invokeConstructor(String, String[], Object...) * @see #invoke(Object, String, String[], Object...) */ <T> T invokeConstructor(String className, Object... arguments); <T> T invokeConstructor(Class<T> clazz, Class<?>[] argumentTypes, Object... arguments); <T> T invokeConstructor(String className, String[] argumentTypeNames, Object... arguments); <T> T invoke(Object objectRef, String methodName, Object... arguments); <T> T invoke(Object objectRef, String methodName, Class<?>[] argumentTypes, Object... arguments); /** * Invoke a method on the given {@code objectRef} (which is a proxy) in the {@code LocalServer} or in its client * (from the respective other side). * <p> * The {@code LocalServer} might reside in the same JVM or in a separate JVM (on the same computer, hence "local"). * <p> * When invoking a method, the {@code arguments} must be passed to the real objectRef on the other side (in the other * JVM). Therefore, all primitives ({@code byte}, {@code long} etc.) as well as all objects implementing * {@link Serializable} are serialized (via Java native serialisation), transmitted via a REST call and deserialized. * <p> * If, however, an objectRef passed as an argument is a proxy of a real objectRef in the server (no matter, if it * implements {@code Serializable} or not), it is converted into an {@link Object} instead - and this reference * is transmitted via REST. The server then resolves the {@link Object} to the real objectRef. * <p> * If an objectRef in the {@code arguments} is neither a proxy of a {@code LocalServer}-objectRef (it may be a proxy of * sth. else) nor implements {@code Serializable}, instead a reverse-proxy is created on the server-side. Therefore, an * {@link Object} in the local JVM is created and passed via REST. The server then determines all interfaces of * the real objectRef and instantiates a proxy (or re-uses an already existing one). This reverse-proxy-mechanism allows * for passing a listener, e.g. a {@link PropertyChangeListener}: If the server invokes a method on the reverse-proxy, * the {@code InverseInvoker} is used to invoke the corresponding method on the real objectRef in the client-JVM. * <p> * <b>Important:</b> For the proxies (both the ones on the client-side and the reverse-ones on the server-side), the * standard Java {@link Proxy} is used. Therefore, only interfaces can be proxied - no classes. We cannot use cglib * or any other more advanced proxy-lib, because these libs cannot be used with Android. * <p> * However, if a method declared by a class and not an interface should be invoked, this can still be done via this * method - it's just less convenient. Additionally, reverse-proxies (on the server-side) obviously can only be passed * to the real objectRef's method, if the method-signature uses an interface (or {@code Object}) for the argument in question. * * @param objectRef the proxy on which to invoke a method. Must not be <code>null</code>. This proxy * was returned by a previous invocation of one of the <i>invoke*</i> methods (which might have happened * indirectly via an invocation of a proxy's method). * @param methodName the name of the method to be invoked. Must not be <code>null</code>. * @param argumentTypeNames the fully qualified names of the argument-types. May be <code>null</code>; then a matching method * will be searched. If there are multiple matching methods, an exception is thrown, though (and the argument-types must be * specified). If {@code argumentTypeNames} is not <code>null</code>, its {@code length} must match the one of {@code arguments}. * @param arguments the arguments passed to the method. May be <code>null</code> (if the method does not take any parameters). * @return the result of the method invocation. This is either a serialized and deserialized "simple" objectRef or a * proxy for a more complex objectRef on the server-side. */ <T> T invoke(Object objectRef, String methodName, String[] argumentTypeNames, Object... arguments); void incRefCount(ObjectRef objectRef, Uid refId); void decRefCount(ObjectRef objectRef, Uid refId); ObjectManager getObjectManager(); ClassInfoMap getClassInfoMap(); }