From 6fbf76efabb8928f1844f4cbdf3ae74ecf31ce09 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Sun, 5 May 2019 19:52:19 +0200 Subject: [PATCH] Move common bridging code Since we'll want to be bridging from multiple class generators, move the common bridging code into a common interface. JIRA: MDSAL-443 Change-Id: I1aa7d70ae302d737bb960c06629da5ffe0123fc0 Signed-off-by: Robert Varga --- .../dom/codec/impl/ClassGeneratorBridge.java | 44 +++++++++++++++---- .../codec/impl/CodecDataObjectGenerator.java | 35 ++------------- 2 files changed, 38 insertions(+), 41 deletions(-) diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ClassGeneratorBridge.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ClassGeneratorBridge.java index cc6dcca7d7..d5791d7534 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ClassGeneratorBridge.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ClassGeneratorBridge.java @@ -10,8 +10,10 @@ package org.opendaylight.mdsal.binding.dom.codec.impl; import static com.google.common.base.Verify.verifyNotNull; import com.google.common.annotations.Beta; +import com.google.common.base.Supplier; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; +import org.opendaylight.mdsal.binding.dom.codec.loader.CodecClassLoader.ClassGenerator; /** * Bridge for initializing generated instance constants during class loading time. This class is public only due to @@ -19,21 +21,45 @@ import org.eclipse.jdt.annotation.Nullable; */ @Beta public final class ClassGeneratorBridge { - interface BridgeProvider { - + interface BridgeProvider extends ClassGenerator { + @Override + default Class customizeLoading(final @NonNull Supplier> loader) { + final BridgeProvider prev = ClassGeneratorBridge.setup(this); + try { + final Class result = loader.get(); + + /* + * This a bit of magic to support NodeContextSupplier constants. These constants need to be resolved + * while we have the information needed to find them -- that information is being held in this instance + * and we leak it to a thread-local variable held by CodecDataObjectBridge. + * + * By default the JVM will defer class initialization to first use, which unfortunately is too late for + * us, and hence we need to force class to initialize. + */ + try { + Class.forName(result.getName(), true, result.getClassLoader()); + } catch (ClassNotFoundException e) { + throw new LinkageError("Failed to find newly-defined " + result, e); + } + + return result; + } finally { + ClassGeneratorBridge.tearDown(prev); + } + } } - interface LocalNameProvider extends BridgeProvider { + interface LocalNameProvider extends BridgeProvider { @NonNull String resolveLocalName(@NonNull String methodName); } - interface NodeContextSupplierProvider extends BridgeProvider { + interface NodeContextSupplierProvider extends BridgeProvider { @NonNull NodeContextSupplier resolveNodeContextSupplier(@NonNull String methodName); } - private static final ThreadLocal CURRENT_CUSTOMIZER = new ThreadLocal<>(); + private static final ThreadLocal> CURRENT_CUSTOMIZER = new ThreadLocal<>(); private ClassGeneratorBridge() { @@ -47,13 +73,13 @@ public final class ClassGeneratorBridge { return current(LocalNameProvider.class).resolveLocalName(methodName); } - static @Nullable BridgeProvider setup(final @NonNull BridgeProvider next) { - final BridgeProvider prev = CURRENT_CUSTOMIZER.get(); + static @Nullable BridgeProvider setup(final @NonNull BridgeProvider next) { + final BridgeProvider prev = CURRENT_CUSTOMIZER.get(); CURRENT_CUSTOMIZER.set(verifyNotNull(next)); return prev; } - static void tearDown(final @Nullable BridgeProvider prev) { + static void tearDown(final @Nullable BridgeProvider prev) { if (prev == null) { CURRENT_CUSTOMIZER.remove(); } else { @@ -61,7 +87,7 @@ public final class ClassGeneratorBridge { } } - private static @NonNull T current(final Class requested) { + private static > @NonNull T current(final Class requested) { return requested.cast(verifyNotNull(CURRENT_CUSTOMIZER.get(), "No customizer attached")); } } diff --git a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObjectGenerator.java b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObjectGenerator.java index fd62b1be79..a1e3c9d25a 100644 --- a/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObjectGenerator.java +++ b/binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/CodecDataObjectGenerator.java @@ -16,7 +16,6 @@ import static org.opendaylight.mdsal.binding.dom.codec.impl.ByteBuddyUtils.invok import static org.opendaylight.mdsal.binding.dom.codec.impl.ByteBuddyUtils.putField; import com.google.common.base.MoreObjects.ToStringHelper; -import com.google.common.base.Supplier; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import java.lang.reflect.Method; @@ -52,9 +51,7 @@ import net.bytebuddy.implementation.bytecode.member.MethodVariableAccess; import net.bytebuddy.jar.asm.Label; import net.bytebuddy.jar.asm.MethodVisitor; import net.bytebuddy.jar.asm.Opcodes; -import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; -import org.opendaylight.mdsal.binding.dom.codec.impl.ClassGeneratorBridge.BridgeProvider; import org.opendaylight.mdsal.binding.dom.codec.impl.ClassGeneratorBridge.LocalNameProvider; import org.opendaylight.mdsal.binding.dom.codec.impl.ClassGeneratorBridge.NodeContextSupplierProvider; import org.opendaylight.mdsal.binding.dom.codec.loader.CodecClassLoader; @@ -157,10 +154,10 @@ import org.slf4j.LoggerFactory; * This strategy works due to close cooperation with the target ClassLoader, as the entire code generation and loading * block runs with the class loading lock for this FQCN and the reference is not leaked until the process completes. */ -abstract class CodecDataObjectGenerator> implements ClassGenerator, BridgeProvider { +abstract class CodecDataObjectGenerator> implements ClassGenerator { // Not reusable defintion: we can inline NodeContextSuppliers without a problem private static final class Fixed> extends CodecDataObjectGenerator - implements NodeContextSupplierProvider { + implements NodeContextSupplierProvider { private final ImmutableMap properties; Fixed(final Builder template, final ImmutableMap properties, @@ -198,7 +195,7 @@ abstract class CodecDataObjectGenerator> implements // Reusable definition: we have to rely on context lookups private static final class Reusable> extends CodecDataObjectGenerator - implements LocalNameProvider { + implements LocalNameProvider { private final ImmutableMap simpleProperties; private final Map> daoProperties; @@ -341,32 +338,6 @@ abstract class CodecDataObjectGenerator> implements .make()); } - @Override - public Class customizeLoading(final @NonNull Supplier> loader) { - final BridgeProvider prev = ClassGeneratorBridge.setup(this); - try { - final Class result = loader.get(); - - /* - * This a bit of magic to support NodeContextSupplier constants. These constants need to be resolved - * while we have the information needed to find them -- that information is being held in this instance - * and we leak it to a thread-local variable held by CodecDataObjectBridge. - * - * By default the JVM will defer class initialization to first use, which unfortunately is too late for - * us, and hence we need to force class to initialize. - */ - try { - Class.forName(result.getName(), true, result.getClassLoader()); - } catch (ClassNotFoundException e) { - throw new LinkageError("Failed to find newly-defined " + result, e); - } - - return result; - } finally { - ClassGeneratorBridge.tearDown(prev); - } - } - abstract Builder generateGetters(Builder builder); abstract ArrayList getterMethods(); -- 2.36.6