mirror of https://github.com/apache/jclouds.git
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
This commit is contained in:
commit
8d84f8c699
|
@ -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 @@ import java.util.Date;
|
|||
*
|
||||
* @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"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -96,12 +96,17 @@ public class EC2ListNodesStrategy implements ListNodesStrategy {
|
|||
@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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,54 +27,47 @@ package org.jclouds.openstack.nova.domain;
|
|||
*/
|
||||
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 @@ public class Flavor extends Resource {
|
|||
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 @@ public class Flavor extends Resource {
|
|||
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 +"]";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,11 @@ public class Resource {
|
|||
};
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -44,7 +44,7 @@ public class FlavorToHardwareTest {
|
|||
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()))
|
||||
|
|
|
@ -55,6 +55,7 @@ public class ParseFlavorFromJsonResponseTest {
|
|||
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() {
|
||||
|
|
|
@ -50,7 +50,7 @@ public class ParseFlavorListFromJsonResponseTest {
|
|||
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 @@ public class ParseFlavorListFromJsonResponseTest {
|
|||
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));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
"name" : "256 MB Server",
|
||||
"ram" : 256,
|
||||
"disk" : 10,
|
||||
"vcpus" : 2,
|
||||
"links": [
|
||||
{
|
||||
"rel" : "self",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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.io.Writer;
|
|||
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 @@ import com.google.gson.JsonLiteral;
|
|||
* @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 @@ public final class JsonWriter implements Closeable {
|
|||
|
||||
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 @@ public final class JsonWriter implements Closeable {
|
|||
*
|
||||
* @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 @@ public final class JsonWriter implements Closeable {
|
|||
* Double#isInfinite() infinities}.
|
||||
* </ul>
|
||||
*/
|
||||
public void setLenient(boolean lenient) {
|
||||
public final void setLenient(boolean lenient) {
|
||||
this.lenient = lenient;
|
||||
}
|
||||
|
||||
|
@ -209,7 +212,7 @@ public final class JsonWriter implements Closeable {
|
|||
* 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,10 +220,26 @@ public final class JsonWriter implements Closeable {
|
|||
* 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}.
|
||||
|
@ -228,6 +247,7 @@ public final class JsonWriter implements Closeable {
|
|||
* @return this writer.
|
||||
*/
|
||||
public JsonWriter beginArray() throws IOException {
|
||||
writeDeferredName();
|
||||
return open(JsonScope.EMPTY_ARRAY, "[");
|
||||
}
|
||||
|
||||
|
@ -247,6 +267,7 @@ public final class JsonWriter implements Closeable {
|
|||
* @return this writer.
|
||||
*/
|
||||
public JsonWriter beginObject() throws IOException {
|
||||
writeDeferredName();
|
||||
return open(JsonScope.EMPTY_OBJECT, "{");
|
||||
}
|
||||
|
||||
|
@ -280,6 +301,9 @@ public final class JsonWriter implements Closeable {
|
|||
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 @@ public final class JsonWriter implements Closeable {
|
|||
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 @@ public final class JsonWriter implements Closeable {
|
|||
if (value == null) {
|
||||
return nullValue();
|
||||
}
|
||||
writeDeferredName();
|
||||
beforeValue(false);
|
||||
string(value);
|
||||
return this;
|
||||
|
@ -339,29 +374,42 @@ public final class JsonWriter implements Closeable {
|
|||
* @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 @@ public final class JsonWriter implements Closeable {
|
|||
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 @@ public final class JsonWriter implements Closeable {
|
|||
* @return this writer.
|
||||
*/
|
||||
public JsonWriter value(long value) throws IOException {
|
||||
writeDeferredName();
|
||||
beforeValue(false);
|
||||
out.write(Long.toString(value));
|
||||
return this;
|
||||
|
@ -406,6 +456,7 @@ public final class JsonWriter implements Closeable {
|
|||
return nullValue();
|
||||
}
|
||||
|
||||
writeDeferredName();
|
||||
String string = value.toString();
|
||||
if (!lenient
|
||||
&& (string.equals("-Infinity") || string.equals("Infinity") || string.equals("NaN"))) {
|
||||
|
@ -447,6 +498,10 @@ public final class JsonWriter implements Closeable {
|
|||
* 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 @@ public final class JsonWriter implements Closeable {
|
|||
}
|
||||
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));
|
||||
|
|
|
@ -36,31 +36,30 @@ import com.google.common.collect.Multimap;
|
|||
* @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 @@ public class HttpMessage extends PayloadEnclosingImpl {
|
|||
return (values.size() >= 1) ? values.iterator().next() : null;
|
||||
}
|
||||
|
||||
public Builder<? extends HttpMessage> toBuilder() {
|
||||
public Builder toBuilder() {
|
||||
return Builder.from(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,32 +39,32 @@ import com.google.common.collect.Multimap;
|
|||
* @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 @@ public class HttpRequest extends HttpMessage {
|
|||
}
|
||||
|
||||
@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 @@ public class HttpRequest extends HttpMessage {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Builder<? extends HttpRequest> toBuilder() {
|
||||
public Builder toBuilder() {
|
||||
return Builder.from(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ public class HttpResponse extends HttpMessage {
|
|||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder extends HttpMessage.Builder<HttpResponse> {
|
||||
public static class Builder extends HttpMessage.Builder {
|
||||
private int statusCode;
|
||||
private String message;
|
||||
|
||||
|
|
|
@ -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.domain.JsonBall;
|
|||
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.GsonBuilder;
|
|||
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 @@ public class GsonModule extends AbstractModule {
|
|||
@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 class GsonModule extends AbstractModule {
|
|||
}
|
||||
|
||||
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 @@ public class GsonModule extends AbstractModule {
|
|||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 @@ public final class JsonLiteral extends JsonElement {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void toString(Appendable sb, Escaper escaper) throws IOException {
|
||||
sb.append(literal);
|
||||
public String toString() {
|
||||
return literal.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -40,11 +40,21 @@ import com.google.common.collect.Multimap;
|
|||
* @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 @@ public class GeneratedHttpRequest<T> extends HttpRequest {
|
|||
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 @@ public class GeneratedHttpRequest<T> extends HttpRequest {
|
|||
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())
|
||||
|
|
|
@ -420,18 +420,10 @@ public class RestAnnotationProcessor<T> {
|
|||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -58,20 +58,22 @@ public class JsonObjectTest {
|
|||
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));
|
||||
// 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(handler.apply(new HttpResponse(200, "ok", Payloads.newStringPayload(json))), map);
|
||||
assertEquals(mapper.toJson(map), json);
|
||||
assertEquals(mapper.toJson(ImmutableMap.<String, Object> of("list", ImmutableList.of(8431, 8433))), json);
|
||||
|
||||
}
|
||||
|
||||
|
@ -86,9 +88,9 @@ public class JsonObjectTest {
|
|||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -22,6 +22,8 @@ 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.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 java.util.concurrent.TimeoutException;
|
|||
|
||||
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;
|
||||
|
@ -54,6 +58,16 @@ public class ParseSaxTest extends BaseHandlerTest {
|
|||
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 {
|
||||
|
@ -118,7 +132,7 @@ public class ParseSaxTest extends BaseHandlerTest {
|
|||
}
|
||||
}
|
||||
|
||||
@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 @@ public class ParseSaxTest extends BaseHandlerTest {
|
|||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,7 +29,6 @@ import org.testng.annotations.Test;
|
|||
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 class JsonTest {
|
|||
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 @@ public class JsonTest {
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -54,8 +54,7 @@ public class BindMapToStringPayloadTest {
|
|||
@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 @@ public class BindMapToStringPayloadTest {
|
|||
@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"));
|
||||
|
|
|
@ -1816,8 +1816,7 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
|||
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 class RestAnnotationProcessorTest extends BaseRestClientTest {
|
|||
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 class RestAnnotationProcessorTest extends BaseRestClientTest {
|
|||
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);
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -35,6 +35,7 @@ import org.jclouds.gogrid.domain.ServerImageType;
|
|||
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 @@ public class GoGridParserModule extends AbstractModule {
|
|||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(DateAdapter.class).to(DateSecondsAdapter.class);
|
||||
bind(DateAdapter.class).to(LongDateAdapter.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -28,7 +28,6 @@ import java.util.Map;
|
|||
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 @@ public class ParseCredentialsFromJsonResponseTest {
|
|||
Injector i = Guice.createInjector(new GsonModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(DateAdapter.class).to(DateSecondsAdapter.class);
|
||||
bind(DateAdapter.class).to(LongDateAdapter.class);
|
||||
super.configure();
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ package org.jclouds.gogrid.functions;
|
|||
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 @@ public class ParseErrorFromJsonResponseTest {
|
|||
Injector i = Guice.createInjector(new GsonModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(DateAdapter.class).to(DateSecondsAdapter.class);
|
||||
bind(DateAdapter.class).to(LongDateAdapter.class);
|
||||
super.configure();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -29,7 +29,6 @@ import java.util.SortedSet;
|
|||
|
||||
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 @@ public class ParseJobsFromJsonResponseTest {
|
|||
Injector i = Guice.createInjector(new GsonModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(DateAdapter.class).to(DateSecondsAdapter.class);
|
||||
bind(DateAdapter.class).to(LongDateAdapter.class);
|
||||
super.configure();
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ import java.util.SortedSet;
|
|||
|
||||
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 @@ public class ParseLoadBalancersFromJsonResponseTest {
|
|||
Injector i = Guice.createInjector(new GsonModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(DateAdapter.class).to(DateSecondsAdapter.class);
|
||||
bind(DateAdapter.class).to(LongDateAdapter.class);
|
||||
super.configure();
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ import java.util.Map;
|
|||
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 @@ public class ParseServerNameToCredentialsMapFromJsonResponseTest {
|
|||
Injector i = Guice.createInjector(new GsonModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(DateAdapter.class).to(DateSecondsAdapter.class);
|
||||
bind(DateAdapter.class).to(LongDateAdapter.class);
|
||||
super.configure();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 javax.inject.Singleton;
|
|||
|
||||
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 @@ public class RimuHostingRestClientModule extends RestClientModule<RimuHostingCli
|
|||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 @@ public class StartVBoxIfNotAlreadyRunningTest {
|
|||
// 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();
|
||||
|
|
Loading…
Reference in New Issue