moves the 'make all methods public' proxy to its own class
authorThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Fri, 13 Dec 2024 16:02:56 +0000 (16:02 +0000)
committerThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Fri, 13 Dec 2024 16:02:56 +0000 (16:02 +0000)
developer/javacđź–‰/Mosaic_AllMethodsPublicProxy.java [new file with mode: 0644]
developer/javacđź–‰/Mosaic_IsPrimitive.java [new file with mode: 0644]
developer/javacđź–‰/Mosaic_Util.java
tester/javacđź–‰/Test_Util_proxy.java [deleted file]

diff --git a/developer/javacđź–‰/Mosaic_AllMethodsPublicProxy.java b/developer/javacđź–‰/Mosaic_AllMethodsPublicProxy.java
new file mode 100644 (file)
index 0000000..ea1a0ed
--- /dev/null
@@ -0,0 +1,180 @@
+package com.ReasoningTechnology.Mosaic;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+class FunctionSignature {
+  private final String method_name;
+  private final Class<?>[] parameter_types;
+
+  public FunctionSignature(String method_name ,Class<?>[] parameter_types){
+    this.method_name = method_name;
+    this.parameter_types = parameter_types;
+  }
+
+  public FunctionSignature(String method_name ,Object[] args){
+    this.method_name = method_name;
+    this.parameter_types = resolve_parameter_types(args);
+  }
+
+  public FunctionSignature(Method method){
+    this.method_name = method.getName();
+    this.parameter_types = method.getParameterTypes();
+  }
+
+  private static Class<?>[] resolve_parameter_types(Object[] args){
+    Class<?>[] parameter_types = new Class<?>[args.length];
+    for( int i = 0; i < args.length; i++ ){
+      if( args[i] instanceof isPrimitive ){
+        parameter_types[i] = ((isPrimitive) args[i]).get_type();
+      }else if( args[i] != null ){
+        parameter_types[i] = args[i].getClass();
+      }else{
+        parameter_types[i] = null;
+      }
+    }
+    return parameter_types;
+  }
+
+  public String get_method_name(){
+    return method_name;
+  }
+
+  public Class<?>[] get_parameter_types(){
+    return parameter_types;
+  }
+
+  @Override
+  public boolean equals(Object o){
+    if( this == o ) return true;
+    if( o == null || getClass() != o.getClass() ) return false;
+    FunctionSignature signature = (FunctionSignature) o;
+    return method_name.equals(signature.method_name) &&
+           java.util.Arrays.equals(parameter_types ,signature.parameter_types);
+  }
+
+  @Override
+  public int hashCode(){
+    int result = method_name.hashCode();
+    result = 31 * result + java.util.Arrays.hashCode(parameter_types);
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append(method_name).append("(");
+    for (int i = 0; i < parameter_types.length; i++) {
+      sb.append(parameter_types[i].getSimpleName());
+      if (i < parameter_types.length - 1) sb.append(", ");
+    }
+    sb.append(")");
+    return sb.toString();
+  }
+
+
+}
+
+class FunctionSignature_To_Handle_Map {
+  private final Map<FunctionSignature ,MethodHandle> map;
+
+  public FunctionSignature_To_Handle_Map(Class<?> class_metadata){
+    this.map = new HashMap<>();
+    add_class(class_metadata);
+  }
+
+  private void add_class(Class<?> class_metadata){
+    try{
+      MethodHandles.Lookup lookup = MethodHandles.lookup();
+      MethodHandles.Lookup private_lookup = MethodHandles.privateLookupIn(class_metadata ,lookup);
+
+      for( Method method : class_metadata.getDeclaredMethods() ){
+        Class<?>[] parameter_types = method.getParameterTypes();
+        MethodType method_type = MethodType.methodType(
+          method.getReturnType() ,parameter_types
+        );
+        MethodHandle method_handle;
+
+        if( (method.getModifiers() & java.lang.reflect.Modifier.PRIVATE) != 0 ){
+          method_handle = private_lookup.findSpecial(class_metadata ,method.getName() ,method_type ,class_metadata);
+        }else{
+          method_handle = lookup.findVirtual(class_metadata ,method.getName() ,method_type);
+        }
+
+        FunctionSignature signature = new FunctionSignature(method);
+        map.put(signature ,method_handle);
+      }
+    }catch(Throwable t){
+      System.out.println("FunctionSignature_To_Handle_Map::add_class exception:");
+      t.printStackTrace();
+    }
+  }
+
+  public MethodHandle get_handle(FunctionSignature signature){
+    return map.get(signature);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("FunctionSignature to MethodHandle Map:\n");
+    for (Map.Entry<FunctionSignature, MethodHandle> entry : map.entrySet()) {
+      sb.append("  ").append(entry.getKey()).append(" -> ").append(entry.getValue()).append("\n");
+    }
+    return sb.toString();
+  }
+
+}
+
+public class Mosaic_AllMethodsPublicProxy {
+  private final FunctionSignature_To_Handle_Map map;
+  private final Class<?> target_type;
+
+  public Mosaic_AllMethodsPublicProxy(Class<?> target_type){
+    this.target_type = target_type;
+    this.map = new FunctionSignature_To_Handle_Map(target_type);
+  }
+
+  public Object invoke(Object target_instance, String method_name, Object... arg_list) {
+    try {
+      if (target_instance == null || !target_type.isInstance(target_instance)) {
+        System.out.println("Warning: Instance is not of type " + target_type.getName());
+      }
+
+      // Resolve the function signature
+      FunctionSignature signature = new FunctionSignature(method_name, arg_list);
+      MethodHandle handle = map.get_handle(signature);
+      System.out.println( "invoked with signature: " + signature.toString() );
+
+      if (handle == null) {
+        throw new NoSuchMethodException("No method found for signature: " + signature.get_method_name());
+      }
+
+      // Unwrap isPrimitive instances in arguments
+      Object[] unwrapped_args = new Object[arg_list.length];
+      for (int i = 0; i < arg_list.length; i++) {
+        if (arg_list[i] instanceof isPrimitive) {
+          unwrapped_args[i] = ((isPrimitive) arg_list[i]).get_value();
+        } else {
+          unwrapped_args[i] = arg_list[i];
+        }
+      }
+
+      return handle.bindTo(target_instance).invokeWithArguments(unwrapped_args);
+
+    } catch (Throwable t) {
+      System.out.println("Mosaic_AllMethodsPublicProxy::invoke exception:");
+      t.printStackTrace();
+      return null;
+    }
+  }
+
+  public FunctionSignature_To_Handle_Map get_map() {
+    return map;
+  }
+
+}
diff --git a/developer/javacđź–‰/Mosaic_IsPrimitive.java b/developer/javacđź–‰/Mosaic_IsPrimitive.java
new file mode 100644 (file)
index 0000000..a50c6b5
--- /dev/null
@@ -0,0 +1,31 @@
+package com.ReasoningTechnology.Mosaic;
+
+public class Mosaic_IsPrimitive {
+  private final Object value;
+
+  public Mosaic_IsPrimitive(Object value){
+    this.value = value;
+  }
+
+  public static Mosaic_IsPrimitive make(Object value) {
+    return new Mosaic_IsPrimitive(value);
+  }
+
+  public Object get_value(){
+    return value;
+  }
+
+  public Class<?> get_type(){
+    if( value instanceof Integer ) return int.class;
+    if( value instanceof Boolean ) return boolean.class;
+    if( value instanceof Double ) return double.class;
+    if( value instanceof Float ) return float.class;
+    if( value instanceof Long ) return long.class;
+    if( value instanceof Short ) return short.class;
+    if( value instanceof Byte ) return byte.class;
+    if( value instanceof Character ) return char.class;
+    return value.getClass();
+  }
+
+}
+
index 1cccc82..1fba0cc 100644 (file)
@@ -1,24 +1,10 @@
 package com.ReasoningTechnology.Mosaic;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.Proxy;
 import java.time.Instant;
 import java.time.ZoneOffset;
 import java.time.format.DateTimeFormatter;
 import java.util.function.Predicate;
 
-
 public class Mosaic_Util{
 
   // Linear search with a predicate
@@ -59,69 +45,6 @@ public class Mosaic_Util{
     return Instant.now().atOffset(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT);
   }
 
-  public static Object make_all_public_proxy(Class<?> class_metadata) {
-    try {
-      // Validate that the class implements at least one interface
-      Class<?>[] interfaces = class_metadata.getInterfaces();
-      if(interfaces.length == 0){
-        throw new IllegalArgumentException
-          (
-           "The class " + class_metadata.getName() + " does not implement any interfaces."
-           );}
-
-      // Create a Lookup for the target class that gives us access to private members
-      MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(class_metadata, MethodHandles.lookup());
-
-      InvocationHandler handler = (proxy_object, method, args) -> {
-        // Find the corresponding method in the target class
-        Method target_method = class_metadata.getDeclaredMethod(method.getName(), method.getParameterTypes());
-
-        // Convert the reflective method into a MethodHandle
-        MethodHandle mh = lookup.unreflect(target_method);
-
-        // Create an instance of the target class
-        Constructor<?> ctor = class_metadata.getDeclaredConstructor();
-        MethodHandle ctorHandle = lookup.unreflectConstructor(ctor);
-        Object real_instance = ctorHandle.invoke();
-
-        // Invoke the target method via the MethodHandle
-        if (args == null) {
-          args = new Object[0];
-        }
-
-
-        // replaces former return code:
-        Object result;
-        if (args == null || args.length == 0) {
-          // No arguments, just the instance
-          result = mh.invokeWithArguments(real_instance);
-        } else {
-          // One argument for the instance + all method arguments
-          Object[] callArgs = new Object[args.length + 1];
-          callArgs[0] = real_instance;
-          System.arraycopy(args, 0, callArgs, 1, args.length);
-          result = mh.invokeWithArguments(callArgs);
-        }
-        return result;
-
-        // former return code
-        //   return mh.invokeWithArguments(real_instance, args);
-
-      };
-
-      // Create the proxy
-      return Proxy.newProxyInstance
-        (
-         class_metadata.getClassLoader(),
-         interfaces,
-         handler
-         );
-
-    } catch (Throwable e) {
-      Mosaic_Logger.message("make_all_public_proxy", "Failed to create proxy: " + e.getMessage());
-      throw new RuntimeException("Failed to create proxy for class: " + class_metadata.getName(), e);
-    }
-  }
 
 
 }
diff --git a/tester/javacđź–‰/Test_Util_proxy.java b/tester/javacđź–‰/Test_Util_proxy.java
deleted file mode 100644 (file)
index 5e42277..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Proxy;
-
-import com.ReasoningTechnology.Mosaic.Mosaic_IO;
-import com.ReasoningTechnology.Mosaic.Mosaic_Testbench;
-import com.ReasoningTechnology.Mosaic.Mosaic_Util;
-import com.ReasoningTechnology.Mosaic.Mosaic_Logger;
-
-public class Test_Util_proxy{
-
-  public class TestSuite{
-
-    public Boolean create_proxy_non_public_class( Mosaic_IO io ){
-      Boolean[] conditions = new Boolean[2];
-      int i = 0;
-
-      try{
-        Object proxy = Mosaic_Util.make_all_public_proxy( NonPublicClass.class );
-        conditions[i++] = proxy != null;
-        conditions[i++] = Proxy.isProxyClass( proxy.getClass() );
-      }catch( Exception e ){
-        Mosaic_Logger.error("Test_Util_proxy" ,"create_proxy_non_public_class" ,e);
-        return false;
-      }
-
-      return Mosaic_Util.all( conditions );
-    }
-
-    public Boolean invoke_proxied_non_public_method(Mosaic_IO io) {
-        Boolean[] conditions = new Boolean[2];
-        int i = 0;
-
-        try {
-            NonPublicInterface proxy = (NonPublicInterface) Mosaic_Util.make_all_public_proxy(NonPublicClass.class);
-            String result = proxy.hidden_method();
-            conditions[i++] = result.equals("Accessed hidden method!");
-            conditions[i++] = Proxy.isProxyClass(proxy.getClass());
-        } catch (Exception e) {
-            Mosaic_Logger.error("invoke_proxied_non_public_method", "Unexpected exception: " + e.getMessage(), e);
-            return false;
-        }
-
-        return Mosaic_Util.all(conditions);
-    }
-
-    public Boolean create_and_invoke_public_class_proxy( Mosaic_IO io ){
-      Boolean[] conditions = new Boolean[2];
-      int i = 0;
-
-      try{
-        PublicInterface proxy = (PublicInterface) Mosaic_Util.make_all_public_proxy( PublicClass.class );
-        String result = proxy.say_hello();
-        conditions[i++] = result.equals( "Hello from PublicClass!" );
-        conditions[i++] = Proxy.isProxyClass( proxy.getClass() );
-      }catch( Exception e ){
-        Mosaic_Logger.error("Test_Util_proxy" ,"create_and_invoke_public_class_proxy" ,e);
-        return false;
-      }
-
-      return Mosaic_Util.all( conditions );
-    }
-
-  }
-
-  public interface PublicInterface{
-    String say_hello();
-  }
-
-  public static class PublicClass implements PublicInterface{
-    @Override
-    public String say_hello(){
-      return "Hello from PublicClass!";
-    }
-  }
-
-  interface NonPublicInterface{
-    String hidden_method();
-  }
-
-  static class NonPublicClass implements NonPublicInterface{
-    @Override
-    public String hidden_method(){
-      return "Accessed hidden method!";
-    }
-  }
-
-  public static void main( String[] args ){
-    Test_Util_proxy outer = new Test_Util_proxy();
-    TestSuite suite = outer.new TestSuite();
-    int result = Mosaic_Testbench.run( suite );
-    System.exit( result );
-  }
-}