
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