2 * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.mdsal.binding.dom.codec.impl;
10 import static com.google.common.base.Verify.verifyNotNull;
12 import com.google.common.annotations.Beta;
13 import com.google.common.base.Supplier;
14 import org.eclipse.jdt.annotation.NonNull;
15 import org.eclipse.jdt.annotation.Nullable;
16 import org.opendaylight.mdsal.binding.dom.codec.loader.CodecClassLoader.ClassGenerator;
19 * Bridge for initializing generated instance constants during class loading time. This class is public only due to
20 * implementation restrictions and can change at any time.
23 public final class ClassGeneratorBridge {
24 interface BridgeProvider<T> extends ClassGenerator<T> {
26 default Class<T> customizeLoading(final @NonNull Supplier<Class<T>> loader) {
27 final BridgeProvider<?> prev = ClassGeneratorBridge.setup(this);
29 final Class<T> result = loader.get();
32 * This a bit of magic to support NodeContextSupplier constants. These constants need to be resolved
33 * while we have the information needed to find them -- that information is being held in this instance
34 * and we leak it to a thread-local variable held by CodecDataObjectBridge.
36 * By default the JVM will defer class initialization to first use, which unfortunately is too late for
37 * us, and hence we need to force class to initialize.
40 Class.forName(result.getName(), true, result.getClassLoader());
41 } catch (ClassNotFoundException e) {
42 throw new LinkageError("Failed to find newly-defined " + result, e);
47 ClassGeneratorBridge.tearDown(prev);
52 interface LocalNameProvider<T> extends BridgeProvider<T> {
54 @NonNull String resolveLocalName(@NonNull String methodName);
57 interface NodeContextSupplierProvider<T> extends BridgeProvider<T> {
59 @NonNull NodeContextSupplier resolveNodeContextSupplier(@NonNull String methodName);
62 private static final ThreadLocal<BridgeProvider<?>> CURRENT_CUSTOMIZER = new ThreadLocal<>();
64 private ClassGeneratorBridge() {
68 public static @NonNull NodeContextSupplier resolveNodeContextSupplier(final @NonNull String methodName) {
69 return current(NodeContextSupplierProvider.class).resolveNodeContextSupplier(methodName);
72 public static @NonNull String resolveLocalName(final @NonNull String methodName) {
73 return current(LocalNameProvider.class).resolveLocalName(methodName);
76 static @Nullable BridgeProvider<?> setup(final @NonNull BridgeProvider<?> next) {
77 final BridgeProvider<?> prev = CURRENT_CUSTOMIZER.get();
78 CURRENT_CUSTOMIZER.set(verifyNotNull(next));
82 static void tearDown(final @Nullable BridgeProvider<?> prev) {
84 CURRENT_CUSTOMIZER.remove();
86 CURRENT_CUSTOMIZER.set(prev);
90 private static <T extends BridgeProvider<?>> @NonNull T current(final Class<T> requested) {
91 return requested.cast(verifyNotNull(CURRENT_CUSTOMIZER.get(), "No customizer attached"));