From ecaa3759dcd4aa4f040eba11dbf04a44622f3bf8 Mon Sep 17 00:00:00 2001
From: Olof Larsson
Date: Wed, 7 Dec 2011 18:31:56 +0100
Subject: [PATCH] added gson2 and persis v2beta
---
...onymousAndLocalClassExclusionStrategy.java | 38 +
.../massivecraft/core/lib/gson2/Cache.java | 43 +
.../gson2/CamelCaseSeparatorNamingPolicy.java | 75 ++
.../gson2/CompositionFieldNamingPolicy.java | 46 +
.../core/lib/gson2/DefaultTypeAdapters.java | 122 ++
.../gson2/DisjunctionExclusionStrategy.java | 53 +
.../core/lib/gson2/ExclusionStrategy.java | 109 ++
...ationDeserializationExclusionStrategy.java | 38 +
...otationSerializationExclusionStrategy.java | 38 +
.../core/lib/gson2/FieldAttributes.java | 222 ++++
.../core/lib/gson2/FieldNamingPolicy.java | 99 ++
.../core/lib/gson2/FieldNamingStrategy.java | 40 +
.../core/lib/gson2/FieldNamingStrategy2.java | 37 +
.../gson2/FieldNamingStrategy2Adapter.java | 39 +
src/com/massivecraft/core/lib/gson2/Gson.java | 802 +++++++++++
.../core/lib/gson2/GsonBuilder.java | 717 ++++++++++
.../GsonToMiniGsonTypeAdapterFactory.java | 110 ++
.../gson2/InnerClassExclusionStrategy.java | 43 +
.../core/lib/gson2/InstanceCreator.java | 92 ++
.../core/lib/gson2/JavaFieldNamingPolicy.java | 51 +
.../core/lib/gson2/JsonArray.java | 282 ++++
.../lib/gson2/JsonDeserializationContext.java | 44 +
.../core/lib/gson2/JsonDeserializer.java | 88 ++
.../JsonDeserializerExceptionWrapper.java | 72 +
.../core/lib/gson2/JsonElement.java | 325 +++++
.../core/lib/gson2/JsonElementVisitor.java | 47 +
.../core/lib/gson2/JsonIOException.java | 46 +
.../massivecraft/core/lib/gson2/JsonNull.java | 58 +
.../core/lib/gson2/JsonObject.java | 200 +++
.../core/lib/gson2/JsonParseException.java | 64 +
.../core/lib/gson2/JsonParser.java | 99 ++
.../core/lib/gson2/JsonPrimitive.java | 336 +++++
.../lib/gson2/JsonSerializationContext.java | 49 +
.../core/lib/gson2/JsonSerializer.java | 86 ++
.../core/lib/gson2/JsonStreamParser.java | 123 ++
.../core/lib/gson2/JsonSyntaxException.java | 47 +
.../lib/gson2/LongSerializationPolicy.java | 74 ++
.../LowerCamelCaseSeparatorNamingPolicy.java | 43 +
.../core/lib/gson2/LowerCaseNamingPolicy.java | 50 +
.../massivecraft/core/lib/gson2/LruCache.java | 53 +
.../gson2/ModifierBasedExclusionStrategy.java | 53 +
.../gson2/ModifyFirstLetterNamingPolicy.java | 108 ++
.../lib/gson2/RecursiveFieldNamingPolicy.java | 45 +
...ameAnnotationInterceptingNamingPolicy.java | 48 +
.../SyntheticFieldExclusionStrategy.java | 44 +
.../UpperCamelCaseSeparatorNamingPolicy.java | 45 +
.../core/lib/gson2/UpperCaseNamingPolicy.java | 48 +
.../core/lib/gson2/VersionConstants.java | 29 +
.../lib/gson2/VersionExclusionStrategy.java | 68 +
.../core/lib/gson2/annotations/Expose.java | 79 ++
.../lib/gson2/annotations/SerializedName.java | 74 ++
.../core/lib/gson2/annotations/Since.java | 61 +
.../core/lib/gson2/annotations/Until.java | 66 +
.../lib/gson2/annotations/package-info.java | 6 +
.../gson2/internal/$Gson$Preconditions.java | 51 +
.../core/lib/gson2/internal/$Gson$Types.java | 592 +++++++++
.../internal/ConstructorConstructor.java | 177 +++
.../gson2/internal/LazilyParsedNumber.java | 69 +
.../lib/gson2/internal/ObjectConstructor.java | 33 +
.../core/lib/gson2/internal/Pair.java | 61 +
.../internal/ParameterizedTypeHandlerMap.java | 247 ++++
.../core/lib/gson2/internal/Primitives.java | 119 ++
.../core/lib/gson2/internal/Streams.java | 116 ++
.../lib/gson2/internal/UnsafeAllocator.java | 104 ++
.../gson2/internal/bind/ArrayTypeAdapter.java | 96 ++
.../internal/bind/BigDecimalTypeAdapter.java | 51 +
.../internal/bind/BigIntegerTypeAdapter.java | 51 +
.../bind/CollectionTypeAdapterFactory.java | 99 ++
.../gson2/internal/bind/DateTypeAdapter.java | 91 ++
.../bind/ExcludedTypeAdapterFactory.java | 80 ++
.../internal/bind/JsonElementReader.java | 219 +++
.../internal/bind/JsonElementWriter.java | 201 +++
.../internal/bind/MapTypeAdapterFactory.java | 261 ++++
.../lib/gson2/internal/bind/MiniGson.java | 207 +++
.../internal/bind/ObjectTypeAdapter.java | 105 ++
.../lib/gson2/internal/bind/Reflection.java | 32 +
.../bind/ReflectiveTypeAdapterFactory.java | 204 +++
.../internal/bind/SqlDateTypeAdapter.java | 65 +
.../StringToValueMapTypeAdapterFactory.java | 108 ++
.../gson2/internal/bind/TimeTypeAdapter.java | 64 +
.../lib/gson2/internal/bind/TypeAdapter.java | 80 ++
.../bind/TypeAdapterRuntimeTypeWrapper.java | 69 +
.../lib/gson2/internal/bind/TypeAdapters.java | 752 +++++++++++
.../core/lib/gson2/internal/package-info.java | 7 +
.../core/lib/gson2/package-info.java | 11 +
.../core/lib/gson2/reflect/TypeToken.java | 307 +++++
.../core/lib/gson2/reflect/package-info.java | 6 +
.../core/lib/gson2/stream/JsonReader.java | 1170 +++++++++++++++++
.../core/lib/gson2/stream/JsonScope.java | 71 +
.../core/lib/gson2/stream/JsonToken.java | 85 ++
.../core/lib/gson2/stream/JsonWriter.java | 610 +++++++++
.../gson2/stream/MalformedJsonException.java | 44 +
.../core/lib/gson2/stream/StringPool.java | 60 +
src/com/massivecraft/core/persist/Entity.java | 45 +
.../core/persist/IClassManager.java | 74 ++
.../massivecraft/core/persist/Persist.java | 209 +++
.../core/persist/PlayerEntity.java | 30 +
.../massivecraft/core/persist/Predictate.java | 6 +
.../massivecraft/core/persist/SaveTask.java | 35 +
.../core/persist/gson/GsonClassManager.java | 458 +++++++
.../persist/gson/GsonPlayerEntityManager.java | 55 +
.../core/persist/gson/JsonFileFilter.java | 24 +
102 files changed, 13485 insertions(+)
create mode 100755 src/com/massivecraft/core/lib/gson2/AnonymousAndLocalClassExclusionStrategy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/Cache.java
create mode 100755 src/com/massivecraft/core/lib/gson2/CamelCaseSeparatorNamingPolicy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/CompositionFieldNamingPolicy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/DefaultTypeAdapters.java
create mode 100755 src/com/massivecraft/core/lib/gson2/DisjunctionExclusionStrategy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/ExclusionStrategy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/ExposeAnnotationDeserializationExclusionStrategy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/ExposeAnnotationSerializationExclusionStrategy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/FieldAttributes.java
create mode 100755 src/com/massivecraft/core/lib/gson2/FieldNamingPolicy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/FieldNamingStrategy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/FieldNamingStrategy2.java
create mode 100755 src/com/massivecraft/core/lib/gson2/FieldNamingStrategy2Adapter.java
create mode 100755 src/com/massivecraft/core/lib/gson2/Gson.java
create mode 100755 src/com/massivecraft/core/lib/gson2/GsonBuilder.java
create mode 100755 src/com/massivecraft/core/lib/gson2/GsonToMiniGsonTypeAdapterFactory.java
create mode 100755 src/com/massivecraft/core/lib/gson2/InnerClassExclusionStrategy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/InstanceCreator.java
create mode 100755 src/com/massivecraft/core/lib/gson2/JavaFieldNamingPolicy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/JsonArray.java
create mode 100755 src/com/massivecraft/core/lib/gson2/JsonDeserializationContext.java
create mode 100755 src/com/massivecraft/core/lib/gson2/JsonDeserializer.java
create mode 100755 src/com/massivecraft/core/lib/gson2/JsonDeserializerExceptionWrapper.java
create mode 100755 src/com/massivecraft/core/lib/gson2/JsonElement.java
create mode 100755 src/com/massivecraft/core/lib/gson2/JsonElementVisitor.java
create mode 100755 src/com/massivecraft/core/lib/gson2/JsonIOException.java
create mode 100755 src/com/massivecraft/core/lib/gson2/JsonNull.java
create mode 100755 src/com/massivecraft/core/lib/gson2/JsonObject.java
create mode 100755 src/com/massivecraft/core/lib/gson2/JsonParseException.java
create mode 100755 src/com/massivecraft/core/lib/gson2/JsonParser.java
create mode 100755 src/com/massivecraft/core/lib/gson2/JsonPrimitive.java
create mode 100755 src/com/massivecraft/core/lib/gson2/JsonSerializationContext.java
create mode 100755 src/com/massivecraft/core/lib/gson2/JsonSerializer.java
create mode 100755 src/com/massivecraft/core/lib/gson2/JsonStreamParser.java
create mode 100755 src/com/massivecraft/core/lib/gson2/JsonSyntaxException.java
create mode 100755 src/com/massivecraft/core/lib/gson2/LongSerializationPolicy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/LowerCamelCaseSeparatorNamingPolicy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/LowerCaseNamingPolicy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/LruCache.java
create mode 100755 src/com/massivecraft/core/lib/gson2/ModifierBasedExclusionStrategy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/ModifyFirstLetterNamingPolicy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/RecursiveFieldNamingPolicy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/SerializedNameAnnotationInterceptingNamingPolicy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/SyntheticFieldExclusionStrategy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/UpperCamelCaseSeparatorNamingPolicy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/UpperCaseNamingPolicy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/VersionConstants.java
create mode 100755 src/com/massivecraft/core/lib/gson2/VersionExclusionStrategy.java
create mode 100755 src/com/massivecraft/core/lib/gson2/annotations/Expose.java
create mode 100755 src/com/massivecraft/core/lib/gson2/annotations/SerializedName.java
create mode 100755 src/com/massivecraft/core/lib/gson2/annotations/Since.java
create mode 100755 src/com/massivecraft/core/lib/gson2/annotations/Until.java
create mode 100755 src/com/massivecraft/core/lib/gson2/annotations/package-info.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/$Gson$Preconditions.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/$Gson$Types.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/ConstructorConstructor.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/LazilyParsedNumber.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/ObjectConstructor.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/Pair.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/ParameterizedTypeHandlerMap.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/Primitives.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/Streams.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/UnsafeAllocator.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/bind/ArrayTypeAdapter.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/bind/BigDecimalTypeAdapter.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/bind/BigIntegerTypeAdapter.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/bind/CollectionTypeAdapterFactory.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/bind/DateTypeAdapter.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/bind/ExcludedTypeAdapterFactory.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/bind/JsonElementReader.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/bind/JsonElementWriter.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/bind/MapTypeAdapterFactory.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/bind/MiniGson.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/bind/ObjectTypeAdapter.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/bind/Reflection.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/bind/ReflectiveTypeAdapterFactory.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/bind/SqlDateTypeAdapter.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/bind/StringToValueMapTypeAdapterFactory.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/bind/TimeTypeAdapter.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/bind/TypeAdapter.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/bind/TypeAdapterRuntimeTypeWrapper.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/bind/TypeAdapters.java
create mode 100755 src/com/massivecraft/core/lib/gson2/internal/package-info.java
create mode 100755 src/com/massivecraft/core/lib/gson2/package-info.java
create mode 100755 src/com/massivecraft/core/lib/gson2/reflect/TypeToken.java
create mode 100755 src/com/massivecraft/core/lib/gson2/reflect/package-info.java
create mode 100755 src/com/massivecraft/core/lib/gson2/stream/JsonReader.java
create mode 100755 src/com/massivecraft/core/lib/gson2/stream/JsonScope.java
create mode 100755 src/com/massivecraft/core/lib/gson2/stream/JsonToken.java
create mode 100755 src/com/massivecraft/core/lib/gson2/stream/JsonWriter.java
create mode 100755 src/com/massivecraft/core/lib/gson2/stream/MalformedJsonException.java
create mode 100755 src/com/massivecraft/core/lib/gson2/stream/StringPool.java
create mode 100755 src/com/massivecraft/core/persist/Entity.java
create mode 100755 src/com/massivecraft/core/persist/IClassManager.java
create mode 100755 src/com/massivecraft/core/persist/Persist.java
create mode 100755 src/com/massivecraft/core/persist/PlayerEntity.java
create mode 100755 src/com/massivecraft/core/persist/Predictate.java
create mode 100755 src/com/massivecraft/core/persist/SaveTask.java
create mode 100755 src/com/massivecraft/core/persist/gson/GsonClassManager.java
create mode 100755 src/com/massivecraft/core/persist/gson/GsonPlayerEntityManager.java
create mode 100755 src/com/massivecraft/core/persist/gson/JsonFileFilter.java
diff --git a/src/com/massivecraft/core/lib/gson2/AnonymousAndLocalClassExclusionStrategy.java b/src/com/massivecraft/core/lib/gson2/AnonymousAndLocalClassExclusionStrategy.java
new file mode 100755
index 00000000..f1d811a7
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/AnonymousAndLocalClassExclusionStrategy.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+/**
+ * Strategy for excluding anonymous and local classes.
+ *
+ * @author Joel Leitch
+ */
+final class AnonymousAndLocalClassExclusionStrategy implements ExclusionStrategy {
+
+ public boolean shouldSkipField(FieldAttributes f) {
+ return isAnonymousOrLocal(f.getDeclaredClass());
+ }
+
+ public boolean shouldSkipClass(Class> clazz) {
+ return isAnonymousOrLocal(clazz);
+ }
+
+ private boolean isAnonymousOrLocal(Class> clazz) {
+ return !Enum.class.isAssignableFrom(clazz)
+ && (clazz.isAnonymousClass() || clazz.isLocalClass());
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/Cache.java b/src/com/massivecraft/core/lib/gson2/Cache.java
new file mode 100755
index 00000000..b91600c6
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/Cache.java
@@ -0,0 +1,43 @@
+/*
+ * 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.massivecraft.core.lib.gson2;
+
+/**
+ * Defines generic cache interface.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+interface Cache {
+
+ /**
+ * Adds the new value object into the cache for the given key. If the key already
+ * exists, then this method will override the value for the key.
+ *
+ * @param key the key identifier for the {@code value} object
+ * @param value the value object to store in the cache
+ */
+ void addElement(K key, V value);
+
+ /**
+ * Retrieve the cached value for the given {@code key}.
+ *
+ * @param key the key identifying the value
+ * @return the cached value for the given {@code key}
+ */
+ V getElement(K key);
+}
diff --git a/src/com/massivecraft/core/lib/gson2/CamelCaseSeparatorNamingPolicy.java b/src/com/massivecraft/core/lib/gson2/CamelCaseSeparatorNamingPolicy.java
new file mode 100755
index 00000000..53c20811
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/CamelCaseSeparatorNamingPolicy.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import com.massivecraft.core.lib.gson2.internal.$Gson$Preconditions;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collection;
+
+/**
+ * Converts the field name that uses camel-case define word separation into separate words that
+ * are separated by the provided {@code separatorString}.
+ *
+ *
The following is an example:
+ *
+ * class IntWrapper {
+ * public int integerField = 0;
+ * }
+ *
+ * CamelCaseSeparatorNamingPolicy policy = new CamelCaseSeparatorNamingPolicy("_");
+ * String translatedFieldName =
+ * policy.translateName(IntWrapper.class.getField("integerField"));
+ *
+ * assert("integer_Field".equals(translatedFieldName));
+ *
+ *
+ * @author Joel Leitch
+ */
+final class CamelCaseSeparatorNamingPolicy extends RecursiveFieldNamingPolicy {
+ private final String separatorString;
+
+ /**
+ * Constructs a new CamelCaseSeparatorNamingPolicy object that will add the
+ * {@code separatorString} between each of the words separated by camel case.
+ *
+ * @param separatorString the string value to place between words
+ * @throws IllegalArgumentException thrown if the {@code separatorString} parameter
+ * is null or empty.
+ */
+ public CamelCaseSeparatorNamingPolicy(String separatorString) {
+ $Gson$Preconditions.checkNotNull(separatorString);
+ $Gson$Preconditions.checkArgument(!"".equals(separatorString));
+ this.separatorString = separatorString;
+ }
+
+ @Override
+ protected String translateName(String target, Type fieldType,
+ Collection annnotations) {
+ StringBuilder translation = new StringBuilder();
+ for (int i = 0; i < target.length(); i++) {
+ char character = target.charAt(i);
+ if (Character.isUpperCase(character) && translation.length() != 0) {
+ translation.append(separatorString);
+ }
+ translation.append(character);
+ }
+
+ return translation.toString();
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/CompositionFieldNamingPolicy.java b/src/com/massivecraft/core/lib/gson2/CompositionFieldNamingPolicy.java
new file mode 100755
index 00000000..710a8cb1
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/CompositionFieldNamingPolicy.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collection;
+
+/**
+ * Performs numerous field naming translations wrapped up as one object.
+ *
+ * @author Joel Leitch
+ */
+abstract class CompositionFieldNamingPolicy extends RecursiveFieldNamingPolicy {
+
+ private final RecursiveFieldNamingPolicy[] fieldPolicies;
+
+ public CompositionFieldNamingPolicy(RecursiveFieldNamingPolicy... fieldNamingPolicies) {
+ if (fieldNamingPolicies == null) {
+ throw new NullPointerException("naming policies can not be null.");
+ }
+ this.fieldPolicies = fieldNamingPolicies;
+ }
+
+ @Override
+ protected String translateName(String target, Type fieldType, Collection annotations) {
+ for (RecursiveFieldNamingPolicy policy : fieldPolicies) {
+ target = policy.translateName(target, fieldType, annotations);
+ }
+ return target;
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/DefaultTypeAdapters.java b/src/com/massivecraft/core/lib/gson2/DefaultTypeAdapters.java
new file mode 100755
index 00000000..fc6cc803
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/DefaultTypeAdapters.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import java.lang.reflect.Type;
+import java.sql.Timestamp;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+/**
+ * List of all the default type adapters ({@link JsonSerializer}s, {@link JsonDeserializer}s,
+ * and {@link InstanceCreator}s.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+final class DefaultTypeAdapters {
+ /**
+ * This type adapter supports three subclasses of date: Date, Timestamp, and
+ * java.sql.Date.
+ */
+ static final class DefaultDateTypeAdapter implements JsonSerializer, JsonDeserializer {
+ private final DateFormat enUsFormat;
+ private final DateFormat localFormat;
+ private final DateFormat iso8601Format;
+
+ DefaultDateTypeAdapter() {
+ this(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US),
+ DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT));
+ }
+
+ DefaultDateTypeAdapter(String datePattern) {
+ this(new SimpleDateFormat(datePattern, Locale.US), new SimpleDateFormat(datePattern));
+ }
+
+ DefaultDateTypeAdapter(int style) {
+ this(DateFormat.getDateInstance(style, Locale.US), DateFormat.getDateInstance(style));
+ }
+
+ public DefaultDateTypeAdapter(int dateStyle, int timeStyle) {
+ this(DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.US),
+ DateFormat.getDateTimeInstance(dateStyle, timeStyle));
+ }
+
+ DefaultDateTypeAdapter(DateFormat enUsFormat, DateFormat localFormat) {
+ this.enUsFormat = enUsFormat;
+ this.localFormat = localFormat;
+ this.iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
+ this.iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC"));
+ }
+
+ // These methods need to be synchronized since JDK DateFormat classes are not thread-safe
+ // See issue 162
+ public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
+ synchronized (localFormat) {
+ String dateFormatAsString = enUsFormat.format(src);
+ return new JsonPrimitive(dateFormatAsString);
+ }
+ }
+
+ public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
+ throws JsonParseException {
+ if (!(json instanceof JsonPrimitive)) {
+ throw new JsonParseException("The date should be a string value");
+ }
+ Date date = deserializeToDate(json);
+ if (typeOfT == Date.class) {
+ return date;
+ } else if (typeOfT == Timestamp.class) {
+ return new Timestamp(date.getTime());
+ } else if (typeOfT == java.sql.Date.class) {
+ return new java.sql.Date(date.getTime());
+ } else {
+ throw new IllegalArgumentException(getClass() + " cannot deserialize to " + typeOfT);
+ }
+ }
+
+ private Date deserializeToDate(JsonElement json) {
+ synchronized (localFormat) {
+ try {
+ return localFormat.parse(json.getAsString());
+ } catch (ParseException ignored) {
+ }
+ try {
+ return enUsFormat.parse(json.getAsString());
+ } catch (ParseException ignored) {
+ }
+ try {
+ return iso8601Format.parse(json.getAsString());
+ } catch (ParseException e) {
+ throw new JsonSyntaxException(json.getAsString(), e);
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(DefaultDateTypeAdapter.class.getSimpleName());
+ sb.append('(').append(localFormat.getClass().getSimpleName()).append(')');
+ return sb.toString();
+ }
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/DisjunctionExclusionStrategy.java b/src/com/massivecraft/core/lib/gson2/DisjunctionExclusionStrategy.java
new file mode 100755
index 00000000..64940e95
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/DisjunctionExclusionStrategy.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import com.massivecraft.core.lib.gson2.internal.$Gson$Preconditions;
+
+import java.util.Collection;
+
+/**
+ * A wrapper class used to collect numerous {@link ExclusionStrategy} objects
+ * and perform a short-circuited OR operation.
+ *
+ * @author Joel Leitch
+ */
+final class DisjunctionExclusionStrategy implements ExclusionStrategy {
+ private final Collection strategies;
+
+ DisjunctionExclusionStrategy(Collection strategies) {
+ this.strategies = $Gson$Preconditions.checkNotNull(strategies);
+ }
+
+ public boolean shouldSkipField(FieldAttributes f) {
+ for (ExclusionStrategy strategy : strategies) {
+ if (strategy.shouldSkipField(f)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean shouldSkipClass(Class> clazz) {
+ for (ExclusionStrategy strategy : strategies) {
+ if (strategy.shouldSkipClass(clazz)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/ExclusionStrategy.java b/src/com/massivecraft/core/lib/gson2/ExclusionStrategy.java
new file mode 100755
index 00000000..bfc17b06
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/ExclusionStrategy.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+/**
+ * A strategy (or policy) definition that is used to decide whether or not a field or top-level
+ * class should be serialized or deserialized as part of the JSON output/input. For serialization,
+ * if the {@link #shouldSkipClass(Class)} method returns false then that class or field type
+ * will not be part of the JSON output. For deserialization, if {@link #shouldSkipClass(Class)}
+ * returns false, then it will not be set as part of the Java object structure.
+ *
+ *
The following are a few examples that shows how you can use this exclusion mechanism.
+ *
+ *
Exclude fields and objects based on a particular class type:
+ *
Excludes fields and objects based on a particular annotation:
+ *
+ * public @interface FooAnnotation {
+ * // some implementation here
+ * }
+ *
+ * // Excludes any field (or class) that is tagged with an "@FooAnnotation"
+ * private static class FooAnnotationExclusionStrategy implements ExclusionStrategy {
+ * public boolean shouldSkipClass(Class<?> clazz) {
+ * return clazz.getAnnotation(FooAnnotation.class) != null;
+ * }
+ *
+ * public boolean shouldSkipField(FieldAttributes f) {
+ * return f.getAnnotation(FooAnnotation.class) != null;
+ * }
+ * }
+ *
+ *
+ *
Now if you want to configure {@code Gson} to use a user defined exclusion strategy, then
+ * the {@code GsonBuilder} is required. The following is an example of how you can use the
+ * {@code GsonBuilder} to configure Gson to use one of the above sample:
+ *
For certain model classes, you may only want to serialize a field, but exclude it for
+ * deserialization. To do that, you can write an {@code ExclusionStrategy} as per normal;
+ * however, you would register it with the
+ * {@link GsonBuilder#addDeserializationExclusionStrategy(ExclusionStrategy)} method.
+ * For example:
+ *
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ *
+ * @see GsonBuilder#setExclusionStrategies(ExclusionStrategy...)
+ * @see GsonBuilder#addDeserializationExclusionStrategy(ExclusionStrategy)
+ * @see GsonBuilder#addSerializationExclusionStrategy(ExclusionStrategy)
+ *
+ * @since 1.4
+ */
+public interface ExclusionStrategy {
+
+ /**
+ * @param f the field object that is under test
+ * @return true if the field should be ignored; otherwise false
+ */
+ public boolean shouldSkipField(FieldAttributes f);
+
+ /**
+ * @param clazz the class object that is under test
+ * @return true if the class should be ignored; otherwise false
+ */
+ public boolean shouldSkipClass(Class> clazz);
+}
diff --git a/src/com/massivecraft/core/lib/gson2/ExposeAnnotationDeserializationExclusionStrategy.java b/src/com/massivecraft/core/lib/gson2/ExposeAnnotationDeserializationExclusionStrategy.java
new file mode 100755
index 00000000..42e22efc
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/ExposeAnnotationDeserializationExclusionStrategy.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2011 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.massivecraft.core.lib.gson2;
+
+import com.massivecraft.core.lib.gson2.annotations.Expose;
+
+/**
+ * Excludes fields that do not have the {@link Expose} annotation
+ *
+ * @author Joel Leitch
+ */
+final class ExposeAnnotationDeserializationExclusionStrategy implements ExclusionStrategy {
+ public boolean shouldSkipClass(Class> clazz) {
+ return false;
+ }
+
+ public boolean shouldSkipField(FieldAttributes f) {
+ Expose annotation = f.getAnnotation(Expose.class);
+ if (annotation == null) {
+ return true;
+ }
+ return !annotation.deserialize();
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/ExposeAnnotationSerializationExclusionStrategy.java b/src/com/massivecraft/core/lib/gson2/ExposeAnnotationSerializationExclusionStrategy.java
new file mode 100755
index 00000000..d9e5df86
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/ExposeAnnotationSerializationExclusionStrategy.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2011 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.massivecraft.core.lib.gson2;
+
+import com.massivecraft.core.lib.gson2.annotations.Expose;
+
+/**
+ * Excludes fields that do not have the {@link Expose} annotation
+ *
+ * @author Joel Leitch
+ */
+final class ExposeAnnotationSerializationExclusionStrategy implements ExclusionStrategy {
+ public boolean shouldSkipClass(Class> clazz) {
+ return false;
+ }
+
+ public boolean shouldSkipField(FieldAttributes f) {
+ Expose annotation = f.getAnnotation(Expose.class);
+ if (annotation == null) {
+ return true;
+ }
+ return !annotation.serialize();
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/FieldAttributes.java b/src/com/massivecraft/core/lib/gson2/FieldAttributes.java
new file mode 100755
index 00000000..05e3b1f8
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/FieldAttributes.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2009 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.massivecraft.core.lib.gson2;
+
+import com.massivecraft.core.lib.gson2.internal.$Gson$Preconditions;
+import com.massivecraft.core.lib.gson2.internal.Pair;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * A data object that stores attributes of a field.
+ *
+ *
This class is immutable; therefore, it can be safely shared across threads.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ *
+ * @since 1.4
+ */
+public final class FieldAttributes {
+ private static final String MAX_CACHE_PROPERTY_NAME =
+ "com.google.gson.annotation_cache_size_hint";
+
+ private static final Cache, String>, Collection> ANNOTATION_CACHE =
+ new LruCache,String>, Collection>(getMaxCacheSize());
+
+ private final Class> declaringClazz;
+ private final Field field;
+ private final Class> declaredType;
+ private final boolean isSynthetic;
+ private final int modifiers;
+ private final String name;
+
+ // Fields used for lazy initialization
+ private Type genericType;
+ private Collection annotations;
+
+ /**
+ * Constructs a Field Attributes object from the {@code f}.
+ *
+ * @param f the field to pull attributes from
+ */
+ FieldAttributes(Class> declaringClazz, Field f) {
+ this.declaringClazz = $Gson$Preconditions.checkNotNull(declaringClazz);
+ this.name = f.getName();
+ this.declaredType = f.getType();
+ this.isSynthetic = f.isSynthetic();
+ this.modifiers = f.getModifiers();
+ this.field = f;
+ }
+
+ private static int getMaxCacheSize() {
+ final int defaultMaxCacheSize = 2000;
+ try {
+ String propertyValue = System.getProperty(
+ MAX_CACHE_PROPERTY_NAME, String.valueOf(defaultMaxCacheSize));
+ return Integer.parseInt(propertyValue);
+ } catch (NumberFormatException e) {
+ return defaultMaxCacheSize;
+ }
+ }
+
+ /**
+ * @return the declaring class that contains this field
+ */
+ public Class> getDeclaringClass() {
+ return declaringClazz;
+ }
+
+ /**
+ * @return the name of the field
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ *
For example, assume the following class definition:
+ *
+ * public class Foo {
+ * private String bar;
+ * private List<String> red;
+ * }
+ *
+ * Type listParmeterizedType = new TypeToken<List<String>>() {}.getType();
+ *
+ *
+ *
This method would return {@code String.class} for the {@code bar} field and
+ * {@code listParameterizedType} for the {@code red} field.
+ *
+ * @return the specific type declared for this field
+ */
+ public Type getDeclaredType() {
+ if (genericType == null) {
+ genericType = field.getGenericType();
+ }
+ return genericType;
+ }
+
+ /**
+ * Returns the {@code Class} object that was declared for this field.
+ *
+ *
For example, assume the following class definition:
+ *
This method would return {@code String.class} for the {@code bar} field and
+ * {@code List.class} for the {@code red} field.
+ *
+ * @return the specific class object that was declared for the field
+ */
+ public Class> getDeclaredClass() {
+ return declaredType;
+ }
+
+ /**
+ * Return the {@code T} annotation object from this field if it exist; otherwise returns
+ * {@code null}.
+ *
+ * @param annotation the class of the annotation that will be retrieved
+ * @return the annotation instance if it is bound to the field; otherwise {@code null}
+ */
+ public T getAnnotation(Class annotation) {
+ return getAnnotationFromArray(getAnnotations(), annotation);
+ }
+
+ /**
+ * Return the annotations that are present on this field.
+ *
+ * @return an array of all the annotations set on the field
+ * @since 1.4
+ */
+ public Collection getAnnotations() {
+ if (annotations == null) {
+ Pair, String> key = new Pair, String>(declaringClazz, name);
+ Collection cachedValue = ANNOTATION_CACHE.getElement(key);
+ if (cachedValue == null) {
+ cachedValue = Collections.unmodifiableCollection(
+ Arrays.asList(field.getAnnotations()));
+ ANNOTATION_CACHE.addElement(key, cachedValue);
+ }
+ annotations = cachedValue;
+ }
+ return annotations;
+ }
+
+ /**
+ * Returns {@code true} if the field is defined with the {@code modifier}.
+ *
+ *
+ *
+ * @see java.lang.reflect.Modifier
+ */
+ public boolean hasModifier(int modifier) {
+ return (modifiers & modifier) != 0;
+ }
+
+ /**
+ * This is exposed internally only for the removing synthetic fields from the JSON output.
+ *
+ * @return true if the field is synthetic; otherwise false
+ * @throws IllegalAccessException
+ * @throws IllegalArgumentException
+ */
+ Object get(Object instance) throws IllegalAccessException {
+ return field.get(instance);
+ }
+
+ /**
+ * This is exposed internally only for the removing synthetic fields from the JSON output.
+ *
+ * @return true if the field is synthetic; otherwise false
+ */
+ boolean isSynthetic() {
+ return isSynthetic;
+ }
+
+ /**
+ * @deprecated remove this when {@link FieldNamingStrategy} is deleted.
+ */
+ @Deprecated
+ Field getFieldObject() {
+ return field;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static T getAnnotationFromArray(
+ Collection annotations, Class annotation) {
+ for (Annotation a : annotations) {
+ if (a.annotationType() == annotation) {
+ return (T) a;
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/FieldNamingPolicy.java b/src/com/massivecraft/core/lib/gson2/FieldNamingPolicy.java
new file mode 100755
index 00000000..cd17671f
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/FieldNamingPolicy.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+/**
+ * An enumeration that defines a few standard naming conventions for JSON field names.
+ * This enumeration should be used in conjunction with {@link com.massivecraft.core.lib.gson2.GsonBuilder}
+ * to configure a {@link com.massivecraft.core.lib.gson2.Gson} instance to properly translate Java field
+ * names into the desired JSON field names.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+public enum FieldNamingPolicy {
+ /**
+ * Using this naming policy with Gson will ensure that the first "letter" of the Java
+ * field name is capitalized when serialized to its JSON form.
+ *
+ *
Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":
+ *
+ *
someFieldName ---> SomeFieldName
+ *
_someFieldName ---> _SomeFieldName
+ *
+ */
+ UPPER_CAMEL_CASE(new ModifyFirstLetterNamingPolicy(
+ ModifyFirstLetterNamingPolicy.LetterModifier.UPPER)),
+
+ /**
+ * Using this naming policy with Gson will ensure that the first "letter" of the Java
+ * field name is capitalized when serialized to its JSON form and the words will be
+ * separated by a space.
+ *
+ *
Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":
+ *
+ *
someFieldName ---> Some Field Name
+ *
_someFieldName ---> _Some Field Name
+ *
+ *
+ * @since 1.4
+ */
+ UPPER_CAMEL_CASE_WITH_SPACES(new UpperCamelCaseSeparatorNamingPolicy(" ")),
+
+ /**
+ * Using this naming policy with Gson will modify the Java Field name from its camel cased
+ * form to a lower case field name where each word is separated by an underscore (_).
+ *
+ *
Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":
+ *
+ *
someFieldName ---> some_field_name
+ *
_someFieldName ---> _some_field_name
+ *
aStringField ---> a_string_field
+ *
aURL ---> a_u_r_l
+ *
+ */
+ LOWER_CASE_WITH_UNDERSCORES(new LowerCamelCaseSeparatorNamingPolicy("_")),
+
+ /**
+ * Using this naming policy with Gson will modify the Java Field name from its camel cased
+ * form to a lower case field name where each word is separated by a dash (-).
+ *
+ *
Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":
+ *
+ *
someFieldName ---> some-field-name
+ *
_someFieldName ---> _some-field-name
+ *
aStringField ---> a-string-field
+ *
aURL ---> a-u-r-l
+ *
+ * Using dashes in JavaScript is not recommended since dash is also used for a minus sign in
+ * expressions. This requires that a field named with dashes is always accessed as a quoted
+ * property like {@code myobject['my-field']}. Accessing it as an object field
+ * {@code myobject.my-field} will result in an unintended javascript expression.
+ * @since 1.4
+ */
+ LOWER_CASE_WITH_DASHES(new LowerCamelCaseSeparatorNamingPolicy("-"));
+
+ private final FieldNamingStrategy2 namingPolicy;
+
+ private FieldNamingPolicy(FieldNamingStrategy2 namingPolicy) {
+ this.namingPolicy = namingPolicy;
+ }
+
+ FieldNamingStrategy2 getFieldNamingPolicy() {
+ return namingPolicy;
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/FieldNamingStrategy.java b/src/com/massivecraft/core/lib/gson2/FieldNamingStrategy.java
new file mode 100755
index 00000000..02ad9528
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/FieldNamingStrategy.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import java.lang.reflect.Field;
+
+/**
+ * A mechanism for providing custom field naming in Gson. This allows the client code to translate
+ * field names into a particular convention that is not supported as a normal Java field
+ * declaration rules. For example, Java does not support "-" characters in a field name.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ * @since 1.3
+ */
+public interface FieldNamingStrategy {
+
+ /**
+ * Translates the field name into its JSON field name representation.
+ *
+ * @param f the field object that we are translating
+ * @return the translated field name.
+ * @since 1.3
+ */
+ public String translateName(Field f);
+}
diff --git a/src/com/massivecraft/core/lib/gson2/FieldNamingStrategy2.java b/src/com/massivecraft/core/lib/gson2/FieldNamingStrategy2.java
new file mode 100755
index 00000000..0768c84a
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/FieldNamingStrategy2.java
@@ -0,0 +1,37 @@
+/*
+ * 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.massivecraft.core.lib.gson2;
+
+/**
+ * The new mechanism for providing custom field naming in Gson. This allows the client code
+ * to translate field names into a particular convention that is not supported as a normal
+ * Java field declaration rules. For example, Java does not support "-" characters in a
+ * field name.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+interface FieldNamingStrategy2 {
+
+ /**
+ * Translates the field name into its JSON field name representation.
+ *
+ * @param f the field that is being translated
+ * @return the translated field name.
+ */
+ public String translateName(FieldAttributes f);
+}
diff --git a/src/com/massivecraft/core/lib/gson2/FieldNamingStrategy2Adapter.java b/src/com/massivecraft/core/lib/gson2/FieldNamingStrategy2Adapter.java
new file mode 100755
index 00000000..19d58c00
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/FieldNamingStrategy2Adapter.java
@@ -0,0 +1,39 @@
+/*
+ * 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.massivecraft.core.lib.gson2;
+
+import com.massivecraft.core.lib.gson2.internal.$Gson$Preconditions;
+
+/**
+ * Adapts the old FieldNamingStrategy to the new {@link FieldNamingStrategy2}
+ * type.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+final class FieldNamingStrategy2Adapter implements FieldNamingStrategy2 {
+ private final FieldNamingStrategy adaptee;
+
+ FieldNamingStrategy2Adapter(FieldNamingStrategy adaptee) {
+ this.adaptee = $Gson$Preconditions.checkNotNull(adaptee);
+ }
+
+ @SuppressWarnings("deprecation")
+ public String translateName(FieldAttributes f) {
+ return adaptee.translateName(f.getFieldObject());
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/Gson.java b/src/com/massivecraft/core/lib/gson2/Gson.java
new file mode 100755
index 00000000..b7bf37cc
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/Gson.java
@@ -0,0 +1,802 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import com.massivecraft.core.lib.gson2.internal.ConstructorConstructor;
+import com.massivecraft.core.lib.gson2.internal.ParameterizedTypeHandlerMap;
+import com.massivecraft.core.lib.gson2.internal.Primitives;
+import com.massivecraft.core.lib.gson2.internal.Streams;
+import com.massivecraft.core.lib.gson2.internal.bind.ArrayTypeAdapter;
+import com.massivecraft.core.lib.gson2.internal.bind.BigDecimalTypeAdapter;
+import com.massivecraft.core.lib.gson2.internal.bind.BigIntegerTypeAdapter;
+import com.massivecraft.core.lib.gson2.internal.bind.CollectionTypeAdapterFactory;
+import com.massivecraft.core.lib.gson2.internal.bind.DateTypeAdapter;
+import com.massivecraft.core.lib.gson2.internal.bind.ExcludedTypeAdapterFactory;
+import com.massivecraft.core.lib.gson2.internal.bind.JsonElementReader;
+import com.massivecraft.core.lib.gson2.internal.bind.JsonElementWriter;
+import com.massivecraft.core.lib.gson2.internal.bind.MapTypeAdapterFactory;
+import com.massivecraft.core.lib.gson2.internal.bind.MiniGson;
+import com.massivecraft.core.lib.gson2.internal.bind.ObjectTypeAdapter;
+import com.massivecraft.core.lib.gson2.internal.bind.ReflectiveTypeAdapterFactory;
+import com.massivecraft.core.lib.gson2.internal.bind.SqlDateTypeAdapter;
+import com.massivecraft.core.lib.gson2.internal.bind.TimeTypeAdapter;
+import com.massivecraft.core.lib.gson2.internal.bind.TypeAdapter;
+import com.massivecraft.core.lib.gson2.internal.bind.TypeAdapters;
+import com.massivecraft.core.lib.gson2.reflect.TypeToken;
+import com.massivecraft.core.lib.gson2.stream.JsonReader;
+import com.massivecraft.core.lib.gson2.stream.JsonToken;
+import com.massivecraft.core.lib.gson2.stream.JsonWriter;
+import com.massivecraft.core.lib.gson2.stream.MalformedJsonException;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This is the main class for using Gson. Gson is typically used by first constructing a
+ * Gson instance and then invoking {@link #toJson(Object)} or {@link #fromJson(String, Class)}
+ * methods on it.
+ *
+ *
You can create a Gson instance by invoking {@code new Gson()} if the default configuration
+ * is all you need. You can also use {@link GsonBuilder} to build a Gson instance with various
+ * configuration options such as versioning support, pretty printing, custom
+ * {@link JsonSerializer}s, {@link JsonDeserializer}s, and {@link InstanceCreator}s.
+ *
+ *
Here is an example of how Gson is used for a simple Class:
+ *
+ *
+ * Gson gson = new Gson(); // Or use new GsonBuilder().create();
+ * MyType target = new MyType();
+ * String json = gson.toJson(target); // serializes target to Json
+ * MyType target2 = gson.fromJson(json, MyType.class); // deserializes json into target2
+ *
+ *
+ *
If the object that your are serializing/deserializing is a {@code ParameterizedType}
+ * (i.e. contains at least one type parameter and may be an array) then you must use the
+ * {@link #toJson(Object, Type)} or {@link #fromJson(String, Type)} method. Here is an
+ * example for serializing and deserialing a {@code ParameterizedType}:
+ *
+ *
See the Gson User Guide
+ * for a more complete set of examples.
+ *
+ * @see com.massivecraft.core.lib.gson2.reflect.TypeToken
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+public final class Gson {
+ @SuppressWarnings("rawtypes")
+ static final ParameterizedTypeHandlerMap EMPTY_MAP =
+ new ParameterizedTypeHandlerMap().makeUnmodifiable();
+
+ static final boolean DEFAULT_JSON_NON_EXECUTABLE = false;
+
+ // Default instances of plug-ins
+ static final AnonymousAndLocalClassExclusionStrategy DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY =
+ new AnonymousAndLocalClassExclusionStrategy();
+ static final SyntheticFieldExclusionStrategy DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY =
+ new SyntheticFieldExclusionStrategy(true);
+ static final ModifierBasedExclusionStrategy DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY =
+ new ModifierBasedExclusionStrategy(Modifier.TRANSIENT, Modifier.STATIC);
+ static final FieldNamingStrategy2 DEFAULT_NAMING_POLICY =
+ new SerializedNameAnnotationInterceptingNamingPolicy(new JavaFieldNamingPolicy());
+
+ private static final ExclusionStrategy DEFAULT_EXCLUSION_STRATEGY = createExclusionStrategy();
+
+ private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n";
+
+ private final ExclusionStrategy deserializationExclusionStrategy;
+ private final ExclusionStrategy serializationExclusionStrategy;
+ private final ConstructorConstructor constructorConstructor;
+
+ /** Map containing Type or Class objects as keys */
+ private final ParameterizedTypeHandlerMap> serializers;
+
+ /** Map containing Type or Class objects as keys */
+ private final ParameterizedTypeHandlerMap> deserializers;
+
+ private final boolean serializeNulls;
+ private final boolean htmlSafe;
+ private final boolean generateNonExecutableJson;
+ private final boolean prettyPrinting;
+
+ private final MiniGson miniGson;
+
+ /**
+ * Constructs a Gson object with default configuration. The default configuration has the
+ * following settings:
+ *
+ *
The JSON generated by toJson methods is in compact representation. This
+ * means that all the unneeded white-space is removed. You can change this behavior with
+ * {@link GsonBuilder#setPrettyPrinting()}.
+ *
The generated JSON omits all the fields that are null. Note that nulls in arrays are
+ * kept as is since an array is an ordered list. Moreover, if a field is not null, but its
+ * generated JSON is empty, the field is kept. You can configure Gson to serialize null values
+ * by setting {@link GsonBuilder#serializeNulls()}.
+ *
Gson provides default serialization and deserialization for Enums, {@link Map},
+ * {@link java.net.URL}, {@link java.net.URI}, {@link java.util.Locale}, {@link java.util.Date},
+ * {@link java.math.BigDecimal}, and {@link java.math.BigInteger} classes. If you would prefer
+ * to change the default representation, you can do so by registering a type adapter through
+ * {@link GsonBuilder#registerTypeAdapter(Type, Object)}.
+ *
The default Date format is same as {@link java.text.DateFormat#DEFAULT}. This format
+ * ignores the millisecond portion of the date during serialization. You can change
+ * this by invoking {@link GsonBuilder#setDateFormat(int)} or
+ * {@link GsonBuilder#setDateFormat(String)}.
+ *
By default, Gson ignores the {@link com.massivecraft.core.lib.gson2.annotations.Expose} annotation.
+ * You can enable Gson to serialize/deserialize only those fields marked with this annotation
+ * through {@link GsonBuilder#excludeFieldsWithoutExposeAnnotation()}.
+ *
By default, Gson ignores the {@link com.massivecraft.core.lib.gson2.annotations.Since} annotation. You
+ * can enable Gson to use this annotation through {@link GsonBuilder#setVersion(double)}.
+ *
The default field naming policy for the output Json is same as in Java. So, a Java class
+ * field versionNumber will be output as "versionNumber@quot; in
+ * Json. The same rules are applied for mapping incoming Json to the Java classes. You can
+ * change this policy through {@link GsonBuilder#setFieldNamingPolicy(FieldNamingPolicy)}.
+ *
By default, Gson excludes transient or static fields from
+ * consideration for serialization and deserialization. You can change this behavior through
+ * {@link GsonBuilder#excludeFieldsWithModifiers(int...)}.
+ *
+ */
+ @SuppressWarnings("unchecked")
+ public Gson() {
+ this(DEFAULT_EXCLUSION_STRATEGY, DEFAULT_EXCLUSION_STRATEGY, DEFAULT_NAMING_POLICY,
+ EMPTY_MAP, false, EMPTY_MAP, EMPTY_MAP, false, DEFAULT_JSON_NON_EXECUTABLE, true,
+ false, false, LongSerializationPolicy.DEFAULT,
+ Collections.emptyList());
+ }
+
+ Gson(final ExclusionStrategy deserializationExclusionStrategy,
+ final ExclusionStrategy serializationExclusionStrategy,
+ final FieldNamingStrategy2 fieldNamingPolicy,
+ final ParameterizedTypeHandlerMap> instanceCreators, boolean serializeNulls,
+ final ParameterizedTypeHandlerMap> serializers,
+ final ParameterizedTypeHandlerMap> deserializers,
+ boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
+ boolean prettyPrinting, boolean serializeSpecialFloatingPointValues,
+ LongSerializationPolicy longSerializationPolicy,
+ List typeAdapterFactories) {
+ this.deserializationExclusionStrategy = deserializationExclusionStrategy;
+ this.serializationExclusionStrategy = serializationExclusionStrategy;
+ this.constructorConstructor = new ConstructorConstructor(instanceCreators);
+ this.serializeNulls = serializeNulls;
+ this.serializers = serializers;
+ this.deserializers = deserializers;
+ this.generateNonExecutableJson = generateNonExecutableGson;
+ this.htmlSafe = htmlSafe;
+ this.prettyPrinting = prettyPrinting;
+
+ /*
+ TODO: for serialization, honor:
+ serializationExclusionStrategy
+ fieldNamingPolicy
+ serializeNulls
+ serializers
+ */
+ TypeAdapter.Factory reflectiveTypeAdapterFactory
+ = new ReflectiveTypeAdapterFactory(constructorConstructor) {
+ @Override
+ public String getFieldName(Class> declaringClazz, Field f, Type declaredType) {
+ return fieldNamingPolicy.translateName(new FieldAttributes(declaringClazz, f));
+ }
+ @Override
+ public boolean serializeField(Class> declaringClazz, Field f, Type declaredType) {
+ ExclusionStrategy strategy = Gson.this.serializationExclusionStrategy;
+ return !strategy.shouldSkipClass(f.getType())
+ && !strategy.shouldSkipField(new FieldAttributes(declaringClazz, f));
+ }
+
+ @Override
+ public boolean deserializeField(Class> declaringClazz, Field f, Type declaredType) {
+ ExclusionStrategy strategy = Gson.this.deserializationExclusionStrategy;
+ return !strategy.shouldSkipClass(f.getType())
+ && !strategy.shouldSkipField(new FieldAttributes(declaringClazz, f));
+ }
+ };
+
+ MiniGson.Builder builder = new MiniGson.Builder()
+ .withoutDefaultFactories()
+ .factory(TypeAdapters.STRING_FACTORY)
+ .factory(TypeAdapters.INTEGER_FACTORY)
+ .factory(TypeAdapters.BOOLEAN_FACTORY)
+ .factory(TypeAdapters.BYTE_FACTORY)
+ .factory(TypeAdapters.SHORT_FACTORY)
+ .factory(TypeAdapters.newFactory(long.class, Long.class,
+ longAdapter(longSerializationPolicy)))
+ .factory(TypeAdapters.newFactory(double.class, Double.class,
+ doubleAdapter(serializeSpecialFloatingPointValues)))
+ .factory(TypeAdapters.newFactory(float.class, Float.class,
+ floatAdapter(serializeSpecialFloatingPointValues)))
+ .factory(new ExcludedTypeAdapterFactory(
+ serializationExclusionStrategy, deserializationExclusionStrategy))
+ .factory(TypeAdapters.NUMBER_FACTORY)
+ .factory(TypeAdapters.CHARACTER_FACTORY)
+ .factory(TypeAdapters.STRING_BUILDER_FACTORY)
+ .factory(TypeAdapters.STRING_BUFFER_FACTORY)
+ .typeAdapter(BigDecimal.class, new BigDecimalTypeAdapter())
+ .typeAdapter(BigInteger.class, new BigIntegerTypeAdapter())
+ .factory(TypeAdapters.JSON_ELEMENT_FACTORY)
+ .factory(ObjectTypeAdapter.FACTORY);
+
+ for (TypeAdapter.Factory factory : typeAdapterFactories) {
+ builder.factory(factory);
+ }
+
+ builder
+ .factory(new GsonToMiniGsonTypeAdapterFactory(this, serializers, deserializers))
+ .factory(new CollectionTypeAdapterFactory(constructorConstructor))
+ .factory(TypeAdapters.URL_FACTORY)
+ .factory(TypeAdapters.URI_FACTORY)
+ .factory(TypeAdapters.UUID_FACTORY)
+ .factory(TypeAdapters.LOCALE_FACTORY)
+ .factory(TypeAdapters.INET_ADDRESS_FACTORY)
+ .factory(TypeAdapters.BIT_SET_FACTORY)
+ .factory(DateTypeAdapter.FACTORY)
+ .factory(TypeAdapters.CALENDAR_FACTORY)
+ .factory(TimeTypeAdapter.FACTORY)
+ .factory(SqlDateTypeAdapter.FACTORY)
+ .factory(TypeAdapters.TIMESTAMP_FACTORY)
+ .factory(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization))
+ .factory(ArrayTypeAdapter.FACTORY)
+ .factory(TypeAdapters.ENUM_FACTORY)
+ .factory(reflectiveTypeAdapterFactory);
+
+ this.miniGson = builder.build();
+ }
+
+ private TypeAdapter doubleAdapter(boolean serializeSpecialFloatingPointValues) {
+ if (serializeSpecialFloatingPointValues) {
+ return TypeAdapters.DOUBLE;
+ }
+ return new TypeAdapter() {
+ @Override public Double read(JsonReader reader) throws IOException {
+ if (reader.peek() == JsonToken.NULL) {
+ reader.nextNull();
+ return null;
+ }
+ return reader.nextDouble();
+ }
+ @Override public void write(JsonWriter writer, Number value) throws IOException {
+ if (value == null) {
+ writer.nullValue(); // TODO: better policy here?
+ return;
+ }
+ double doubleValue = value.doubleValue();
+ checkValidFloatingPoint(doubleValue);
+ writer.value(value);
+ }
+ };
+ }
+
+ private TypeAdapter floatAdapter(boolean serializeSpecialFloatingPointValues) {
+ if (serializeSpecialFloatingPointValues) {
+ return TypeAdapters.FLOAT;
+ }
+ return new TypeAdapter() {
+ @Override public Float read(JsonReader reader) throws IOException {
+ if (reader.peek() == JsonToken.NULL) {
+ reader.nextNull();
+ return null;
+ }
+ return (float) reader.nextDouble();
+ }
+ @Override public void write(JsonWriter writer, Number value) throws IOException {
+ if (value == null) {
+ writer.nullValue(); // TODO: better policy here?
+ return;
+ }
+ float floatValue = value.floatValue();
+ checkValidFloatingPoint(floatValue);
+ writer.value(value);
+ }
+ };
+ }
+
+ private void checkValidFloatingPoint(double value) {
+ if (Double.isNaN(value) || Double.isInfinite(value)) {
+ throw new IllegalArgumentException(value
+ + " is not a valid double value as per JSON specification. To override this"
+ + " behavior, use GsonBuilder.serializeSpecialDoubleValues() method.");
+ }
+ }
+
+ private TypeAdapter longAdapter(LongSerializationPolicy longSerializationPolicy) {
+ if (longSerializationPolicy == LongSerializationPolicy.DEFAULT) {
+ return TypeAdapters.LONG;
+ }
+ return new TypeAdapter() {
+ @Override public Number read(JsonReader reader) throws IOException {
+ if (reader.peek() == JsonToken.NULL) {
+ reader.nextNull();
+ return null;
+ }
+ return reader.nextLong();
+ }
+ @Override public void write(JsonWriter writer, Number value) throws IOException {
+ if (value == null) {
+ writer.nullValue(); // TODO: better policy here?
+ return;
+ }
+ writer.value(value.toString());
+ }
+ };
+ }
+
+ private static ExclusionStrategy createExclusionStrategy() {
+ List strategies = new LinkedList();
+ strategies.add(DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY);
+ strategies.add(DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY);
+ strategies.add(DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY);
+ return new DisjunctionExclusionStrategy(strategies);
+ }
+
+ /**
+ * This method serializes the specified object into its equivalent representation as a tree of
+ * {@link JsonElement}s. This method should be used when the specified object is not a generic
+ * type. This method uses {@link Class#getClass()} to get the type for the specified object, but
+ * the {@code getClass()} loses the generic type information because of the Type Erasure feature
+ * of Java. Note that this method works fine if the any of the object fields are of generic type,
+ * just the object itself should not be of a generic type. If the object is of generic type, use
+ * {@link #toJsonTree(Object, Type)} instead.
+ *
+ * @param src the object for which Json representation is to be created setting for Gson
+ * @return Json representation of {@code src}.
+ * @since 1.4
+ */
+ public JsonElement toJsonTree(Object src) {
+ if (src == null) {
+ return JsonNull.INSTANCE;
+ }
+ return toJsonTree(src, src.getClass());
+ }
+
+ /**
+ * This method serializes the specified object, including those of generic types, into its
+ * equivalent representation as a tree of {@link JsonElement}s. This method must be used if the
+ * specified object is a generic type. For non-generic objects, use {@link #toJsonTree(Object)}
+ * instead.
+ *
+ * @param src the object for which JSON representation is to be created
+ * @param typeOfSrc The specific genericized type of src. You can obtain
+ * this type by using the {@link com.massivecraft.core.lib.gson2.reflect.TypeToken} class. For example,
+ * to get the type for {@code Collection}, you should use:
+ *
+ * Type typeOfSrc = new TypeToken<Collection<Foo>>(){}.getType();
+ *
+ * @return Json representation of {@code src}
+ * @since 1.4
+ */
+ @SuppressWarnings({"unchecked", "rawtypes"}) // the caller is required to make src and typeOfSrc consistent
+ public JsonElement toJsonTree(Object src, Type typeOfSrc) {
+ JsonElementWriter writer = new JsonElementWriter();
+ toJson(src, typeOfSrc, writer);
+ return writer.get();
+ }
+
+ /**
+ * This method serializes the specified object into its equivalent Json representation.
+ * This method should be used when the specified object is not a generic type. This method uses
+ * {@link Class#getClass()} to get the type for the specified object, but the
+ * {@code getClass()} loses the generic type information because of the Type Erasure feature
+ * of Java. Note that this method works fine if the any of the object fields are of generic type,
+ * just the object itself should not be of a generic type. If the object is of generic type, use
+ * {@link #toJson(Object, Type)} instead. If you want to write out the object to a
+ * {@link Writer}, use {@link #toJson(Object, Appendable)} instead.
+ *
+ * @param src the object for which Json representation is to be created setting for Gson
+ * @return Json representation of {@code src}.
+ */
+ public String toJson(Object src) {
+ if (src == null) {
+ return toJson(JsonNull.INSTANCE);
+ }
+ return toJson(src, src.getClass());
+ }
+
+ /**
+ * This method serializes the specified object, including those of generic types, into its
+ * equivalent Json representation. This method must be used if the specified object is a generic
+ * type. For non-generic objects, use {@link #toJson(Object)} instead. If you want to write out
+ * the object to a {@link Appendable}, use {@link #toJson(Object, Type, Appendable)} instead.
+ *
+ * @param src the object for which JSON representation is to be created
+ * @param typeOfSrc The specific genericized type of src. You can obtain
+ * this type by using the {@link com.massivecraft.core.lib.gson2.reflect.TypeToken} class. For example,
+ * to get the type for {@code Collection}, you should use:
+ *
+ * Type typeOfSrc = new TypeToken<Collection<Foo>>(){}.getType();
+ *
+ * @return Json representation of {@code src}
+ */
+ public String toJson(Object src, Type typeOfSrc) {
+ StringWriter writer = new StringWriter();
+ toJson(src, typeOfSrc, writer);
+ return writer.toString();
+ }
+
+ /**
+ * This method serializes the specified object into its equivalent Json representation.
+ * This method should be used when the specified object is not a generic type. This method uses
+ * {@link Class#getClass()} to get the type for the specified object, but the
+ * {@code getClass()} loses the generic type information because of the Type Erasure feature
+ * of Java. Note that this method works fine if the any of the object fields are of generic type,
+ * just the object itself should not be of a generic type. If the object is of generic type, use
+ * {@link #toJson(Object, Type, Appendable)} instead.
+ *
+ * @param src the object for which Json representation is to be created setting for Gson
+ * @param writer Writer to which the Json representation needs to be written
+ * @throws JsonIOException if there was a problem writing to the writer
+ * @since 1.2
+ */
+ public void toJson(Object src, Appendable writer) throws JsonIOException {
+ if (src != null) {
+ toJson(src, src.getClass(), writer);
+ } else {
+ toJson(JsonNull.INSTANCE, writer);
+ }
+ }
+
+ /**
+ * This method serializes the specified object, including those of generic types, into its
+ * equivalent Json representation. This method must be used if the specified object is a generic
+ * type. For non-generic objects, use {@link #toJson(Object, Appendable)} instead.
+ *
+ * @param src the object for which JSON representation is to be created
+ * @param typeOfSrc The specific genericized type of src. You can obtain
+ * this type by using the {@link com.massivecraft.core.lib.gson2.reflect.TypeToken} class. For example,
+ * to get the type for {@code Collection}, you should use:
+ *
+ * Type typeOfSrc = new TypeToken<Collection<Foo>>(){}.getType();
+ *
+ * @param writer Writer to which the Json representation of src needs to be written.
+ * @throws JsonIOException if there was a problem writing to the writer
+ * @since 1.2
+ */
+ public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOException {
+ try {
+ JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer));
+ toJson(src, typeOfSrc, jsonWriter);
+ } catch (IOException e) {
+ throw new JsonIOException(e);
+ }
+ }
+
+ /**
+ * Writes the JSON representation of {@code src} of type {@code typeOfSrc} to
+ * {@code writer}.
+ * @throws JsonIOException if there was a problem writing to the writer
+ */
+ @SuppressWarnings("unchecked")
+ public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException {
+ TypeAdapter> adapter = miniGson.getAdapter(TypeToken.get(typeOfSrc));
+ boolean oldLenient = writer.isLenient();
+ writer.setLenient(true);
+ boolean oldHtmlSafe = writer.isHtmlSafe();
+ writer.setHtmlSafe(htmlSafe);
+ boolean oldSerializeNulls = writer.getSerializeNulls();
+ writer.setSerializeNulls(serializeNulls);
+ try {
+ ((TypeAdapter
+ *
+ *
NOTES:
+ *
+ *
the order of invocation of configuration methods does not matter.
+ *
The default serialization of {@link Date} and its subclasses in Gson does
+ * not contain time-zone information. So, if you are using date/time instances,
+ * use {@code GsonBuilder} and its {@code setDateFormat} methods.
+ *
+ *
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+public final class GsonBuilder {
+ private static final InnerClassExclusionStrategy innerClassExclusionStrategy =
+ new InnerClassExclusionStrategy();
+ private static final ExposeAnnotationDeserializationExclusionStrategy
+ exposeAnnotationDeserializationExclusionStrategy =
+ new ExposeAnnotationDeserializationExclusionStrategy();
+ private static final ExposeAnnotationSerializationExclusionStrategy
+ exposeAnnotationSerializationExclusionStrategy =
+ new ExposeAnnotationSerializationExclusionStrategy();
+
+ private final Set serializeExclusionStrategies =
+ new HashSet();
+ private final Set deserializeExclusionStrategies =
+ new HashSet();
+
+ private double ignoreVersionsAfter;
+ private ModifierBasedExclusionStrategy modifierBasedExclusionStrategy;
+ private boolean serializeInnerClasses;
+ private boolean excludeFieldsWithoutExposeAnnotation;
+ private LongSerializationPolicy longSerializationPolicy;
+ private FieldNamingStrategy2 fieldNamingPolicy;
+ private final ParameterizedTypeHandlerMap> instanceCreators;
+ private final ParameterizedTypeHandlerMap> serializers;
+ private final ParameterizedTypeHandlerMap> deserializers;
+ private final List typeAdapterFactories
+ = new ArrayList();
+ private boolean serializeNulls;
+ private String datePattern;
+ private int dateStyle;
+ private int timeStyle;
+ private boolean complexMapKeySerialization = false;
+ private boolean serializeSpecialFloatingPointValues;
+ private boolean escapeHtmlChars;
+ private boolean prettyPrinting;
+ private boolean generateNonExecutableJson;
+
+ /**
+ * Creates a GsonBuilder instance that can be used to build Gson with various configuration
+ * settings. GsonBuilder follows the builder pattern, and it is typically used by first
+ * invoking various configuration methods to set desired options, and finally calling
+ * {@link #create()}.
+ */
+ public GsonBuilder() {
+ // add default exclusion strategies
+ deserializeExclusionStrategies.add(Gson.DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY);
+ deserializeExclusionStrategies.add(Gson.DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY);
+ serializeExclusionStrategies.add(Gson.DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY);
+ serializeExclusionStrategies.add(Gson.DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY);
+
+ // setup default values
+ ignoreVersionsAfter = VersionConstants.IGNORE_VERSIONS;
+ serializeInnerClasses = true;
+ prettyPrinting = false;
+ escapeHtmlChars = true;
+ modifierBasedExclusionStrategy = Gson.DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY;
+ excludeFieldsWithoutExposeAnnotation = false;
+ longSerializationPolicy = LongSerializationPolicy.DEFAULT;
+ fieldNamingPolicy = Gson.DEFAULT_NAMING_POLICY;
+ instanceCreators = new ParameterizedTypeHandlerMap>();
+ serializers = new ParameterizedTypeHandlerMap>();
+ deserializers = new ParameterizedTypeHandlerMap>();
+ serializeNulls = false;
+ dateStyle = DateFormat.DEFAULT;
+ timeStyle = DateFormat.DEFAULT;
+ serializeSpecialFloatingPointValues = false;
+ generateNonExecutableJson = false;
+ }
+
+ /**
+ * Configures Gson to enable versioning support.
+ *
+ * @param ignoreVersionsAfter any field or type marked with a version higher than this value
+ * are ignored during serialization or deserialization.
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ */
+ public GsonBuilder setVersion(double ignoreVersionsAfter) {
+ this.ignoreVersionsAfter = ignoreVersionsAfter;
+ return this;
+ }
+
+ /**
+ * Configures Gson to excludes all class fields that have the specified modifiers. By default,
+ * Gson will exclude all fields marked transient or static. This method will override that
+ * behavior.
+ *
+ * @param modifiers the field modifiers. You must use the modifiers specified in the
+ * {@link java.lang.reflect.Modifier} class. For example,
+ * {@link java.lang.reflect.Modifier#TRANSIENT},
+ * {@link java.lang.reflect.Modifier#STATIC}.
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ */
+ public GsonBuilder excludeFieldsWithModifiers(int... modifiers) {
+ modifierBasedExclusionStrategy = new ModifierBasedExclusionStrategy(modifiers);
+ return this;
+ }
+
+ /**
+ * Makes the output JSON non-executable in Javascript by prefixing the generated JSON with some
+ * special text. This prevents attacks from third-party sites through script sourcing. See
+ * Gson Issue 42
+ * for details.
+ *
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ * @since 1.3
+ */
+ public GsonBuilder generateNonExecutableJson() {
+ this.generateNonExecutableJson = true;
+ return this;
+ }
+
+ /**
+ * Configures Gson to exclude all fields from consideration for serialization or deserialization
+ * that do not have the {@link com.massivecraft.core.lib.gson2.annotations.Expose} annotation.
+ *
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ */
+ public GsonBuilder excludeFieldsWithoutExposeAnnotation() {
+ excludeFieldsWithoutExposeAnnotation = true;
+ return this;
+ }
+
+ /**
+ * Configure Gson to serialize null fields. By default, Gson omits all fields that are null
+ * during serialization.
+ *
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ * @since 1.2
+ */
+ public GsonBuilder serializeNulls() {
+ this.serializeNulls = true;
+ return this;
+ }
+
+ /**
+ * Enabling this feature will only change the serialized form if the map key is
+ * a complex type (i.e. non-primitive) in its serialized JSON
+ * form. The default implementation of map serialization uses {@code toString()}
+ * on the key; however, when this is called then one of the following cases
+ * apply:
+ *
+ *
Maps as JSON objects
+ * For this case, assume that a type adapter is registered to serialize and
+ * deserialize some {@code Point} class, which contains an x and y coordinate,
+ * to/from the JSON Primitive string value {@code "(x,y)"}. The Java map would
+ * then be serialized as a {@link JsonObject}.
+ *
+ *
+ * For this case, assume that a type adapter was NOT registered for some
+ * {@code Point} class, but rather the default Gson serialization is applied.
+ * In this case, some {@code new Point(2,3)} would serialize as {@code
+ * {"x":2,"y":5}}.
+ *
+ *
Given the assumption above, a {@code Map} will be
+ * serialize as an array of arrays (can be viewed as an entry set of pairs).
+ *
+ *
Below is an example of serializing complex types as JSON arrays:
+ *
{@code
+ * Gson gson = new GsonBuilder()
+ * .enableComplexMapKeySerialization()
+ * .create();
+ *
+ * Map original = new LinkedHashMap();
+ * original.put(new Point(5, 6), "a");
+ * original.put(new Point(8, 8), "b");
+ * System.out.println(gson.toJson(original, type));
+ * }
+ *
+ * The JSON output would look as follows:
+ *
+ *
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ * @since 1.7
+ */
+ public GsonBuilder enableComplexMapKeySerialization() {
+ complexMapKeySerialization = true;
+ return this;
+ }
+
+ /**
+ * Configures Gson to exclude inner classes during serialization.
+ *
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ * @since 1.3
+ */
+ public GsonBuilder disableInnerClassSerialization() {
+ serializeInnerClasses = false;
+ return this;
+ }
+
+ /**
+ * Configures Gson to apply a specific serialization policy for {@code Long} and {@code long}
+ * objects.
+ *
+ * @param serializationPolicy the particular policy to use for serializing longs.
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ * @since 1.3
+ */
+ public GsonBuilder setLongSerializationPolicy(LongSerializationPolicy serializationPolicy) {
+ this.longSerializationPolicy = serializationPolicy;
+ return this;
+ }
+
+ /**
+ * Configures Gson to apply a specific naming policy to an object's field during serialization
+ * and deserialization.
+ *
+ * @param namingConvention the JSON field naming convention to use for serialization and
+ * deserialization.
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ */
+ public GsonBuilder setFieldNamingPolicy(FieldNamingPolicy namingConvention) {
+ return setFieldNamingStrategy(namingConvention.getFieldNamingPolicy());
+ }
+
+ /**
+ * Configures Gson to apply a specific naming policy strategy to an object's field during
+ * serialization and deserialization.
+ *
+ * @param fieldNamingStrategy the actual naming strategy to apply to the fields
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ * @since 1.3
+ */
+ public GsonBuilder setFieldNamingStrategy(FieldNamingStrategy fieldNamingStrategy) {
+ return setFieldNamingStrategy(new FieldNamingStrategy2Adapter(fieldNamingStrategy));
+ }
+
+ /**
+ * Configures Gson to apply a specific naming policy strategy to an object's field during
+ * serialization and deserialization.
+ *
+ * @param fieldNamingStrategy the actual naming strategy to apply to the fields
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ */
+ GsonBuilder setFieldNamingStrategy(FieldNamingStrategy2 fieldNamingStrategy) {
+ this.fieldNamingPolicy =
+ new SerializedNameAnnotationInterceptingNamingPolicy(fieldNamingStrategy);
+ return this;
+ }
+
+ /**
+ * Configures Gson to apply a set of exclusion strategies during both serialization and
+ * deserialization. Each of the {@code strategies} will be applied as a disjunction rule.
+ * This means that if one of the {@code strategies} suggests that a field (or class) should be
+ * skipped then that field (or object) is skipped during serializaiton/deserialization.
+ *
+ * @param strategies the set of strategy object to apply during object (de)serialization.
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ * @since 1.4
+ */
+ public GsonBuilder setExclusionStrategies(ExclusionStrategy... strategies) {
+ List strategyList = Arrays.asList(strategies);
+ serializeExclusionStrategies.addAll(strategyList);
+ deserializeExclusionStrategies.addAll(strategyList);
+ return this;
+ }
+
+ /**
+ * Configures Gson to apply the passed in exclusion strategy during serialization.
+ * If this method is invoked numerous times with different exclusion strategy objects
+ * then the exclusion strategies that were added will be applied as a disjunction rule.
+ * This means that if one of the added exclusion strategies suggests that a field (or
+ * class) should be skipped then that field (or object) is skipped during its
+ * serialization.
+ *
+ * @param strategy an exclusion strategy to apply during serialization.
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ * @since 1.7
+ */
+ public GsonBuilder addSerializationExclusionStrategy(ExclusionStrategy strategy) {
+ serializeExclusionStrategies.add(strategy);
+ return this;
+ }
+
+ /**
+ * Configures Gson to apply the passed in exclusion strategy during deserialization.
+ * If this method is invoked numerous times with different exclusion strategy objects
+ * then the exclusion strategies that were added will be applied as a disjunction rule.
+ * This means that if one of the added exclusion strategies suggests that a field (or
+ * class) should be skipped then that field (or object) is skipped during its
+ * deserialization.
+ *
+ * @param strategy an exclusion strategy to apply during deserialization.
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ * @since 1.7
+ */
+ public GsonBuilder addDeserializationExclusionStrategy(ExclusionStrategy strategy) {
+ deserializeExclusionStrategies.add(strategy);
+ return this;
+ }
+
+ /**
+ * Configures Gson to output Json that fits in a page for pretty printing. This option only
+ * affects Json serialization.
+ *
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ */
+ public GsonBuilder setPrettyPrinting() {
+ prettyPrinting = true;
+ return this;
+ }
+
+ /**
+ * By default, Gson escapes HTML characters such as < > etc. Use this option to configure
+ * Gson to pass-through HTML characters as is.
+ *
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ * @since 1.3
+ */
+ public GsonBuilder disableHtmlEscaping() {
+ this.escapeHtmlChars = false;
+ return this;
+ }
+
+ /**
+ * Configures Gson to serialize {@code Date} objects according to the pattern provided. You can
+ * call this method or {@link #setDateFormat(int)} multiple times, but only the last invocation
+ * will be used to decide the serialization format.
+ *
+ *
The date format will be used to serialize and deserialize {@link java.util.Date}, {@link
+ * java.sql.Timestamp} and {@link java.sql.Date}.
+ *
+ *
Note that this pattern must abide by the convention provided by {@code SimpleDateFormat}
+ * class. See the documentation in {@link java.text.SimpleDateFormat} for more information on
+ * valid date and time patterns.
+ *
+ * @param pattern the pattern that dates will be serialized/deserialized to/from
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ * @since 1.2
+ */
+ public GsonBuilder setDateFormat(String pattern) {
+ // TODO(Joel): Make this fail fast if it is an invalid date format
+ this.datePattern = pattern;
+ return this;
+ }
+
+ /**
+ * Configures Gson to to serialize {@code Date} objects according to the style value provided.
+ * You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
+ * invocation will be used to decide the serialization format.
+ *
+ *
Note that this style value should be one of the predefined constants in the
+ * {@code DateFormat} class. See the documentation in {@link java.text.DateFormat} for more
+ * information on the valid style constants.
+ *
+ * @param style the predefined date style that date objects will be serialized/deserialized
+ * to/from
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ * @since 1.2
+ */
+ public GsonBuilder setDateFormat(int style) {
+ this.dateStyle = style;
+ this.datePattern = null;
+ return this;
+ }
+
+ /**
+ * Configures Gson to to serialize {@code Date} objects according to the style value provided.
+ * You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
+ * invocation will be used to decide the serialization format.
+ *
+ *
Note that this style value should be one of the predefined constants in the
+ * {@code DateFormat} class. See the documentation in {@link java.text.DateFormat} for more
+ * information on the valid style constants.
+ *
+ * @param dateStyle the predefined date style that date objects will be serialized/deserialized
+ * to/from
+ * @param timeStyle the predefined style for the time portion of the date objects
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ * @since 1.2
+ */
+ public GsonBuilder setDateFormat(int dateStyle, int timeStyle) {
+ this.dateStyle = dateStyle;
+ this.timeStyle = timeStyle;
+ this.datePattern = null;
+ return this;
+ }
+
+ /**
+ * Configures Gson for custom serialization or deserialization. This method combines the
+ * registration of an {@link InstanceCreator}, {@link JsonSerializer}, and a
+ * {@link JsonDeserializer}. It is best used when a single object {@code typeAdapter} implements
+ * all the required interfaces for custom serialization with Gson. If an instance creator,
+ * serializer or deserializer was previously registered for the specified {@code type}, it is
+ * overwritten.
+ *
+ * @param type the type definition for the type adapter being registered
+ * @param typeAdapter This object must implement at least one of the {@link InstanceCreator},
+ * {@link JsonSerializer}, and a {@link JsonDeserializer} interfaces.
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ */
+ public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
+ return registerTypeAdapter(type, typeAdapter, false);
+ }
+
+ private GsonBuilder registerTypeAdapter(Type type, Object typeAdapter, boolean isSystem) {
+ $Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer>
+ || typeAdapter instanceof JsonDeserializer>
+ || typeAdapter instanceof InstanceCreator>
+ || typeAdapter instanceof TypeAdapter.Factory);
+ if (Primitives.isPrimitive(type) || Primitives.isWrapperType(type)) {
+ throw new IllegalArgumentException(
+ "Cannot register type adapters for " + type);
+ }
+ if (typeAdapter instanceof InstanceCreator>) {
+ registerInstanceCreator(type, (InstanceCreator>) typeAdapter, isSystem);
+ }
+ if (typeAdapter instanceof JsonSerializer>) {
+ registerSerializer(type, (JsonSerializer>) typeAdapter, isSystem);
+ }
+ if (typeAdapter instanceof JsonDeserializer>) {
+ registerDeserializer(type, (JsonDeserializer>) typeAdapter, isSystem);
+ }
+ if (typeAdapter instanceof TypeAdapter.Factory) {
+ typeAdapterFactories.add((TypeAdapter.Factory) typeAdapter);
+ }
+ return this;
+ }
+
+ /**
+ * Configures Gson to use a custom {@link InstanceCreator} for the specified type. If an instance
+ * creator was previously registered for the specified class, it is overwritten. Since this method
+ * takes a type instead of a Class object, it can be used to register a specific handler for a
+ * generic type corresponding to a raw type.
+ *
+ * @param the type for which instance creator is being registered
+ * @param typeOfT The Type definition for T
+ * @param instanceCreator the instance creator for T
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ */
+ private GsonBuilder registerInstanceCreator(Type typeOfT,
+ InstanceCreator extends T> instanceCreator, boolean isSystem) {
+ instanceCreators.register(typeOfT, instanceCreator, isSystem);
+ return this;
+ }
+
+ /**
+ * Configures Gson to use a custom JSON serializer for the specified type. You should use this
+ * method if you want to register different serializers for different generic types corresponding
+ * to a raw type.
+ *
+ * @param the type for which the serializer is being registered
+ * @param typeOfT The type definition for T
+ * @param serializer the custom serializer
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ */
+ private GsonBuilder registerSerializer(Type typeOfT, JsonSerializer serializer,
+ boolean isSystem) {
+ serializers.register(typeOfT, serializer, isSystem);
+ return this;
+ }
+
+ /**
+ * Configures Gson to use a custom JSON deserializer for the specified type. You should use this
+ * method if you want to register different deserializers for different generic types
+ * corresponding to a raw type.
+ *
+ * @param the type for which the deserializer is being registered
+ * @param typeOfT The type definition for T
+ * @param deserializer the custom deserializer
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ */
+ private GsonBuilder registerDeserializer(Type typeOfT, JsonDeserializer deserializer,
+ boolean isSystem) {
+ deserializers.register(typeOfT, new JsonDeserializerExceptionWrapper(deserializer), isSystem);
+ return this;
+ }
+
+ /**
+ * Configures Gson for custom serialization or deserialization for an inheritance type hierarchy.
+ * This method combines the registration of an {@link InstanceCreator}, {@link JsonSerializer},
+ * and a {@link JsonDeserializer}. It is best used when a single object {@code typeAdapter}
+ * implements all the required interfaces for custom serialization with Gson.
+ * If an instance creator, serializer or deserializer was previously registered for the specified
+ * type hierarchy, it is overwritten. If an instance creator, serializer or deserializer is
+ * registered for a specific type in the type hierarchy, it will be invoked instead of the one
+ * registered for the type hierarchy.
+ *
+ * @param baseType the class definition for the type adapter being registered for the base class
+ * or interface
+ * @param typeAdapter This object must implement at least one of the {@link InstanceCreator},
+ * {@link JsonSerializer}, and a {@link JsonDeserializer} interfaces.
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ * @since 1.7
+ */
+ public GsonBuilder registerTypeHierarchyAdapter(Class> baseType, Object typeAdapter) {
+ return registerTypeHierarchyAdapter(baseType, typeAdapter, false);
+ }
+
+ private GsonBuilder registerTypeHierarchyAdapter(Class> baseType, Object typeAdapter,
+ boolean isSystem) {
+ $Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer>
+ || typeAdapter instanceof JsonDeserializer> || typeAdapter instanceof InstanceCreator>);
+ if (typeAdapter instanceof InstanceCreator>) {
+ registerInstanceCreatorForTypeHierarchy(baseType, (InstanceCreator>) typeAdapter, isSystem);
+ }
+ if (typeAdapter instanceof JsonSerializer>) {
+ registerSerializerForTypeHierarchy(baseType, (JsonSerializer>) typeAdapter, isSystem);
+ }
+ if (typeAdapter instanceof JsonDeserializer>) {
+ registerDeserializerForTypeHierarchy(baseType, (JsonDeserializer>) typeAdapter, isSystem);
+ }
+ return this;
+ }
+
+ private GsonBuilder registerInstanceCreatorForTypeHierarchy(Class> classOfT,
+ InstanceCreator extends T> instanceCreator, boolean isSystem) {
+ instanceCreators.registerForTypeHierarchy(classOfT, instanceCreator, isSystem);
+ return this;
+ }
+
+ private GsonBuilder registerSerializerForTypeHierarchy(Class> classOfT,
+ JsonSerializer serializer, boolean isSystem) {
+ serializers.registerForTypeHierarchy(classOfT, serializer, isSystem);
+ return this;
+ }
+
+ private GsonBuilder registerDeserializerForTypeHierarchy(Class> classOfT,
+ JsonDeserializer deserializer, boolean isSystem) {
+ deserializers.registerForTypeHierarchy(classOfT,
+ new JsonDeserializerExceptionWrapper(deserializer), isSystem);
+ return this;
+ }
+
+ /**
+ * Section 2.4 of JSON specification disallows
+ * special double values (NaN, Infinity, -Infinity). However,
+ * Javascript
+ * specification (see section 4.3.20, 4.3.22, 4.3.23) allows these values as valid Javascript
+ * values. Moreover, most JavaScript engines will accept these special values in JSON without
+ * problem. So, at a practical level, it makes sense to accept these values as valid JSON even
+ * though JSON specification disallows them.
+ *
+ *
Gson always accepts these special values during deserialization. However, it outputs
+ * strictly compliant JSON. Hence, if it encounters a float value {@link Float#NaN},
+ * {@link Float#POSITIVE_INFINITY}, {@link Float#NEGATIVE_INFINITY}, or a double value
+ * {@link Double#NaN}, {@link Double#POSITIVE_INFINITY}, {@link Double#NEGATIVE_INFINITY}, it
+ * will throw an {@link IllegalArgumentException}. This method provides a way to override the
+ * default behavior when you know that the JSON receiver will be able to handle these special
+ * values.
+ *
+ * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
+ * @since 1.3
+ */
+ public GsonBuilder serializeSpecialFloatingPointValues() {
+ this.serializeSpecialFloatingPointValues = true;
+ return this;
+ }
+
+ /**
+ * Creates a {@link Gson} instance based on the current configuration. This method is free of
+ * side-effects to this {@code GsonBuilder} instance and hence can be called multiple times.
+ *
+ * @return an instance of Gson configured with the options currently set in this builder
+ */
+ public Gson create() {
+ List deserializationStrategies =
+ new LinkedList(deserializeExclusionStrategies);
+ List serializationStrategies =
+ new LinkedList(serializeExclusionStrategies);
+ deserializationStrategies.add(modifierBasedExclusionStrategy);
+ serializationStrategies.add(modifierBasedExclusionStrategy);
+
+ if (!serializeInnerClasses) {
+ deserializationStrategies.add(innerClassExclusionStrategy);
+ serializationStrategies.add(innerClassExclusionStrategy);
+ }
+ if (ignoreVersionsAfter != VersionConstants.IGNORE_VERSIONS) {
+ VersionExclusionStrategy versionExclusionStrategy =
+ new VersionExclusionStrategy(ignoreVersionsAfter);
+ deserializationStrategies.add(versionExclusionStrategy);
+ serializationStrategies.add(versionExclusionStrategy);
+ }
+ if (excludeFieldsWithoutExposeAnnotation) {
+ deserializationStrategies.add(exposeAnnotationDeserializationExclusionStrategy);
+ serializationStrategies.add(exposeAnnotationSerializationExclusionStrategy);
+ }
+ addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, serializers, deserializers);
+
+ return new Gson(new DisjunctionExclusionStrategy(deserializationStrategies),
+ new DisjunctionExclusionStrategy(serializationStrategies),
+ fieldNamingPolicy, instanceCreators.copyOf().makeUnmodifiable(), serializeNulls,
+ serializers.copyOf().makeUnmodifiable(), deserializers.copyOf().makeUnmodifiable(),
+ complexMapKeySerialization, generateNonExecutableJson, escapeHtmlChars, prettyPrinting,
+ serializeSpecialFloatingPointValues, longSerializationPolicy, typeAdapterFactories);
+ }
+
+ private static void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle,
+ ParameterizedTypeHandlerMap> serializers,
+ ParameterizedTypeHandlerMap> deserializers) {
+ DefaultDateTypeAdapter dateTypeAdapter = null;
+ if (datePattern != null && !"".equals(datePattern.trim())) {
+ dateTypeAdapter = new DefaultDateTypeAdapter(datePattern);
+ } else if (dateStyle != DateFormat.DEFAULT && timeStyle != DateFormat.DEFAULT) {
+ dateTypeAdapter = new DefaultDateTypeAdapter(dateStyle, timeStyle);
+ }
+
+ if (dateTypeAdapter != null) {
+ registerIfAbsent(Date.class, serializers, dateTypeAdapter);
+ registerIfAbsent(Date.class, deserializers, dateTypeAdapter);
+ registerIfAbsent(Timestamp.class, serializers, dateTypeAdapter);
+ registerIfAbsent(Timestamp.class, deserializers, dateTypeAdapter);
+ registerIfAbsent(java.sql.Date.class, serializers, dateTypeAdapter);
+ registerIfAbsent(java.sql.Date.class, deserializers, dateTypeAdapter);
+ }
+ }
+
+ private static void registerIfAbsent(Class> type,
+ ParameterizedTypeHandlerMap adapters, T adapter) {
+ if (!adapters.hasSpecificHandlerFor(type)) {
+ adapters.register(type, adapter, false);
+ }
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/GsonToMiniGsonTypeAdapterFactory.java b/src/com/massivecraft/core/lib/gson2/GsonToMiniGsonTypeAdapterFactory.java
new file mode 100755
index 00000000..33f73ea6
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/GsonToMiniGsonTypeAdapterFactory.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2011 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.massivecraft.core.lib.gson2;
+
+import com.massivecraft.core.lib.gson2.internal.ParameterizedTypeHandlerMap;
+import com.massivecraft.core.lib.gson2.internal.Streams;
+import com.massivecraft.core.lib.gson2.internal.bind.MiniGson;
+import com.massivecraft.core.lib.gson2.internal.bind.TypeAdapter;
+import com.massivecraft.core.lib.gson2.reflect.TypeToken;
+import com.massivecraft.core.lib.gson2.stream.JsonReader;
+import com.massivecraft.core.lib.gson2.stream.JsonWriter;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+
+final class GsonToMiniGsonTypeAdapterFactory implements TypeAdapter.Factory {
+ private final ParameterizedTypeHandlerMap> serializers;
+ private final ParameterizedTypeHandlerMap> deserializers;
+ private final JsonDeserializationContext deserializationContext;
+ private final JsonSerializationContext serializationContext;
+
+ public GsonToMiniGsonTypeAdapterFactory(final Gson gson,
+ ParameterizedTypeHandlerMap> serializers,
+ ParameterizedTypeHandlerMap> deserializers) {
+ this.serializers = serializers;
+ this.deserializers = deserializers;
+
+ this.deserializationContext = new JsonDeserializationContext() {
+ public T deserialize(JsonElement json, Type typeOfT) throws JsonParseException {
+ return (T) gson.fromJson(json, typeOfT);
+ }
+ };
+
+ this.serializationContext = new JsonSerializationContext() {
+ public JsonElement serialize(Object src) {
+ return gson.toJsonTree(src);
+ }
+ public JsonElement serialize(Object src, Type typeOfSrc) {
+ return gson.toJsonTree(src, typeOfSrc);
+ }
+ };
+ }
+
+ public TypeAdapter create(final MiniGson context, final TypeToken typeToken) {
+ final Type type = typeToken.getType();
+
+ @SuppressWarnings("unchecked") // guaranteed to match typeOfT
+ final JsonSerializer serializer
+ = (JsonSerializer) serializers.getHandlerFor(type, false);
+ @SuppressWarnings("unchecked") // guaranteed to match typeOfT
+ final JsonDeserializer deserializer
+ = (JsonDeserializer) deserializers.getHandlerFor(type, false);
+
+ if (serializer == null && deserializer == null) {
+ return null;
+ }
+
+ return new TypeAdapter() {
+ /**
+ * The delegate is lazily created because it may not be needed, and
+ * creating it may fail.
+ */
+ private TypeAdapter delegate;
+
+ @Override public T read(JsonReader reader) throws IOException {
+ if (deserializer == null) {
+ return delegate().read(reader);
+ }
+ JsonElement value = Streams.parse(reader);
+ if (value.isJsonNull()) {
+ return null;
+ }
+ return deserializer.deserialize(value, type, deserializationContext);
+ }
+
+ @Override public void write(JsonWriter writer, T value) throws IOException {
+ if (serializer == null) {
+ delegate().write(writer, value);
+ return;
+ }
+ if (value == null) {
+ writer.nullValue();
+ return;
+ }
+ JsonElement element = serializer.serialize(value, type, serializationContext);
+ Streams.write(element, writer);
+ }
+
+ private TypeAdapter delegate() {
+ TypeAdapter d = delegate;
+ return d != null
+ ? d
+ : (delegate = context.getNextAdapter(GsonToMiniGsonTypeAdapterFactory.this, typeToken));
+ }
+ };
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/InnerClassExclusionStrategy.java b/src/com/massivecraft/core/lib/gson2/InnerClassExclusionStrategy.java
new file mode 100755
index 00000000..63816b7f
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/InnerClassExclusionStrategy.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import java.lang.reflect.Modifier;
+
+/**
+ * Strategy for excluding inner classes.
+ *
+ * @author Joel Leitch
+ */
+final class InnerClassExclusionStrategy implements ExclusionStrategy {
+
+ public boolean shouldSkipField(FieldAttributes f) {
+ return isInnerClass(f.getDeclaredClass());
+ }
+
+ public boolean shouldSkipClass(Class> clazz) {
+ return isInnerClass(clazz);
+ }
+
+ private boolean isInnerClass(Class> clazz) {
+ return clazz.isMemberClass() && !isStatic(clazz);
+ }
+
+ private boolean isStatic(Class> clazz) {
+ return (clazz.getModifiers() & Modifier.STATIC) != 0;
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/InstanceCreator.java b/src/com/massivecraft/core/lib/gson2/InstanceCreator.java
new file mode 100755
index 00000000..15961c16
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/InstanceCreator.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import java.lang.reflect.Type;
+
+/**
+ * This interface is implemented to create instances of a class that does not define a no-args
+ * constructor. If you can modify the class, you should instead add a private, or public
+ * no-args constructor. However, that is not possible for library classes, such as JDK classes, or
+ * a third-party library that you do not have source-code of. In such cases, you should define an
+ * instance creator for the class. Implementations of this interface should be registered with
+ * {@link GsonBuilder#registerTypeAdapter(Type, Object)} method before Gson will be able to use
+ * them.
+ *
Let us look at an example where defining an InstanceCreator might be useful. The
+ * {@code Id} class defined below does not have a default no-args constructor.
+ *
+ *
+ * public class Id<T> {
+ * private final Class<T> clazz;
+ * private final long value;
+ * public Id(Class<T> clazz, long value) {
+ * this.clazz = clazz;
+ * this.value = value;
+ * }
+ * }
+ *
+ *
+ *
If Gson encounters an object of type {@code Id} during deserialization, it will throw an
+ * exception. The easiest way to solve this problem will be to add a (public or private) no-args
+ * constructor as follows:
However, let us assume that the developer does not have access to the source-code of the
+ * {@code Id} class, or does not want to define a no-args constructor for it. The developer
+ * can solve this problem by defining an {@code InstanceCreator} for {@code Id}:
+ *
+ *
+ * class IdInstanceCreator implements InstanceCreator<Id> {
+ * public Id createInstance(Type type) {
+ * return new Id(Object.class, 0L);
+ * }
+ * }
+ *
+ *
+ *
Note that it does not matter what the fields of the created instance contain since Gson will
+ * overwrite them with the deserialized values specified in Json. You should also ensure that a
+ * new object is returned, not a common object since its fields will be overwritten.
+ * The developer will need to register {@code IdInstanceCreator} with Gson as follows:
+ *
+ *
+ * Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdInstanceCreator()).create();
+ *
+ *
+ * @param the type of object that will be created by this implementation.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+public interface InstanceCreator {
+
+ /**
+ * Gson invokes this call-back method during deserialization to create an instance of the
+ * specified type. The fields of the returned instance are overwritten with the data present
+ * in the Json. Since the prior contents of the object are destroyed and overwritten, do not
+ * return an instance that is useful elsewhere. In particular, do not return a common instance,
+ * always use {@code new} to create a new instance.
+ *
+ * @param type the parameterized T represented as a {@link Type}.
+ * @return a default object instance of type T.
+ */
+ public T createInstance(Type type);
+}
diff --git a/src/com/massivecraft/core/lib/gson2/JavaFieldNamingPolicy.java b/src/com/massivecraft/core/lib/gson2/JavaFieldNamingPolicy.java
new file mode 100755
index 00000000..fcf4f168
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/JavaFieldNamingPolicy.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collection;
+
+/**
+ * A simple implementation of the {@link FieldNamingStrategy2} interface such that it does not
+ * perform any string translation of the incoming field name.
+ *
+ *
The following is an example:
+ *
+ *
+ * class IntWrapper {
+ * public int integerField = 0;
+ * }
+ *
+ * JavaFieldNamingPolicy policy = new JavaFieldNamingPolicy();
+ * String translatedFieldName =
+ * policy.translateName(IntWrapper.class.getField("integerField"));
+ *
+ * assert("integerField".equals(translatedFieldName));
+ *
+ *
+ *
This is the default {@link FieldNamingStrategy2} used by Gson.
+ *
+ * @author Joel Leitch
+ */
+final class JavaFieldNamingPolicy extends RecursiveFieldNamingPolicy {
+
+ @Override
+ protected String translateName(String target, Type fieldType, Collection annotations) {
+ return target;
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/JsonArray.java b/src/com/massivecraft/core/lib/gson2/JsonArray.java
new file mode 100755
index 00000000..11640b28
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/JsonArray.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * A class representing an array type in Json. An array is a list of {@link JsonElement}s each of
+ * which can be of a different type. This is an ordered list, meaning that the order in which
+ * elements are added is preserved.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+public final class JsonArray extends JsonElement implements Iterable {
+ private final List elements;
+
+ /**
+ * Creates an empty JsonArray.
+ */
+ public JsonArray() {
+ elements = new ArrayList();
+ }
+
+ /**
+ * Adds the specified element to self.
+ *
+ * @param element the element that needs to be added to the array.
+ */
+ public void add(JsonElement element) {
+ if (element == null) {
+ element = JsonNull.INSTANCE;
+ }
+ elements.add(element);
+ }
+
+ /**
+ * Adds all the elements of the specified array to self.
+ *
+ * @param array the array whose elements need to be added to the array.
+ */
+ public void addAll(JsonArray array) {
+ elements.addAll(array.elements);
+ }
+
+ /**
+ * Returns the number of elements in the array.
+ *
+ * @return the number of elements in the array.
+ */
+ public int size() {
+ return elements.size();
+ }
+
+ /**
+ * Returns an iterator to navigate the elemetns of the array. Since the array is an ordered list,
+ * the iterator navigates the elements in the order they were inserted.
+ *
+ * @return an iterator to navigate the elements of the array.
+ */
+ public Iterator iterator() {
+ return elements.iterator();
+ }
+
+ /**
+ * Returns the ith element of the array.
+ *
+ * @param i the index of the element that is being sought.
+ * @return the element present at the ith index.
+ * @throws IndexOutOfBoundsException if i is negative or greater than or equal to the
+ * {@link #size()} of the array.
+ */
+ public JsonElement get(int i) {
+ return elements.get(i);
+ }
+
+ /**
+ * convenience method to get this array as a {@link Number} if it contains a single element.
+ *
+ * @return get this element as a number if it is single element array.
+ * @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
+ * is not a valid Number.
+ * @throws IllegalStateException if the array has more than one element.
+ */
+ @Override
+ public Number getAsNumber() {
+ if (elements.size() == 1) {
+ return elements.get(0).getAsNumber();
+ }
+ throw new IllegalStateException();
+ }
+
+ /**
+ * convenience method to get this array as a {@link String} if it contains a single element.
+ *
+ * @return get this element as a String if it is single element array.
+ * @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
+ * is not a valid String.
+ * @throws IllegalStateException if the array has more than one element.
+ */
+ @Override
+ public String getAsString() {
+ if (elements.size() == 1) {
+ return elements.get(0).getAsString();
+ }
+ throw new IllegalStateException();
+ }
+
+ /**
+ * convenience method to get this array as a double if it contains a single element.
+ *
+ * @return get this element as a double if it is single element array.
+ * @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
+ * is not a valid double.
+ * @throws IllegalStateException if the array has more than one element.
+ */
+ @Override
+ public double getAsDouble() {
+ if (elements.size() == 1) {
+ return elements.get(0).getAsDouble();
+ }
+ throw new IllegalStateException();
+ }
+
+ /**
+ * convenience method to get this array as a {@link BigDecimal} if it contains a single element.
+ *
+ * @return get this element as a {@link BigDecimal} if it is single element array.
+ * @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive}.
+ * @throws NumberFormatException if the element at index 0 is not a valid {@link BigDecimal}.
+ * @throws IllegalStateException if the array has more than one element.
+ * @since 1.2
+ */
+ @Override
+ public BigDecimal getAsBigDecimal() {
+ if (elements.size() == 1) {
+ return elements.get(0).getAsBigDecimal();
+ }
+ throw new IllegalStateException();
+ }
+
+ /**
+ * convenience method to get this array as a {@link BigInteger} if it contains a single element.
+ *
+ * @return get this element as a {@link BigInteger} if it is single element array.
+ * @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive}.
+ * @throws NumberFormatException if the element at index 0 is not a valid {@link BigInteger}.
+ * @throws IllegalStateException if the array has more than one element.
+ * @since 1.2
+ */
+ @Override
+ public BigInteger getAsBigInteger() {
+ if (elements.size() == 1) {
+ return elements.get(0).getAsBigInteger();
+ }
+ throw new IllegalStateException();
+ }
+
+ /**
+ * convenience method to get this array as a float if it contains a single element.
+ *
+ * @return get this element as a float if it is single element array.
+ * @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
+ * is not a valid float.
+ * @throws IllegalStateException if the array has more than one element.
+ */
+ @Override
+ public float getAsFloat() {
+ if (elements.size() == 1) {
+ return elements.get(0).getAsFloat();
+ }
+ throw new IllegalStateException();
+ }
+
+ /**
+ * convenience method to get this array as a long if it contains a single element.
+ *
+ * @return get this element as a long if it is single element array.
+ * @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
+ * is not a valid long.
+ * @throws IllegalStateException if the array has more than one element.
+ */
+ @Override
+ public long getAsLong() {
+ if (elements.size() == 1) {
+ return elements.get(0).getAsLong();
+ }
+ throw new IllegalStateException();
+ }
+
+ /**
+ * convenience method to get this array as an integer if it contains a single element.
+ *
+ * @return get this element as an integer if it is single element array.
+ * @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
+ * is not a valid integer.
+ * @throws IllegalStateException if the array has more than one element.
+ */
+ @Override
+ public int getAsInt() {
+ if (elements.size() == 1) {
+ return elements.get(0).getAsInt();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public byte getAsByte() {
+ if (elements.size() == 1) {
+ return elements.get(0).getAsByte();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public char getAsCharacter() {
+ if (elements.size() == 1) {
+ return elements.get(0).getAsCharacter();
+ }
+ throw new IllegalStateException();
+ }
+
+ /**
+ * convenience method to get this array as a primitive short if it contains a single element.
+ *
+ * @return get this element as a primitive short if it is single element array.
+ * @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
+ * is not a valid short.
+ * @throws IllegalStateException if the array has more than one element.
+ */
+ @Override
+ public short getAsShort() {
+ if (elements.size() == 1) {
+ return elements.get(0).getAsShort();
+ }
+ throw new IllegalStateException();
+ }
+
+ /**
+ * convenience method to get this array as a boolean if it contains a single element.
+ *
+ * @return get this element as a boolean if it is single element array.
+ * @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
+ * is not a valid boolean.
+ * @throws IllegalStateException if the array has more than one element.
+ */
+ @Override
+ public boolean getAsBoolean() {
+ if (elements.size() == 1) {
+ return elements.get(0).getAsBoolean();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return (o == this) || (o instanceof JsonArray && ((JsonArray) o).elements.equals(elements));
+ }
+
+ @Override
+ public int hashCode() {
+ return elements.hashCode();
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/JsonDeserializationContext.java b/src/com/massivecraft/core/lib/gson2/JsonDeserializationContext.java
new file mode 100755
index 00000000..0082d16f
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/JsonDeserializationContext.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import java.lang.reflect.Type;
+
+/**
+ * Context for deserialization that is passed to a custom deserializer during invocation of its
+ * {@link JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext)}
+ * method.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+public interface JsonDeserializationContext {
+
+ /**
+ * Invokes default deserialization on the specified object. It should never be invoked on
+ * the element received as a parameter of the
+ * {@link JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext)} method. Doing
+ * so will result in an infinite loop since Gson will in-turn call the custom deserializer again.
+ *
+ * @param json the parse tree.
+ * @param typeOfT type of the expected return value.
+ * @param The type of the deserialized object.
+ * @return An object of type typeOfT.
+ * @throws JsonParseException if the parse tree does not contain expected data.
+ */
+ public T deserialize(JsonElement json, Type typeOfT) throws JsonParseException;
+}
\ No newline at end of file
diff --git a/src/com/massivecraft/core/lib/gson2/JsonDeserializer.java b/src/com/massivecraft/core/lib/gson2/JsonDeserializer.java
new file mode 100755
index 00000000..a8637488
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/JsonDeserializer.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import java.lang.reflect.Type;
+
+/**
+ *
Interface representing a custom deserializer for Json. You should write a custom
+ * deserializer, if you are not happy with the default deserialization done by Gson. You will
+ * also need to register this deserializer through
+ * {@link GsonBuilder#registerTypeAdapter(Type, Object)}.
+ *
+ *
Let us look at example where defining a deserializer will be useful. The {@code Id} class
+ * defined below has two fields: {@code clazz} and {@code value}.
+ *
+ *
+ * public class Id<T> {
+ * private final Class<T> clazz;
+ * private final long value;
+ * public Id(Class<T> clazz, long value) {
+ * this.clazz = clazz;
+ * this.value = value;
+ * }
+ * public long getValue() {
+ * return value;
+ * }
+ * }
+ *
+ *
+ *
The default deserialization of {@code Id(com.foo.MyObject.class, 20L)} will require the
+ * Json string to be {"clazz":com.foo.MyObject,"value":20}. Suppose, you already know
+ * the type of the field that the {@code Id} will be deserialized into, and hence just want to
+ * deserialize it from a Json string {@code 20}. You can achieve that by writing a custom
+ * deserializer:
+ *
+ *
+ * class IdDeserializer implements JsonDeserializer<Id>() {
+ * public Id deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
+ * throws JsonParseException {
+ * return new Id((Class)typeOfT, id.getValue());
+ * }
+ *
+ *
+ *
You will also need to register {@code IdDeserializer} with Gson as follows:
+ *
+ *
+ * Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdDeserializer()).create();
+ *
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ *
+ * @param type for which the deserializer is being registered. It is possible that a
+ * deserializer may be asked to deserialize a specific generic type of the T.
+ */
+public interface JsonDeserializer {
+
+ /**
+ * Gson invokes this call-back method during deserialization when it encounters a field of the
+ * specified type.
+ *
In the implementation of this call-back method, you should consider invoking
+ * {@link JsonDeserializationContext#deserialize(JsonElement, Type)} method to create objects
+ * for any non-trivial field of the returned object. However, you should never invoke it on the
+ * the same type passing {@code json} since that will cause an infinite loop (Gson will call your
+ * call-back method again).
+ *
+ * @param json The Json data being deserialized
+ * @param typeOfT The type of the Object to deserialize to
+ * @return a deserialized object of the specified type typeOfT which is a subclass of {@code T}
+ * @throws JsonParseException if json is not in the expected format of {@code typeofT}
+ */
+ public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
+ throws JsonParseException;
+}
diff --git a/src/com/massivecraft/core/lib/gson2/JsonDeserializerExceptionWrapper.java b/src/com/massivecraft/core/lib/gson2/JsonDeserializerExceptionWrapper.java
new file mode 100755
index 00000000..d17060be
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/JsonDeserializerExceptionWrapper.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import com.massivecraft.core.lib.gson2.internal.$Gson$Preconditions;
+
+import java.lang.reflect.Type;
+
+/**
+ * Decorators a {@code JsonDeserializer} instance with exception handling. This wrapper class
+ * ensures that a {@code JsonDeserializer} will not propagate any exception other than a
+ * {@link JsonParseException}.
+ *
+ * @param type of the deserializer being wrapped.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+final class JsonDeserializerExceptionWrapper implements JsonDeserializer {
+
+ private final JsonDeserializer delegate;
+
+ /**
+ * Returns a wrapped {@link JsonDeserializer} object that has been decorated with
+ * {@link JsonParseException} handling.
+ *
+ * @param delegate the {@code JsonDeserializer} instance to be wrapped.
+ * @throws IllegalArgumentException if {@code delegate} is {@code null}.
+ */
+ JsonDeserializerExceptionWrapper(JsonDeserializer delegate) {
+ this.delegate = $Gson$Preconditions.checkNotNull(delegate);
+ }
+
+ public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
+ throws JsonParseException {
+ try {
+ return delegate.deserialize(json, typeOfT, context);
+ } catch (JsonParseException e) {
+ // just rethrow the exception
+ throw e;
+ } catch (Exception e) {
+ // rethrow as a JsonParseException
+ StringBuilder errorMsg = new StringBuilder()
+ .append("The JsonDeserializer ")
+ .append(delegate)
+ .append(" failed to deserialize json object ")
+ .append(json)
+ .append(" given the type ")
+ .append(typeOfT);
+ throw new JsonParseException(errorMsg.toString(), e);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return delegate.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/com/massivecraft/core/lib/gson2/JsonElement.java b/src/com/massivecraft/core/lib/gson2/JsonElement.java
new file mode 100755
index 00000000..1b3e5144
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/JsonElement.java
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import com.massivecraft.core.lib.gson2.internal.Streams;
+import com.massivecraft.core.lib.gson2.stream.JsonWriter;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+/**
+ * A class representing an element of Json. It could either be a {@link JsonObject}, a
+ * {@link JsonArray}, a {@link JsonPrimitive} or a {@link JsonNull}.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+public abstract class JsonElement {
+ /**
+ * provides check for verifying if this element is an array or not.
+ *
+ * @return true if this element is of type {@link JsonArray}, false otherwise.
+ */
+ public boolean isJsonArray() {
+ return this instanceof JsonArray;
+ }
+
+ /**
+ * provides check for verifying if this element is a Json object or not.
+ *
+ * @return true if this element is of type {@link JsonObject}, false otherwise.
+ */
+ public boolean isJsonObject() {
+ return this instanceof JsonObject;
+ }
+
+ /**
+ * provides check for verifying if this element is a primitive or not.
+ *
+ * @return true if this element is of type {@link JsonPrimitive}, false otherwise.
+ */
+ public boolean isJsonPrimitive() {
+ return this instanceof JsonPrimitive;
+ }
+
+ /**
+ * provides check for verifying if this element represents a null value or not.
+ *
+ * @return true if this element is of type {@link JsonNull}, false otherwise.
+ * @since 1.2
+ */
+ public boolean isJsonNull() {
+ return this instanceof JsonNull;
+ }
+
+ /**
+ * convenience method to get this element as a {@link JsonObject}. If the element is of some
+ * other type, a {@link ClassCastException} will result. Hence it is best to use this method
+ * after ensuring that this element is of the desired type by calling {@link #isJsonObject()}
+ * first.
+ *
+ * @return get this element as a {@link JsonObject}.
+ * @throws IllegalStateException if the element is of another type.
+ */
+ public JsonObject getAsJsonObject() {
+ if (isJsonObject()) {
+ return (JsonObject) this;
+ }
+ throw new IllegalStateException("Not a JSON Object: " + this);
+ }
+
+ /**
+ * convenience method to get this element as a {@link JsonArray}. If the element is of some
+ * other type, a {@link ClassCastException} will result. Hence it is best to use this method
+ * after ensuring that this element is of the desired type by calling {@link #isJsonArray()}
+ * first.
+ *
+ * @return get this element as a {@link JsonArray}.
+ * @throws IllegalStateException if the element is of another type.
+ */
+ public JsonArray getAsJsonArray() {
+ if (isJsonArray()) {
+ return (JsonArray) this;
+ }
+ throw new IllegalStateException("This is not a JSON Array.");
+ }
+
+ /**
+ * convenience method to get this element as a {@link JsonPrimitive}. If the element is of some
+ * other type, a {@link ClassCastException} will result. Hence it is best to use this method
+ * after ensuring that this element is of the desired type by calling {@link #isJsonPrimitive()}
+ * first.
+ *
+ * @return get this element as a {@link JsonPrimitive}.
+ * @throws IllegalStateException if the element is of another type.
+ */
+ public JsonPrimitive getAsJsonPrimitive() {
+ if (isJsonPrimitive()) {
+ return (JsonPrimitive) this;
+ }
+ throw new IllegalStateException("This is not a JSON Primitive.");
+ }
+
+ /**
+ * convenience method to get this element as a {@link JsonNull}. If the element is of some
+ * other type, a {@link ClassCastException} will result. Hence it is best to use this method
+ * after ensuring that this element is of the desired type by calling {@link #isJsonNull()}
+ * first.
+ *
+ * @return get this element as a {@link JsonNull}.
+ * @throws IllegalStateException if the element is of another type.
+ * @since 1.2
+ */
+ public JsonNull getAsJsonNull() {
+ if (isJsonNull()) {
+ return (JsonNull) this;
+ }
+ throw new IllegalStateException("This is not a JSON Null.");
+ }
+
+ /**
+ * convenience method to get this element as a boolean value.
+ *
+ * @return get this element as a primitive boolean value.
+ * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
+ * boolean value.
+ * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
+ * more than a single element.
+ */
+ public boolean getAsBoolean() {
+ throw new UnsupportedOperationException(getClass().getSimpleName());
+ }
+
+ /**
+ * convenience method to get this element as a {@link Boolean} value.
+ *
+ * @return get this element as a {@link Boolean} value.
+ * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
+ * boolean value.
+ * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
+ * more than a single element.
+ */
+ Boolean getAsBooleanWrapper() {
+ throw new UnsupportedOperationException(getClass().getSimpleName());
+ }
+
+ /**
+ * convenience method to get this element as a {@link Number}.
+ *
+ * @return get this element as a {@link Number}.
+ * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
+ * number.
+ * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
+ * more than a single element.
+ */
+ public Number getAsNumber() {
+ throw new UnsupportedOperationException(getClass().getSimpleName());
+ }
+
+ /**
+ * convenience method to get this element as a string value.
+ *
+ * @return get this element as a string value.
+ * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
+ * string value.
+ * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
+ * more than a single element.
+ */
+ public String getAsString() {
+ throw new UnsupportedOperationException(getClass().getSimpleName());
+ }
+
+ /**
+ * convenience method to get this element as a primitive double value.
+ *
+ * @return get this element as a primitive double value.
+ * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
+ * double value.
+ * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
+ * more than a single element.
+ */
+ public double getAsDouble() {
+ throw new UnsupportedOperationException(getClass().getSimpleName());
+ }
+
+ /**
+ * convenience method to get this element as a primitive float value.
+ *
+ * @return get this element as a primitive float value.
+ * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
+ * float value.
+ * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
+ * more than a single element.
+ */
+ public float getAsFloat() {
+ throw new UnsupportedOperationException(getClass().getSimpleName());
+ }
+
+ /**
+ * convenience method to get this element as a primitive long value.
+ *
+ * @return get this element as a primitive long value.
+ * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
+ * long value.
+ * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
+ * more than a single element.
+ */
+ public long getAsLong() {
+ throw new UnsupportedOperationException(getClass().getSimpleName());
+ }
+
+ /**
+ * convenience method to get this element as a primitive integer value.
+ *
+ * @return get this element as a primitive integer value.
+ * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
+ * integer value.
+ * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
+ * more than a single element.
+ */
+ public int getAsInt() {
+ throw new UnsupportedOperationException(getClass().getSimpleName());
+ }
+
+ /**
+ * convenience method to get this element as a primitive byte value.
+ *
+ * @return get this element as a primitive byte value.
+ * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
+ * byte value.
+ * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
+ * more than a single element.
+ * @since 1.3
+ */
+ public byte getAsByte() {
+ throw new UnsupportedOperationException(getClass().getSimpleName());
+ }
+
+ /**
+ * convenience method to get this element as a primitive character value.
+ *
+ * @return get this element as a primitive char value.
+ * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
+ * char value.
+ * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
+ * more than a single element.
+ * @since 1.3
+ */
+ public char getAsCharacter() {
+ throw new UnsupportedOperationException(getClass().getSimpleName());
+ }
+
+ /**
+ * convenience method to get this element as a {@link BigDecimal}.
+ *
+ * @return get this element as a {@link BigDecimal}.
+ * @throws ClassCastException if the element is of not a {@link JsonPrimitive}.
+ * * @throws NumberFormatException if the element is not a valid {@link BigDecimal}.
+ * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
+ * more than a single element.
+ * @since 1.2
+ */
+ public BigDecimal getAsBigDecimal() {
+ throw new UnsupportedOperationException(getClass().getSimpleName());
+ }
+
+ /**
+ * convenience method to get this element as a {@link BigInteger}.
+ *
+ * @return get this element as a {@link BigInteger}.
+ * @throws ClassCastException if the element is of not a {@link JsonPrimitive}.
+ * @throws NumberFormatException if the element is not a valid {@link BigInteger}.
+ * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
+ * more than a single element.
+ * @since 1.2
+ */
+ public BigInteger getAsBigInteger() {
+ throw new UnsupportedOperationException(getClass().getSimpleName());
+ }
+
+ /**
+ * convenience method to get this element as a primitive short value.
+ *
+ * @return get this element as a primitive short value.
+ * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
+ * short value.
+ * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
+ * more than a single element.
+ */
+ public short getAsShort() {
+ throw new UnsupportedOperationException(getClass().getSimpleName());
+ }
+
+ /**
+ * Returns a String representation of this element.
+ */
+ @Override
+ public String toString() {
+ try {
+ StringWriter stringWriter = new StringWriter();
+ JsonWriter jsonWriter = new JsonWriter(stringWriter);
+ jsonWriter.setLenient(true);
+ Streams.write(this, jsonWriter);
+ return stringWriter.toString();
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/JsonElementVisitor.java b/src/com/massivecraft/core/lib/gson2/JsonElementVisitor.java
new file mode 100755
index 00000000..4aca2948
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/JsonElementVisitor.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import java.io.IOException;
+
+/**
+ * Definition of a visitor for a JsonElement tree.
+ *
+ * @author Inderjeet Singh
+ */
+interface JsonElementVisitor {
+ void visitPrimitive(JsonPrimitive primitive) throws IOException;
+ void visitNull() throws IOException;
+
+ void startArray(JsonArray array) throws IOException;
+ void visitArrayMember(JsonArray parent, JsonPrimitive member, boolean isFirst) throws IOException;
+ void visitArrayMember(JsonArray parent, JsonArray member, boolean isFirst) throws IOException;
+ void visitArrayMember(JsonArray parent, JsonObject member, boolean isFirst) throws IOException;
+ void visitNullArrayMember(JsonArray parent, boolean isFirst) throws IOException;
+ void endArray(JsonArray array) throws IOException;
+
+ void startObject(JsonObject object) throws IOException;
+ void visitObjectMember(JsonObject parent, String memberName, JsonPrimitive member,
+ boolean isFirst) throws IOException;
+ void visitObjectMember(JsonObject parent, String memberName, JsonArray member,
+ boolean isFirst) throws IOException;
+ void visitObjectMember(JsonObject parent, String memberName, JsonObject member,
+ boolean isFirst) throws IOException;
+ void visitNullObjectMember(JsonObject parent, String memberName,
+ boolean isFirst) throws IOException;
+ void endObject(JsonObject object) throws IOException;
+}
\ No newline at end of file
diff --git a/src/com/massivecraft/core/lib/gson2/JsonIOException.java b/src/com/massivecraft/core/lib/gson2/JsonIOException.java
new file mode 100755
index 00000000..ba74f5be
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/JsonIOException.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+/**
+ * This exception is raised when Gson was unable to read an input stream
+ * or write to one.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+public final class JsonIOException extends JsonParseException {
+
+ private static final long serialVersionUID = 1L;
+
+ public JsonIOException(String msg) {
+ super(msg);
+ }
+
+ public JsonIOException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+ /**
+ * Creates exception with the specified cause. Consider using
+ * {@link #JsonIOException(String, Throwable)} instead if you can describe what happened.
+ *
+ * @param cause root exception that caused this exception to be thrown.
+ */
+ public JsonIOException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/JsonNull.java b/src/com/massivecraft/core/lib/gson2/JsonNull.java
new file mode 100755
index 00000000..b08226ba
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/JsonNull.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+/**
+ * A class representing a Json {@code null} value.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ * @since 1.2
+ */
+public final class JsonNull extends JsonElement {
+ /**
+ * singleton for JsonNull
+ *
+ * @since 1.8
+ */
+ public static final JsonNull INSTANCE = new JsonNull();
+
+ /**
+ * Creates a new JsonNull object.
+ * Deprecated since Gson version 1.8. Use {@link #INSTANCE} instead
+ */
+ @Deprecated
+ public JsonNull() {
+ // Do nothing
+ }
+
+ /**
+ * All instances of JsonNull have the same hash code since they are indistinguishable
+ */
+ @Override
+ public int hashCode() {
+ return JsonNull.class.hashCode();
+ }
+
+ /**
+ * All instances of JsonNull are the same
+ */
+ @Override
+ public boolean equals(Object other) {
+ return this == other || other instanceof JsonNull;
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/JsonObject.java b/src/com/massivecraft/core/lib/gson2/JsonObject.java
new file mode 100755
index 00000000..9a231161
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/JsonObject.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import com.massivecraft.core.lib.gson2.internal.$Gson$Preconditions;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A class representing an object type in Json. An object consists of name-value pairs where names
+ * are strings, and values are any other type of {@link JsonElement}. This allows for a creating a
+ * tree of JsonElements. The member elements of this object are maintained in order they were added.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+public final class JsonObject extends JsonElement {
+ // We are using a linked hash map because it is important to preserve
+ // the order in which elements are inserted. This is needed to ensure
+ // that the fields of an object are inserted in the order they were
+ // defined in the class.
+ private final Map members = new LinkedHashMap();
+
+ /**
+ * Creates an empty JsonObject.
+ */
+ public JsonObject() {
+ }
+
+ /**
+ * Adds a member, which is a name-value pair, to self. The name must be a String, but the value
+ * can be an arbitrary JsonElement, thereby allowing you to build a full tree of JsonElements
+ * rooted at this node.
+ *
+ * @param property name of the member.
+ * @param value the member object.
+ */
+ public void add(String property, JsonElement value) {
+ if (value == null) {
+ value = JsonNull.INSTANCE;
+ }
+ members.put($Gson$Preconditions.checkNotNull(property), value);
+ }
+
+ /**
+ * Removes the {@code property} from this {@link JsonObject}.
+ *
+ * @param property name of the member that should be removed.
+ * @return the {@link JsonElement} object that is being removed.
+ * @since 1.3
+ */
+ public JsonElement remove(String property) {
+ return members.remove(property);
+ }
+
+ /**
+ * Convenience method to add a primitive member. The specified value is converted to a
+ * JsonPrimitive of String.
+ *
+ * @param property name of the member.
+ * @param value the string value associated with the member.
+ */
+ public void addProperty(String property, String value) {
+ add(property, createJsonElement(value));
+ }
+
+ /**
+ * Convenience method to add a primitive member. The specified value is converted to a
+ * JsonPrimitive of Number.
+ *
+ * @param property name of the member.
+ * @param value the number value associated with the member.
+ */
+ public void addProperty(String property, Number value) {
+ add(property, createJsonElement(value));
+ }
+
+ /**
+ * Convenience method to add a boolean member. The specified value is converted to a
+ * JsonPrimitive of Boolean.
+ *
+ * @param property name of the member.
+ * @param value the number value associated with the member.
+ */
+ public void addProperty(String property, Boolean value) {
+ add(property, createJsonElement(value));
+ }
+
+ /**
+ * Convenience method to add a char member. The specified value is converted to a
+ * JsonPrimitive of Character.
+ *
+ * @param property name of the member.
+ * @param value the number value associated with the member.
+ */
+ public void addProperty(String property, Character value) {
+ add(property, createJsonElement(value));
+ }
+
+ /**
+ * Creates the proper {@link JsonElement} object from the given {@code value} object.
+ *
+ * @param value the object to generate the {@link JsonElement} for
+ * @return a {@link JsonPrimitive} if the {@code value} is not null, otherwise a {@link JsonNull}
+ */
+ private JsonElement createJsonElement(Object value) {
+ return value == null ? JsonNull.INSTANCE : new JsonPrimitive(value);
+ }
+
+ /**
+ * Returns a set of members of this object. The set is ordered, and the order is in which the
+ * elements were added.
+ *
+ * @return a set of members of this object.
+ */
+ public Set> entrySet() {
+ return members.entrySet();
+ }
+
+ /**
+ * Convenience method to check if a member with the specified name is present in this object.
+ *
+ * @param memberName name of the member that is being checked for presence.
+ * @return true if there is a member with the specified name, false otherwise.
+ */
+ public boolean has(String memberName) {
+ return members.containsKey(memberName);
+ }
+
+ /**
+ * Returns the member with the specified name.
+ *
+ * @param memberName name of the member that is being requested.
+ * @return the member matching the name. Null if no such member exists.
+ */
+ public JsonElement get(String memberName) {
+ if (members.containsKey(memberName)) {
+ JsonElement member = members.get(memberName);
+ return member == null ? JsonNull.INSTANCE : member;
+ }
+ return null;
+ }
+
+ /**
+ * Convenience method to get the specified member as a JsonPrimitive element.
+ *
+ * @param memberName name of the member being requested.
+ * @return the JsonPrimitive corresponding to the specified member.
+ */
+ public JsonPrimitive getAsJsonPrimitive(String memberName) {
+ return (JsonPrimitive) members.get(memberName);
+ }
+
+ /**
+ * Convenience method to get the specified member as a JsonArray.
+ *
+ * @param memberName name of the member being requested.
+ * @return the JsonArray corresponding to the specified member.
+ */
+ public JsonArray getAsJsonArray(String memberName) {
+ return (JsonArray) members.get(memberName);
+ }
+
+ /**
+ * Convenience method to get the specified member as a JsonObject.
+ *
+ * @param memberName name of the member being requested.
+ * @return the JsonObject corresponding to the specified member.
+ */
+ public JsonObject getAsJsonObject(String memberName) {
+ return (JsonObject) members.get(memberName);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return (o == this) || (o instanceof JsonObject
+ && ((JsonObject) o).members.equals(members));
+ }
+
+ @Override
+ public int hashCode() {
+ return members.hashCode();
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/JsonParseException.java b/src/com/massivecraft/core/lib/gson2/JsonParseException.java
new file mode 100755
index 00000000..61f9beac
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/JsonParseException.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+/**
+ * This exception is raised if there is a serious issue that occurs during parsing of a Json
+ * string. One of the main usages for this class is for the Gson infrastructure. If the incoming
+ * Json is bad/malicious, an instance of this exception is raised.
+ *
+ *
This exception is a {@link RuntimeException} because it is exposed to the client. Using a
+ * {@link RuntimeException} avoids bad coding practices on the client side where they catch the
+ * exception and do nothing. It is often the case that you want to blow up if there is a parsing
+ * error (i.e. often clients do not know how to recover from a {@link JsonParseException}.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+public class JsonParseException extends RuntimeException {
+ static final long serialVersionUID = -4086729973971783390L;
+
+ /**
+ * Creates exception with the specified message. If you are wrapping another exception, consider
+ * using {@link #JsonParseException(String, Throwable)} instead.
+ *
+ * @param msg error message describing a possible cause of this exception.
+ */
+ public JsonParseException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Creates exception with the specified message and cause.
+ *
+ * @param msg error message describing what happened.
+ * @param cause root exception that caused this exception to be thrown.
+ */
+ public JsonParseException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+ /**
+ * Creates exception with the specified cause. Consider using
+ * {@link #JsonParseException(String, Throwable)} instead if you can describe what happened.
+ *
+ * @param cause root exception that caused this exception to be thrown.
+ */
+ public JsonParseException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/JsonParser.java b/src/com/massivecraft/core/lib/gson2/JsonParser.java
new file mode 100755
index 00000000..79f92fc5
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/JsonParser.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2009 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.massivecraft.core.lib.gson2;
+
+import com.massivecraft.core.lib.gson2.internal.Streams;
+import com.massivecraft.core.lib.gson2.stream.JsonReader;
+import com.massivecraft.core.lib.gson2.stream.JsonToken;
+import com.massivecraft.core.lib.gson2.stream.MalformedJsonException;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+
+/**
+ * A parser to parse Json into a parse tree of {@link JsonElement}s
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ * @since 1.3
+ */
+public final class JsonParser {
+
+ /**
+ * Parses the specified JSON string into a parse tree
+ *
+ * @param json JSON text
+ * @return a parse tree of {@link JsonElement}s corresponding to the specified JSON
+ * @throws JsonParseException if the specified text is not valid JSON
+ * @since 1.3
+ */
+ public JsonElement parse(String json) throws JsonSyntaxException {
+ return parse(new StringReader(json));
+ }
+
+ /**
+ * Parses the specified JSON string into a parse tree
+ *
+ * @param json JSON text
+ * @return a parse tree of {@link JsonElement}s corresponding to the specified JSON
+ * @throws JsonParseException if the specified text is not valid JSON
+ * @since 1.3
+ */
+ public JsonElement parse(Reader json) throws JsonIOException, JsonSyntaxException {
+ try {
+ JsonReader jsonReader = new JsonReader(json);
+ JsonElement element = parse(jsonReader);
+ if (!element.isJsonNull() && jsonReader.peek() != JsonToken.END_DOCUMENT) {
+ throw new JsonSyntaxException("Did not consume the entire document.");
+ }
+ return element;
+ } catch (MalformedJsonException e) {
+ throw new JsonSyntaxException(e);
+ } catch (IOException e) {
+ throw new JsonIOException(e);
+ } catch (NumberFormatException e) {
+ throw new JsonSyntaxException(e);
+ }
+ }
+
+ /**
+ * Returns the next value from the JSON stream as a parse tree.
+ *
+ * @throws JsonParseException if there is an IOException or if the specified
+ * text is not valid JSON
+ * @since 1.6
+ */
+ public JsonElement parse(JsonReader json) throws JsonIOException, JsonSyntaxException {
+ boolean lenient = json.isLenient();
+ json.setLenient(true);
+ try {
+ return Streams.parse(json);
+ } catch (StackOverflowError e) {
+ throw new JsonParseException("Failed parsing JSON source: " + json + " to Json", e);
+ } catch (OutOfMemoryError e) {
+ throw new JsonParseException("Failed parsing JSON source: " + json + " to Json", e);
+ } catch (JsonParseException e) {
+ if (e.getCause() instanceof EOFException) {
+ return JsonNull.INSTANCE;
+ }
+ throw e;
+ } finally {
+ json.setLenient(lenient);
+ }
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/JsonPrimitive.java b/src/com/massivecraft/core/lib/gson2/JsonPrimitive.java
new file mode 100755
index 00000000..95dec800
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/JsonPrimitive.java
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import com.massivecraft.core.lib.gson2.internal.$Gson$Preconditions;
+import com.massivecraft.core.lib.gson2.internal.LazilyParsedNumber;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+/**
+ * A class representing a Json primitive value. A primitive value
+ * is either a String, a Java primitive, or a Java primitive
+ * wrapper type.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+public final class JsonPrimitive extends JsonElement {
+
+ private static final Class>[] PRIMITIVE_TYPES = { int.class, long.class, short.class,
+ float.class, double.class, byte.class, boolean.class, char.class, Integer.class, Long.class,
+ Short.class, Float.class, Double.class, Byte.class, Boolean.class, Character.class };
+
+ private Object value;
+
+ /**
+ * Create a primitive containing a boolean value.
+ *
+ * @param bool the value to create the primitive with.
+ */
+ public JsonPrimitive(Boolean bool) {
+ setValue(bool);
+ }
+
+ /**
+ * Create a primitive containing a {@link Number}.
+ *
+ * @param number the value to create the primitive with.
+ */
+ public JsonPrimitive(Number number) {
+ setValue(number);
+ }
+
+ /**
+ * Create a primitive containing a String value.
+ *
+ * @param string the value to create the primitive with.
+ */
+ public JsonPrimitive(String string) {
+ setValue(string);
+ }
+
+ /**
+ * Create a primitive containing a character. The character is turned into a one character String
+ * since Json only supports String.
+ *
+ * @param c the value to create the primitive with.
+ */
+ public JsonPrimitive(Character c) {
+ setValue(c);
+ }
+
+ /**
+ * Create a primitive using the specified Object. It must be an instance of {@link Number}, a
+ * Java primitive type, or a String.
+ *
+ * @param primitive the value to create the primitive with.
+ */
+ JsonPrimitive(Object primitive) {
+ setValue(primitive);
+ }
+
+ void setValue(Object primitive) {
+ if (primitive instanceof Character) {
+ // convert characters to strings since in JSON, characters are represented as a single
+ // character string
+ char c = ((Character) primitive).charValue();
+ this.value = String.valueOf(c);
+ } else {
+ $Gson$Preconditions.checkArgument(primitive instanceof Number
+ || isPrimitiveOrString(primitive));
+ this.value = primitive;
+ }
+ }
+
+ /**
+ * Check whether this primitive contains a boolean value.
+ *
+ * @return true if this primitive contains a boolean value, false otherwise.
+ */
+ public boolean isBoolean() {
+ return value instanceof Boolean;
+ }
+
+ /**
+ * convenience method to get this element as a {@link Boolean}.
+ *
+ * @return get this element as a {@link Boolean}.
+ */
+ @Override
+ Boolean getAsBooleanWrapper() {
+ return (Boolean) value;
+ }
+
+ /**
+ * convenience method to get this element as a boolean value.
+ *
+ * @return get this element as a primitive boolean value.
+ */
+ @Override
+ public boolean getAsBoolean() {
+ if (isBoolean()) {
+ return getAsBooleanWrapper().booleanValue();
+ } else {
+ // Check to see if the value as a String is "true" in any case.
+ return Boolean.parseBoolean(getAsString());
+ }
+ }
+
+ /**
+ * Check whether this primitive contains a Number.
+ *
+ * @return true if this primitive contains a Number, false otherwise.
+ */
+ public boolean isNumber() {
+ return value instanceof Number;
+ }
+
+ /**
+ * convenience method to get this element as a Number.
+ *
+ * @return get this element as a Number.
+ * @throws NumberFormatException if the value contained is not a valid Number.
+ */
+ @Override
+ public Number getAsNumber() {
+ return value instanceof String ? new LazilyParsedNumber((String) value) : (Number) value;
+ }
+
+ /**
+ * Check whether this primitive contains a String value.
+ *
+ * @return true if this primitive contains a String value, false otherwise.
+ */
+ public boolean isString() {
+ return value instanceof String;
+ }
+
+ /**
+ * convenience method to get this element as a String.
+ *
+ * @return get this element as a String.
+ */
+ @Override
+ public String getAsString() {
+ if (isNumber()) {
+ return getAsNumber().toString();
+ } else if (isBoolean()) {
+ return getAsBooleanWrapper().toString();
+ } else {
+ return (String) value;
+ }
+ }
+
+ /**
+ * convenience method to get this element as a primitive double.
+ *
+ * @return get this element as a primitive double.
+ * @throws NumberFormatException if the value contained is not a valid double.
+ */
+ @Override
+ public double getAsDouble() {
+ return isNumber() ? getAsNumber().doubleValue() : Double.parseDouble(getAsString());
+ }
+
+ /**
+ * convenience method to get this element as a {@link BigDecimal}.
+ *
+ * @return get this element as a {@link BigDecimal}.
+ * @throws NumberFormatException if the value contained is not a valid {@link BigDecimal}.
+ */
+ @Override
+ public BigDecimal getAsBigDecimal() {
+ return value instanceof BigDecimal ? (BigDecimal) value : new BigDecimal(value.toString());
+ }
+
+ /**
+ * convenience method to get this element as a {@link BigInteger}.
+ *
+ * @return get this element as a {@link BigInteger}.
+ * @throws NumberFormatException if the value contained is not a valid {@link BigInteger}.
+ */
+ @Override
+ public BigInteger getAsBigInteger() {
+ return value instanceof BigInteger ?
+ (BigInteger) value : new BigInteger(value.toString());
+ }
+
+ /**
+ * convenience method to get this element as a float.
+ *
+ * @return get this element as a float.
+ * @throws NumberFormatException if the value contained is not a valid float.
+ */
+ @Override
+ public float getAsFloat() {
+ return isNumber() ? getAsNumber().floatValue() : Float.parseFloat(getAsString());
+ }
+
+ /**
+ * convenience method to get this element as a primitive long.
+ *
+ * @return get this element as a primitive long.
+ * @throws NumberFormatException if the value contained is not a valid long.
+ */
+ @Override
+ public long getAsLong() {
+ return isNumber() ? getAsNumber().longValue() : Long.parseLong(getAsString());
+ }
+
+ /**
+ * convenience method to get this element as a primitive short.
+ *
+ * @return get this element as a primitive short.
+ * @throws NumberFormatException if the value contained is not a valid short value.
+ */
+ @Override
+ public short getAsShort() {
+ return isNumber() ? getAsNumber().shortValue() : Short.parseShort(getAsString());
+ }
+
+ /**
+ * convenience method to get this element as a primitive integer.
+ *
+ * @return get this element as a primitive integer.
+ * @throws NumberFormatException if the value contained is not a valid integer.
+ */
+ @Override
+ public int getAsInt() {
+ return isNumber() ? getAsNumber().intValue() : Integer.parseInt(getAsString());
+ }
+
+ @Override
+ public byte getAsByte() {
+ return isNumber() ? getAsNumber().byteValue() : Byte.parseByte(getAsString());
+ }
+
+ @Override
+ public char getAsCharacter() {
+ return getAsString().charAt(0);
+ }
+
+ private static boolean isPrimitiveOrString(Object target) {
+ if (target instanceof String) {
+ return true;
+ }
+
+ Class> classOfPrimitive = target.getClass();
+ for (Class> standardPrimitive : PRIMITIVE_TYPES) {
+ if (standardPrimitive.isAssignableFrom(classOfPrimitive)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ if (value == null) {
+ return 31;
+ }
+ // Using recommended hashing algorithm from Effective Java for longs and doubles
+ if (isIntegral(this)) {
+ long value = getAsNumber().longValue();
+ return (int) (value ^ (value >>> 32));
+ }
+ if (value instanceof Number) {
+ long value = Double.doubleToLongBits(getAsNumber().doubleValue());
+ return (int) (value ^ (value >>> 32));
+ }
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ JsonPrimitive other = (JsonPrimitive)obj;
+ if (value == null) {
+ return other.value == null;
+ }
+ if (isIntegral(this) && isIntegral(other)) {
+ return getAsNumber().longValue() == other.getAsNumber().longValue();
+ }
+ if (value instanceof Number && other.value instanceof Number) {
+ double a = getAsNumber().doubleValue();
+ // Java standard types other than double return true for two NaN. So, need
+ // special handling for double.
+ double b = other.getAsNumber().doubleValue();
+ return a == b || (Double.isNaN(a) && Double.isNaN(b));
+ }
+ return value.equals(other.value);
+ }
+
+ /**
+ * Returns true if the specified number is an integral type
+ * (Long, Integer, Short, Byte, BigInteger)
+ */
+ private static boolean isIntegral(JsonPrimitive primitive) {
+ if (primitive.value instanceof Number) {
+ Number number = (Number) primitive.value;
+ return number instanceof BigInteger || number instanceof Long || number instanceof Integer
+ || number instanceof Short || number instanceof Byte;
+ }
+ return false;
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/JsonSerializationContext.java b/src/com/massivecraft/core/lib/gson2/JsonSerializationContext.java
new file mode 100755
index 00000000..f13f0377
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/JsonSerializationContext.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import java.lang.reflect.Type;
+
+/**
+ * Context for serialization that is passed to a custom serializer during invocation of its
+ * {@link JsonSerializer#serialize(Object, Type, JsonSerializationContext)} method.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+public interface JsonSerializationContext {
+
+ /**
+ * Invokes default serialization on the specified object.
+ *
+ * @param src the object that needs to be serialized.
+ * @return a tree of {@link JsonElement}s corresponding to the serialized form of {@code src}.
+ */
+ public JsonElement serialize(Object src);
+
+ /**
+ * Invokes default serialization on the specified object passing the specific type information.
+ * It should never be invoked on the element received as a parameter of the
+ * {@link JsonSerializer#serialize(Object, Type, JsonSerializationContext)} method. Doing
+ * so will result in an infinite loop since Gson will in-turn call the custom serializer again.
+ *
+ * @param src the object that needs to be serialized.
+ * @param typeOfSrc the actual genericized type of src object.
+ * @return a tree of {@link JsonElement}s corresponding to the serialized form of {@code src}.
+ */
+ public JsonElement serialize(Object src, Type typeOfSrc);
+}
diff --git a/src/com/massivecraft/core/lib/gson2/JsonSerializer.java b/src/com/massivecraft/core/lib/gson2/JsonSerializer.java
new file mode 100755
index 00000000..9589cec1
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/JsonSerializer.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import java.lang.reflect.Type;
+
+/**
+ * Interface representing a custom serializer for Json. You should write a custom serializer, if
+ * you are not happy with the default serialization done by Gson. You will also need to register
+ * this serializer through {@link com.massivecraft.core.lib.gson2.GsonBuilder#registerTypeAdapter(Type, Object)}.
+ *
+ *
Let us look at example where defining a serializer will be useful. The {@code Id} class
+ * defined below has two fields: {@code clazz} and {@code value}.
+ *
+ *
+ * public class Id<T> {
+ * private final Class<T> clazz;
+ * private final long value;
+ *
+ * public Id(Class<T> clazz, long value) {
+ * this.clazz = clazz;
+ * this.value = value;
+ * }
+ *
+ * public long getValue() {
+ * return value;
+ * }
+ * }
+ *
+ *
+ *
The default serialization of {@code Id(com.foo.MyObject.class, 20L)} will be
+ * {"clazz":com.foo.MyObject,"value":20}. Suppose, you just want the output to be
+ * the value instead, which is {@code 20} in this case. You can achieve that by writing a custom
+ * serializer:
+ *
+ *
+ * class IdSerializer implements JsonSerializer<Id>() {
+ * public JsonElement serialize(Id id, Type typeOfId, JsonSerializationContext context) {
+ * return new JsonPrimitive(id.getValue());
+ * }
+ * }
+ *
+ *
+ *
You will also need to register {@code IdSerializer} with Gson as follows:
+ *
+ * Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdSerializer()).create();
+ *
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ *
+ * @param type for which the serializer is being registered. It is possible that a serializer
+ * may be asked to serialize a specific generic type of the T.
+ */
+public interface JsonSerializer {
+
+ /**
+ * Gson invokes this call-back method during serialization when it encounters a field of the
+ * specified type.
+ *
+ *
In the implementation of this call-back method, you should consider invoking
+ * {@link JsonSerializationContext#serialize(Object, Type)} method to create JsonElements for any
+ * non-trivial field of the {@code src} object. However, you should never invoke it on the
+ * {@code src} object itself since that will cause an infinite loop (Gson will call your
+ * call-back method again).
+ *
+ * @param src the object that needs to be converted to Json.
+ * @param typeOfSrc the actual type (fully genericized version) of the source object.
+ * @return a JsonElement corresponding to the specified object.
+ */
+ public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context);
+}
diff --git a/src/com/massivecraft/core/lib/gson2/JsonStreamParser.java b/src/com/massivecraft/core/lib/gson2/JsonStreamParser.java
new file mode 100755
index 00000000..e01d5571
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/JsonStreamParser.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2009 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.massivecraft.core.lib.gson2;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import com.massivecraft.core.lib.gson2.internal.Streams;
+import com.massivecraft.core.lib.gson2.stream.JsonReader;
+import com.massivecraft.core.lib.gson2.stream.JsonToken;
+import com.massivecraft.core.lib.gson2.stream.MalformedJsonException;
+
+/**
+ * A streaming parser that allows reading of multiple {@link JsonElement}s from the specified reader
+ * asynchronously.
+ *
+ *
This class is conditionally thread-safe (see Item 70, Effective Java second edition). To
+ * properly use this class across multiple threads, you will need to add some external
+ * synchronization. For example:
+ *
+ *
+ * JsonStreamParser parser = new JsonStreamParser("['first'] {'second':10} 'third'");
+ * JsonElement element;
+ * synchronized (parser) { // synchronize on an object shared by threads
+ * if (parser.hasNext()) {
+ * element = parser.next();
+ * }
+ * }
+ *
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ * @since 1.4
+ */
+public final class JsonStreamParser implements Iterator {
+
+ private final JsonReader parser;
+ private final Object lock;
+
+ /**
+ * @param json The string containing JSON elements concatenated to each other.
+ * @since 1.4
+ */
+ public JsonStreamParser(String json) {
+ this(new StringReader(json));
+ }
+
+ /**
+ * @param reader The data stream containing JSON elements concatenated to each other.
+ * @since 1.4
+ */
+ public JsonStreamParser(Reader reader) {
+ parser = new JsonReader(reader);
+ parser.setLenient(true);
+ lock = new Object();
+ }
+
+ /**
+ * Returns the next available {@link JsonElement} on the reader. Null if none available.
+ *
+ * @return the next available {@link JsonElement} on the reader. Null if none available.
+ * @throws JsonParseException if the incoming stream is malformed JSON.
+ * @since 1.4
+ */
+ public JsonElement next() throws JsonParseException {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+
+ try {
+ return Streams.parse(parser);
+ } catch (StackOverflowError e) {
+ throw new JsonParseException("Failed parsing JSON source to Json", e);
+ } catch (OutOfMemoryError e) {
+ throw new JsonParseException("Failed parsing JSON source to Json", e);
+ } catch (JsonParseException e) {
+ throw e.getCause() instanceof EOFException ? new NoSuchElementException() : e;
+ }
+ }
+
+ /**
+ * Returns true if a {@link JsonElement} is available on the input for consumption
+ * @return true if a {@link JsonElement} is available on the input, false otherwise
+ * @since 1.4
+ */
+ public boolean hasNext() {
+ synchronized (lock) {
+ try {
+ return parser.peek() != JsonToken.END_DOCUMENT;
+ } catch (MalformedJsonException e) {
+ throw new JsonSyntaxException(e);
+ } catch (IOException e) {
+ throw new JsonIOException(e);
+ }
+ }
+ }
+
+ /**
+ * This optional {@link Iterator} method is not relevant for stream parsing and hence is not
+ * implemented.
+ * @since 1.4
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/JsonSyntaxException.java b/src/com/massivecraft/core/lib/gson2/JsonSyntaxException.java
new file mode 100755
index 00000000..624c0d2a
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/JsonSyntaxException.java
@@ -0,0 +1,47 @@
+/*
+ * 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.massivecraft.core.lib.gson2;
+
+/**
+ * This exception is raised when Gson attempts to read (or write) a malformed
+ * JSON element.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+public final class JsonSyntaxException extends JsonParseException {
+
+ private static final long serialVersionUID = 1L;
+
+ public JsonSyntaxException(String msg) {
+ super(msg);
+ }
+
+ public JsonSyntaxException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+ /**
+ * Creates exception with the specified cause. Consider using
+ * {@link #JsonSyntaxException(String, Throwable)} instead if you can
+ * describe what actually happened.
+ *
+ * @param cause root exception that caused this exception to be thrown.
+ */
+ public JsonSyntaxException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/LongSerializationPolicy.java b/src/com/massivecraft/core/lib/gson2/LongSerializationPolicy.java
new file mode 100755
index 00000000..c164d027
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/LongSerializationPolicy.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2009 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.massivecraft.core.lib.gson2;
+
+/**
+ * Defines the expected format for a {@code long} or {@code Long} type when its serialized.
+ *
+ * @since 1.3
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+public enum LongSerializationPolicy {
+ /**
+ * This is the "default" serialization policy that will output a {@code long} object as a JSON
+ * number. For example, assume an object has a long field named "f" then the serialized output
+ * would be:
+ * {@code {"f":123}}.
+ */
+ DEFAULT(new DefaultStrategy()),
+
+ /**
+ * Serializes a long value as a quoted string. For example, assume an object has a long field
+ * named "f" then the serialized output would be:
+ * {@code {"f":"123"}}.
+ */
+ STRING(new StringStrategy());
+
+ private final Strategy strategy;
+
+ private LongSerializationPolicy(Strategy strategy) {
+ this.strategy = strategy;
+ }
+
+ /**
+ * Serialize this {@code value} using this serialization policy.
+ *
+ * @param value the long value to be serialized into a {@link JsonElement}
+ * @return the serialized version of {@code value}
+ */
+ public JsonElement serialize(Long value) {
+ return strategy.serialize(value);
+ }
+
+ private interface Strategy {
+ JsonElement serialize(Long value);
+ }
+
+ private static class DefaultStrategy implements Strategy {
+ public JsonElement serialize(Long value) {
+ return new JsonPrimitive(value);
+ }
+ }
+
+ private static class StringStrategy implements Strategy {
+ public JsonElement serialize(Long value) {
+ return new JsonPrimitive(String.valueOf(value));
+ }
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/LowerCamelCaseSeparatorNamingPolicy.java b/src/com/massivecraft/core/lib/gson2/LowerCamelCaseSeparatorNamingPolicy.java
new file mode 100755
index 00000000..880eeea9
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/LowerCamelCaseSeparatorNamingPolicy.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+/**
+ * A {@link FieldNamingStrategy2} that ensures the JSON field names consist of only
+ * lower case letters and are separated by a particular {@code separatorString}.
+ *
+ *
+ *
+ * @author Joel Leitch
+ */
+final class LowerCamelCaseSeparatorNamingPolicy extends CompositionFieldNamingPolicy {
+
+ public LowerCamelCaseSeparatorNamingPolicy(String separatorString) {
+ super(new CamelCaseSeparatorNamingPolicy(separatorString), new LowerCaseNamingPolicy());
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/LowerCaseNamingPolicy.java b/src/com/massivecraft/core/lib/gson2/LowerCaseNamingPolicy.java
new file mode 100755
index 00000000..db0c79c0
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/LowerCaseNamingPolicy.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collection;
+
+/**
+ * A {@link FieldNamingStrategy2} that ensures the JSON field names consist of only
+ * lower case letters.
+ *
+ *
The following is an example:
+ *
+ * class IntWrapper {
+ * public int integerField = 0;
+ * }
+ *
+ * LowerCaseNamingPolicy policy = new LowerCaseNamingPolicy();
+ * String translatedFieldName =
+ * policy.translateName(IntWrapper.class.getField("integerField"));
+ *
+ * assert("integerfield".equals(translatedFieldName));
+ *
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+final class LowerCaseNamingPolicy extends RecursiveFieldNamingPolicy {
+
+ @Override
+ protected String translateName(String target, Type fieldType,
+ Collection annotations) {
+ return target.toLowerCase();
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/LruCache.java b/src/com/massivecraft/core/lib/gson2/LruCache.java
new file mode 100755
index 00000000..9348f6be
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/LruCache.java
@@ -0,0 +1,53 @@
+/*
+ * 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.massivecraft.core.lib.gson2;
+
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * An implementation of the {@link Cache} interface that evict objects from the cache using an
+ * LRU (least recently used) algorithm. Object start getting evicted from the cache once the
+ * {@code maxCapacity} is reached.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+final class LruCache extends LinkedHashMap implements Cache {
+ private static final long serialVersionUID = 1L;
+
+ private final int maxCapacity;
+
+ public LruCache(int maxCapacity) {
+ super(maxCapacity, 0.7F, true);
+ this.maxCapacity = maxCapacity;
+ }
+
+ public synchronized void addElement(K key, V value) {
+ put(key, value);
+ }
+
+ public synchronized V getElement(K key) {
+ return get(key);
+ }
+
+ @Override
+ protected boolean removeEldestEntry(Map.Entry entry) {
+ return size() > maxCapacity;
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/ModifierBasedExclusionStrategy.java b/src/com/massivecraft/core/lib/gson2/ModifierBasedExclusionStrategy.java
new file mode 100755
index 00000000..80bcfad5
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/ModifierBasedExclusionStrategy.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import java.util.Collection;
+import java.util.HashSet;
+
+/**
+ * Exclude fields based on particular field modifiers. For a list of possible
+ * modifiers, see {@link java.lang.reflect.Modifier}.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+final class ModifierBasedExclusionStrategy implements ExclusionStrategy {
+ private final Collection modifiers;
+
+ public ModifierBasedExclusionStrategy(int... modifiers) {
+ this.modifiers = new HashSet();
+ if (modifiers != null) {
+ for (int modifier : modifiers) {
+ this.modifiers.add(modifier);
+ }
+ }
+ }
+
+ public boolean shouldSkipField(FieldAttributes f) {
+ for (int modifier : modifiers) {
+ if (f.hasModifier(modifier)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean shouldSkipClass(Class> clazz) {
+ return false;
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/ModifyFirstLetterNamingPolicy.java b/src/com/massivecraft/core/lib/gson2/ModifyFirstLetterNamingPolicy.java
new file mode 100755
index 00000000..2da37cdc
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/ModifyFirstLetterNamingPolicy.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import com.massivecraft.core.lib.gson2.internal.$Gson$Preconditions;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collection;
+
+/**
+ * A {@link FieldNamingStrategy2} that ensures the JSON field names begins with
+ * an upper case letter.
+ *
+ *
+ *
+ * @author Joel Leitch
+ */
+final class ModifyFirstLetterNamingPolicy extends RecursiveFieldNamingPolicy {
+
+ public enum LetterModifier {
+ UPPER,
+ LOWER;
+ }
+
+ private final LetterModifier letterModifier;
+
+ /**
+ * Creates a new ModifyFirstLetterNamingPolicy that will either modify the first letter of the
+ * target name to either UPPER case or LOWER case depending on the {@code modifier} parameter.
+ *
+ * @param modifier the type of modification that should be performed
+ * @throws IllegalArgumentException if {@code modifier} is null
+ */
+ ModifyFirstLetterNamingPolicy(LetterModifier modifier) {
+ this.letterModifier = $Gson$Preconditions.checkNotNull(modifier);
+ }
+
+ @Override
+ protected String translateName(String target, Type fieldType,
+ Collection annotations) {
+ StringBuilder fieldNameBuilder = new StringBuilder();
+ int index = 0;
+ char firstCharacter = target.charAt(index);
+
+ while (index < target.length() - 1) {
+ if (Character.isLetter(firstCharacter)) {
+ break;
+ }
+
+ fieldNameBuilder.append(firstCharacter);
+ firstCharacter = target.charAt(++index);
+ }
+
+ if (index == target.length()) {
+ return fieldNameBuilder.toString();
+ }
+
+ boolean capitalizeFirstLetter = (letterModifier == LetterModifier.UPPER);
+ if (capitalizeFirstLetter && !Character.isUpperCase(firstCharacter)) {
+ String modifiedTarget = modifyString(Character.toUpperCase(firstCharacter), target, ++index);
+ return fieldNameBuilder.append(modifiedTarget).toString();
+ } else if (!capitalizeFirstLetter && Character.isUpperCase(firstCharacter)) {
+ String modifiedTarget = modifyString(Character.toLowerCase(firstCharacter), target, ++index);
+ return fieldNameBuilder.append(modifiedTarget).toString();
+ } else {
+ return target;
+ }
+ }
+
+ private String modifyString(char firstCharacter, String srcString, int indexOfSubstring) {
+ return (indexOfSubstring < srcString.length())
+ ? firstCharacter + srcString.substring(indexOfSubstring)
+ : String.valueOf(firstCharacter);
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/RecursiveFieldNamingPolicy.java b/src/com/massivecraft/core/lib/gson2/RecursiveFieldNamingPolicy.java
new file mode 100755
index 00000000..3da9f779
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/RecursiveFieldNamingPolicy.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collection;
+
+/**
+ * A mechanism for providing custom field naming in Gson. This allows the client code to translate
+ * field names into a particular convention that is not supported as a normal Java field
+ * declaration rules. For example, Java does not support "-" characters in a field name.
+ *
+ * @author Joel Leitch
+ */
+abstract class RecursiveFieldNamingPolicy implements FieldNamingStrategy2 {
+
+ public final String translateName(FieldAttributes f) {
+ return translateName(f.getName(), f.getDeclaredType(), f.getAnnotations());
+ }
+
+ /**
+ * Performs the specific string translation.
+ *
+ * @param target the string object that will be manipulation/translated
+ * @param fieldType the actual type value of the field
+ * @param annotations the annotations set on the field
+ * @return the translated field name
+ */
+ protected abstract String translateName(String target, Type fieldType, Collection annotations);
+}
diff --git a/src/com/massivecraft/core/lib/gson2/SerializedNameAnnotationInterceptingNamingPolicy.java b/src/com/massivecraft/core/lib/gson2/SerializedNameAnnotationInterceptingNamingPolicy.java
new file mode 100755
index 00000000..6edba502
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/SerializedNameAnnotationInterceptingNamingPolicy.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import com.massivecraft.core.lib.gson2.annotations.SerializedName;
+
+/**
+ * A {@link FieldNamingStrategy2} that acts as a chain of responsibility. If the
+ * {@link com.massivecraft.core.lib.gson2.annotations.SerializedName} annotation is applied to a
+ * field then this strategy will translate the name to the {@code
+ * serializedName.value()}; otherwise it delegates to the wrapped
+ * {@link FieldNamingStrategy2}.
+ *
+ *
+ * NOTE: this class performs JSON field name validation for any of the fields
+ * marked with an {@code @SerializedName} annotation.
+ *
+ *
+ * @see SerializedName
+ *
+ * @author Joel Leitch
+ */
+final class SerializedNameAnnotationInterceptingNamingPolicy implements FieldNamingStrategy2 {
+ private final FieldNamingStrategy2 delegate;
+
+ SerializedNameAnnotationInterceptingNamingPolicy(FieldNamingStrategy2 delegate) {
+ this.delegate = delegate;
+ }
+
+ public String translateName(FieldAttributes f) {
+ SerializedName serializedName = f.getAnnotation(SerializedName.class);
+ return serializedName == null ? delegate.translateName(f) : serializedName.value();
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/SyntheticFieldExclusionStrategy.java b/src/com/massivecraft/core/lib/gson2/SyntheticFieldExclusionStrategy.java
new file mode 100755
index 00000000..43a0e2d2
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/SyntheticFieldExclusionStrategy.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 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.massivecraft.core.lib.gson2;
+
+/**
+ * A data object that stores attributes of a field.
+ *
+ *
This class is immutable; therefore, it can be safely shared across threads.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ *
+ * @since 1.4
+ */
+final class SyntheticFieldExclusionStrategy implements ExclusionStrategy {
+ private final boolean skipSyntheticFields;
+
+ SyntheticFieldExclusionStrategy(boolean skipSyntheticFields) {
+ this.skipSyntheticFields = skipSyntheticFields;
+ }
+
+ public boolean shouldSkipClass(Class> clazz) {
+ return false;
+ }
+
+ public boolean shouldSkipField(FieldAttributes f) {
+ return skipSyntheticFields && f.isSynthetic();
+ }
+
+}
diff --git a/src/com/massivecraft/core/lib/gson2/UpperCamelCaseSeparatorNamingPolicy.java b/src/com/massivecraft/core/lib/gson2/UpperCamelCaseSeparatorNamingPolicy.java
new file mode 100755
index 00000000..f3901be0
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/UpperCamelCaseSeparatorNamingPolicy.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+/**
+ * A {@link FieldNamingStrategy2} that ensures the JSON field names consist of mixed
+ * case letters starting with a capital and are separated by a particular
+ * {@code separatorString}.
+ *
+ *
+ *
+ * @author Joel Leitch
+ */
+final class UpperCamelCaseSeparatorNamingPolicy extends CompositionFieldNamingPolicy {
+
+ public UpperCamelCaseSeparatorNamingPolicy(String separatorString) {
+ super(new CamelCaseSeparatorNamingPolicy(separatorString),
+ new ModifyFirstLetterNamingPolicy(ModifyFirstLetterNamingPolicy.LetterModifier.UPPER));
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/UpperCaseNamingPolicy.java b/src/com/massivecraft/core/lib/gson2/UpperCaseNamingPolicy.java
new file mode 100755
index 00000000..557e328c
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/UpperCaseNamingPolicy.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collection;
+
+/**
+ * A {@link FieldNamingStrategy2} that ensures the JSON field names consist of only
+ * upper case letters.
+ *
+ *
The following is an example:
+ *
+ * class IntWrapper {
+ * public int integerField = 0;
+ * }
+ *
+ * UpperCaseNamingPolicy policy = new UpperCaseNamingPolicy();
+ * String translatedFieldName =
+ * policy.translateName(IntWrapper.class.getField("integerField"));
+ *
+ * assert("INTEGERFIELD".equals(translatedFieldName));
+ *
+ *
+ * @author Joel Leitch
+ */
+final class UpperCaseNamingPolicy extends RecursiveFieldNamingPolicy {
+
+ @Override
+ protected String translateName(String target, Type fieldType, Collection annotations) {
+ return target.toUpperCase();
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/VersionConstants.java b/src/com/massivecraft/core/lib/gson2/VersionConstants.java
new file mode 100755
index 00000000..ce904f69
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/VersionConstants.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+/**
+ * Class contain all constants for versioning support.
+ *
+ * @author Joel Leitch
+ */
+final class VersionConstants {
+ // Prevent instantiation
+ private VersionConstants() { }
+
+ static final double IGNORE_VERSIONS = -1D;
+}
diff --git a/src/com/massivecraft/core/lib/gson2/VersionExclusionStrategy.java b/src/com/massivecraft/core/lib/gson2/VersionExclusionStrategy.java
new file mode 100755
index 00000000..cb6dd545
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/VersionExclusionStrategy.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2;
+
+import com.massivecraft.core.lib.gson2.annotations.Since;
+import com.massivecraft.core.lib.gson2.annotations.Until;
+import com.massivecraft.core.lib.gson2.internal.$Gson$Preconditions;
+
+/**
+ * This strategy will exclude any files and/or class that are passed the
+ * {@link #version} value.
+ *
+ * @author Joel Leitch
+ */
+final class VersionExclusionStrategy implements ExclusionStrategy {
+ private final double version;
+
+ VersionExclusionStrategy(double version) {
+ $Gson$Preconditions.checkArgument(version >= 0.0D);
+ this.version = version;
+ }
+
+ public boolean shouldSkipField(FieldAttributes f) {
+ return !isValidVersion(f.getAnnotation(Since.class), f.getAnnotation(Until.class));
+ }
+
+ public boolean shouldSkipClass(Class> clazz) {
+ return !isValidVersion(clazz.getAnnotation(Since.class), clazz.getAnnotation(Until.class));
+ }
+
+ private boolean isValidVersion(Since since, Until until) {
+ return (isValidSince(since) && isValidUntil(until));
+ }
+
+ private boolean isValidSince(Since annotation) {
+ if (annotation != null) {
+ double annotationVersion = annotation.value();
+ if (annotationVersion > version) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean isValidUntil(Until annotation) {
+ if (annotation != null) {
+ double annotationVersion = annotation.value();
+ if (annotationVersion <= version) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/annotations/Expose.java b/src/com/massivecraft/core/lib/gson2/annotations/Expose.java
new file mode 100755
index 00000000..1a1f4987
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/annotations/Expose.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation that indicates this member should be exposed for JSON
+ * serialization or deserialization.
+ *
+ *
This annotation has no effect unless you build {@link com.massivecraft.core.lib.gson2.Gson}
+ * with a {@link com.massivecraft.core.lib.gson2.GsonBuilder} and invoke
+ * {@link com.massivecraft.core.lib.gson2.GsonBuilder#excludeFieldsWithoutExposeAnnotation()}
+ * method.
+ *
+ *
Here is an example of how this annotation is meant to be used:
+ *
+ * If you created Gson with {@code new Gson()}, the {@code toJson()} and {@code fromJson()}
+ * methods will use the {@code password} field along-with {@code firstName}, {@code lastName},
+ * and {@code emailAddress} for serialization and deserialization. However, if you created Gson
+ * with {@code Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()}
+ * then the {@code toJson()} and {@code fromJson()} methods of Gson will exclude the
+ * {@code password} field. This is because the {@code password} field is not marked with the
+ * {@code @Expose} annotation. Gson will also exclude {@code lastName} and {@code emailAddress}
+ * from serialization since {@code serialize} is set to {@code false}. Similarly, Gson will
+ * exclude {@code emailAddress} from deserialization since {@code deserialize} is set to false.
+ *
+ *
Note that another way to achieve the same effect would have been to just mark the
+ * {@code password} field as {@code transient}, and Gson would have excluded it even with default
+ * settings. The {@code @Expose} annotation is useful in a style of programming where you want to
+ * explicitly specify all fields that should get considered for serialization or deserialization.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface Expose {
+
+ /**
+ * If {@code true}, the field marked with this annotation is written out in the JSON while
+ * serializing. If {@code false}, the field marked with this annotation is skipped from the
+ * serialized output. Defaults to {@code true}.
+ * @since 1.4
+ */
+ public boolean serialize() default true;
+
+ /**
+ * If {@code true}, the field marked with this annotation is deserialized from the JSON.
+ * If {@code false}, the field marked with this annotation is skipped during deserialization.
+ * Defaults to {@code true}.
+ * @since 1.4
+ */
+ public boolean deserialize() default true;
+}
diff --git a/src/com/massivecraft/core/lib/gson2/annotations/SerializedName.java b/src/com/massivecraft/core/lib/gson2/annotations/SerializedName.java
new file mode 100755
index 00000000..a3bb0044
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/annotations/SerializedName.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation that indicates this member should be serialized to JSON with
+ * the provided name value as its field name.
+ *
+ *
This annotation will override any {@link com.massivecraft.core.lib.gson2.FieldNamingPolicy}, including
+ * the default field naming policy, that may have been set on the {@link com.massivecraft.core.lib.gson2.Gson}
+ * instance. A different naming policy can set using the {@code GsonBuilder} class. See
+ * {@link com.massivecraft.core.lib.gson2.GsonBuilder#setFieldNamingPolicy(com.massivecraft.core.lib.gson2.FieldNamingPolicy)}
+ * for more information.
+ *
+ *
Here is an example of how this annotation is meant to be used:
+ *
+ * public class SomeClassWithFields {
+ * @SerializedName("name") private final String someField;
+ * private final String someOtherField;
+ *
+ * public SomeClassWithFields(String a, String b) {
+ * this.someField = a;
+ * this.someOtherField = b;
+ * }
+ * }
+ *
+ *
+ *
The following shows the output that is generated when serializing an instance of the
+ * above example class:
NOTE: The value you specify in this annotation must be a valid JSON field name.
+ *
+ * @see com.massivecraft.core.lib.gson2.FieldNamingPolicy
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface SerializedName {
+
+ /**
+ * @return the desired name of the field when it is serialized
+ */
+ String value();
+}
diff --git a/src/com/massivecraft/core/lib/gson2/annotations/Since.java b/src/com/massivecraft/core/lib/gson2/annotations/Since.java
new file mode 100755
index 00000000..01453203
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/annotations/Since.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation that indicates the version number since a member or a type has been present.
+ * This annotation is useful to manage versioning of your Json classes for a web-service.
+ *
+ *
+ * This annotation has no effect unless you build {@link com.massivecraft.core.lib.gson2.Gson} with a
+ * {@link com.massivecraft.core.lib.gson2.GsonBuilder} and invoke
+ * {@link com.massivecraft.core.lib.gson2.GsonBuilder#setVersion(double)} method.
+ *
+ *
Here is an example of how this annotation is meant to be used:
If you created Gson with {@code new Gson()}, the {@code toJson()} and {@code fromJson()}
+ * methods will use all the fields for serialization and deserialization. However, if you created
+ * Gson with {@code Gson gson = new GsonBuilder().setVersion(1.0).create()} then the
+ * {@code toJson()} and {@code fromJson()} methods of Gson will exclude the {@code address} field
+ * since it's version number is set to {@code 1.1}.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.TYPE})
+public @interface Since {
+ /**
+ * the value indicating a version number since this member
+ * or type has been present.
+ */
+ double value();
+}
diff --git a/src/com/massivecraft/core/lib/gson2/annotations/Until.java b/src/com/massivecraft/core/lib/gson2/annotations/Until.java
new file mode 100755
index 00000000..1cbcaea6
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/annotations/Until.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation that indicates the version number until a member or a type should be present.
+ * Basically, if Gson is created with a version number that exceeds the value stored in the
+ * {@code Until} annotation then the field will be ignored from the JSON output. This annotation
+ * is useful to manage versioning of your JSON classes for a web-service.
+ *
+ *
+ * This annotation has no effect unless you build {@link com.massivecraft.core.lib.gson2.Gson} with a
+ * {@link com.massivecraft.core.lib.gson2.GsonBuilder} and invoke
+ * {@link com.massivecraft.core.lib.gson2.GsonBuilder#setVersion(double)} method.
+ *
+ *
Here is an example of how this annotation is meant to be used:
If you created Gson with {@code new Gson()}, the {@code toJson()} and {@code fromJson()}
+ * methods will use all the fields for serialization and deserialization. However, if you created
+ * Gson with {@code Gson gson = new GsonBuilder().setVersion(1.2).create()} then the
+ * {@code toJson()} and {@code fromJson()} methods of Gson will exclude the {@code emailAddress}
+ * and {@code password} fields from the example above, because the version number passed to the
+ * GsonBuilder, {@code 1.2}, exceeds the version number set on the {@code Until} annotation,
+ * {@code 1.1}, for those fields.
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ * @since 1.3
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.TYPE})
+public @interface Until {
+
+ /**
+ * the value indicating a version number until this member
+ * or type should be ignored.
+ */
+ double value();
+}
diff --git a/src/com/massivecraft/core/lib/gson2/annotations/package-info.java b/src/com/massivecraft/core/lib/gson2/annotations/package-info.java
new file mode 100755
index 00000000..015cf9a2
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/annotations/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * This package provides annotations that can be used with {@link com.massivecraft.core.lib.gson2.Gson}.
+ *
+ * @author Inderjeet Singh, Joel Leitch
+ */
+package com.massivecraft.core.lib.gson2.annotations;
\ No newline at end of file
diff --git a/src/com/massivecraft/core/lib/gson2/internal/$Gson$Preconditions.java b/src/com/massivecraft/core/lib/gson2/internal/$Gson$Preconditions.java
new file mode 100755
index 00000000..bc08dbcf
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/internal/$Gson$Preconditions.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2.internal;
+
+/**
+ * A simple utility class used to check method Preconditions.
+ *
+ *
+ *
+ * @author Inderjeet Singh
+ * @author Joel Leitch
+ */
+public final class $Gson$Preconditions {
+ public static T checkNotNull(T obj) {
+ if (obj == null) {
+ throw new NullPointerException();
+ }
+ return obj;
+ }
+
+ public static void checkArgument(boolean condition) {
+ if (!condition) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public static void checkState(boolean condition) {
+ if (!condition) {
+ throw new IllegalStateException();
+ }
+ }
+}
diff --git a/src/com/massivecraft/core/lib/gson2/internal/$Gson$Types.java b/src/com/massivecraft/core/lib/gson2/internal/$Gson$Types.java
new file mode 100755
index 00000000..e3970a77
--- /dev/null
+++ b/src/com/massivecraft/core/lib/gson2/internal/$Gson$Types.java
@@ -0,0 +1,592 @@
+/**
+ * Copyright (C) 2008 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.massivecraft.core.lib.gson2.internal;
+
+import static com.massivecraft.core.lib.gson2.internal.$Gson$Preconditions.checkArgument;
+import static com.massivecraft.core.lib.gson2.internal.$Gson$Preconditions.checkNotNull;
+
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.GenericDeclaration;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Properties;
+
+/**
+ * Static methods for working with types.
+ *
+ * @author Bob Lee
+ * @author Jesse Wilson
+ */
+public final class $Gson$Types {
+ static final Type[] EMPTY_TYPE_ARRAY = new Type[] {};
+
+ private $Gson$Types() {}
+
+ /**
+ * Returns a new parameterized type, applying {@code typeArguments} to
+ * {@code rawType} and enclosed by {@code ownerType}.
+ *
+ * @return a {@link java.io.Serializable serializable} parameterized type.
+ */
+ public static ParameterizedType newParameterizedTypeWithOwner(
+ Type ownerType, Type rawType, Type... typeArguments) {
+ return new ParameterizedTypeImpl(ownerType, rawType, typeArguments);
+ }
+
+ /**
+ * Returns an array type whose elements are all instances of
+ * {@code componentType}.
+ *
+ * @return a {@link java.io.Serializable serializable} generic array type.
+ */
+ public static GenericArrayType arrayOf(Type componentType) {
+ return new GenericArrayTypeImpl(componentType);
+ }
+
+ /**
+ * Returns a type that represents an unknown type that extends {@code bound}.
+ * For example, if {@code bound} is {@code CharSequence.class}, this returns
+ * {@code ? extends CharSequence}. If {@code bound} is {@code Object.class},
+ * this returns {@code ?}, which is shorthand for {@code ? extends Object}.
+ */
+ public static WildcardType subtypeOf(Type bound) {
+ return new WildcardTypeImpl(new Type[] { bound }, EMPTY_TYPE_ARRAY);
+ }
+
+ /**
+ * Returns a type that represents an unknown supertype of {@code bound}. For
+ * example, if {@code bound} is {@code String.class}, this returns {@code ?
+ * super String}.
+ */
+ public static WildcardType supertypeOf(Type bound) {
+ return new WildcardTypeImpl(new Type[] { Object.class }, new Type[] { bound });
+ }
+
+ /**
+ * Returns a type that is functionally equal but not necessarily equal
+ * according to {@link Object#equals(Object) Object.equals()}. The returned
+ * type is {@link java.io.Serializable}.
+ */
+ public static Type canonicalize(Type type) {
+ if (type instanceof Class) {
+ Class> c = (Class>) type;
+ return c.isArray() ? new GenericArrayTypeImpl(canonicalize(c.getComponentType())) : c;
+
+ } else if (type instanceof ParameterizedType) {
+ ParameterizedType p = (ParameterizedType) type;
+ return new ParameterizedTypeImpl(p.getOwnerType(),
+ p.getRawType(), p.getActualTypeArguments());
+
+ } else if (type instanceof GenericArrayType) {
+ GenericArrayType g = (GenericArrayType) type;
+ return new GenericArrayTypeImpl(g.getGenericComponentType());
+
+ } else if (type instanceof WildcardType) {
+ WildcardType w = (WildcardType) type;
+ return new WildcardTypeImpl(w.getUpperBounds(), w.getLowerBounds());
+
+ } else {
+ // type is either serializable as-is or unsupported
+ return type;
+ }
+ }
+
+ public static Class> getRawType(Type type) {
+ if (type instanceof Class>) {
+ // type is a normal class.
+ return (Class>) type;
+
+ } else if (type instanceof ParameterizedType) {
+ ParameterizedType parameterizedType = (ParameterizedType) type;
+
+ // I'm not exactly sure why getRawType() returns Type instead of Class.
+ // Neal isn't either but suspects some pathological case related
+ // to nested classes exists.
+ Type rawType = parameterizedType.getRawType();
+ checkArgument(rawType instanceof Class);
+ return (Class>) rawType;
+
+ } else if (type instanceof GenericArrayType) {
+ Type componentType = ((GenericArrayType)type).getGenericComponentType();
+ return Array.newInstance(getRawType(componentType), 0).getClass();
+
+ } else if (type instanceof TypeVariable) {
+ // we could use the variable's bounds, but that won't work if there are multiple.
+ // having a raw type that's more general than necessary is okay
+ return Object.class;
+
+ } else if (type instanceof WildcardType) {
+ return getRawType(((WildcardType) type).getUpperBounds()[0]);
+
+ } else {
+ String className = type == null ? "null" : type.getClass().getName();
+ throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
+ + "GenericArrayType, but <" + type + "> is of type " + className);
+ }
+ }
+
+ static boolean equal(Object a, Object b) {
+ return a == b || (a != null && a.equals(b));
+ }
+
+ /**
+ * Returns true if {@code a} and {@code b} are equal.
+ */
+ public static boolean equals(Type a, Type b) {
+ if (a == b) {
+ // also handles (a == null && b == null)
+ return true;
+
+ } else if (a instanceof Class) {
+ // Class already specifies equals().
+ return a.equals(b);
+
+ } else if (a instanceof ParameterizedType) {
+ if (!(b instanceof ParameterizedType)) {
+ return false;
+ }
+
+ // TODO: save a .clone() call
+ ParameterizedType pa = (ParameterizedType) a;
+ ParameterizedType pb = (ParameterizedType) b;
+ return equal(pa.getOwnerType(), pb.getOwnerType())
+ && pa.getRawType().equals(pb.getRawType())
+ && Arrays.equals(pa.getActualTypeArguments(), pb.getActualTypeArguments());
+
+ } else if (a instanceof GenericArrayType) {
+ if (!(b instanceof GenericArrayType)) {
+ return false;
+ }
+
+ GenericArrayType ga = (GenericArrayType) a;
+ GenericArrayType gb = (GenericArrayType) b;
+ return equals(ga.getGenericComponentType(), gb.getGenericComponentType());
+
+ } else if (a instanceof WildcardType) {
+ if (!(b instanceof WildcardType)) {
+ return false;
+ }
+
+ WildcardType wa = (WildcardType) a;
+ WildcardType wb = (WildcardType) b;
+ return Arrays.equals(wa.getUpperBounds(), wb.getUpperBounds())
+ && Arrays.equals(wa.getLowerBounds(), wb.getLowerBounds());
+
+ } else if (a instanceof TypeVariable) {
+ if (!(b instanceof TypeVariable)) {
+ return false;
+ }
+ TypeVariable> va = (TypeVariable>) a;
+ TypeVariable> vb = (TypeVariable>) b;
+ return va.getGenericDeclaration() == vb.getGenericDeclaration()
+ && va.getName().equals(vb.getName());
+
+ } else {
+ // This isn't a type we support. Could be a generic array type, wildcard type, etc.
+ return false;
+ }
+ }
+
+ private static int hashCodeOrZero(Object o) {
+ return o != null ? o.hashCode() : 0;
+ }
+
+ public static String typeToString(Type type) {
+ return type instanceof Class ? ((Class>) type).getName() : type.toString();
+ }
+
+ /**
+ * Returns the generic supertype for {@code supertype}. For example, given a class {@code
+ * IntegerSet}, the result for when supertype is {@code Set.class} is {@code Set} and the
+ * result when the supertype is {@code Collection.class} is {@code Collection}.
+ */
+ static Type getGenericSupertype(Type context, Class> rawType, Class> toResolve) {
+ if (toResolve == rawType) {
+ return context;
+ }
+
+ // we skip searching through interfaces if unknown is an interface
+ if (toResolve.isInterface()) {
+ Class>[] interfaces = rawType.getInterfaces();
+ for (int i = 0, length = interfaces.length; i < length; i++) {
+ if (interfaces[i] == toResolve) {
+ return rawType.getGenericInterfaces()[i];
+ } else if (toResolve.isAssignableFrom(interfaces[i])) {
+ return getGenericSupertype(rawType.getGenericInterfaces()[i], interfaces[i], toResolve);
+ }
+ }
+ }
+
+ // check our supertypes
+ if (!rawType.isInterface()) {
+ while (rawType != Object.class) {
+ Class> rawSupertype = rawType.getSuperclass();
+ if (rawSupertype == toResolve) {
+ return rawType.getGenericSuperclass();
+ } else if (toResolve.isAssignableFrom(rawSupertype)) {
+ return getGenericSupertype(rawType.getGenericSuperclass(), rawSupertype, toResolve);
+ }
+ rawType = rawSupertype;
+ }
+ }
+
+ // we can't resolve this further
+ return toResolve;
+ }
+
+ /**
+ * Returns the generic form of {@code supertype}. For example, if this is {@code
+ * ArrayList}, this returns {@code Iterable} given the input {@code
+ * Iterable.class}.
+ *
+ * @param supertype a superclass of, or interface implemented by, this.
+ */
+ static Type getSupertype(Type context, Class> contextRawType, Class> supertype) {
+ checkArgument(supertype.isAssignableFrom(contextRawType));
+ return resolve(context, contextRawType,
+ $Gson$Types.getGenericSupertype(context, contextRawType, supertype));
+ }
+
+ /**
+ * Returns true if this type is an array.
+ */
+ public static boolean isArray(Type type) {
+ return type instanceof GenericArrayType
+ || (type instanceof Class && ((Class>) type).isArray());
+ }
+
+ /**
+ * Returns the component type of this array type.
+ * @throws ClassCastException if this type is not an array.
+ */
+ public static Type getArrayComponentType(Type array) {
+ return array instanceof GenericArrayType
+ ? ((GenericArrayType) array).getGenericComponentType()
+ : ((Class>) array).getComponentType();
+ }
+
+ /**
+ * Returns the element type of this collection type.
+ * @throws IllegalArgumentException if this type is not a collection.
+ */
+ public static Type getCollectionElementType(Type context, Class> contextRawType) {
+ Type collectionType = getSupertype(context, contextRawType, Collection.class);
+
+ if (collectionType instanceof WildcardType) {
+ collectionType = ((WildcardType)collectionType).getUpperBounds()[0];
+ }
+ if (collectionType instanceof ParameterizedType) {
+ return ((ParameterizedType) collectionType).getActualTypeArguments()[0];
+ }
+ return Object.class;
+ }
+
+ /**
+ * Returns a two element array containing this map's key and value types in
+ * positions 0 and 1 respectively.
+ */
+ public static Type[] getMapKeyAndValueTypes(Type context, Class> contextRawType) {
+ /*
+ * Work around a problem with the declaration of java.util.Properties. That
+ * class should extend Hashtable, but it's declared to
+ * extend Hashtable