BUG-6028: check value types for encapsulation 03/52203/1
authorRobert Varga <rovarga@cisco.com>
Wed, 8 Jun 2016 17:09:17 +0000 (19:09 +0200)
committerIvan Hrasko <ivan.hrasko@pantheon.tech>
Thu, 23 Feb 2017 09:48:07 +0000 (09:48 +0000)
This is a fast check to see if the argument matches expected
value class. If it does not it does not make sense to invoke
the serializer, as it will fail.

Change-Id: I4ca556fea057f2188fa1c34d303467565af38d5c
Signed-off-by: Robert Varga <rovarga@cisco.com>
(cherry picked from commit a6d0735732b202f40bd37f7ae291c8a4af9e3ccf)

binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/EncapsulatedValueCodec.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/UnionValueOptionContext.java

index 3de5085c1d7c9f8decb1b407e91453781f6957a0..03414a0e8e673be97bc2d1afba18e082d8cc365c 100644 (file)
@@ -28,25 +28,41 @@ final class EncapsulatedValueCodec extends ReflectionBasedCodec implements Schem
     private static final MethodType OBJ_METHOD = MethodType.methodType(Object.class, Object.class);
     private final MethodHandle constructor;
     private final MethodHandle getter;
+    private final Class<?> valueType;
 
-    private EncapsulatedValueCodec(final Class<?> typeClz, final MethodHandle constructor, final MethodHandle getter) {
+    private EncapsulatedValueCodec(final Class<?> typeClz, final MethodHandle constructor, final MethodHandle getter,
+            final Class<?> valueType) {
         super(typeClz);
         this.constructor = Preconditions.checkNotNull(constructor);
         this.getter = Preconditions.checkNotNull(getter);
+        this.valueType = Preconditions.checkNotNull(valueType);
     }
 
     static Callable<EncapsulatedValueCodec> loader(final Class<?> typeClz) {
         return new Callable<EncapsulatedValueCodec>() {
             @Override
-            public EncapsulatedValueCodec call() throws Exception {
+            public EncapsulatedValueCodec call() throws IllegalAccessException, NoSuchMethodException, SecurityException {
                 final Method m = typeClz.getMethod("getValue");
                 final MethodHandle getter = LOOKUP.unreflect(m).asType(OBJ_METHOD);
-                final MethodHandle constructor = LOOKUP.findConstructor(typeClz, MethodType.methodType(void.class, m.getReturnType())).asType(OBJ_METHOD);
-                return new EncapsulatedValueCodec(typeClz, constructor, getter);
+                final Class<?> valueType = m.getReturnType();
+
+                final MethodHandle constructor = LOOKUP.findConstructor(typeClz,
+                    MethodType.methodType(void.class, valueType)).asType(OBJ_METHOD);
+                return new EncapsulatedValueCodec(typeClz, constructor, getter, valueType);
             }
         };
     }
 
+    /**
+     * Quick check if a value object has a chance to deserialize using {@link #deserialize(Object)}.
+     *
+     * @param value Value to be checked
+     * @return True if the value can be encapsulated
+     */
+    boolean canAcceptObject(final Object value) {
+        return valueType.isInstance(value);
+    }
+
     @Override
     public Object deserialize(final Object input) {
         try {
index 52dd88e33d31d0f9b77c5ae5956847827509a6a9..06130fb824b773ab3ca53daecc3d5a6365bcefb5 100644 (file)
@@ -51,8 +51,12 @@ final class UnionValueOptionContext {
     }
 
     Object deserializeUnion(final Object input) {
-        final Object value;
+        // Side-step potential exceptions by checking the type if it is available
+        if (codec instanceof EncapsulatedValueCodec && !((EncapsulatedValueCodec) codec).canAcceptObject(input)) {
+            return null;
+        }
 
+        final Object value;
         try {
             value = codec.deserialize(input);
         } catch (Exception e) {