Enable spotbugs in mdsal-binding-dom-codec 09/76909/2
authorRobert Varga <robert.varga@pantheon.tech>
Thu, 11 Oct 2018 19:13:53 +0000 (21:13 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Thu, 11 Oct 2018 19:28:52 +0000 (21:28 +0200)
This fixes up the issues reported and flips enforcement to on.

Change-Id: I7e5b5c20a8b9f1ce3de42aac512ac3b31779821f
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-dom-codec/pom.xml
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/gen/impl/AbstractStreamWriterGenerator.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/BindingNormalizedNodeCodecRegistry.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/ChoiceNodeCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/LazyDataObject.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/MissingSchemaForClassException.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/NotificationCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/util/AbstractBindingLazyContainerNode.java

index 27c29d04e4cbc61f87cd198003dc99f998f66efb..bfd16493d8a5febc6531a2ff2e88b8c6769c4ab8 100644 (file)
                     <propertyExpansion>checkstyle.violationSeverity=error</propertyExpansion>
                 </configuration>
             </plugin>
+            <plugin>
+                <groupId>com.github.spotbugs</groupId>
+                <artifactId>spotbugs-maven-plugin</artifactId>
+                <configuration>
+                    <failOnError>true</failOnError>
+                </configuration>
+            </plugin>
         </plugins>
     </build>
 </project>
index 8e34080d43b0e36d7033563a5c66219200699474..847260010d7e7dcf8cf76d3e6bd01e9a97da6745 100644 (file)
@@ -15,6 +15,8 @@ import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Map.Entry;
 import javassist.CannotCompileException;
 import javassist.CtClass;
@@ -49,28 +51,38 @@ abstract class AbstractStreamWriterGenerator extends AbstractGenerator implement
 
     protected static final String SERIALIZE_METHOD_NAME = "serialize";
     protected static final AugmentableDispatchSerializer AUGMENTABLE = new AugmentableDispatchSerializer();
-    private static final Field FIELD_MODIFIERS;
+    private static final Field FIELD_MODIFIERS = getModifiersField();
 
     private final LoadingCache<Class<?>, DataObjectSerializerImplementation> implementations;
     private final CtClass[] serializeArguments;
     private final JavassistUtils javassist;
     private BindingRuntimeContext context;
 
-    static {
+    private static Field getModifiersField() {
         /*
          * Cache reflection access to field modifiers field. We need this to set
          * fix the static declared fields to final once we initialize them. If we
          * cannot get access, that's fine, too.
          */
-        Field field = null;
+        final Field field;
         try {
             field = Field.class.getDeclaredField("modifiers");
-            field.setAccessible(true);
         } catch (NoSuchFieldException | SecurityException e) {
-            LOG.warn("Could not get Field modifiers field, serializers run at decreased efficiency", e);
+            LOG.warn("Could not get modifiers field, serializers run at decreased efficiency", e);
+            return null;
         }
 
-        FIELD_MODIFIERS = field;
+        try {
+            AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+                field.setAccessible(true);
+                return null;
+            });
+        } catch (SecurityException e) {
+            LOG.warn("Could not get access to modifiers field, serializers run at decreased efficiency", e);
+            return null;
+        }
+
+        return field;
     }
 
     protected AbstractStreamWriterGenerator(final JavassistUtils utils) {
index 16f2d971b2e92146510ea2f49bd5fc9b8ae19587..9a72ce2e7d85ec362bcb9ad0718a58b6ea8138d5 100644 (file)
@@ -7,7 +7,10 @@
  */
 package org.opendaylight.mdsal.binding.dom.codec.impl;
 
-import com.google.common.base.Preconditions;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+import static java.util.Objects.requireNonNull;
+
 import com.google.common.collect.ImmutableMap;
 import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
@@ -75,11 +78,11 @@ final class BindingCodecContext implements CodecContextFactory, BindingCodecTree
     private final SchemaRootCodecContext<?> root;
 
     BindingCodecContext(final BindingRuntimeContext context, final BindingNormalizedNodeCodecRegistry registry) {
-        this.context = Preconditions.checkNotNull(context, "Binding Runtime Context is required.");
+        this.context = requireNonNull(context, "Binding Runtime Context is required.");
         this.root = SchemaRootCodecContext.create(this);
         this.identityCodec = new IdentityCodec(context);
         this.instanceIdentifierCodec = new InstanceIdentifierCodec(this);
-        this.registry = Preconditions.checkNotNull(registry);
+        this.registry = requireNonNull(registry);
     }
 
     @Override
@@ -128,7 +131,7 @@ final class BindingCodecContext implements CodecContextFactory, BindingCodecTree
         DataContainerCodecContext<?,?> currentNode = root;
         for (final InstanceIdentifier.PathArgument bindingArg : binding.getPathArguments()) {
             currentNode = currentNode.bindingPathArgumentChild(bindingArg, builder);
-            Preconditions.checkArgument(currentNode != null, "Supplied Instance Identifier %s is not valid.", binding);
+            checkArgument(currentNode != null, "Supplied Instance Identifier %s is not valid.", binding);
         }
         return currentNode;
     }
@@ -151,9 +154,9 @@ final class BindingCodecContext implements CodecContextFactory, BindingCodecTree
         ListNodeCodecContext<?> currentList = null;
 
         for (final YangInstanceIdentifier.PathArgument domArg : dom.getPathArguments()) {
-            Preconditions.checkArgument(currentNode instanceof DataContainerCodecContext<?,?>,
+            checkArgument(currentNode instanceof DataContainerCodecContext,
                 "Unexpected child of non-container node %s", currentNode);
-            final DataContainerCodecContext<?,?> previous = (DataContainerCodecContext<?,?>) currentNode;
+            final DataContainerCodecContext<?,?> previous = (DataContainerCodecContext<?, ?>) currentNode;
             final NodeCodecContext<?> nextNode = previous.yangPathArgumentChild(domArg);
 
             /*
@@ -165,7 +168,7 @@ final class BindingCodecContext implements CodecContextFactory, BindingCodecTree
              * Identifier as Item or IdentifiableItem
              */
             if (currentList != null) {
-                Preconditions.checkArgument(currentList == nextNode,
+                checkArgument(currentList == nextNode,
                         "List should be referenced two times in YANG Instance Identifier %s", dom);
 
                 // We entered list, so now we have all information to emit
@@ -183,13 +186,13 @@ final class BindingCodecContext implements CodecContextFactory, BindingCodecTree
                 // We do not add path argument for choice, since
                 // it is not supported by binding instance identifier.
                 currentNode = nextNode;
-            } else if (nextNode instanceof DataContainerCodecContext<?,?>) {
+            } else if (nextNode instanceof DataContainerCodecContext) {
                 if (bindingArguments != null) {
-                    bindingArguments.add(((DataContainerCodecContext<?,?>) nextNode).getBindingPathArgument(domArg));
+                    bindingArguments.add(((DataContainerCodecContext<?, ?>) nextNode).getBindingPathArgument(domArg));
                 }
                 currentNode = nextNode;
             } else if (nextNode instanceof LeafNodeCodecContext) {
-                LOG.debug("Instance identifier referencing a leaf is not representable (%s)", dom);
+                LOG.debug("Instance identifier referencing a leaf is not representable ({})", dom);
                 return null;
             }
         }
@@ -197,11 +200,11 @@ final class BindingCodecContext implements CodecContextFactory, BindingCodecTree
         // Algorithm ended in list as whole representation
         // we sill need to emit identifier for list
         if (currentNode instanceof ChoiceNodeCodecContext) {
-            LOG.debug("Instance identifier targeting a choice is not representable (%s)", dom);
+            LOG.debug("Instance identifier targeting a choice is not representable ({})", dom);
             return null;
         }
         if (currentNode instanceof CaseNodeCodecContext) {
-            LOG.debug("Instance identifier targeting a case is not representable (%s)", dom);
+            LOG.debug("Instance identifier targeting a case is not representable ({})", dom);
             return null;
         }
 
@@ -282,8 +285,7 @@ final class BindingCodecContext implements CodecContextFactory, BindingCodecTree
     }
 
     private Codec<Object, Object> getCodec(final Class<?> valueType, final DataSchemaNode schema) {
-        Preconditions.checkArgument(schema instanceof TypedDataSchemaNode, "Unsupported leaf node type %s", schema);
-
+        checkArgument(schema instanceof TypedDataSchemaNode, "Unsupported leaf node type %s", schema);
         return getCodec(valueType, ((TypedDataSchemaNode)schema).getType());
     }
 
@@ -323,7 +325,7 @@ final class BindingCodecContext implements CodecContextFactory, BindingCodecTree
         } else if (typeDef instanceof LeafrefTypeDefinition) {
             final Entry<GeneratedType, WithStatus> typeWithSchema = context.getTypeWithSchema(valueType);
             final WithStatus schema = typeWithSchema.getValue();
-            Preconditions.checkState(schema instanceof TypeDefinition<?>);
+            checkState(schema instanceof TypeDefinition);
             return getCodec(valueType, (TypeDefinition<?>) schema);
         }
         return ValueTypeCodec.getCodecFor(valueType, typeDef);
index 7829d83a151233ff16af5485be5802e6ee51fa9d..37c16b45b880c170e8181026228c0b4246c05086 100644 (file)
@@ -9,10 +9,10 @@ package org.opendaylight.mdsal.binding.dom.codec.impl;
 
 import static java.util.Objects.requireNonNull;
 
-import com.google.common.base.Preconditions;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.io.IOException;
 import java.util.AbstractMap.SimpleEntry;
 import java.util.ArrayList;
@@ -73,7 +73,7 @@ public class BindingNormalizedNodeCodecRegistry implements DataObjectSerializerR
     private volatile BindingCodecContext codecContext;
 
     public BindingNormalizedNodeCodecRegistry(final DataObjectSerializerGenerator generator) {
-        this.generator = Preconditions.checkNotNull(generator);
+        this.generator = requireNonNull(generator);
         this.serializers = CacheBuilder.newBuilder().weakKeys().build(new GeneratorLoader());
     }
 
@@ -123,6 +123,7 @@ public class BindingNormalizedNodeCodecRegistry implements DataObjectSerializerR
     }
 
     @Override
+    @SuppressFBWarnings("BC_UNCONFIRMED_CAST")
     public ContainerNode toNormalizedNodeNotification(final Notification data) {
         // FIXME: Should the cast to DataObject be necessary?
         return serializeDataObject((DataObject) data,
index 0d9699e68621561976357c856f2bd476bbfbc64f..76853ed5729ab6fcf2848af874431f13ca4cb279 100644 (file)
@@ -7,7 +7,8 @@
  */
 package org.opendaylight.mdsal.binding.dom.codec.impl;
 
-import com.google.common.base.Preconditions;
+import static com.google.common.base.Preconditions.checkArgument;
+
 import com.google.common.collect.ImmutableListMultimap;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableMap.Builder;
@@ -35,7 +36,6 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
 import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
@@ -215,7 +215,7 @@ final class ChoiceNodeCodecContext<D extends DataObject> extends DataContainerCo
             return DataContainerCodecPrototype.from(childClass, childSchema.get(), factory());
         }
 
-        LOG.debug("Supplied class %s is not valid case in schema %s", childClass, getSchema());
+        LOG.debug("Supplied class {} is not valid case in schema {}", childClass, getSchema());
         return null;
     }
 
@@ -228,16 +228,15 @@ final class ChoiceNodeCodecContext<D extends DataObject> extends DataContainerCo
             cazeProto = byYangCaseChild.get(arg);
         }
 
-        return childNonNull(cazeProto, arg,"Argument %s is not valid child of %s", arg, getSchema()).get()
+        return childNonNull(cazeProto, arg, "Argument %s is not valid child of %s", arg, getSchema()).get()
                 .yangPathArgumentChild(arg);
     }
 
     @SuppressWarnings("unchecked")
     @Override
     public D deserialize(final NormalizedNode<?, ?> data) {
-        Preconditions.checkArgument(data instanceof ChoiceNode);
-        final NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> casted =
-                (NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>>) data;
+        checkArgument(data instanceof ChoiceNode);
+        final ChoiceNode casted = (ChoiceNode) data;
         final NormalizedNode<?, ?> first = Iterables.getFirst(casted.getValue(), null);
 
         if (first == null) {
@@ -255,7 +254,7 @@ final class ChoiceNodeCodecContext<D extends DataObject> extends DataContainerCo
 
     @Override
     public PathArgument deserializePathArgument(final YangInstanceIdentifier.PathArgument arg) {
-        Preconditions.checkArgument(getDomPathArgument().equals(arg));
+        checkArgument(getDomPathArgument().equals(arg));
         return null;
     }
 
index 3b615f25b0c199811ad013ba5de89e50b19e3487..88731f31cddc14ceeb1a9cb5ea4b7c5a92f60a47 100644 (file)
@@ -12,6 +12,7 @@ import static com.google.common.base.Preconditions.checkArgument;
 import com.google.common.base.Throwables;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSortedMap;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
@@ -130,6 +131,7 @@ abstract class DataObjectCodecContext<D extends DataObject, T extends DataNodeCo
         }
     }
 
+    @SuppressFBWarnings("RV_RETURN_VALUE_OF_PUTIFABSENT_IGNORED")
     private void reloadAllAugmentations() {
         for (final Entry<AugmentationIdentifier, Type> augment : possibleAugmentations.entrySet()) {
             final DataContainerCodecPrototype<?> augProto = getAugmentationPrototype(augment.getValue());
index 0c7a16586c9e566d43e07833eda750cbdbde67d3..a535eab2ee249d2c55db86eafa9d57c135a9c9ec 100644 (file)
@@ -7,9 +7,11 @@
  */
 package org.opendaylight.mdsal.binding.dom.codec.impl;
 
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
 import com.google.common.base.MoreObjects;
 import com.google.common.base.MoreObjects.ToStringHelper;
-import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMap;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.InvocationTargetException;
@@ -51,8 +53,8 @@ class LazyDataObject<D extends DataObject> implements InvocationHandler, Augment
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
     LazyDataObject(final DataObjectCodecContext<D,?> ctx, final NormalizedNodeContainer data) {
-        this.context = Preconditions.checkNotNull(ctx, "Context must not be null");
-        this.data = Preconditions.checkNotNull(data, "Data must not be null");
+        this.context = requireNonNull(ctx, "Context must not be null");
+        this.data = requireNonNull(data, "Data must not be null");
     }
 
     @Override
@@ -146,12 +148,13 @@ class LazyDataObject<D extends DataObject> implements InvocationHandler, Augment
         Object cached = cachedData.get(method);
         if (cached == null) {
             final Object readedValue = context.getBindingChildValue(method, data);
-            if (readedValue == null) {
-                cached = NULL_VALUE;
-            } else {
-                cached = readedValue;
+            cached = readedValue == null ? NULL_VALUE : readedValue;
+
+            final Object raced = cachedData.putIfAbsent(method, cached);
+            if (raced != null) {
+                // Load/store raced, we should return the stored value
+                cached = raced;
             }
-            cachedData.putIfAbsent(method, cached);
         }
 
         return cached == NULL_VALUE ? null : cached;
@@ -174,14 +177,14 @@ class LazyDataObject<D extends DataObject> implements InvocationHandler, Augment
 
     @Override
     public Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAugmentations(final Object obj) {
-        Preconditions.checkArgument(this == Proxy.getInvocationHandler(obj),
+        checkArgument(this == Proxy.getInvocationHandler(obj),
                 "Supplied object is not associated with this proxy handler");
 
         return getAugmentationsImpl();
     }
 
     private Object getAugmentationImpl(final Class<?> cls) {
-        Preconditions.checkNotNull(cls, "Supplied augmentation must not be null.");
+        requireNonNull(cls, "Supplied augmentation must not be null.");
 
         final ImmutableMap<Class<? extends Augmentation<?>>, Augmentation<?>> aug = cachedAugmentations;
         if (aug != null) {
index 87a57819458147ad0f2c384575b73beb78c98743..c2f0e676c6760bb6311da76c70e70ff2ebc70c8d 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.mdsal.binding.dom.codec.impl;
 
 import com.google.common.base.Preconditions;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import org.opendaylight.mdsal.binding.generator.util.BindingRuntimeContext;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 
@@ -21,6 +22,7 @@ public final class MissingSchemaForClassException extends MissingSchemaException
 
     private static final long serialVersionUID = 1L;
 
+    @SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED")
     private final transient Class<?> bindingClass;
 
     private MissingSchemaForClassException(final Class<?> clz) {
index 61d7eecf4137f3b607bbc9bf8c2471d94569b9e5..514fead67ee2f4099f4a52bb328d141721235b31 100644 (file)
@@ -7,12 +7,12 @@
  */
 package org.opendaylight.mdsal.binding.dom.codec.impl;
 
-import com.google.common.base.Preconditions;
+import static com.google.common.base.Preconditions.checkState;
+
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.Notification;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
 
 final class NotificationCodecContext<D extends DataObject & Notification>
@@ -25,8 +25,8 @@ final class NotificationCodecContext<D extends DataObject & Notification>
 
     @Override
     public D deserialize(final NormalizedNode<?, ?> data) {
-        Preconditions.checkState(data instanceof ContainerNode);
-        return createBindingProxy((NormalizedNodeContainer<?, ?, ?>) data);
+        checkState(data instanceof ContainerNode);
+        return createBindingProxy((ContainerNode) data);
     }
 
     @Override
index 0527de2b0e94a4115ff4207fd4f83f674cf4c846..da6ab8cdb358e8ca6ced01cb23bfe2a0c84f23ff 100644 (file)
@@ -104,7 +104,7 @@ public abstract class AbstractBindingLazyContainerNode<T extends DataObject, C>
             return false;
         }
         final ContainerNode other = (ContainerNode) obj;
-        return delegate().equals(obj);
+        return delegate().equals(other);
     }
 
     @Override