Merge branch 'master' of github.com:jclouds/jclouds into 1.3.x

* 'master' of github.com:jclouds/jclouds:
  Issue 797: converted many adapters to the new gson streaming method
  Issue 797: moved JsonLiteral out of the gson package hierarchy as it is unnecessarily there
  Issue 797: update to gson 2.1
  Issue 797: gson 2+ defaults numbers to double
  Issue 797: gson 2+ addresses gson issue 325
  Add tests for Virtual CPU attribute in Flavor json
  Refactor Flavor class so that it is immutable
  Add vcpus to the flavor entity.
  Fixed broken test in VirtualBox.
  [issue 795] Fixing a compilation failure in EC2ListNodesStrategy - looks like something happened with generic casts between Java 6 and 7 (see http://stackoverflow.com/questions/8637937/why-does-a-generic-cast-of-a-list-extends-set-to-listset-succeed-on-sun)
  [issue 795] Added a @DataProvider and modified failing tests to selectively run under Java6/7
  [issue 795] De-generified HttpMessage.Builder and HttpRequest.Builder, prevented the "ambiguous method" compile errors caused by GeneratedHttpRequest.builder() and from() (see [issue 461]) and added a convenience requestBuilder() and fromRequest() methods with the former signatures of builder() and from() resp.
  GAE SDK 1.5.5 -> 1.6.1
  fixed problem with creating nova client inside karaf
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/config/CloudStackDateAdapter.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/config/CloudStackDateAdapter.java
index 4835a50..c44c587 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/config/CloudStackDateAdapter.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/config/CloudStackDateAdapter.java
@@ -18,17 +18,15 @@
  */
 package org.jclouds.cloudstack.config;
 
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonParseException;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.JsonSerializationContext;
-import org.jclouds.date.DateService;
-import org.jclouds.json.config.GsonModule;
+import java.io.IOException;
+import java.util.Date;
 
 import javax.inject.Inject;
-import java.lang.reflect.Type;
-import java.util.Date;
+
+import org.jclouds.date.DateService;
+import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
+
+import com.google.gson.stream.JsonReader;
 
 /**
  * Data adapter for the date formats used by CloudStack.
@@ -39,27 +37,15 @@
  *
  * @author Richard Downer
  */
-public class CloudStackDateAdapter implements GsonModule.DateAdapter {
-   private final DateService dateService;
+public class CloudStackDateAdapter extends Iso8601DateAdapter {
 
    @Inject
    private CloudStackDateAdapter(DateService dateService) {
-      this.dateService = dateService;
+      super(dateService);
    }
 
-   public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
-      return new JsonPrimitive(dateService.iso8601DateFormat(src));
-   }
-
-   public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
-            throws JsonParseException {
-      String toParse = json.getAsJsonPrimitive().getAsString();
-      toParse = toParse.replaceAll("'T'", "T");
-      try {
-         return dateService.iso8601DateParse(toParse);
-      } catch (RuntimeException e) {
-         return dateService.iso8601SecondsDateParse(toParse);
-      }
+   public Date read(JsonReader reader) throws IOException {
+      return parseDate(reader.nextString().replaceAll("'T'", "T"));
    }
 
 }
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2ListNodesStrategy.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2ListNodesStrategy.java
index 88a65ec..6e67abc 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2ListNodesStrategy.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2ListNodesStrategy.java
@@ -96,12 +96,17 @@
                   @SuppressWarnings("unchecked")
                   @Override
                   public Future<Set<? extends Reservation<? extends RunningInstance>>> apply(String from) {
-                     return (Future<Set<? extends Reservation<? extends RunningInstance>>>) client
-                              .getInstanceServices().describeInstancesInRegion(from);
+                     return castToSpecificTypedFuture(client.getInstanceServices().describeInstancesInRegion(from));
                   }
 
                }, executor, null, logger, "reservations");
 
       return concat(concat(reservations));
    }
+
+   // "hide" this cast (i.e. do not perform inline) from the Java 7 compiler - see http://stackoverflow.com/questions/8637937/why-does-a-generic-cast-of-a-list-extends-set-to-listset-succeed-on-sun
+   @SuppressWarnings("unchecked")
+   private static <T> Future<T> castToSpecificTypedFuture(Future<? extends T> input) {
+       return (Future<T>) input;
+   }
 }
diff --git a/apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Flavor.java b/apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Flavor.java
index 2916be9..f0491e1 100644
--- a/apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Flavor.java
+++ b/apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Flavor.java
@@ -27,54 +27,47 @@
  */
 public class Flavor extends Resource {
 
-   public Flavor() {
+   private final int id;
+   private final String name;
+   private final Integer disk;
+   private final Integer ram;
+   private final Integer vcpus;
+
+   //Required because of how Gson is being used to do wire marshalling with the Server class
+   private Flavor(){
+      id=0;
+      name=null;
+      disk=null;
+      ram=null;
+      vcpus=null;
    }
 
-   @Override
-   public String toString() {
-      return "Flavor [disk=" + disk + ", id=" + id + ", name=" + name + ", ram=" + ram + "]";
-   }
-
-   public Flavor(int id, String name) {
+   public Flavor(int id, String name, Integer disk, Integer ram, Integer vcpus) {
       this.id = id;
       this.name = name;
+      this.disk = disk;
+      this.ram = ram;
+      this.vcpus = vcpus;
    }
 
-   private int id;
-   private String name;
-   private Integer disk;
-   private Integer ram;
-
    public Integer getDisk() {
       return disk;
    }
 
-   public void setDisk(Integer value) {
-      this.disk = value;
-   }
-
    public int getId() {
       return id;
    }
 
-   public void setId(int value) {
-      this.id = value;
-   }
-
    public String getName() {
       return name;
    }
 
-   public void setName(String value) {
-      this.name = value;
-   }
-
    public Integer getRam() {
       return ram;
    }
 
-   public void setRam(Integer value) {
-      this.ram = value;
+   public Integer getVcpus() {
+      return vcpus;
    }
 
    @Override
@@ -85,6 +78,7 @@
       result = prime * result + id;
       result = prime * result + ((name == null) ? 0 : name.hashCode());
       result = prime * result + ((ram == null) ? 0 : ram.hashCode());
+      result = prime * result + ((vcpus == null) ? 0 : vcpus.hashCode());
       return result;
    }
 
@@ -114,7 +108,16 @@
             return false;
       } else if (!ram.equals(other.ram))
          return false;
+      if (vcpus == null) {
+         if (other.vcpus != null)
+            return false;
+      } else if (!vcpus.equals(other.vcpus))
+         return false;
       return true;
    }
 
+   @Override
+   public String toString() {
+      return "Flavor [disk=" + disk + ", id=" + id + ", name=" + name + ", ram=" + ram + ", vcpus=" + vcpus +"]";
+   }
 }
diff --git a/apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Resource.java b/apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Resource.java
index 156730b..8dea23f 100644
--- a/apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Resource.java
+++ b/apis/nova/src/main/java/org/jclouds/openstack/nova/domain/Resource.java
@@ -67,7 +67,11 @@
        };
    }
 
-   private final ConcurrentSkipListMap<LinkType,URI> orderedSelfReferences = new ConcurrentSkipListMap<LinkType,URI>();
+   private final ConcurrentSkipListMap<LinkType,URI> orderedSelfReferences;
+
+   public Resource(){
+      orderedSelfReferences = new ConcurrentSkipListMap<LinkType,URI>();
+   }
 
    private void populateOrderedSelfReferences() {
       for (Map<String, String> linkProperties : links) {
diff --git a/apis/nova/src/test/java/org/jclouds/openstack/nova/compute/functions/FlavorToHardwareTest.java b/apis/nova/src/test/java/org/jclouds/openstack/nova/compute/functions/FlavorToHardwareTest.java
index c42ad4e..616487a 100644
--- a/apis/nova/src/test/java/org/jclouds/openstack/nova/compute/functions/FlavorToHardwareTest.java
+++ b/apis/nova/src/test/java/org/jclouds/openstack/nova/compute/functions/FlavorToHardwareTest.java
@@ -44,7 +44,7 @@
    public void test() throws UnknownHostException, URISyntaxException {
       Hardware flavor = convertFlavor();
       Hardware tempFlavor = new HardwareBuilder().ids("1").name("256 MB Server")
-            .processors(ImmutableList.of(new Processor(1.0, 1.0)))
+            .processors(ImmutableList.of(new Processor(2.0, 2.0)))
             .ram(256)
             .volumes(ImmutableList.of(
                   new VolumeBuilder().type(Volume.Type.LOCAL).size(10.0f).durable(true).bootDevice(true).build()))
diff --git a/apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseFlavorFromJsonResponseTest.java b/apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseFlavorFromJsonResponseTest.java
index a6b2c72..c1128e3 100644
--- a/apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseFlavorFromJsonResponseTest.java
+++ b/apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseFlavorFromJsonResponseTest.java
@@ -55,6 +55,7 @@
       assertEquals(response.getName(), "256 MB Server");
       assertEquals(response.getDisk().intValue(), 10);
       assertEquals(response.getRam().intValue(), 256);
+      assertEquals(response.getVcpus().intValue(), 2);
    }
 
    public static Flavor parseFlavor() {
diff --git a/apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseFlavorListFromJsonResponseTest.java b/apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseFlavorListFromJsonResponseTest.java
index bc90d31..a3edb25 100644
--- a/apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseFlavorListFromJsonResponseTest.java
+++ b/apis/nova/src/test/java/org/jclouds/openstack/nova/functions/ParseFlavorListFromJsonResponseTest.java
@@ -50,7 +50,7 @@
    public void testApplyInputStream() {
       InputStream is = getClass().getResourceAsStream("/test_list_flavors.json");
 
-      List<Flavor> expects = ImmutableList.of(new Flavor(1, "256 MB Server"), new Flavor(2, "512 MB Server"));
+      List<Flavor> expects = ImmutableList.of(new Flavor(1, "256 MB Server", null, null, null), new Flavor(2, "512 MB Server", null, null, null));
 
       UnwrapOnlyJsonValue<List<Flavor>> parser = i.getInstance(Key
             .get(new TypeLiteral<UnwrapOnlyJsonValue<List<Flavor>>>() {
@@ -69,13 +69,15 @@
       List<Flavor> response = parser.apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is)));
       assertEquals(response.get(0).getId(), 1);
       assertEquals(response.get(0).getName(), "256 MB Server");
-      assertEquals(response.get(0).getDisk(), new Integer(10));
-      assertEquals(response.get(0).getRam(), new Integer(256));
+      assertEquals(response.get(0).getDisk(), Integer.valueOf(10));
+      assertEquals(response.get(0).getRam(), Integer.valueOf(256));
+      assertEquals(response.get(0).getVcpus(), Integer.valueOf(2));
 
       assertEquals(response.get(1).getId(), 2);
       assertEquals(response.get(1).getName(), "512 MB Server");
-      assertEquals(response.get(1).getDisk(), new Integer(20));
-      assertEquals(response.get(1).getRam(), new Integer(512));
+      assertEquals(response.get(1).getDisk(), Integer.valueOf(20));
+      assertEquals(response.get(1).getRam(), Integer.valueOf(512));
+      assertEquals(response.get(1).getVcpus(), Integer.valueOf(5));
 
    }
 
diff --git a/apis/nova/src/test/resources/test_get_flavor_details.json b/apis/nova/src/test/resources/test_get_flavor_details.json
index bd3266c..ed1b29c 100644
--- a/apis/nova/src/test/resources/test_get_flavor_details.json
+++ b/apis/nova/src/test/resources/test_get_flavor_details.json
@@ -4,6 +4,7 @@
         "name" : "256 MB Server",
         "ram" : 256,
         "disk" : 10,
+        "vcpus" : 2,
         "links": [
             {
                 "rel" : "self",
diff --git a/apis/nova/src/test/resources/test_list_flavors_detail.json b/apis/nova/src/test/resources/test_list_flavors_detail.json
index c8939ee..867a596 100644
--- a/apis/nova/src/test/resources/test_list_flavors_detail.json
+++ b/apis/nova/src/test/resources/test_list_flavors_detail.json
@@ -5,6 +5,7 @@
             "name" : "256 MB Server",
             "ram"  : 256,
             "disk" : 10,
+            "vcpus" : 2,
             "links": [
                 {
                     "rel" : "self",
@@ -27,6 +28,7 @@
             "name" : "512 MB Server",
             "ram"  : 512,
             "disk" : 20,
+            "vcpus" : 5,
             "links": [
                 {
                     "rel" : "self",
diff --git a/core/pom.xml b/core/pom.xml
index 143e27b..e395f78 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -104,7 +104,7 @@
         <dependency>
             <groupId>com.google.code.gson</groupId>
             <artifactId>gson</artifactId>
-            <version>1.7.2</version>
+            <version>2.1</version>
         </dependency>
         <dependency>
             <groupId>com.google.guava</groupId>
diff --git a/core/src/main/java/com/google/gson/ObjectMapTypeAdapter.java b/core/src/main/java/com/google/gson/ObjectMapTypeAdapter.java
deleted file mode 100644
index 94312c3..0000000
--- a/core/src/main/java/com/google/gson/ObjectMapTypeAdapter.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package com.google.gson;
-
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.Map;
-import java.util.Set;
-
-import org.jclouds.json.internal.ParseObjectFromElement;
-
-import com.google.gson.internal.$Gson$Types;
-
-/**
- * Default serialization and deserialization of a map type. This implementation really only works
- * well with simple primitive types as the map key. If the key is not a simple primitive then the
- * object is {@code toString}ed and that value is used as its key.
- *   <p/>
- *   Patched depending on <a href="http://code.google.com/p/google-gson/issues/detail?id=325">this</a>
- * @author Joel Leitch
- */
-@SuppressWarnings("unchecked")
-public final class ObjectMapTypeAdapter extends BaseMapTypeAdapter {
-
-  public JsonElement serialize(Map src, Type typeOfSrc, JsonSerializationContext context) {
-    JsonObject map = new JsonObject();
-    Type childGenericType = null;
-    if (typeOfSrc instanceof ParameterizedType) {
-      Class<?> rawTypeOfSrc = $Gson$Types.getRawType(typeOfSrc);
-      childGenericType = $Gson$Types.getMapKeyAndValueTypes(typeOfSrc, rawTypeOfSrc)[1];
-    }
-
-    for (Map.Entry entry : (Set<Map.Entry>) src.entrySet()) {
-      Object value = entry.getValue();
-
-      JsonElement valueElement;
-      if (value == null) {
-        valueElement = JsonNull.createJsonNull();
-      } else {
-        Type childType = (childGenericType == null)
-            ? value.getClass() : childGenericType;
-        valueElement = serialize(context, value, childType);
-      }
-      map.add(String.valueOf(entry.getKey()), valueElement);
-    }
-    return map;
-  }
-
-  public Map deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
-      throws JsonParseException {
-    // Use ObjectConstructor to create instance instead of hard-coding a specific type.
-    // This handles cases where users are using their own subclass of Map.
-    Map<Object, Object> map = constructMapType(typeOfT, context);
-    Type[] keyAndValueTypes = $Gson$Types.getMapKeyAndValueTypes(typeOfT, $Gson$Types.getRawType(typeOfT));
-    for (Map.Entry<String, JsonElement> entry : json.getAsJsonObject().entrySet()) {
-      Object key = context.deserialize(new JsonPrimitive(entry.getKey()), keyAndValueTypes[0]);
-      // START JCLOUDS PATCH
-      // http://code.google.com/p/google-gson/issues/detail?id=325
-      Object value = null;
-      if (keyAndValueTypes[1] == Object.class) {
-         value = ParseObjectFromElement.SINGLETON.apply(entry.getValue());
-      }
-      if (value == null) {
-         value = context.deserialize(entry.getValue(), keyAndValueTypes[1]);
-      }
-      // END JCLOUDS PATCH
-      map.put(key, value);
-    }
-    return map;
-  }
-
-  @Override
-  public String toString() {
-    return MapTypeAdapter.class.getSimpleName();
-  }
-}
\ No newline at end of file
diff --git a/core/src/main/java/com/google/gson/Streams.java b/core/src/main/java/com/google/gson/Streams.java
deleted file mode 100644
index b16ecb7..0000000
--- a/core/src/main/java/com/google/gson/Streams.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package com.google.gson;
-
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonWriter;
-import com.google.gson.stream.MalformedJsonException;
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Map;
-
-/**
- * Reads and writes GSON parse trees over streams.
- */
-final class Streams {
-
-  /**
-   * Takes a reader in any state and returns the next value as a JsonElement.
-   */
-  static JsonElement parse(JsonReader reader) throws JsonParseException {
-    boolean isEmpty = true;
-    try {
-      reader.peek();
-      isEmpty = false;
-      return parseRecursive(reader);
-    } catch (EOFException e) {
-      /*
-       * For compatibility with JSON 1.5 and earlier, we return a JsonNull for
-       * empty documents instead of throwing.
-       */
-      if (isEmpty) {
-        return JsonNull.createJsonNull();
-      }
-      throw new JsonIOException(e);
-    } catch (MalformedJsonException e) {
-      throw new JsonSyntaxException(e);
-    } catch (IOException e) {
-      throw new JsonIOException(e);
-    } catch (NumberFormatException e) {
-      throw new JsonSyntaxException(e);
-    }
-  }
-
-  private static JsonElement parseRecursive(JsonReader reader) throws IOException {
-    switch (reader.peek()) {
-    case STRING:
-      return new JsonPrimitive(reader.nextString());
-    case NUMBER:
-      String number = reader.nextString();
-      return new JsonPrimitive(JsonPrimitive.stringToNumber(number));
-    case BOOLEAN:
-      return new JsonPrimitive(reader.nextBoolean());
-    case NULL:
-      reader.nextNull();
-      return JsonNull.createJsonNull();
-    case BEGIN_ARRAY:
-      JsonArray array = new JsonArray();
-      reader.beginArray();
-      while (reader.hasNext()) {
-        array.add(parseRecursive(reader));
-      }
-      reader.endArray();
-      return array;
-    case BEGIN_OBJECT:
-      JsonObject object = new JsonObject();
-      reader.beginObject();
-      while (reader.hasNext()) {
-        object.add(reader.nextName(), parseRecursive(reader));
-      }
-      reader.endObject();
-      return object;
-    case END_DOCUMENT:
-    case NAME:
-    case END_OBJECT:
-    case END_ARRAY:
-    default:
-      throw new IllegalArgumentException();
-    }
-  }
-
-  /**
-   * Writes the JSON element to the writer, recursively.
-   */
-  static void write(JsonElement element, boolean serializeNulls, JsonWriter writer)
-      throws IOException {
-    if (element == null || element.isJsonNull()) {
-      if (serializeNulls) {
-        writer.nullValue();
-      }
-    //BEGIN JCLOUDS PATCH
-    // * @see <a href="http://code.google.com/p/google-gson/issues/detail?id=326"/>
-    } else if (element instanceof JsonLiteral ) {
-       writer.value(JsonLiteral.class.cast(element));
-       //END JCLOUDS PATCH
-    } else if (element.isJsonPrimitive()) {
-      JsonPrimitive primitive = element.getAsJsonPrimitive();
-      if (primitive.isNumber()) {
-        writer.value(primitive.getAsNumber());
-      } else if (primitive.isBoolean()) {
-        writer.value(primitive.getAsBoolean());
-      } else {
-        writer.value(primitive.getAsString());
-      }
-
-    } else if (element.isJsonArray()) {
-      writer.beginArray();
-      for (JsonElement e : element.getAsJsonArray()) {
-        /* always print null when its parent element is an array! */
-        if (e.isJsonNull()) {
-          writer.nullValue();
-          continue;
-        }
-        write(e, serializeNulls, writer);
-      }
-      writer.endArray();
-
-    } else if (element.isJsonObject()) {
-      writer.beginObject();
-      for (Map.Entry<String, JsonElement> e : element.getAsJsonObject().entrySet()) {
-        JsonElement value = e.getValue();
-        if (!serializeNulls && value.isJsonNull()) {
-          continue;
-        }
-        writer.name(e.getKey());
-        write(value, serializeNulls, writer);
-      }
-      writer.endObject();
-
-    } else {
-      throw new IllegalArgumentException("Couldn't write " + element.getClass());
-    }
-  }
-
-  static Writer writerForAppendable(Appendable appendable) {
-    return appendable instanceof Writer ? (Writer) appendable : new AppendableWriter(appendable);
-  }
-
-  /**
-   * Adapts an {@link Appendable} so it can be passed anywhere a {@link Writer}
-   * is used.
-   */
-  private static class AppendableWriter extends Writer {
-    private final Appendable appendable;
-    private final CurrentWrite currentWrite = new CurrentWrite();
-
-    private AppendableWriter(Appendable appendable) {
-      this.appendable = appendable;
-    }
-
-    @Override public void write(char[] chars, int offset, int length) throws IOException {
-      currentWrite.chars = chars;
-      appendable.append(currentWrite, offset, offset + length);
-    }
-
-    @Override public void write(int i) throws IOException {
-      appendable.append((char) i);
-    }
-
-    @Override public void flush() {}
-    @Override public void close() {}
-
-    /**
-     * A mutable char sequence pointing at a single char[].
-     */
-    static class CurrentWrite implements CharSequence {
-      char[] chars;
-      public int length() {
-        return chars.length;
-      }
-      public char charAt(int i) {
-        return chars[i];
-      }
-      public CharSequence subSequence(int start, int end) {
-        return new String(chars, start, end - start);
-      }
-    }
-  }
-}
diff --git a/core/src/main/java/com/google/gson/internal/Streams.java b/core/src/main/java/com/google/gson/internal/Streams.java
new file mode 100644
index 0000000..0459793
--- /dev/null
+++ b/core/src/main/java/com/google/gson/internal/Streams.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.gson.internal;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonIOException;
+import com.google.gson.JsonNull;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.internal.bind.TypeAdapters;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+import com.google.gson.stream.MalformedJsonException;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.Writer;
+
+import org.jclouds.json.internal.JsonLiteral;
+
+/**
+ * Reads and writes GSON parse trees over streams.
+ */
+public final class Streams {
+  /**
+   * Takes a reader in any state and returns the next value as a JsonElement.
+   */
+  public static JsonElement parse(JsonReader reader) throws JsonParseException {
+    boolean isEmpty = true;
+    try {
+      reader.peek();
+      isEmpty = false;
+      return TypeAdapters.JSON_ELEMENT.read(reader);
+    } catch (EOFException e) {
+      /*
+       * For compatibility with JSON 1.5 and earlier, we return a JsonNull for
+       * empty documents instead of throwing.
+       */
+      if (isEmpty) {
+        return JsonNull.INSTANCE;
+      }
+      throw new JsonIOException(e);
+    } catch (MalformedJsonException e) {
+      throw new JsonSyntaxException(e);
+    } catch (IOException e) {
+      throw new JsonIOException(e);
+    } catch (NumberFormatException e) {
+      throw new JsonSyntaxException(e);
+    }
+  }
+
+  /**
+   * Writes the JSON element to the writer, recursively.
+   */
+  public static void write(JsonElement element, JsonWriter writer) throws IOException {
+     //BEGIN JCLOUDS PATCH
+     // * @see <a href="http://code.google.com/p/google-gson/issues/detail?id=326"/>
+     if (element instanceof JsonLiteral ) {
+        writer.value(JsonLiteral.class.cast(element));
+        //END JCLOUDS PATCH
+     } else {
+        TypeAdapters.JSON_ELEMENT.write(writer, element);
+     }
+  }
+
+  public static Writer writerForAppendable(Appendable appendable) {
+    return appendable instanceof Writer ? (Writer) appendable : new AppendableWriter(appendable);
+  }
+
+  /**
+   * Adapts an {@link Appendable} so it can be passed anywhere a {@link Writer}
+   * is used.
+   */
+  private static class AppendableWriter extends Writer {
+    private final Appendable appendable;
+    private final CurrentWrite currentWrite = new CurrentWrite();
+
+    private AppendableWriter(Appendable appendable) {
+      this.appendable = appendable;
+    }
+
+    @Override public void write(char[] chars, int offset, int length) throws IOException {
+      currentWrite.chars = chars;
+      appendable.append(currentWrite, offset, offset + length);
+    }
+
+    @Override public void write(int i) throws IOException {
+      appendable.append((char) i);
+    }
+
+    @Override public void flush() {}
+    @Override public void close() {}
+
+    /**
+     * A mutable char sequence pointing at a single char[].
+     */
+    static class CurrentWrite implements CharSequence {
+      char[] chars;
+      public int length() {
+        return chars.length;
+      }
+      public char charAt(int i) {
+        return chars[i];
+      }
+      public CharSequence subSequence(int start, int end) {
+        return new String(chars, start, end - start);
+      }
+    }
+  }
+
+}
diff --git a/core/src/main/java/com/google/gson/stream/JsonWriter.java b/core/src/main/java/com/google/gson/stream/JsonWriter.java
index e6541ed..c5996e9 100644
--- a/core/src/main/java/com/google/gson/stream/JsonWriter.java
+++ b/core/src/main/java/com/google/gson/stream/JsonWriter.java
@@ -1,21 +1,19 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
+/*
+ * Copyright (C) 2010 Google Inc.
  *
- *   http://www.apache.org/licenses/LICENSE-2.0
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
+
 package com.google.gson.stream;
 
 import java.io.Closeable;
@@ -24,7 +22,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import com.google.gson.JsonLiteral;
+import org.jclouds.json.internal.JsonLiteral;
+
 
 /**
  * Writes a JSON (<a href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>)
@@ -124,7 +123,7 @@
  * @author Jesse Wilson
  * @since 1.6
  */
-public final class JsonWriter implements Closeable {
+public class JsonWriter implements Closeable {
 
   /** The output data, containing at most one top-level array or object. */
   private final Writer out;
@@ -149,6 +148,10 @@
 
   private boolean htmlSafe;
 
+  private String deferredName;
+
+  private boolean serializeNulls = true;
+
   /**
    * Creates a new instance that writes a JSON-encoded stream to {@code out}.
    * For best performance, ensure {@link Writer} is buffered; wrapping in
@@ -169,7 +172,7 @@
    *
    * @param indent a string containing only whitespace.
    */
-  public void setIndent(String indent) {
+  public final void setIndent(String indent) {
     if (indent.length() == 0) {
       this.indent = null;
       this.separator = ":";
@@ -191,7 +194,7 @@
    *       Double#isInfinite() infinities}.
    * </ul>
    */
-  public void setLenient(boolean lenient) {
+  public final void setLenient(boolean lenient) {
     this.lenient = lenient;
   }
 
@@ -209,7 +212,7 @@
    * setting, your XML/HTML encoder should replace these characters with the
    * corresponding escape sequences.
    */
-  public void setHtmlSafe(boolean htmlSafe) {
+  public final void setHtmlSafe(boolean htmlSafe) {
     this.htmlSafe = htmlSafe;
   }
 
@@ -217,17 +220,34 @@
    * Returns true if this writer writes JSON that's safe for inclusion in HTML
    * and XML documents.
    */
-  public boolean isHtmlSafe() {
+  public final boolean isHtmlSafe() {
     return htmlSafe;
   }
 
   /**
+   * Sets whether object members are serialized when their value is null.
+   * This has no impact on array elements. The default is true.
+   */
+  public final void setSerializeNulls(boolean serializeNulls) {
+    this.serializeNulls = serializeNulls;
+  }
+
+  /**
+   * Returns true if object members are serialized when their value is null.
+   * This has no impact on array elements. The default is true.
+   */
+  public final boolean getSerializeNulls() {
+    return serializeNulls;
+  }
+
+  /**
    * Begins encoding a new array. Each call to this method must be paired with
    * a call to {@link #endArray}.
    *
    * @return this writer.
    */
   public JsonWriter beginArray() throws IOException {
+    writeDeferredName();
     return open(JsonScope.EMPTY_ARRAY, "[");
   }
 
@@ -247,6 +267,7 @@
    * @return this writer.
    */
   public JsonWriter beginObject() throws IOException {
+    writeDeferredName();
     return open(JsonScope.EMPTY_OBJECT, "{");
   }
 
@@ -280,6 +301,9 @@
     if (context != nonempty && context != empty) {
       throw new IllegalStateException("Nesting problem: " + stack);
     }
+    if (deferredName != null) {
+      throw new IllegalStateException("Dangling name: " + deferredName);
+    }
 
     stack.remove(stack.size() - 1);
     if (context == nonempty) {
@@ -313,11 +337,21 @@
     if (name == null) {
       throw new NullPointerException("name == null");
     }
-    beforeName();
-    string(name);
+    if (deferredName != null) {
+      throw new IllegalStateException();
+    }
+    deferredName = name;
     return this;
   }
 
+  private void writeDeferredName() throws IOException {
+    if (deferredName != null) {
+      beforeName();
+      string(deferredName);
+      deferredName = null;
+    }
+  }
+
   /**
    * Encodes {@code value}.
    *
@@ -328,6 +362,7 @@
     if (value == null) {
       return nullValue();
     }
+    writeDeferredName();
     beforeValue(false);
     string(value);
     return this;
@@ -339,29 +374,42 @@
    * @return this writer.
    */
   public JsonWriter nullValue() throws IOException {
+    if (deferredName != null) {
+      if (serializeNulls) {
+        writeDeferredName();
+      } else {
+        deferredName = null;
+        return this; // skip the name and the value
+      }
+    }
     beforeValue(false);
     out.write("null");
     return this;
   }
 //BEGIN JCLOUDS PATCH
-// * @see <a href="http://code.google.com/p/google-gson/issues/detail?id=326"/>
+//* @see <a href="http://code.google.com/p/google-gson/issues/detail?id=326"/>
   /**
    * Writes {@code value} literally
-   *
+   * 
    * @return this writer.
    */
   public JsonWriter value(JsonLiteral value) throws IOException {
-    beforeValue(false);
-    out.write(value.toString());
-    return this;
+     if (value == null) {
+        return nullValue();
+     }
+     writeDeferredName();
+     beforeValue(false);
+     out.write(value.toString());
+     return this;
   }
-  //END JCLOUDS PATCH
+//END JCLOUDS PATCH
   /**
    * Encodes {@code value}.
    *
    * @return this writer.
    */
   public JsonWriter value(boolean value) throws IOException {
+    writeDeferredName();
     beforeValue(false);
     out.write(value ? "true" : "false");
     return this;
@@ -378,6 +426,7 @@
     if (Double.isNaN(value) || Double.isInfinite(value)) {
       throw new IllegalArgumentException("Numeric values must be finite, but was " + value);
     }
+    writeDeferredName();
     beforeValue(false);
     out.append(Double.toString(value));
     return this;
@@ -389,6 +438,7 @@
    * @return this writer.
    */
   public JsonWriter value(long value) throws IOException {
+    writeDeferredName();
     beforeValue(false);
     out.write(Long.toString(value));
     return this;
@@ -406,6 +456,7 @@
       return nullValue();
     }
 
+    writeDeferredName();
     String string = value.toString();
     if (!lenient
         && (string.equals("-Infinity") || string.equals("Infinity") || string.equals("NaN"))) {
@@ -447,6 +498,10 @@
        * quotation marks except for the characters that must be escaped:
        * quotation mark, reverse solidus, and the control characters
        * (U+0000 through U+001F)."
+       *
+       * We also escape '\u2028' and '\u2029', which JavaScript interprets as
+       * newline characters. This prevents eval() from failing with a syntax
+       * error. http://code.google.com/p/google-gson/issues/detail?id=341
        */
       switch (c) {
       case '"':
@@ -487,6 +542,11 @@
         }
         break;
 
+      case '\u2028':
+      case '\u2029':
+        out.write(String.format("\\u%04x", (int) c));
+        break;
+
       default:
         if (c <= 0x1F) {
           out.write(String.format("\\u%04x", (int) c));
diff --git a/core/src/main/java/org/jclouds/http/HttpMessage.java b/core/src/main/java/org/jclouds/http/HttpMessage.java
index 4845b42..226d3cf 100644
--- a/core/src/main/java/org/jclouds/http/HttpMessage.java
+++ b/core/src/main/java/org/jclouds/http/HttpMessage.java
@@ -36,31 +36,30 @@
  * @author Adrian Cole
  */
 public class HttpMessage extends PayloadEnclosingImpl {
-   public static Builder<? extends HttpMessage> builder() {
-      return new Builder<HttpMessage>();
+   public static Builder builder() {
+      return new Builder();
    }
 
-   public static class Builder<T extends HttpMessage> {
+   public static class Builder {
       protected Payload payload;
       protected Multimap<String, String> headers = ImmutableMultimap.of();
 
-      public Builder<T> payload(Payload payload) {
+      public Builder payload(Payload payload) {
          this.payload = payload;
          return this;
       }
 
-      public Builder<T> headers(Multimap<String, String> headers) {
+      public Builder headers(Multimap<String, String> headers) {
          this.headers = ImmutableMultimap.copyOf(checkNotNull(headers, "headers"));
          return this;
       }
 
-      @SuppressWarnings("unchecked")
-      public T build() {
-         return (T) new HttpMessage(payload, headers);
+      public HttpMessage build() {
+         return new HttpMessage(payload, headers);
       }
 
-      public static <X extends HttpMessage> Builder<X> from(X input) {
-         return new Builder<X>().payload(input.getPayload()).headers(input.getHeaders());
+      public static Builder from(HttpMessage input) {
+         return new Builder().payload(input.getPayload()).headers(input.getHeaders());
       }
    }
 
@@ -85,7 +84,7 @@
       return (values.size() >= 1) ? values.iterator().next() : null;
    }
 
-   public Builder<? extends HttpMessage> toBuilder() {
+   public Builder toBuilder() {
       return Builder.from(this);
    }
 
diff --git a/core/src/main/java/org/jclouds/http/HttpRequest.java b/core/src/main/java/org/jclouds/http/HttpRequest.java
index 9f0dc5c..340ab88 100644
--- a/core/src/main/java/org/jclouds/http/HttpRequest.java
+++ b/core/src/main/java/org/jclouds/http/HttpRequest.java
@@ -39,32 +39,32 @@
  * @author Adrian Cole
  */
 public class HttpRequest extends HttpMessage {
-   public static Builder<? extends HttpRequest> builder() {
-      return new Builder<HttpRequest>();
+   public static Builder builder() {
+      return new Builder();
    }
 
-   public static class Builder<T extends HttpRequest> extends HttpMessage.Builder<T> {
+   public static class Builder extends HttpMessage.Builder {
       protected String method;
       protected URI endpoint;
       protected char[] skips = new char[] {};
       protected List<HttpRequestFilter> requestFilters = ImmutableList.of();
 
-      public Builder<T> filters(List<HttpRequestFilter> requestFilters) {
+      public Builder filters(List<HttpRequestFilter> requestFilters) {
          this.requestFilters = ImmutableList.copyOf(checkNotNull(requestFilters, "requestFilters"));
          return this;
       }
 
-      public Builder<T> method(String method) {
+      public Builder method(String method) {
          this.method = checkNotNull(method, "method");
          return this;
       }
 
-      public Builder<T> endpoint(URI endpoint) {
+      public Builder endpoint(URI endpoint) {
          this.endpoint = checkNotNull(endpoint, "endpoint");
          return this;
       }
 
-      public Builder<T> skips(char[] skips) {
+      public Builder skips(char[] skips) {
          char[] retval = new char[checkNotNull(skips, "skips").length];
          System.arraycopy(skips, 0, retval, 0, skips.length);
          this.skips = retval;
@@ -72,23 +72,22 @@
       }
 
       @Override
-      public Builder<T> payload(Payload payload) {
-         return (Builder<T>) super.payload(payload);
+      public Builder payload(Payload payload) {
+         return (Builder) super.payload(payload);
       }
 
       @Override
-      public Builder<T> headers(Multimap<String, String> headers) {
-         return (Builder<T>) super.headers(headers);
+      public Builder headers(Multimap<String, String> headers) {
+         return (Builder) super.headers(headers);
       }
 
       @Override
-      @SuppressWarnings("unchecked")
-      public T build() {
-         return (T) new HttpRequest(method, endpoint, skips, requestFilters, payload, headers);
+      public HttpRequest build() {
+         return new HttpRequest(method, endpoint, skips, requestFilters, payload, headers);
       }
 
-      public static <X extends HttpRequest> Builder<X> from(X input) {
-         return new Builder<X>().method(input.getMethod()).endpoint(input.getEndpoint()).skips(input.getSkips())
+      public static Builder from(HttpRequest input) {
+         return new Builder().method(input.getMethod()).endpoint(input.getEndpoint()).skips(input.getSkips())
                   .filters(input.getFilters()).payload(input.getPayload()).headers(input.getHeaders());
       }
 
@@ -189,7 +188,7 @@
    }
 
    @Override
-   public Builder<? extends HttpRequest> toBuilder() {
+   public Builder toBuilder() {
       return Builder.from(this);
    }
 
diff --git a/core/src/main/java/org/jclouds/http/HttpResponse.java b/core/src/main/java/org/jclouds/http/HttpResponse.java
index b36c721..95db165 100644
--- a/core/src/main/java/org/jclouds/http/HttpResponse.java
+++ b/core/src/main/java/org/jclouds/http/HttpResponse.java
@@ -35,7 +35,7 @@
       return new Builder();
    }
 
-   public static class Builder extends HttpMessage.Builder<HttpResponse> {
+   public static class Builder extends HttpMessage.Builder {
       private int statusCode;
       private String message;
 
diff --git a/core/src/main/java/org/jclouds/json/config/GsonModule.java b/core/src/main/java/org/jclouds/json/config/GsonModule.java
index 0749d25..aaece5b 100644
--- a/core/src/main/java/org/jclouds/json/config/GsonModule.java
+++ b/core/src/main/java/org/jclouds/json/config/GsonModule.java
@@ -18,14 +18,13 @@
  */
 package org.jclouds.json.config;
 
+import java.io.IOException;
 import java.lang.reflect.Type;
 import java.util.Date;
 import java.util.Enumeration;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
-import java.util.logging.Level;
-import java.util.logging.Logger;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -36,6 +35,7 @@
 import org.jclouds.json.Json;
 import org.jclouds.json.internal.EnumTypeAdapterThatReturnsFromValue;
 import org.jclouds.json.internal.GsonWrapper;
+import org.jclouds.json.internal.JsonLiteral;
 
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableMap.Builder;
@@ -46,13 +46,14 @@
 import com.google.gson.JsonDeserializationContext;
 import com.google.gson.JsonDeserializer;
 import com.google.gson.JsonElement;
-import com.google.gson.JsonLiteral;
 import com.google.gson.JsonParseException;
-import com.google.gson.JsonPrimitive;
 import com.google.gson.JsonSerializationContext;
 import com.google.gson.JsonSerializer;
-import com.google.gson.ObjectMapTypeAdapter;
+import com.google.gson.TypeAdapter;
+import com.google.gson.internal.JsonReaderInternalAccess;
 import com.google.gson.reflect.TypeToken;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
 import com.google.inject.AbstractModule;
 import com.google.inject.ImplementedBy;
 import com.google.inject.Provides;
@@ -69,21 +70,25 @@
    @Provides
    @Singleton
    Gson provideGson(JsonBallAdapter jsonAdapter, DateAdapter adapter, ByteListAdapter byteListAdapter,
-            ByteArrayAdapter byteArrayAdapter, SerializePropertiesDefaults propertiesAdapter,
-            JsonAdapterBindings bindings) throws ClassNotFoundException, Exception {
+         ByteArrayAdapter byteArrayAdapter, PropertiesAdapter propertiesAdapter, JsonAdapterBindings bindings)
+         throws ClassNotFoundException, Exception {
       GsonBuilder builder = new GsonBuilder();
-      Logger.getLogger("com.google.gson.ParameterizedTypeHandlerMap").setLevel(Level.OFF);
-      builder.registerTypeHierarchyAdapter(Enum.class, new EnumTypeAdapterThatReturnsFromValue());
-      builder.registerTypeHierarchyAdapter(Map.class, new ObjectMapTypeAdapter());
-      builder.registerTypeAdapter(JsonBall.class, jsonAdapter);
-      builder.registerTypeAdapter(Date.class, adapter);
-      builder.registerTypeAdapter(Properties.class, propertiesAdapter);
+
+      // simple (type adapters)
+      builder.registerTypeAdapter(Properties.class, propertiesAdapter.nullSafe());
+      builder.registerTypeAdapter(Date.class, adapter.nullSafe());
       builder.registerTypeAdapter(new TypeToken<List<Byte>>() {
-      }.getType(), byteListAdapter);
-      builder.registerTypeAdapter(byte[].class, byteArrayAdapter);
+      }.getType(), byteListAdapter.nullSafe());
+      builder.registerTypeAdapter(byte[].class, byteArrayAdapter.nullSafe());
+
+      // complicated (serializers/deserializers as they need context to operate)
+      builder.registerTypeHierarchyAdapter(Enum.class, new EnumTypeAdapterThatReturnsFromValue());
+      builder.registerTypeAdapter(JsonBall.class, jsonAdapter);
+
       for (Map.Entry<Type, Object> binding : bindings.getBindings().entrySet()) {
          builder.registerTypeAdapter(binding.getKey(), binding.getValue());
       }
+      
       return builder.create();
    }
 
@@ -101,74 +106,74 @@
       }
 
       public JsonBall deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
-               throws JsonParseException {
+            throws JsonParseException {
          return new JsonBall(json.toString());
       }
 
    }
 
    @ImplementedBy(CDateAdapter.class)
-   public static interface DateAdapter extends JsonSerializer<Date>, JsonDeserializer<Date> {
+   public static abstract class DateAdapter extends TypeAdapter<Date> {
 
    }
 
    @ImplementedBy(HexByteListAdapter.class)
-   public static interface ByteListAdapter extends JsonSerializer<List<Byte>>, JsonDeserializer<List<Byte>> {
+   public static abstract class ByteListAdapter extends TypeAdapter<List<Byte>> {
 
    }
 
    @ImplementedBy(HexByteArrayAdapter.class)
-   public static interface ByteArrayAdapter extends JsonSerializer<byte[]>, JsonDeserializer<byte[]> {
+   public static abstract class ByteArrayAdapter extends TypeAdapter<byte[]> {
 
    }
 
    @Singleton
-   public static class HexByteListAdapter implements ByteListAdapter {
+   public static class HexByteListAdapter extends ByteListAdapter {
 
       @Override
-      public List<Byte> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
-               throws JsonParseException {
-         return Bytes.asList(CryptoStreams.hex(json.getAsString()));
+      public void write(JsonWriter writer, List<Byte> value) throws IOException {
+         writer.value(CryptoStreams.hex(Bytes.toArray(value)));
       }
 
       @Override
-      public JsonElement serialize(List<Byte> src, Type typeOfSrc, JsonSerializationContext context) {
-         return new JsonPrimitive(CryptoStreams.hex(Bytes.toArray(src)));
+      public List<Byte> read(JsonReader reader) throws IOException {
+         return Bytes.asList(CryptoStreams.hex(reader.nextString()));
       }
 
    }
 
    @Singleton
-   public static class HexByteArrayAdapter implements ByteArrayAdapter {
+   public static class HexByteArrayAdapter extends ByteArrayAdapter {
 
       @Override
-      public byte[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
-               throws JsonParseException {
-         return CryptoStreams.hex(json.getAsString());
+      public void write(JsonWriter writer, byte[] value) throws IOException {
+         writer.value(CryptoStreams.hex(value));
       }
 
       @Override
-      public JsonElement serialize(byte[] src, Type typeOfSrc, JsonSerializationContext context) {
-         return new JsonPrimitive(CryptoStreams.hex(src));
+      public byte[] read(JsonReader reader) throws IOException {
+         return CryptoStreams.hex(reader.nextString());
       }
    }
 
    @Singleton
-   public static class Iso8601DateAdapter implements DateAdapter {
+   public static class Iso8601DateAdapter extends DateAdapter {
       private final DateService dateService;
 
       @Inject
-      private Iso8601DateAdapter(DateService dateService) {
+      public Iso8601DateAdapter(DateService dateService) {
          this.dateService = dateService;
       }
 
-      public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
-         return new JsonPrimitive(dateService.iso8601DateFormat(src));
+      public void write(JsonWriter writer, Date value) throws IOException {
+         writer.value(dateService.iso8601DateFormat(value));
       }
 
-      public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
-               throws JsonParseException {
-         String toParse = json.getAsJsonPrimitive().getAsString();
+      public Date read(JsonReader reader) throws IOException {
+         return parseDate(reader.nextString());
+      }
+
+      protected Date parseDate(String toParse) {
          try {
             return dateService.iso8601DateParse(toParse);
          } catch (RuntimeException e) {
@@ -179,63 +184,71 @@
    }
 
    @Singleton
-   public static class SerializePropertiesDefaults implements JsonSerializer<Properties> {
+   public static class PropertiesAdapter extends TypeAdapter<Properties> {
       private final Json json;
       private final Type mapType = new TypeLiteral<Map<String, String>>() {
       }.getRawType();
 
       @Inject
-      public SerializePropertiesDefaults(Json json) {
+      public PropertiesAdapter(Json json) {
          this.json = json;
       }
-
-      public JsonElement serialize(Properties src, Type typeOfSrc, JsonSerializationContext context) {
+      
+      @Override
+      public void write(JsonWriter out, Properties value) throws IOException {
          Builder<String, String> srcMap = ImmutableMap.<String, String> builder();
-         for (Enumeration<?> propNames = src.propertyNames(); propNames.hasMoreElements();) {
+         for (Enumeration<?> propNames = value.propertyNames(); propNames.hasMoreElements();) {
             String propName = (String) propNames.nextElement();
-            srcMap.put(propName, src.getProperty(propName));
+            srcMap.put(propName, value.getProperty(propName));
          }
-         return new JsonLiteral(json.toJson(srcMap.build(), mapType));
+         out.value(new JsonLiteral(json.toJson(srcMap.build(), mapType)));
+      }
+
+      @Override
+      public Properties read(JsonReader in) throws IOException {
+         Properties props = new Properties();
+         in.beginObject();
+         while (in.hasNext()) {
+           JsonReaderInternalAccess.INSTANCE.promoteNameToValue(in);
+           props.setProperty(in.nextString(), in.nextString());
+         }
+         in.endObject();
+         return props;
       }
 
    }
 
    @Singleton
-   public static class CDateAdapter implements DateAdapter {
+   public static class CDateAdapter extends DateAdapter {
       private final DateService dateService;
 
       @Inject
-      private CDateAdapter(DateService dateService) {
+      public CDateAdapter(DateService dateService) {
          this.dateService = dateService;
       }
 
-      public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
-         return new JsonPrimitive(dateService.cDateFormat(src));
+      public void write(JsonWriter writer, Date value) throws IOException {
+         writer.value(dateService.cDateFormat(value));
       }
 
-      public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
-               throws JsonParseException {
-         String toParse = json.getAsJsonPrimitive().getAsString();
-         Date toReturn = dateService.cDateParse(toParse);
-         return toReturn;
+      public Date read(JsonReader reader) throws IOException {
+         return dateService.cDateParse(reader.nextString());
       }
 
    }
 
    @Singleton
-   public static class LongDateAdapter implements DateAdapter {
+   public static class LongDateAdapter extends DateAdapter {
 
-      public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
-         return new JsonPrimitive(src.getTime());
+      public void write(JsonWriter writer, Date value) throws IOException {
+         writer.value(value.getTime());
       }
 
-      public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
-               throws JsonParseException {
-         long toParse = json.getAsJsonPrimitive().getAsLong();
+      public Date read(JsonReader reader) throws IOException {
+         long toParse = reader.nextLong();
          if (toParse == -1)
             return null;
-         Date toReturn = new Date(toParse);
-         return toReturn;
+         return new Date(toParse);
       }
    }
 
diff --git a/core/src/main/java/com/google/gson/JsonLiteral.java b/core/src/main/java/org/jclouds/json/internal/JsonLiteral.java
similarity index 83%
rename from core/src/main/java/com/google/gson/JsonLiteral.java
rename to core/src/main/java/org/jclouds/json/internal/JsonLiteral.java
index a9453bc..6fee782 100644
--- a/core/src/main/java/com/google/gson/JsonLiteral.java
+++ b/core/src/main/java/org/jclouds/json/internal/JsonLiteral.java
@@ -16,15 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package com.google.gson;
+package org.jclouds.json.internal;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
-import java.io.IOException;
+import com.google.gson.JsonElement;
 
 /**
  * The gson project use package to control access to their objects. However, this prevents us from
- * doing valid work, like controling the json emitted on a per-object basis. This is here to afford
+ * doing valid work, like controlling the json emitted on a per-object basis. This is here to afford
  * us to do this.
  * 
  * @author Adrian Cole
@@ -38,8 +38,8 @@
    }
 
    @Override
-   protected void toString(Appendable sb, Escaper escaper) throws IOException {
-      sb.append(literal);
+   public String toString() {
+      return literal.toString();
    }
 
 }
diff --git a/core/src/main/java/org/jclouds/json/internal/JsonObjectAsMap.java b/core/src/main/java/org/jclouds/json/internal/JsonObjectAsMap.java
deleted file mode 100644
index 678da27..0000000
--- a/core/src/main/java/org/jclouds/json/internal/JsonObjectAsMap.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.json.internal;
-
-import java.lang.reflect.Field;
-import java.util.Map;
-
-import com.google.common.base.Function;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-
-/**
- * Exposes the JsonObject as a map so that we can use gauva apis on it.
- * http://code.google.com/p/google-gson/issues/detail?id=325
- * @author Adrian Cole
- */
-public enum JsonObjectAsMap implements Function<JsonObject, Map<String, JsonElement>> {
-   INSTANCE;
-
-   private final Field members;
-
-   JsonObjectAsMap() {
-      try {
-         members = JsonObject.class.getDeclaredField("members");
-         members.setAccessible(true);
-      } catch (NoSuchFieldException e) {
-         throw new UnsupportedOperationException("cannot access gson internals", e);
-      }
-   }
-
-   @SuppressWarnings("unchecked")
-   @Override
-   public Map<String, JsonElement> apply(JsonObject in) {
-      try {
-         return (Map<String, JsonElement>) members.get(in);
-      } catch (IllegalArgumentException e) {
-         throw new UnsupportedOperationException("cannot access gson internals", e);
-      } catch (IllegalAccessException e) {
-         throw new UnsupportedOperationException("cannot access gson internals", e);
-      }
-   }
-}
\ No newline at end of file
diff --git a/core/src/main/java/org/jclouds/json/internal/ParseObjectFromElement.java b/core/src/main/java/org/jclouds/json/internal/ParseObjectFromElement.java
deleted file mode 100644
index 91055c0..0000000
--- a/core/src/main/java/org/jclouds/json/internal/ParseObjectFromElement.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.json.internal;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonPrimitive;
-
-/**
- * This is a class that helps the default {@link MapTypeAdapter} make a sane object graph when the
- * value is set to {@code Object}
- * http://code.google.com/p/google-gson/issues/detail?id=325
- * @author Adrian Cole
- */
-public enum ParseObjectFromElement implements Function<JsonElement, Object> {
-   SINGLETON;
-   public Object apply(JsonElement input) {
-      Object value = null;
-      if (input == null || input.isJsonNull()) {
-         value = null;
-      } else if (input.isJsonPrimitive()) {
-         JsonPrimitive primitive = input.getAsJsonPrimitive();
-         if (primitive.isNumber()) {
-            value = primitive.getAsNumber();
-         } else if (primitive.isBoolean()) {
-            value = primitive.getAsBoolean();
-         } else {
-            value = primitive.getAsString();
-         }
-      } else if (input.isJsonArray()) {
-         value = Lists.newArrayList(Iterables.transform(input.getAsJsonArray(), this));
-      } else if (input.isJsonObject()) {
-         value = Maps.<String,Object>newLinkedHashMap(Maps.transformValues(JsonObjectAsMap.INSTANCE.apply(input.getAsJsonObject()),
-               this));
-      }
-      return value;
-   }
-}
\ No newline at end of file
diff --git a/core/src/main/java/org/jclouds/rest/internal/GeneratedHttpRequest.java b/core/src/main/java/org/jclouds/rest/internal/GeneratedHttpRequest.java
index 0f0ddaf..064aa18 100644
--- a/core/src/main/java/org/jclouds/rest/internal/GeneratedHttpRequest.java
+++ b/core/src/main/java/org/jclouds/rest/internal/GeneratedHttpRequest.java
@@ -40,11 +40,21 @@
  * @author Adrian Cole
  */
 public class GeneratedHttpRequest<T> extends HttpRequest {
-   public static <T> Builder<T> builder() {
-      return new Builder<T>();
+   public static Builder<?> builder() {
+      // empty builder, so can be safely cast to Builder<T> by the caller
+      return new Builder<Object>();
    }
 
-   public static class Builder<T> extends HttpRequest.Builder<GeneratedHttpRequest<T>> {
+   /*
+    * Convenience method - cannot have the same signature as builder() - see
+    * http://code.google.com/p/jclouds/issues/detail?id=795
+    */
+   @SuppressWarnings("unchecked")
+   public static <T> Builder<T> requestBuilder() {
+       return (Builder<T>) builder();
+   }
+
+   public static class Builder<T> extends HttpRequest.Builder {
       protected Class<T> declaring;
       protected Method javaMethod;
       protected List<Object> args;
@@ -69,31 +79,37 @@
          return this;
       }
 
+      @SuppressWarnings("unchecked")
       @Override
       public Builder<T> filters(List<HttpRequestFilter> requestFilters) {
          return (Builder<T>) super.filters(requestFilters);
       }
 
+      @SuppressWarnings("unchecked")
       @Override
       public Builder<T> method(String method) {
          return (Builder<T>) super.method(method);
       }
 
+      @SuppressWarnings("unchecked")
       @Override
       public Builder<T> endpoint(URI endpoint) {
          return (Builder<T>) super.endpoint(endpoint);
       }
 
+      @SuppressWarnings("unchecked")
       @Override
       public Builder<T> skips(char[] skips) {
          return (Builder<T>) super.skips(skips);
       }
 
+      @SuppressWarnings("unchecked")
       @Override
       public Builder<T> payload(Payload payload) {
          return (Builder<T>) super.payload(payload);
       }
 
+      @SuppressWarnings("unchecked")
       @Override
       public Builder<T> headers(Multimap<String, String> headers) {
          return (Builder<T>) super.headers(headers);
@@ -105,11 +121,24 @@
                javaMethod, args);
       }
 
-      public static <Y> Builder<Y> from(HttpRequest input) {
-         return new Builder<Y>().method(input.getMethod()).endpoint(input.getEndpoint()).skips(input.getSkips())
+      public static Builder<?> from(HttpRequest input) {
+         /*
+          * State added to builder will not conflict with return type so caller can
+          * safely cast result to Builder<T>
+          */
+         return new Builder<Object>().method(input.getMethod()).endpoint(input.getEndpoint()).skips(input.getSkips())
                .filters(input.getFilters()).payload(input.getPayload()).headers(input.getHeaders());
       }
 
+      /*
+       * Convenience method - cannot have the same signature as from(HttpRequest) - see
+       * http://code.google.com/p/jclouds/issues/detail?id=795
+       */
+      @SuppressWarnings("unchecked")
+      public static <Y> Builder<Y> fromRequest(HttpRequest input) {
+          return (Builder<Y>) from(input);
+      }
+
       public static <Y> Builder<Y> from(GeneratedHttpRequest<Y> input) {
          return new Builder<Y>().method(input.getMethod()).endpoint(input.getEndpoint()).skips(input.getSkips())
                .filters(input.getFilters()).payload(input.getPayload()).headers(input.getHeaders())
diff --git a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java
index b2bbeb0..4b2133d 100644
--- a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java
+++ b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java
@@ -420,18 +420,10 @@
          GeneratedHttpRequest.Builder<T> requestBuilder;
          HttpRequest r = RestAnnotationProcessor.findHttpRequestInArgs(args);
          if (r != null) {
-            requestBuilder = GeneratedHttpRequest.Builder.<T> from(r);
+            requestBuilder = GeneratedHttpRequest.Builder.fromRequest(r);
             endpoint = r.getEndpoint();
          } else {
-            /*
-             * Can't use GeneratedHttpRequest.<T>builder() because the T is too
-             * general for the compiler to be able to distinguish between
-             * GeneratedHttpRequest.builder() and HttpMessage.builder() - the
-             * latter is available because GHR inherits from HM.
-             *
-             * See http://code.google.com/p/jclouds/issues/detail?id=461
-             */
-            requestBuilder = new GeneratedHttpRequest.Builder<T>();
+            requestBuilder = GeneratedHttpRequest.requestBuilder();
             requestBuilder.method(getHttpMethodOrConstantOrThrowException(method));
          }
 
diff --git a/core/src/test/java/org/jclouds/domain/JsonObjectTest.java b/core/src/test/java/org/jclouds/domain/JsonObjectTest.java
index 4fbd337..dd0bdab 100644
--- a/core/src/test/java/org/jclouds/domain/JsonObjectTest.java
+++ b/core/src/test/java/org/jclouds/domain/JsonObjectTest.java
@@ -58,20 +58,22 @@
    public void testHash() {
       String json = "{\"tomcat6\":{\"ssl_port\":8433}}";
 
-      Map<String, Object> map = ImmutableMap.<String, Object> of("tomcat6", ImmutableMap.of("ssl_port", 8433));
+      // gson deserialized numbers to double, so integers end up changed to fractions
+      assertEquals(handler.apply(new HttpResponse(200, "ok", Payloads.newStringPayload(json))),
+            ImmutableMap.<String, Object> of("tomcat6", ImmutableMap.of("ssl_port", 8433d)));
 
-      assertEquals(handler.apply(new HttpResponse(200, "ok", Payloads.newStringPayload(json))), map);
-      assertEquals(mapper.toJson(map), json);
+      assertEquals(mapper.toJson(ImmutableMap.<String, Object> of("tomcat6", ImmutableMap.of("ssl_port", 8433))), json);
 
    }
 
    public void testList() {
       String json = "{\"list\":[8431,8433]}";
 
-      Map<String, Object> map = ImmutableMap.<String, Object> of("list", ImmutableList.of(8431, 8433));
-
-      assertEquals(handler.apply(new HttpResponse(200, "ok", Payloads.newStringPayload(json))), map);
-      assertEquals(mapper.toJson(map), json);
+      // gson deserialized numbers to double, so integers end up changed to fractions
+      assertEquals(handler.apply(new HttpResponse(200, "ok", Payloads.newStringPayload(json))),
+            ImmutableMap.<String, Object> of("list", ImmutableList.of(8431d, 8433d)));
+      
+      assertEquals(mapper.toJson(ImmutableMap.<String, Object> of("list", ImmutableList.of(8431, 8433))), json);
 
    }
 
@@ -86,9 +88,9 @@
    }
 
    public void testNumber() {
-      String json = "{\"number\":1}";
+      String json = "{\"number\":1.0}";
 
-      Map<String, Object> map = ImmutableMap.<String, Object> of("number", 1);
+      Map<String, Object> map = ImmutableMap.<String, Object> of("number", 1d);
 
       assertEquals(handler.apply(new HttpResponse(200, "ok", Payloads.newStringPayload(json))), map);
       assertEquals(mapper.toJson(map), json);
diff --git a/core/src/test/java/org/jclouds/http/functions/ParseSaxTest.java b/core/src/test/java/org/jclouds/http/functions/ParseSaxTest.java
index 61bf1dd..4d9456f 100644
--- a/core/src/test/java/org/jclouds/http/functions/ParseSaxTest.java
+++ b/core/src/test/java/org/jclouds/http/functions/ParseSaxTest.java
@@ -22,6 +22,8 @@
 import static org.easymock.classextension.EasyMock.createMock;
 import static org.easymock.classextension.EasyMock.replay;
 import static org.easymock.classextension.EasyMock.verify;
+import static org.jclouds.utils.TestUtils.NO_INVOCATIONS;
+import static org.jclouds.utils.TestUtils.SINGLE_NO_ARG_INVOCATION;
 import static org.testng.Assert.assertEquals;
 
 import java.io.IOException;
@@ -31,6 +33,8 @@
 
 import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
+import org.jclouds.utils.TestUtils;
+import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 import org.xml.sax.Locator;
 import org.xml.sax.SAXParseException;
@@ -53,7 +57,17 @@
    ParseSax<String> createParser() {
       return factory.create(injector.getInstance(TestHandler.class));
    }
+   
+   @DataProvider
+   public Object[][] runUnderJava7() {
+       return (TestUtils.isJava7() ? SINGLE_NO_ARG_INVOCATION : NO_INVOCATIONS);
+   }
 
+   @DataProvider
+   public Object[][] ignoreUnderJava7() {
+       return (TestUtils.isJava7() ? NO_INVOCATIONS : SINGLE_NO_ARG_INVOCATION);
+   }
+   
    @Test
    public void testAddDetailsAndPropagateOkWhenRequestWithNoDataAndRuntimeExceptionThrowsOriginalException()
          throws ExecutionException, InterruptedException, TimeoutException, IOException {
@@ -99,7 +113,7 @@
          assertEquals(e.getCause(), input);
       }
    }
-
+   
    @Test
    public void testAddDetailsAndPropagateOkWithValidRequestResponse() throws ExecutionException, InterruptedException,
          TimeoutException, IOException {
@@ -118,7 +132,7 @@
       }
    }
 
-   @Test
+   @Test(dataProvider = "ignoreUnderJava7", description = "see http://code.google.com/p/jclouds/issues/detail?id=795")
    public void testAddDetailsAndPropagateOkWithValidRequestResponseWithSAXParseException() throws ExecutionException,
          InterruptedException, TimeoutException, IOException {
 
@@ -144,4 +158,29 @@
       }
    }
 
+   @Test(dataProvider = "runUnderJava7", description = "see http://code.google.com/p/jclouds/issues/detail?id=795")
+   public void testAddDetailsAndPropagateOkWithValidRequestResponseWithSAXParseException_java7() throws ExecutionException,
+         InterruptedException, TimeoutException, IOException {
+
+      ParseSax<String> parser = createParser();
+      HttpRequest request = new HttpRequest("GET", URI.create("http://foohost"));
+      HttpResponse response = new HttpResponse(304, "Not Modified", null);
+      Locator locator = createMock(Locator.class);
+      expect(locator.getColumnNumber()).andReturn(1);
+      expect(locator.getLineNumber()).andReturn(1);
+      expect(locator.getPublicId()).andReturn("publicId");
+      expect(locator.getSystemId()).andReturn("systemId");
+      replay(locator);
+      Exception input = new SAXParseException("foo", locator);
+      verify(locator);
+
+      try {
+         parser.setContext(request);
+         parser.addDetailsAndPropagate(response, input);
+      } catch (RuntimeException e) {
+         assertEquals(e.getMessage(),
+               "request: GET http://foohost HTTP/1.1; response: HTTP/1.1 304 Not Modified; error at 1:1 in document systemId; cause: org.xml.sax.SAXParseExceptionpublicId: publicId; systemId: systemId; lineNumber: 1; columnNumber: 1; foo");
+         assertEquals(e.getCause(), input);
+      }
+   }
 }
\ No newline at end of file
diff --git a/core/src/test/java/org/jclouds/json/JsonTest.java b/core/src/test/java/org/jclouds/json/JsonTest.java
index 7e90c92..8cee0e4 100644
--- a/core/src/test/java/org/jclouds/json/JsonTest.java
+++ b/core/src/test/java/org/jclouds/json/JsonTest.java
@@ -29,7 +29,6 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Maps;
-import com.google.gson.JsonParseException;
 import com.google.inject.Guice;
 import com.google.inject.TypeLiteral;
 
@@ -107,12 +106,12 @@
    public void testMapStringObjectWithAllValidValuesOneDeep() {
       Map<String, Object> map = Maps.newHashMap();
       map.put("string", "string");
-      map.put("number", 1);
+      map.put("number", 1.0);
       map.put("boolean", true);
       map.put("map", ImmutableMap.of("key", "value"));
       map.put("list", ImmutableList.of("key", "value"));
       assertEquals(json.toJson(map),
-               "{\"string\":\"string\",\"map\":{\"key\":\"value\"},\"list\":[\"key\",\"value\"],\"boolean\":true,\"number\":1}");
+               "{\"string\":\"string\",\"map\":{\"key\":\"value\"},\"list\":[\"key\",\"value\"],\"boolean\":true,\"number\":1.0}");
       Map<String, Object> map2 = json.fromJson(json.toJson(map), new TypeLiteral<Map<String, Object>>() {
       }.getType());
       assertEquals(map2, map);
@@ -143,7 +142,7 @@
       assertEquals(json.fromJson("{enumValue : \"FOO\"}", EnumInside.class).enumValue, EnumInside.Test.FOO);
    }
 
-   @Test(expectedExceptions = JsonParseException.class)
+   @Test(expectedExceptions = IllegalArgumentException.class)
    public void testDeserializeEnumWhenBadValue() {
       assertEquals(json.fromJson("{enumValue : \"s\"}", EnumInside.class).enumValue, EnumInside.Test.FOO);
    }
diff --git a/core/src/test/java/org/jclouds/rest/binders/BindMapToStringPayloadTest.java b/core/src/test/java/org/jclouds/rest/binders/BindMapToStringPayloadTest.java
index c09803d..c38fecf 100644
--- a/core/src/test/java/org/jclouds/rest/binders/BindMapToStringPayloadTest.java
+++ b/core/src/test/java/org/jclouds/rest/binders/BindMapToStringPayloadTest.java
@@ -54,8 +54,7 @@
    @Test
    public void testCorrect() throws SecurityException, NoSuchMethodException {
       Method testPayload = TestPayload.class.getMethod("testPayload", String.class);
-      // can't use GHR.builder() - see http://code.google.com/p/jclouds/issues/detail?id=461
-      GeneratedHttpRequest<TestPayload> request = new GeneratedHttpRequest.Builder<TestPayload>()
+      GeneratedHttpRequest<TestPayload> request = GeneratedHttpRequest.<TestPayload>requestBuilder()
             .declaring(TestPayload.class).javaMethod(testPayload).args(ImmutableList.<Object> of("robot"))
             .method(HttpMethod.POST).endpoint(URI.create("http://localhost")).build();
 
@@ -69,8 +68,7 @@
    @Test(expectedExceptions = IllegalArgumentException.class)
    public void testMustHavePayloadAnnotation() throws SecurityException, NoSuchMethodException {
       Method noPayload = TestPayload.class.getMethod("noPayload", String.class);
-      // can't use GHR.builder() - see http://code.google.com/p/jclouds/issues/detail?id=461
-      GeneratedHttpRequest<TestPayload> request = new GeneratedHttpRequest.Builder<TestPayload>()
+      GeneratedHttpRequest<TestPayload> request = GeneratedHttpRequest.<TestPayload>requestBuilder()
             .declaring(TestPayload.class).javaMethod(noPayload).args(ImmutableList.<Object> of("robot"))
             .method(HttpMethod.POST).endpoint(URI.create("http://localhost")).build();
       binder().bindToRequest(request, ImmutableMap.of("fooble", "robot"));
diff --git a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java
index 6acea0b..5f2bbdc 100644
--- a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java
+++ b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java
@@ -1816,8 +1816,7 @@
    public void oneTransformerWithContext() throws SecurityException, NoSuchMethodException {
       RestAnnotationProcessor<TestTransformers> processor = factory(TestTransformers.class);
       Method method = TestTransformers.class.getMethod("oneTransformerWithContext");
-      // can't use GHR.builder() - see http://code.google.com/p/jclouds/issues/detail?id=461
-      GeneratedHttpRequest<TestTransformers> request = new GeneratedHttpRequest.Builder<TestTransformers>().method("GET")
+      GeneratedHttpRequest<TestTransformers> request = GeneratedHttpRequest.<TestTransformers>requestBuilder().method("GET")
             .endpoint(URI.create("http://localhost")).declaring(TestTransformers.class).javaMethod(method)
             .args(new Object[] {}).build();
       Function<HttpResponse, ?> transformer = processor.createResponseParser(method, request);
@@ -2349,8 +2348,7 @@
    public void testCreateJAXBResponseParserWithAnnotation() throws SecurityException, NoSuchMethodException {
       RestAnnotationProcessor<TestJAXBResponseParser> processor = factory(TestJAXBResponseParser.class);
       Method method = TestJAXBResponseParser.class.getMethod("jaxbGetWithAnnotation");
-      // can't use GHR.builder() - see http://code.google.com/p/jclouds/issues/detail?id=461
-      GeneratedHttpRequest<TestJAXBResponseParser> request = new GeneratedHttpRequest.Builder<TestJAXBResponseParser>()
+      GeneratedHttpRequest<TestJAXBResponseParser> request = GeneratedHttpRequest.<TestJAXBResponseParser>requestBuilder()
             .method("GET").endpoint(URI.create("http://localhost")).declaring(TestJAXBResponseParser.class)
             .javaMethod(method).args(new Object[] {}).build();
       Function<HttpResponse, ?> transformer = processor.createResponseParser(method, request);
@@ -2361,8 +2359,7 @@
    public void testCreateJAXBResponseParserWithAcceptHeader() throws SecurityException, NoSuchMethodException {
       RestAnnotationProcessor<TestJAXBResponseParser> processor = factory(TestJAXBResponseParser.class);
       Method method = TestJAXBResponseParser.class.getMethod("jaxbGetWithAcceptHeader");
-      // can't use GHR.builder() - see http://code.google.com/p/jclouds/issues/detail?id=461
-      GeneratedHttpRequest<TestJAXBResponseParser> request = new GeneratedHttpRequest.Builder<TestJAXBResponseParser>()
+      GeneratedHttpRequest<TestJAXBResponseParser> request = GeneratedHttpRequest.<TestJAXBResponseParser>requestBuilder()
             .method("GET").endpoint(URI.create("http://localhost")).declaring(TestJAXBResponseParser.class)
             .javaMethod(method).args(new Object[] {}).build();
       Function<HttpResponse, ?> transformer = processor.createResponseParser(method, request);
diff --git a/core/src/test/java/org/jclouds/utils/TestUtils.java b/core/src/test/java/org/jclouds/utils/TestUtils.java
new file mode 100644
index 0000000..a3c1d4d
--- /dev/null
+++ b/core/src/test/java/org/jclouds/utils/TestUtils.java
@@ -0,0 +1,35 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.utils;
+
+/**
+ * Utility class for test
+ * 
+ * @author Andrew Phillips
+ * 
+ */
+public class TestUtils {
+    public static final Object[][] NO_INVOCATIONS = new Object[0][0];
+    public static final Object[][] SINGLE_NO_ARG_INVOCATION = new Object[][] { new Object[0] };
+
+    public static boolean isJava7() {
+        System.out.println(System.getProperty("java.version", "None??"));
+        return System.getProperty("java.version", "").contains("1.7.");
+    }
+}
diff --git a/demos/tweetstore/gae-tweetstore-spring/pom.xml b/demos/tweetstore/gae-tweetstore-spring/pom.xml
index c8882ca..8ef5caa 100644
--- a/demos/tweetstore/gae-tweetstore-spring/pom.xml
+++ b/demos/tweetstore/gae-tweetstore-spring/pom.xml
@@ -37,7 +37,7 @@
             extraction of appengine-java-sdk
         -->
         <appengine.applicationid>jclouds-tweetstore-spring</appengine.applicationid>
-        <appengine.sdk.version>1.5.5</appengine.sdk.version>
+        <appengine.sdk.version>1.6.1</appengine.sdk.version>
         <devappserver.address>localhost</devappserver.address>
         <devappserver.port>8088</devappserver.port>
         <jclouds.tweetstore.container>jclouds-gae-tweetstore-spring</jclouds.tweetstore.container>
diff --git a/demos/tweetstore/gae-tweetstore/pom.xml b/demos/tweetstore/gae-tweetstore/pom.xml
index 39e17b5..d1d5393 100644
--- a/demos/tweetstore/gae-tweetstore/pom.xml
+++ b/demos/tweetstore/gae-tweetstore/pom.xml
@@ -37,7 +37,7 @@
           extraction of appengine-java-sdk
         -->
         <appengine.applicationid>jclouds-tweetstore</appengine.applicationid>
-        <appengine.sdk.version>1.5.5</appengine.sdk.version>
+        <appengine.sdk.version>1.6.1</appengine.sdk.version>
         <devappserver.address>localhost</devappserver.address>
         <devappserver.port>8088</devappserver.port>
         <jclouds.tweetstore.container>jclouds-gae-tweetstore</jclouds.tweetstore.container>
diff --git a/providers/gogrid/src/main/java/org/jclouds/gogrid/config/DateSecondsAdapter.java b/providers/gogrid/src/main/java/org/jclouds/gogrid/config/DateSecondsAdapter.java
deleted file mode 100644
index 985b5e4..0000000
--- a/providers/gogrid/src/main/java/org/jclouds/gogrid/config/DateSecondsAdapter.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.gogrid.config;
-
-import java.lang.reflect.Type;
-import java.util.Date;
-
-import javax.inject.Singleton;
-
-import org.jclouds.json.config.GsonModule.DateAdapter;
-
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonParseException;
-import com.google.gson.JsonPrimitive;
-import com.google.gson.JsonSerializationContext;
-
-/**
- * Configures the GoGrid connection, including logging and http transport.
- * 
- * @author Adrian Cole
- * @author Oleksiy Yarmula
- */
-@Singleton
-public class DateSecondsAdapter implements DateAdapter {
-
-   public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
-      return new JsonPrimitive(src.getTime());
-   }
-
-   public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
-            throws JsonParseException {
-      String toParse = json.getAsJsonPrimitive().getAsString();
-      return new Date(Long.valueOf(toParse));
-   }
-}
\ No newline at end of file
diff --git a/providers/gogrid/src/main/java/org/jclouds/gogrid/config/GoGridParserModule.java b/providers/gogrid/src/main/java/org/jclouds/gogrid/config/GoGridParserModule.java
index d5205b7..41626cb 100644
--- a/providers/gogrid/src/main/java/org/jclouds/gogrid/config/GoGridParserModule.java
+++ b/providers/gogrid/src/main/java/org/jclouds/gogrid/config/GoGridParserModule.java
@@ -35,6 +35,7 @@
 import org.jclouds.gogrid.domain.ServerState;
 import org.jclouds.gogrid.functions.internal.CustomDeserializers;
 import org.jclouds.json.config.GsonModule.DateAdapter;
+import org.jclouds.json.config.GsonModule.LongDateAdapter;
 
 import com.google.common.collect.Maps;
 import com.google.inject.AbstractModule;
@@ -68,7 +69,7 @@
 
    @Override
    protected void configure() {
-      bind(DateAdapter.class).to(DateSecondsAdapter.class);
+      bind(DateAdapter.class).to(LongDateAdapter.class);
    }
 
 }
\ No newline at end of file
diff --git a/providers/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseCredentialsFromJsonResponseTest.java b/providers/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseCredentialsFromJsonResponseTest.java
index 5aa7638..3590f10 100644
--- a/providers/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseCredentialsFromJsonResponseTest.java
+++ b/providers/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseCredentialsFromJsonResponseTest.java
@@ -28,7 +28,6 @@
 import javax.inject.Singleton;
 
 import org.jclouds.domain.Credentials;
-import org.jclouds.gogrid.config.DateSecondsAdapter;
 import org.jclouds.gogrid.domain.IpState;
 import org.jclouds.gogrid.domain.ServerImageState;
 import org.jclouds.gogrid.domain.ServerImageType;
@@ -77,7 +76,7 @@
    Injector i = Guice.createInjector(new GsonModule() {
       @Override
       protected void configure() {
-         bind(DateAdapter.class).to(DateSecondsAdapter.class);
+         bind(DateAdapter.class).to(LongDateAdapter.class);
          super.configure();
       }
 
diff --git a/providers/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseErrorFromJsonResponseTest.java b/providers/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseErrorFromJsonResponseTest.java
index 7f8169a..9121038 100644
--- a/providers/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseErrorFromJsonResponseTest.java
+++ b/providers/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseErrorFromJsonResponseTest.java
@@ -21,7 +21,6 @@
 import java.io.InputStream;
 import java.net.UnknownHostException;
 
-import org.jclouds.gogrid.config.DateSecondsAdapter;
 import org.jclouds.gogrid.domain.internal.ErrorResponse;
 import org.jclouds.http.HttpResponse;
 import org.jclouds.io.Payloads;
@@ -42,7 +41,7 @@
    Injector i = Guice.createInjector(new GsonModule() {
       @Override
       protected void configure() {
-         bind(DateAdapter.class).to(DateSecondsAdapter.class);
+         bind(DateAdapter.class).to(LongDateAdapter.class);
          super.configure();
       }
    });
diff --git a/providers/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseJobsFromJsonResponseTest.java b/providers/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseJobsFromJsonResponseTest.java
index c699dc4..a5f5d7d 100644
--- a/providers/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseJobsFromJsonResponseTest.java
+++ b/providers/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseJobsFromJsonResponseTest.java
@@ -29,7 +29,6 @@
 
 import javax.inject.Singleton;
 
-import org.jclouds.gogrid.config.DateSecondsAdapter;
 import org.jclouds.gogrid.domain.Job;
 import org.jclouds.gogrid.domain.JobProperties;
 import org.jclouds.gogrid.domain.JobState;
@@ -80,7 +79,7 @@
    Injector i = Guice.createInjector(new GsonModule() {
       @Override
       protected void configure() {
-         bind(DateAdapter.class).to(DateSecondsAdapter.class);
+         bind(DateAdapter.class).to(LongDateAdapter.class);
          super.configure();
       }
 
diff --git a/providers/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseLoadBalancersFromJsonResponseTest.java b/providers/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseLoadBalancersFromJsonResponseTest.java
index a936bd6..d697f86 100644
--- a/providers/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseLoadBalancersFromJsonResponseTest.java
+++ b/providers/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseLoadBalancersFromJsonResponseTest.java
@@ -28,7 +28,6 @@
 
 import javax.inject.Singleton;
 
-import org.jclouds.gogrid.config.DateSecondsAdapter;
 import org.jclouds.gogrid.domain.Ip;
 import org.jclouds.gogrid.domain.IpPortPair;
 import org.jclouds.gogrid.domain.IpState;
@@ -79,7 +78,7 @@
    Injector i = Guice.createInjector(new GsonModule() {
       @Override
       protected void configure() {
-         bind(DateAdapter.class).to(DateSecondsAdapter.class);
+         bind(DateAdapter.class).to(LongDateAdapter.class);
          super.configure();
       }
 
diff --git a/providers/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseServerNameToCredentialsMapFromJsonResponseTest.java b/providers/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseServerNameToCredentialsMapFromJsonResponseTest.java
index a86a3e6..f955906 100644
--- a/providers/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseServerNameToCredentialsMapFromJsonResponseTest.java
+++ b/providers/gogrid/src/test/java/org/jclouds/gogrid/functions/ParseServerNameToCredentialsMapFromJsonResponseTest.java
@@ -28,7 +28,6 @@
 import javax.inject.Singleton;
 
 import org.jclouds.domain.Credentials;
-import org.jclouds.gogrid.config.DateSecondsAdapter;
 import org.jclouds.gogrid.domain.IpState;
 import org.jclouds.gogrid.domain.ServerImageState;
 import org.jclouds.gogrid.domain.ServerImageType;
@@ -65,7 +64,7 @@
    Injector i = Guice.createInjector(new GsonModule() {
       @Override
       protected void configure() {
-         bind(DateAdapter.class).to(DateSecondsAdapter.class);
+         bind(DateAdapter.class).to(LongDateAdapter.class);
          super.configure();
       }
 
diff --git a/providers/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/config/RimuHostingRestClientModule.java b/providers/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/config/RimuHostingRestClientModule.java
index c7b5071..56f6562 100644
--- a/providers/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/config/RimuHostingRestClientModule.java
+++ b/providers/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/config/RimuHostingRestClientModule.java
@@ -18,7 +18,7 @@
  */
 package org.jclouds.rimuhosting.miro.config;
 
-import java.lang.reflect.Type;
+import java.io.IOException;
 import java.util.Date;
 
 import javax.inject.Inject;
@@ -26,17 +26,16 @@
 
 import org.jclouds.date.DateService;
 import org.jclouds.http.RequiresHttp;
-import org.jclouds.json.Json;
+import org.jclouds.json.config.GsonModule;
 import org.jclouds.json.config.GsonModule.DateAdapter;
+import org.jclouds.json.config.GsonModule.PropertiesAdapter;
 import org.jclouds.rest.ConfiguresRestClient;
 import org.jclouds.rest.config.RestClientModule;
 import org.jclouds.rimuhosting.miro.RimuHostingAsyncClient;
 import org.jclouds.rimuhosting.miro.RimuHostingClient;
 
-import com.google.gson.JsonDeserializationContext;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonParseException;
-import com.google.gson.JsonSerializationContext;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
 
 /**
  * 
@@ -57,29 +56,25 @@
    }
 
    @Singleton
-   public static class RimuIso8601DateAdapter implements DateAdapter {
+   public static class RimuIso8601DateAdapter extends GsonModule.DateAdapter {
       private final DateService dateService;
-      private final Json json;
-
-      private static class DateHolder {
-         String iso_format;
-      }
+      private final PropertiesAdapter propertiesAdapter;
 
       @Inject
-      private RimuIso8601DateAdapter(DateService dateService, Json json) {
+      private RimuIso8601DateAdapter(DateService dateService, PropertiesAdapter propertiesAdapter) {
          this.dateService = dateService;
-         this.json = json;
+         this.propertiesAdapter = propertiesAdapter;
       }
 
-      public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
+      public void write(JsonWriter writer, Date value) throws IOException {
          throw new UnsupportedOperationException();
       }
 
-      public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
-               throws JsonParseException {
-         String toParse = json.toString();
-         DateHolder dateHolder = this.json.fromJson(toParse, DateHolder.class);
-         return (dateHolder.iso_format != null) ? dateService.iso8601SecondsDateParse(dateHolder.iso_format) : null;
+      public Date read(JsonReader in) throws IOException {
+         String isoFormat = propertiesAdapter.read(in).getProperty("iso_format");
+         if (isoFormat != null)
+            return dateService.iso8601SecondsDateParse(isoFormat);
+         return null;
       }
 
    }
diff --git a/sandbox-apis/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/StartVBoxIfNotAlreadyRunningTest.java b/sandbox-apis/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/StartVBoxIfNotAlreadyRunningTest.java
index 00506d2..6328cf1 100644
--- a/sandbox-apis/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/StartVBoxIfNotAlreadyRunningTest.java
+++ b/sandbox-apis/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/StartVBoxIfNotAlreadyRunningTest.java
@@ -19,30 +19,28 @@
 
 package org.jclouds.virtualbox.functions.admin;
 
-import static org.easymock.EasyMock.expect;
-import static org.easymock.classextension.EasyMock.createMock;
-import static org.easymock.classextension.EasyMock.replay;
-import static org.easymock.classextension.EasyMock.verify;
-import static org.testng.Assert.assertEquals;
-
-import java.net.URI;
-
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.inject.AbstractModule;
+import com.google.inject.Module;
 import org.jclouds.compute.ComputeService;
 import org.jclouds.compute.ComputeServiceContextFactory;
 import org.jclouds.compute.domain.ExecResponse;
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.domain.Credentials;
+import org.jclouds.domain.LoginCredentials;
 import org.jclouds.net.IPSocket;
 import org.jclouds.ssh.ConfiguresSshClient;
 import org.jclouds.ssh.SshClient;
 import org.testng.annotations.Test;
 import org.virtualbox_4_1.VirtualBoxManager;
 
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.inject.AbstractModule;
-import com.google.inject.Module;
+import java.net.URI;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.classextension.EasyMock.*;
+import static org.testng.Assert.assertEquals;
 
 @Test(groups = "unit", singleThreaded = true, testName = "StartVBoxIfNotAlreadyRunningTest")
 public class StartVBoxIfNotAlreadyRunningTest {
@@ -112,11 +110,11 @@
          // these values. Right now, it is node 2 since the above test made node
          // 1.
          IPSocket expectedSshSockectFor2ndCreatedNode = new IPSocket("144.175.1.2", 22);
-         Credentials expectedCredentialsFor2ndCreatedNode = new Credentials("root", "password2");
-         expect(factory.create(expectedSshSockectFor2ndCreatedNode, expectedCredentialsFor2ndCreatedNode)).andReturn(
+         LoginCredentials loginCredentials = new LoginCredentials("root", "password2", null, false);
+         expect(factory.create(expectedSshSockectFor2ndCreatedNode, loginCredentials)).andReturn(
                client).times(2);
 
-         expect(client.getUsername()).andReturn(expectedCredentialsFor2ndCreatedNode.identity).times(2);
+         expect(client.getUsername()).andReturn(loginCredentials.identity).times(2);
          expect(client.getHostAddress()).andReturn(expectedSshSockectFor2ndCreatedNode.getAddress()).times(2);
 
          client.disconnect();