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

net.sf.jstuff.integration.serviceregistry.impl.ByteBuddyServiceRegistry Maven / Gradle / Ivy

/*
 * Copyright 2010-2022 by Sebastian Thomschke and contributors.
 * SPDX-License-Identifier: EPL-2.0
 */
package net.sf.jstuff.integration.serviceregistry.impl;

import java.lang.reflect.Method;

import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.DynamicType.Loaded;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bind.annotation.AllArguments;
import net.bytebuddy.implementation.bind.annotation.Origin;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
import net.bytebuddy.matcher.ElementMatchers;
import net.sf.jstuff.core.reflection.Types;
import net.sf.jstuff.integration.serviceregistry.ServiceUnavailableException;

/**
 * @author Sebastian Thomschke
 */
public class ByteBuddyServiceRegistry extends DefaultServiceRegistry {
   protected static final class ByteBuddyServiceInterceptor {
      private final ServiceEndpointState serviceEndpointState;
      private final Class serviceInterface;

      protected ByteBuddyServiceInterceptor(final ServiceEndpointState serviceEPState, final Class serviceInterface) {
         this.serviceEndpointState = serviceEPState;
         this.serviceInterface = serviceInterface;
      }

      @RuntimeType
      public @Nullable Object intercept(@Origin final Method method, @AllArguments final Object... args) throws Exception {
         final Object service = serviceEndpointState.getActiveServiceIfCompatible(serviceInterface);
         if (service == null)
            throw new ServiceUnavailableException(serviceEndpointState.getServiceEndpointId(), serviceInterface);
         return method.invoke(service, args);
      }
   }

   @Override
   @SuppressWarnings({"rawtypes", "resource"})
   protected <@NonNull SERVICE_INTERFACE> ServiceProxyInternal createServiceProxy(
      final ServiceEndpointState serviceEndpointState, final Class serviceInterface) {

      final MethodDelegation interceptor = MethodDelegation.to(new ByteBuddyServiceInterceptor<>(serviceEndpointState, serviceInterface));

      DynamicType.Builder builder = new ByteBuddy() //
         .subclass(DefaultServiceProxyAdvice.class, ConstructorStrategy.Default.IMITATE_SUPER_CLASS_PUBLIC) //
         .implement(serviceInterface) //
         .method(ElementMatchers.isDeclaredBy(serviceInterface)).intercept(interceptor);

      for (final Class iface : Types.getInterfacesRecursive(serviceInterface)) {
         builder = builder.implement(iface) //
            .method(ElementMatchers.isDeclaredBy(iface)).intercept(interceptor);
      }

      final Loaded> clazz = builder.make().load(DefaultServiceRegistry.class.getClassLoader(),
         ClassLoadingStrategy.Default.WRAPPER);

      /*try {
          clazz.saveIn(new java.io.File("F:\\out"));
      } catch (final java.io.IOException ex) {
          ex.printStackTrace();
      }*/

      final var proxy = Types.newInstance(clazz.getLoaded(), serviceEndpointState, serviceInterface);
      proxy.setProxy(proxy);
      return proxy;
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy