All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.snapscript.platform.android.ProxyConstructorInvocation Maven / Gradle / Ivy

There is a newer version: 1.4.6
Show newest version
package org.snapscript.platform.android;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicLong;

import org.snapscript.core.InternalStateException;
import org.snapscript.core.function.Invocation;
import org.snapscript.core.scope.Scope;
import org.snapscript.dx.stock.ProxyAdapter;

public class ProxyConstructorInvocation implements Invocation {
   
   private volatile ConstructorExchanger exchanger;
   private volatile ProxyAdapter reference;
   private volatile Constructor constructor;
   private volatile Executor executor;
   
   public ProxyConstructorInvocation(ProxyAdapterBuilder generator, Constructor constructor, Executor executor) {
      this.exchanger = new ConstructorExchanger(generator, constructor);
      this.reference = new ConstructorAdapter(constructor);
      this.constructor = constructor;
      this.executor = executor;
   }

   @Override
   public Object invoke(Scope scope, Object value, Object... arguments) throws Exception {
      try {
         return reference.invoke(value, arguments);
      }catch(InvocationTargetException cause) {
         Throwable target = cause.getTargetException();
         
         if(target != null) {
            throw new InternalStateException("Error occured invoking " + constructor, target);
         }
         throw cause;
      }catch(InternalError cause) {
         Throwable target = cause.getCause();
         
         if(target != null) {
            throw new InternalStateException("Error occured invoking " + constructor, target);
         }
         throw cause;
      }
   }
   
   private class ConstructorAdapter implements ProxyAdapter {

      private final Constructor constructor;
      private final AtomicLong counter;
      
      public ConstructorAdapter(Constructor constructor) {
         this(constructor, 10);
      }
      
      public ConstructorAdapter(Constructor constructor, int threshold) {
         this.counter = new AtomicLong(threshold);
         this.constructor = constructor;
      }
      
      @Override
      public Object invoke(Object object, Object... list) throws Exception {
         long count = counter.getAndDecrement();
         
         if(count == 0) {
            executor.execute(exchanger); // generate proxy adapter
         }
         return constructor.newInstance(list);
      }   
   }
   
   private class ConstructorExchanger implements Runnable {
      
      private final ProxyAdapterBuilder generator;
      private final InternalClassFilter filter;
      private final Constructor constructor;
      
      public ConstructorExchanger(ProxyAdapterBuilder generator, Constructor constructor) {
         this.filter = new InternalClassFilter();
         this.constructor = constructor;
         this.generator = generator;
      }

      @Override
      public void run() {
         if(filter.accept(constructor)) { // in a private dex class loader
            ProxyAdapter adapter = generator.generate(constructor);
         
            if(adapter != null) {
               reference = adapter;
            }
         }
      }
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy