Move BindingReflections to mdsal-binding-spec-util
[mdsal.git] / binding / mdsal-binding-dom-codec / src / main / java / org / opendaylight / mdsal / binding / dom / codec / gen / impl / AbstractStreamWriterGenerator.java
index a54a83513b3dc1ede2c45edf97ec6cce02894430..51ef4320390cbce3c5ae8d6c5d1738e92d54b9a2 100644 (file)
@@ -7,8 +7,9 @@
  */
 package org.opendaylight.mdsal.binding.dom.codec.gen.impl;
 
-import com.google.common.base.Preconditions;
-import com.google.common.base.Supplier;
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
@@ -27,16 +28,17 @@ import org.opendaylight.mdsal.binding.generator.util.BindingRuntimeContext;
 import org.opendaylight.mdsal.binding.generator.util.JavassistUtils;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.model.util.Types;
+import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
 import org.opendaylight.yangtools.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.DataObjectSerializerImplementation;
 import org.opendaylight.yangtools.yang.binding.DataObjectSerializerRegistry;
-import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
 import org.slf4j.Logger;
@@ -72,14 +74,20 @@ abstract class AbstractStreamWriterGenerator extends AbstractGenerator implement
     }
 
     protected AbstractStreamWriterGenerator(final JavassistUtils utils) {
-        this.javassist = Preconditions.checkNotNull(utils,"JavassistUtils instance is required.");
-        this.serializeArguments = new CtClass[] {
-                javassist.asCtClass(DataObjectSerializerRegistry.class),
-                javassist.asCtClass(DataObject.class),
-                javassist.asCtClass(BindingStreamEventWriter.class),
-        };
-        javassist.appendClassLoaderIfMissing(DataObjectSerializerPrototype.class.getClassLoader());
-        this.implementations = CacheBuilder.newBuilder().weakKeys().build(new SerializerImplementationLoader());
+        this.javassist = requireNonNull(utils, "JavassistUtils instance is required.");
+        synchronized (javassist) {
+            this.serializeArguments = new CtClass[] {
+                    javassist.asCtClass(DataObjectSerializerRegistry.class),
+                    javassist.asCtClass(DataObject.class),
+                    javassist.asCtClass(BindingStreamEventWriter.class),
+            };
+            javassist.appendClassLoaderIfMissing(DataObjectSerializerPrototype.class.getClassLoader());
+        }
+        this.implementations = CacheBuilder.newBuilder()
+                .removalListener(notification -> LOG.debug("onRemoval: cause={}, wasEvicted={}",
+                        notification.getCause(), notification.wasEvicted()))
+                .weakKeys().build(new SerializerImplementationLoader());
+        LOG.debug("AbstractStreamWriterGenerator constructor, new instance: {}", this);
     }
 
     @Override
@@ -90,11 +98,12 @@ abstract class AbstractStreamWriterGenerator extends AbstractGenerator implement
     @Override
     public final void onBindingRuntimeContextUpdated(final BindingRuntimeContext runtime) {
         this.context = runtime;
+        LOG.debug("onBindingRuntimeContextUpdated() : {}", runtime);
     }
 
     @Override
     protected final String loadSerializerFor(final Class<?> cls) {
-        return implementations.getUnchecked(cls).getClass().getName();
+        return getSerializer(cls).getClass().getName();
     }
 
     private final class SerializerImplementationLoader
@@ -110,8 +119,8 @@ abstract class AbstractStreamWriterGenerator extends AbstractGenerator implement
         @Override
         @SuppressWarnings("unchecked")
         public DataObjectSerializerImplementation load(final Class<?> type) throws Exception {
-            Preconditions.checkArgument(BindingReflections.isBindingClass(type));
-            Preconditions.checkArgument(DataContainer.class.isAssignableFrom(type),
+            checkArgument(BindingReflections.isBindingClass(type));
+            checkArgument(DataContainer.class.isAssignableFrom(type),
                 "DataContainer is not assingnable from %s from classloader %s.", type, type.getClassLoader());
 
             final String serializerName = getSerializerName(type);
@@ -126,7 +135,7 @@ abstract class AbstractStreamWriterGenerator extends AbstractGenerator implement
 
             final DataObjectSerializerImplementation obj =
                     (DataObjectSerializerImplementation) cls.getDeclaredMethod(GETINSTANCE_METHOD_NAME).invoke(null);
-            LOG.debug("Loaded serializer {} for class {}", obj, type);
+            LOG.trace("Loaded serializer {} for class {}", obj, type);
             return obj;
         }
 
@@ -134,6 +143,8 @@ abstract class AbstractStreamWriterGenerator extends AbstractGenerator implement
                 final String serializerName) throws CannotCompileException, IllegalAccessException,
                 IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException,
                 NoSuchFieldException {
+            LOG.debug("generateSerializer() due to Cache miss: typeName={}, typeClassLoader={}, serializerName={}",
+                    type.getTypeName(), type.getClassLoader(), serializerName);
             final DataObjectSerializerSource source = generateEmitterSource(type, serializerName);
             final CtClass poolClass = generateEmitter0(type, source, serializerName);
             @SuppressWarnings("unchecked")
@@ -163,9 +174,9 @@ abstract class AbstractStreamWriterGenerator extends AbstractGenerator implement
     private DataObjectSerializerSource generateEmitterSource(final Class<?> type, final String serializerName) {
         Types.typeForClass(type);
         javassist.appendClassLoaderIfMissing(type.getClassLoader());
-        final Entry<GeneratedType, Object> typeWithSchema = context.getTypeWithSchema(type);
+        final Entry<GeneratedType, WithStatus> typeWithSchema = context.getTypeWithSchema(type);
         final GeneratedType generatedType = typeWithSchema.getKey();
-        final Object schema = typeWithSchema.getValue();
+        final WithStatus schema = typeWithSchema.getValue();
 
         final DataObjectSerializerSource source;
         if (schema instanceof ContainerSchemaNode) {
@@ -201,8 +212,8 @@ abstract class AbstractStreamWriterGenerator extends AbstractGenerator implement
          * care of this before calling instantiatePrototype(), as that will call our customizer with the lock held,
          * hence any code generation will end up being blocked on the javassist lock.
          */
-        final String body = ClassLoaderUtils.withClassLoader(type.getClassLoader(),
-            (Supplier<String>) () -> source.getSerializerBody().toString());
+        final String body = ClassLoaderUtils.getWithClassLoader(type.getClassLoader(), source::getSerializerBody)
+                .toString();
 
         try {
             product = javassist.instantiatePrototype(DataObjectSerializerPrototype.class.getName(), serializerName,
@@ -221,7 +232,7 @@ abstract class AbstractStreamWriterGenerator extends AbstractGenerator implement
                     // The prototype is not visible, so we need to take care of that
                     cls.setModifiers(Modifier.setPublic(cls.getModifiers()));
                 });
-        } catch (final NotFoundException e) {
+        } catch (NotFoundException | CannotCompileException e) {
             LOG.error("Failed to instatiate serializer {}", source, e);
             throw new LinkageError("Unexpected instantation problem: serializer prototype not found", e);
         }