You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by na...@apache.org on 2015/12/05 23:52:55 UTC

jclouds git commit: JCLOUDS-1044 fix handling NULL JsonTokens in adapters under NullFilteringTypeAdapterFactories class

Repository: jclouds
Updated Branches:
  refs/heads/master 4d899caca -> 0fb1b459a


JCLOUDS-1044 fix handling NULL JsonTokens in adapters under NullFilteringTypeAdapterFactories class


Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/0fb1b459
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/0fb1b459
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/0fb1b459

Branch: refs/heads/master
Commit: 0fb1b459a607f21f6a8ebd7492879d02553c4b88
Parents: 4d899ca
Author: Josef Cacek <jc...@redhat.com>
Authored: Wed Dec 2 23:50:15 2015 +0100
Committer: Ignasi Barrera <na...@apache.org>
Committed: Sat Dec 5 22:45:24 2015 +0100

----------------------------------------------------------------------
 .../jclouds/chef/config/ChefParserModule.java   | 59 ++++----------------
 .../chef/config/ChefParserModuleTest.java       | 24 ++++++++
 .../NullFilteringTypeAdapterFactories.java      | 11 +++-
 .../NullFilteringTypeAdapterFactoriesTest.java  | 21 +++++++
 4 files changed, 67 insertions(+), 48 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/0fb1b459/apis/chef/src/main/java/org/jclouds/chef/config/ChefParserModule.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/config/ChefParserModule.java b/apis/chef/src/main/java/org/jclouds/chef/config/ChefParserModule.java
index 3ebe2ea..da4084d 100644
--- a/apis/chef/src/main/java/org/jclouds/chef/config/ChefParserModule.java
+++ b/apis/chef/src/main/java/org/jclouds/chef/config/ChefParserModule.java
@@ -16,8 +16,6 @@
  */
 package org.jclouds.chef.config;
 
-import static com.google.common.base.Objects.equal;
-import static com.google.common.base.Objects.toStringHelper;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
 
@@ -39,11 +37,11 @@ import org.jclouds.crypto.Crypto;
 import org.jclouds.crypto.Pems;
 import org.jclouds.json.config.GsonModule.DateAdapter;
 import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
+import org.jclouds.json.internal.NullFilteringTypeAdapterFactories;
 import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.MapTypeAdapterFactory;
 import org.jclouds.json.internal.NullHackJsonLiteralAdapter;
 
 import com.google.common.base.Charsets;
-import com.google.common.base.Objects;
 import com.google.common.base.Throwables;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Maps;
@@ -57,7 +55,7 @@ import com.google.gson.JsonSyntaxException;
 import com.google.gson.TypeAdapter;
 import com.google.gson.internal.JsonReaderInternalAccess;
 import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonWriter;
+import com.google.gson.stream.JsonToken;
 import com.google.inject.AbstractModule;
 import com.google.inject.ImplementedBy;
 import com.google.inject.Provides;
@@ -205,33 +203,19 @@ public class ChefParserModule extends AbstractModule {
       private String id;
    }
 
-   // The NullFilteringTypeAdapterFactories.MapTypeAdapter class is final. Do
-   // the same logic here
-   private static final class KeepLastRepeatedKeyMapTypeAdapter<K, V> extends TypeAdapter<Map<K, V>> {
-
-      protected final TypeAdapter<K> keyAdapter;
-      protected final TypeAdapter<V> valueAdapter;
+   private static final class KeepLastRepeatedKeyMapTypeAdapter<K, V>
+         extends NullFilteringTypeAdapterFactories.MapTypeAdapter<K, V> {
 
       protected KeepLastRepeatedKeyMapTypeAdapter(TypeAdapter<K> keyAdapter, TypeAdapter<V> valueAdapter) {
-         this.keyAdapter = keyAdapter;
-         this.valueAdapter = valueAdapter;
-         nullSafe();
-      }
-
-      public void write(JsonWriter out, Map<K, V> value) throws IOException {
-         if (value == null) {
-            out.nullValue();
-            return;
-         }
-         out.beginObject();
-         for (Map.Entry<K, V> element : value.entrySet()) {
-            out.name(String.valueOf(element.getKey()));
-            valueAdapter.write(out, element.getValue());
-         }
-         out.endObject();
+         super(keyAdapter, valueAdapter);
       }
 
+      @Override
       public Map<K, V> read(JsonReader in) throws IOException {
+         if (in.peek() == JsonToken.NULL) {
+            in.nextNull();
+            return null;
+         }
          Map<K, V> result = Maps.newHashMap();
          in.beginObject();
          while (in.hasNext()) {
@@ -239,33 +223,14 @@ public class ChefParserModule extends AbstractModule {
             K name = keyAdapter.read(in);
             V value = valueAdapter.read(in);
             if (value != null) {
-               // If there are repeated keys, overwrite them to only keep the last one
+               // If there are repeated keys, overwrite them to only keep the
+               // last one
                result.put(name, value);
             }
          }
          in.endObject();
          return ImmutableMap.copyOf(result);
       }
-
-      @Override
-      public int hashCode() {
-         return Objects.hashCode(keyAdapter, valueAdapter);
-      }
-
-      @Override
-      public boolean equals(Object obj) {
-         if (this == obj)
-            return true;
-         if (obj == null || getClass() != obj.getClass())
-            return false;
-         KeepLastRepeatedKeyMapTypeAdapter<?, ?> that = KeepLastRepeatedKeyMapTypeAdapter.class.cast(obj);
-         return equal(this.keyAdapter, that.keyAdapter) && equal(this.valueAdapter, that.valueAdapter);
-      }
-
-      @Override
-      public String toString() {
-         return toStringHelper(this).add("keyAdapter", keyAdapter).add("valueAdapter", valueAdapter).toString();
-      }
    }
 
    public static class KeepLastRepeatedKeyMapTypeAdapterFactory extends MapTypeAdapterFactory {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/0fb1b459/apis/chef/src/test/java/org/jclouds/chef/config/ChefParserModuleTest.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/test/java/org/jclouds/chef/config/ChefParserModuleTest.java b/apis/chef/src/test/java/org/jclouds/chef/config/ChefParserModuleTest.java
index 9b1354e..8ab60ee 100644
--- a/apis/chef/src/test/java/org/jclouds/chef/config/ChefParserModuleTest.java
+++ b/apis/chef/src/test/java/org/jclouds/chef/config/ChefParserModuleTest.java
@@ -20,12 +20,15 @@ import static com.google.common.base.Objects.equal;
 import static org.testng.Assert.assertEquals;
 
 import java.lang.reflect.Type;
+import java.util.List;
 import java.util.Map;
 
 import org.jclouds.chef.config.ChefParserModule.KeepLastRepeatedKeyMapTypeAdapterFactory;
+import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.ListTypeAdapterFactory;
 import org.testng.annotations.Test;
 
 import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.reflect.TypeToken;
 import com.google.gson.Gson;
@@ -90,4 +93,25 @@ public class ChefParserModuleTest {
       assertEquals(duplicates,
             ImmutableMap.of("i-foo", new KeyValue("i-foo", "foo2"), "i-bar", new KeyValue("i-bar", "bar2")));
    }
+
+   private Gson listInMap = new GsonBuilder().registerTypeAdapterFactory(new KeepLastRepeatedKeyMapTypeAdapterFactory())
+         .registerTypeAdapterFactory(new ListTypeAdapterFactory()).create();
+   private Type listInMapType = new TypeToken<Map<String, List<Map<String, String>>>>() {
+      private static final long serialVersionUID = 1L;
+   }.getType();
+
+   public void testListInMap() {
+      Map<String, List<Map<String, String>>> notNull = listInMap
+            .fromJson("{\"value\":[{\"x\":\"y\",\"a\":\"b\"},{\"u\":\"v\"}]}", listInMapType);
+      assertEquals(notNull,
+            ImmutableMap.of("value", ImmutableList.of(ImmutableMap.of("x", "y", "a", "b"), ImmutableMap.of("u", "v"))));
+      Map<String, List<Map<String, String>>> innerMapValueNull = listInMap
+            .fromJson("{\"value\":[{\"x\":\"y\",\"a\":null},{\"u\":\"v\"}]}", listInMapType);
+      assertEquals(innerMapValueNull,
+            ImmutableMap.of("value", ImmutableList.of(ImmutableMap.of("x", "y"), ImmutableMap.of("u", "v"))));
+      Map<String, List<Map<String, String>>> withNullInList = listInMap.fromJson("{\"value\":[null]}", listInMapType);
+      assertEquals(withNullInList, ImmutableMap.of("value", ImmutableList.of()));
+      Map<String, List<Map<String, String>>> withNullAsList = listInMap.fromJson("{\"parent\":null}", listInMapType);
+      assertEquals(withNullAsList, ImmutableMap.of());
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/0fb1b459/core/src/main/java/org/jclouds/json/internal/NullFilteringTypeAdapterFactories.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/json/internal/NullFilteringTypeAdapterFactories.java b/core/src/main/java/org/jclouds/json/internal/NullFilteringTypeAdapterFactories.java
index 0479d87..7ad257e 100644
--- a/core/src/main/java/org/jclouds/json/internal/NullFilteringTypeAdapterFactories.java
+++ b/core/src/main/java/org/jclouds/json/internal/NullFilteringTypeAdapterFactories.java
@@ -30,6 +30,7 @@ import com.google.gson.TypeAdapterFactory;
 import com.google.gson.internal.JsonReaderInternalAccess;
 import com.google.gson.reflect.TypeToken;
 import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
 import com.google.gson.stream.JsonWriter;
 
 import java.io.IOException;
@@ -85,6 +86,10 @@ public class NullFilteringTypeAdapterFactories {
       @SuppressWarnings("unchecked")
       protected <C extends Iterable<E>, B extends ImmutableCollection.Builder<E>> C readAndBuild(JsonReader in,
             B builder) throws IOException {
+         if (in.peek() == JsonToken.NULL) {
+            in.nextNull();
+            return null;
+         }
          in.beginArray();
          while (in.hasNext()) {
             E element = elementAdapter.read(in);
@@ -278,7 +283,7 @@ public class NullFilteringTypeAdapterFactories {
       }
    }
 
-   private static final class MapTypeAdapter<K, V> extends TypeAdapter<Map<K, V>> {
+   public static class MapTypeAdapter<K, V> extends TypeAdapter<Map<K, V>> {
 
       protected final TypeAdapter<K> keyAdapter;
       protected final TypeAdapter<V> valueAdapter;
@@ -303,6 +308,10 @@ public class NullFilteringTypeAdapterFactories {
       }
 
       public Map<K, V> read(JsonReader in) throws IOException {
+         if (in.peek() == JsonToken.NULL) {
+            in.nextNull();
+            return null;
+         }
          ImmutableMap.Builder<K, V> result = ImmutableMap.builder();
          in.beginObject();
          while (in.hasNext()) {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/0fb1b459/core/src/test/java/org/jclouds/json/internal/NullFilteringTypeAdapterFactoriesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/jclouds/json/internal/NullFilteringTypeAdapterFactoriesTest.java b/core/src/test/java/org/jclouds/json/internal/NullFilteringTypeAdapterFactoriesTest.java
index bf82bc6..52f94ab 100644
--- a/core/src/test/java/org/jclouds/json/internal/NullFilteringTypeAdapterFactoriesTest.java
+++ b/core/src/test/java/org/jclouds/json/internal/NullFilteringTypeAdapterFactoriesTest.java
@@ -297,4 +297,25 @@ public class NullFilteringTypeAdapterFactoriesTest {
       assertEquals(resourceDupes.get("i-foo"),
             ImmutableList.of(new Resource("i-foo", "foo"), new Resource("i-bar", "bar")));
    }
+
+   private Gson listInMap = new GsonBuilder().registerTypeAdapterFactory(new MapTypeAdapterFactory())
+         .registerTypeAdapterFactory(new ListTypeAdapterFactory()).create();
+   private Type listInMapType = new TypeToken<Map<String, List<Map<String, String>>>>() {
+      private static final long serialVersionUID = 1L;
+   }.getType();
+
+   public void testListInMap() {
+      Map<String, List<Map<String, String>>> notNull = listInMap
+            .fromJson("{\"value\":[{\"x\":\"y\",\"a\":\"b\"},{\"u\":\"v\"}]}", listInMapType);
+      assertEquals(notNull,
+            ImmutableMap.of("value", ImmutableList.of(ImmutableMap.of("x", "y", "a", "b"), ImmutableMap.of("u", "v"))));
+      Map<String, List<Map<String, String>>> innerMapValueNull = listInMap
+            .fromJson("{\"value\":[{\"x\":\"y\",\"a\":null},{\"u\":\"v\"}]}", listInMapType);
+      assertEquals(innerMapValueNull,
+            ImmutableMap.of("value", ImmutableList.of(ImmutableMap.of("x", "y"), ImmutableMap.of("u", "v"))));
+      Map<String, List<Map<String, String>>> withNullInList = listInMap.fromJson("{\"value\":[null]}", listInMapType);
+      assertEquals(withNullInList, ImmutableMap.of("value", ImmutableList.of()));
+      Map<String, List<Map<String, String>>> withNullAsList = listInMap.fromJson("{\"parent\":null}", listInMapType);
+      assertEquals(withNullAsList, ImmutableMap.of());
+   }
 }