From: Thomas Walker Lynch Date: Fri, 13 Dec 2024 16:02:56 +0000 (+0000) Subject: moves the 'make all methods public' proxy to its own class X-Git-Url: https://git.reasoningtechnology.com/style/static/git-favicon.png?a=commitdiff_plain;h=d6b74776c010e302f91d49c92efe741bbeb12336;p=Mosaic moves the 'make all methods public' proxy to its own class --- diff --git "a/developer/javac\360\237\226\211/Mosaic_AllMethodsPublicProxy.java" "b/developer/javac\360\237\226\211/Mosaic_AllMethodsPublicProxy.java" new file mode 100644 index 0000000..ea1a0ed --- /dev/null +++ "b/developer/javac\360\237\226\211/Mosaic_AllMethodsPublicProxy.java" @@ -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 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 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\360\237\226\211/Mosaic_IsPrimitive.java" "b/developer/javac\360\237\226\211/Mosaic_IsPrimitive.java" new file mode 100644 index 0000000..a50c6b5 --- /dev/null +++ "b/developer/javac\360\237\226\211/Mosaic_IsPrimitive.java" @@ -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(); + } + +} + diff --git "a/developer/javac\360\237\226\211/Mosaic_Util.java" "b/developer/javac\360\237\226\211/Mosaic_Util.java" index 1cccc82..1fba0cc 100644 --- "a/developer/javac\360\237\226\211/Mosaic_Util.java" +++ "b/developer/javac\360\237\226\211/Mosaic_Util.java" @@ -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\360\237\226\211/Test_Util_proxy.java" "b/tester/javac\360\237\226\211/Test_Util_proxy.java" deleted file mode 100644 index 5e42277..0000000 --- "a/tester/javac\360\237\226\211/Test_Util_proxy.java" +++ /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 ); - } -}