Sorry could not shade. m2eclipse does not handle it well enough.
This commit is contained in:
parent
e1d92aa421
commit
b732a26a9e
47
pom.xml
47
pom.xml
@ -35,43 +35,6 @@
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<include>com.google.code.gson:gson</include>
|
||||
<include>org.mongodb:mongo-java-driver</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>com.google.gson</pattern>
|
||||
<shadedPattern>com.massivecraft.massivecore.xlib.gson</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.mongodb</pattern>
|
||||
<shadedPattern>com.massivecraft.massivecore.xlib.mongodb</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>org.bson</pattern>
|
||||
<shadedPattern>com.massivecraft.massivecore.xlib.bson</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
@ -86,16 +49,6 @@
|
||||
<artifactId>Vault</artifactId>
|
||||
<version>1.4.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.2.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongo-java-driver</artifactId>
|
||||
<version>2.12.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<repositories>
|
||||
|
@ -4,8 +4,8 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.massivecraft.massivecore.store.Entity;
|
||||
import com.massivecraft.massivecore.xlib.gson.annotations.SerializedName;
|
||||
|
||||
public class Aspect extends Entity<Aspect>
|
||||
{
|
||||
|
@ -7,23 +7,15 @@ import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonNull;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.massivecraft.massivecore.adapter.InventoryAdapter;
|
||||
import com.massivecraft.massivecore.adapter.ItemStackAdapter;
|
||||
import com.massivecraft.massivecore.adapter.JsonElementAdapter;
|
||||
import com.massivecraft.massivecore.adapter.ModdedEnumTypeAdapter;
|
||||
import com.massivecraft.massivecore.adapter.ObjectIdAdapter;
|
||||
import com.massivecraft.massivecore.adapter.PlayerInventoryAdapter;
|
||||
import com.massivecraft.massivecore.adapter.UUIDAdapter;
|
||||
import com.massivecraft.massivecore.cmd.massivecore.CmdMassiveCore;
|
||||
@ -43,6 +35,12 @@ import com.massivecraft.massivecore.teleport.EngineScheduledTeleport;
|
||||
import com.massivecraft.massivecore.util.IdUtil;
|
||||
import com.massivecraft.massivecore.util.PlayerUtil;
|
||||
import com.massivecraft.massivecore.util.Txt;
|
||||
import com.massivecraft.massivecore.xlib.gson.Gson;
|
||||
import com.massivecraft.massivecore.xlib.gson.GsonBuilder;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonArray;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonNull;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonObject;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonPrimitive;
|
||||
|
||||
public class MassiveCore extends MassivePlugin
|
||||
{
|
||||
@ -78,7 +76,6 @@ public class MassiveCore extends MassivePlugin
|
||||
.registerTypeAdapter(JsonPrimitive.class, JsonElementAdapter.get())
|
||||
.registerTypeAdapter(JsonArray.class, JsonElementAdapter.get())
|
||||
.registerTypeAdapter(JsonObject.class, JsonElementAdapter.get())
|
||||
.registerTypeAdapter(ObjectId.class, ObjectIdAdapter.get())
|
||||
.registerTypeAdapter(UUID.class, UUIDAdapter.get())
|
||||
.registerTypeAdapter(ItemStack.class, ItemStackAdapter.get())
|
||||
.registerTypeAdapter(Inventory.class, InventoryAdapter.get())
|
||||
|
@ -9,7 +9,7 @@ import org.bukkit.permissions.Permissible;
|
||||
import com.massivecraft.massivecore.store.Entity;
|
||||
import com.massivecraft.massivecore.util.MUtil;
|
||||
import com.massivecraft.massivecore.util.PermUtil;
|
||||
import com.mongodb.WriteConcern;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.WriteConcern;
|
||||
|
||||
public class MassiveCoreMConf extends Entity<MassiveCoreMConf>
|
||||
{
|
||||
@ -72,7 +72,7 @@ public class MassiveCoreMConf extends Entity<MassiveCoreMConf>
|
||||
|
||||
public static WriteConcern getMongoDbWriteConcern(boolean catchingErrors)
|
||||
{
|
||||
return catchingErrors ? WriteConcern.ACKNOWLEDGED : WriteConcern.ERRORS_IGNORED;
|
||||
return catchingErrors ? WriteConcern.ACKNOWLEDGED : WriteConcern.UNACKNOWLEDGED;
|
||||
}
|
||||
public WriteConcern getMongoDbWriteConcernSave()
|
||||
{
|
||||
|
@ -14,8 +14,8 @@ import com.massivecraft.massivecore.integration.IntegrationGlue;
|
||||
import com.massivecraft.massivecore.integration.Integration;
|
||||
import com.massivecraft.massivecore.store.Coll;
|
||||
import com.massivecraft.massivecore.util.Txt;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.massivecraft.massivecore.xlib.gson.Gson;
|
||||
import com.massivecraft.massivecore.xlib.gson.GsonBuilder;
|
||||
|
||||
public abstract class MassivePlugin extends JavaPlugin implements Listener
|
||||
{
|
||||
|
@ -6,7 +6,7 @@ import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.massivecraft.massivecore.store.accessor.Accessor;
|
||||
import com.massivecraft.massivecore.util.DiscUtil;
|
||||
import com.google.gson.Gson;
|
||||
import com.massivecraft.massivecore.xlib.gson.Gson;
|
||||
|
||||
public class SimpleConfig
|
||||
{
|
||||
|
@ -11,10 +11,10 @@ import org.bukkit.FireworkEffect;
|
||||
import org.bukkit.FireworkEffect.Type;
|
||||
|
||||
import com.massivecraft.massivecore.util.MUtil;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonArray;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonObject;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonPrimitive;
|
||||
|
||||
public class FireworkEffectAdapter
|
||||
{
|
||||
|
@ -8,14 +8,14 @@ import org.bukkit.inventory.PlayerInventory;
|
||||
|
||||
import com.massivecraft.massivecore.MassiveCore;
|
||||
import com.massivecraft.massivecore.mixin.Mixin;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonDeserializationContext;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonDeserializer;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonObject;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonParseException;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonPrimitive;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonSerializationContext;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonSerializer;
|
||||
|
||||
/**
|
||||
* This is my Gson adapter for Inventories.
|
||||
|
@ -26,15 +26,15 @@ import org.bukkit.inventory.meta.Repairable;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonArray;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonDeserializationContext;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonDeserializer;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonObject;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonParseException;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonPrimitive;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonSerializationContext;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonSerializer;
|
||||
|
||||
/**
|
||||
* This is a GSON serializer/deserializer for the Bukkit ItemStack. Why not use
|
||||
|
@ -2,12 +2,12 @@ package com.massivecraft.massivecore.adapter;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonDeserializationContext;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonDeserializer;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonParseException;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonSerializationContext;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonSerializer;
|
||||
|
||||
public class JsonElementAdapter implements JsonDeserializer<JsonElement>, JsonSerializer<JsonElement>
|
||||
{
|
||||
|
@ -1,13 +1,13 @@
|
||||
package com.massivecraft.massivecore.adapter;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.TypeAdapterFactory;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonToken;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import com.massivecraft.massivecore.xlib.gson.Gson;
|
||||
import com.massivecraft.massivecore.xlib.gson.TypeAdapter;
|
||||
import com.massivecraft.massivecore.xlib.gson.TypeAdapterFactory;
|
||||
import com.massivecraft.massivecore.xlib.gson.annotations.SerializedName;
|
||||
import com.massivecraft.massivecore.xlib.gson.reflect.TypeToken;
|
||||
import com.massivecraft.massivecore.xlib.gson.stream.JsonReader;
|
||||
import com.massivecraft.massivecore.xlib.gson.stream.JsonToken;
|
||||
import com.massivecraft.massivecore.xlib.gson.stream.JsonWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
@ -1,65 +0,0 @@
|
||||
package com.massivecraft.massivecore.adapter;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
|
||||
public class ObjectIdAdapter implements JsonDeserializer<ObjectId>, JsonSerializer<ObjectId>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE & CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static ObjectIdAdapter i = new ObjectIdAdapter();
|
||||
public static ObjectIdAdapter get() { return i; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// OVERRIDE
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(ObjectId src, Type typeOfSrc, JsonSerializationContext context)
|
||||
{
|
||||
return convertObjectIdToJsonPrimitive(src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectId deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
||||
{
|
||||
return convertJsonElementToObjectId(json);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// STATIC LOGIC
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static String convertObjectIdToString(ObjectId objectId)
|
||||
{
|
||||
return objectId.toString();
|
||||
}
|
||||
|
||||
public static JsonPrimitive convertObjectIdToJsonPrimitive(ObjectId objectId)
|
||||
{
|
||||
return new JsonPrimitive(convertObjectIdToString(objectId));
|
||||
}
|
||||
|
||||
// Can return null
|
||||
public static ObjectId convertStringToObjectId(String string)
|
||||
{
|
||||
return ObjectId.massageToObjectId(string);
|
||||
}
|
||||
|
||||
public static ObjectId convertJsonElementToObjectId(JsonElement jsonElement)
|
||||
{
|
||||
return convertStringToObjectId(jsonElement.getAsString());
|
||||
}
|
||||
|
||||
}
|
@ -4,12 +4,12 @@ import java.lang.reflect.Type;
|
||||
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonDeserializationContext;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonDeserializer;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonParseException;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonSerializationContext;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonSerializer;
|
||||
|
||||
public class PlayerInventoryAdapter implements JsonDeserializer<PlayerInventory>, JsonSerializer<PlayerInventory>
|
||||
{
|
||||
|
@ -2,15 +2,15 @@ package com.massivecraft.massivecore.adapter;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonNull;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonDeserializationContext;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonDeserializer;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonNull;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonObject;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonParseException;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonPrimitive;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonSerializationContext;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonSerializer;
|
||||
|
||||
public class PolymorphicAdapter<T> implements JsonDeserializer<T>, JsonSerializer<T>
|
||||
{
|
||||
|
@ -3,8 +3,8 @@ package com.massivecraft.massivecore.adapter;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonObject;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class PotionEffectAdapter
|
||||
|
@ -3,13 +3,13 @@ package com.massivecraft.massivecore.adapter;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonDeserializationContext;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonDeserializer;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonParseException;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonPrimitive;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonSerializationContext;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonSerializer;
|
||||
|
||||
public class UUIDAdapter implements JsonDeserializer<UUID>, JsonSerializer<UUID>
|
||||
{
|
||||
@ -40,14 +40,14 @@ public class UUIDAdapter implements JsonDeserializer<UUID>, JsonSerializer<UUID>
|
||||
// STATIC LOGIC
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static String convertUUIDToString(UUID objectId)
|
||||
public static String convertUUIDToString(UUID uuid)
|
||||
{
|
||||
return objectId.toString();
|
||||
return uuid.toString();
|
||||
}
|
||||
|
||||
public static JsonPrimitive convertUUIDToJsonPrimitive(UUID objectId)
|
||||
public static JsonPrimitive convertUUIDToJsonPrimitive(UUID uuid)
|
||||
{
|
||||
return new JsonPrimitive(convertUUIDToString(objectId));
|
||||
return new JsonPrimitive(convertUUIDToString(uuid));
|
||||
}
|
||||
|
||||
public static UUID convertStringToUUID(String string)
|
||||
|
@ -12,7 +12,7 @@ import com.massivecraft.massivecore.store.Coll;
|
||||
import com.massivecraft.massivecore.store.Db;
|
||||
import com.massivecraft.massivecore.store.Driver;
|
||||
import com.massivecraft.massivecore.store.MStore;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
|
||||
public class CmdMassiveCoreStoreCopydb extends MassiveCommand
|
||||
{
|
||||
|
@ -15,9 +15,9 @@ import com.massivecraft.massivecore.Aspect;
|
||||
import com.massivecraft.massivecore.MassiveCore;
|
||||
import com.massivecraft.massivecore.Multiverse;
|
||||
import com.massivecraft.massivecore.util.MUtil;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonObject;
|
||||
import com.massivecraft.massivecore.xlib.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* # Introduction
|
||||
|
@ -2,10 +2,10 @@ package com.massivecraft.massivecore.ps;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonDeserializationContext;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonDeserializer;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonParseException;
|
||||
|
||||
public class PSAdapter implements JsonDeserializer<PS>
|
||||
{
|
||||
|
@ -22,9 +22,9 @@ import com.massivecraft.massivecore.NaturalOrderComparator;
|
||||
import com.massivecraft.massivecore.Predictate;
|
||||
import com.massivecraft.massivecore.store.accessor.Accessor;
|
||||
import com.massivecraft.massivecore.util.Txt;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.massivecraft.massivecore.xlib.gson.Gson;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonObject;
|
||||
|
||||
public class Coll<E> implements CollInterface<E>
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.massivecraft.massivecore.store;
|
||||
|
||||
import com.mongodb.DB;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.DB;
|
||||
|
||||
public class DbMongo extends DbAbstract
|
||||
{
|
||||
|
@ -5,7 +5,7 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
|
||||
public interface Driver
|
||||
{
|
||||
|
@ -12,8 +12,8 @@ import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.massivecraft.massivecore.util.DiscUtil;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonParser;
|
||||
|
||||
public class DriverFlatfile extends DriverAbstract
|
||||
{
|
||||
|
@ -10,13 +10,13 @@ import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.massivecraft.massivecore.MassiveCoreMConf;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBCursor;
|
||||
import com.mongodb.MongoClient;
|
||||
import com.mongodb.MongoClientURI;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.BasicDBObject;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.DB;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.DBCollection;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.DBCursor;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.MongoClient;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.MongoClientURI;
|
||||
|
||||
public class DriverMongo extends DriverAbstract
|
||||
{
|
||||
@ -190,6 +190,7 @@ public class DriverMongo extends DriverAbstract
|
||||
return (DBCollection) coll.getCollDriverObject();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
protected DB getDbInner(String uri)
|
||||
{
|
||||
MongoClientURI muri = new MongoClientURI(uri);
|
||||
|
@ -3,8 +3,8 @@ package com.massivecraft.massivecore.store;
|
||||
import com.massivecraft.massivecore.MassiveCore;
|
||||
import com.massivecraft.massivecore.NaturalOrderComparator;
|
||||
import com.massivecraft.massivecore.store.accessor.Accessor;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.massivecraft.massivecore.xlib.gson.Gson;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* Usage of this class is highly optional. You may persist anything. If you are
|
||||
|
@ -3,10 +3,10 @@ package com.massivecraft.massivecore.store;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonNull;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonArray;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonNull;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonObject;
|
||||
|
||||
public class GsonCloner
|
||||
{
|
||||
|
@ -4,12 +4,12 @@ import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonNull;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.internal.LazilyParsedNumber;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonArray;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonNull;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonObject;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonPrimitive;
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.LazilyParsedNumber;
|
||||
|
||||
public class GsonEqualsChecker
|
||||
{
|
||||
|
@ -3,17 +3,17 @@ package com.massivecraft.massivecore.store;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonNull;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.internal.LazilyParsedNumber;
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonArray;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonNull;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonObject;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonPrimitive;
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.LazilyParsedNumber;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.BasicDBList;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.BasicDBObject;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.DBObject;
|
||||
|
||||
public final class GsonMongoConverter
|
||||
{
|
||||
|
@ -7,7 +7,7 @@ import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.massivecraft.massivecore.ConfServer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
|
||||
public class MStore
|
||||
{
|
||||
|
@ -37,7 +37,7 @@ import com.massivecraft.massivecore.mixin.Mixin;
|
||||
import com.massivecraft.massivecore.store.Coll;
|
||||
import com.massivecraft.massivecore.store.SenderColl;
|
||||
import com.massivecraft.massivecore.store.SenderEntity;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.massivecraft.massivecore.xlib.gson.reflect.TypeToken;
|
||||
|
||||
/**
|
||||
* Identification of a CommandSender can be done in 4 different ways.
|
||||
|
350
src/main/java/com/massivecraft/massivecore/xlib/bson/BSON.java
Normal file
350
src/main/java/com/massivecraft/massivecore/xlib/bson/BSON.java
Normal file
@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// BSON.java
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.util.ClassMap;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
public class BSON {
|
||||
|
||||
static final Logger LOGGER = Logger.getLogger( "org.bson.BSON" );
|
||||
|
||||
// ---- basics ----
|
||||
|
||||
public static final byte EOO = 0;
|
||||
public static final byte NUMBER = 1;
|
||||
public static final byte STRING = 2;
|
||||
public static final byte OBJECT = 3;
|
||||
public static final byte ARRAY = 4;
|
||||
public static final byte BINARY = 5;
|
||||
public static final byte UNDEFINED = 6;
|
||||
public static final byte OID = 7;
|
||||
public static final byte BOOLEAN = 8;
|
||||
public static final byte DATE = 9;
|
||||
public static final byte NULL = 10;
|
||||
public static final byte REGEX = 11;
|
||||
public static final byte REF = 12;
|
||||
public static final byte CODE = 13;
|
||||
public static final byte SYMBOL = 14;
|
||||
public static final byte CODE_W_SCOPE = 15;
|
||||
public static final byte NUMBER_INT = 16;
|
||||
public static final byte TIMESTAMP = 17;
|
||||
public static final byte NUMBER_LONG = 18;
|
||||
|
||||
public static final byte MINKEY = -1;
|
||||
public static final byte MAXKEY = 127;
|
||||
|
||||
// --- binary types
|
||||
/*
|
||||
these are binary types
|
||||
so the format would look like
|
||||
<BINARY><name><BINARY_TYPE><...>
|
||||
*/
|
||||
|
||||
public static final byte B_GENERAL = 0;
|
||||
public static final byte B_FUNC = 1;
|
||||
public static final byte B_BINARY = 2;
|
||||
public static final byte B_UUID = 3;
|
||||
|
||||
// ---- regular expression handling ----
|
||||
|
||||
/** Converts a string of regular expression flags from the database in Java regular
|
||||
* expression flags.
|
||||
* @param flags flags from database
|
||||
* @return the Java flags
|
||||
*/
|
||||
public static int regexFlags( String flags ){
|
||||
int fint = 0;
|
||||
if ( flags == null || flags.length() == 0 )
|
||||
return fint;
|
||||
|
||||
flags = flags.toLowerCase();
|
||||
|
||||
for( int i=0; i<flags.length(); i++ ) {
|
||||
RegexFlag flag = RegexFlag.getByCharacter( flags.charAt( i ) );
|
||||
if( flag != null ) {
|
||||
fint |= flag.javaFlag;
|
||||
if( flag.unsupported != null )
|
||||
_warnUnsupportedRegex( flag.unsupported );
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException( "unrecognized flag ["+flags.charAt( i ) + "] " + (int)flags.charAt(i) );
|
||||
}
|
||||
}
|
||||
return fint;
|
||||
}
|
||||
|
||||
public static int regexFlag( char c ){
|
||||
RegexFlag flag = RegexFlag.getByCharacter( c );
|
||||
if ( flag == null )
|
||||
throw new IllegalArgumentException( "unrecognized flag [" + c + "]" );
|
||||
|
||||
if ( flag.unsupported != null ){
|
||||
_warnUnsupportedRegex( flag.unsupported );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return flag.javaFlag;
|
||||
}
|
||||
|
||||
/** Converts Java regular expression flags into a string of flags for the database
|
||||
* @param flags Java flags
|
||||
* @return the flags for the database
|
||||
*/
|
||||
public static String regexFlags( int flags ){
|
||||
StringBuilder buf = new StringBuilder();
|
||||
|
||||
for( RegexFlag flag : RegexFlag.values() ) {
|
||||
if( ( flags & flag.javaFlag ) > 0 ) {
|
||||
buf.append( flag.flagChar );
|
||||
flags -= flag.javaFlag;
|
||||
}
|
||||
}
|
||||
|
||||
if( flags > 0 )
|
||||
throw new IllegalArgumentException( "some flags could not be recognized." );
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private static enum RegexFlag {
|
||||
CANON_EQ( Pattern.CANON_EQ, 'c', "Pattern.CANON_EQ" ),
|
||||
UNIX_LINES(Pattern.UNIX_LINES, 'd', "Pattern.UNIX_LINES" ),
|
||||
GLOBAL( GLOBAL_FLAG, 'g', null ),
|
||||
CASE_INSENSITIVE( Pattern.CASE_INSENSITIVE, 'i', null ),
|
||||
MULTILINE(Pattern.MULTILINE, 'm', null ),
|
||||
DOTALL( Pattern.DOTALL, 's', "Pattern.DOTALL" ),
|
||||
LITERAL( Pattern.LITERAL, 't', "Pattern.LITERAL" ),
|
||||
UNICODE_CASE( Pattern.UNICODE_CASE, 'u', "Pattern.UNICODE_CASE" ),
|
||||
COMMENTS( Pattern.COMMENTS, 'x', null );
|
||||
|
||||
private static final Map<Character, RegexFlag> byCharacter = new HashMap<Character, RegexFlag>();
|
||||
|
||||
static {
|
||||
for (RegexFlag flag : values()) {
|
||||
byCharacter.put(flag.flagChar, flag);
|
||||
}
|
||||
}
|
||||
|
||||
public static RegexFlag getByCharacter(char ch) {
|
||||
return byCharacter.get(ch);
|
||||
}
|
||||
public final int javaFlag;
|
||||
public final char flagChar;
|
||||
public final String unsupported;
|
||||
|
||||
RegexFlag( int f, char ch, String u ) {
|
||||
javaFlag = f;
|
||||
flagChar = ch;
|
||||
unsupported = u;
|
||||
}
|
||||
}
|
||||
|
||||
private static void _warnUnsupportedRegex( String flag ) {
|
||||
LOGGER.info( "flag " + flag + " not supported by db." );
|
||||
}
|
||||
|
||||
private static final int GLOBAL_FLAG = 256;
|
||||
|
||||
// --- (en|de)coding hooks -----
|
||||
|
||||
public static boolean hasDecodeHooks() { return _decodeHooks; }
|
||||
|
||||
public static void addEncodingHook( Class c , Transformer t ){
|
||||
_encodeHooks = true;
|
||||
List<Transformer> l = _encodingHooks.get( c );
|
||||
if ( l == null ){
|
||||
l = new CopyOnWriteArrayList<Transformer>();
|
||||
_encodingHooks.put( c , l );
|
||||
}
|
||||
l.add( t );
|
||||
}
|
||||
|
||||
public static void addDecodingHook( Class c , Transformer t ){
|
||||
_decodeHooks = true;
|
||||
List<Transformer> l = _decodingHooks.get( c );
|
||||
if ( l == null ){
|
||||
l = new CopyOnWriteArrayList<Transformer>();
|
||||
_decodingHooks.put( c , l );
|
||||
}
|
||||
l.add( t );
|
||||
}
|
||||
|
||||
public static Object applyEncodingHooks( Object o ){
|
||||
if ( ! _anyHooks() )
|
||||
return o;
|
||||
|
||||
if ( _encodingHooks.size() == 0 || o == null )
|
||||
return o;
|
||||
List<Transformer> l = _encodingHooks.get( o.getClass() );
|
||||
if ( l != null )
|
||||
for ( Transformer t : l )
|
||||
o = t.transform( o );
|
||||
return o;
|
||||
}
|
||||
|
||||
public static Object applyDecodingHooks( Object o ){
|
||||
if ( ! _anyHooks() || o == null )
|
||||
return o;
|
||||
|
||||
List<Transformer> l = _decodingHooks.get( o.getClass() );
|
||||
if ( l != null )
|
||||
for ( Transformer t : l )
|
||||
o = t.transform( o );
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the encoding hook(s) associated with the specified class
|
||||
*
|
||||
*/
|
||||
public static List<Transformer> getEncodingHooks( Class c ){
|
||||
return _encodingHooks.get( c );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears *all* encoding hooks.
|
||||
*/
|
||||
public static void clearEncodingHooks(){
|
||||
_encodeHooks = false;
|
||||
_encodingHooks.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all encoding hooks for a specific class.
|
||||
*/
|
||||
public static void removeEncodingHooks( Class c ){
|
||||
_encodingHooks.remove( c );
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a specific encoding hook for a specific class.
|
||||
*/
|
||||
public static void removeEncodingHook( Class c , Transformer t ){
|
||||
getEncodingHooks( c ).remove( t );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the decoding hook(s) associated with the specific class
|
||||
*/
|
||||
public static List<Transformer> getDecodingHooks( Class c ){
|
||||
return _decodingHooks.get( c );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears *all* decoding hooks.
|
||||
*/
|
||||
public static void clearDecodingHooks(){
|
||||
_decodeHooks = false;
|
||||
_decodingHooks.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all decoding hooks for a specific class.
|
||||
*/
|
||||
public static void removeDecodingHooks( Class c ){
|
||||
_decodingHooks.remove( c );
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a specific encoding hook for a specific class.
|
||||
*/
|
||||
public static void removeDecodingHook( Class c , Transformer t ){
|
||||
getDecodingHooks( c ).remove( t );
|
||||
}
|
||||
|
||||
|
||||
public static void clearAllHooks(){
|
||||
clearEncodingHooks();
|
||||
clearDecodingHooks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if any encoding or decoding hooks are loaded.
|
||||
*/
|
||||
private static boolean _anyHooks(){
|
||||
return _encodeHooks || _decodeHooks;
|
||||
}
|
||||
|
||||
private static boolean _encodeHooks = false;
|
||||
private static boolean _decodeHooks = false;
|
||||
static ClassMap<List<Transformer>> _encodingHooks =
|
||||
new ClassMap<List<Transformer>>();
|
||||
|
||||
static ClassMap<List<Transformer>> _decodingHooks =
|
||||
new ClassMap<List<Transformer>>();
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link Charset#forName(String)} to create UTF-8 charset.
|
||||
*/
|
||||
@Deprecated
|
||||
static protected Charset _utf8 = Charset.forName( "UTF-8" );
|
||||
|
||||
// ----- static encode/decode -----
|
||||
|
||||
public static byte[] encode( BSONObject o ){
|
||||
BSONEncoder e = _staticEncoder.get();
|
||||
try {
|
||||
return e.encode( o );
|
||||
}
|
||||
finally {
|
||||
e.done();
|
||||
}
|
||||
}
|
||||
|
||||
public static BSONObject decode( byte[] b ){
|
||||
BSONDecoder d = _staticDecoder.get();
|
||||
return d.readObject( b );
|
||||
}
|
||||
|
||||
static ThreadLocal<BSONEncoder> _staticEncoder = new ThreadLocal<BSONEncoder>(){
|
||||
protected BSONEncoder initialValue(){
|
||||
return new BasicBSONEncoder();
|
||||
}
|
||||
};
|
||||
|
||||
static ThreadLocal<BSONDecoder> _staticDecoder = new ThreadLocal<BSONDecoder>(){
|
||||
protected BSONDecoder initialValue(){
|
||||
return new BasicBSONDecoder();
|
||||
}
|
||||
};
|
||||
|
||||
// --- coercing ---
|
||||
|
||||
public static int toInt( Object o ){
|
||||
if ( o == null )
|
||||
throw new NullPointerException( "can't be null" );
|
||||
|
||||
if ( o instanceof Number )
|
||||
return ((Number)o).intValue();
|
||||
|
||||
if ( o instanceof Boolean )
|
||||
return ((Boolean)o) ? 1 : 0;
|
||||
|
||||
throw new IllegalArgumentException( "can't convert: " + o.getClass().getName() + " to int" );
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// BSONCallback.java
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
|
||||
|
||||
public interface BSONCallback {
|
||||
|
||||
void objectStart();
|
||||
void objectStart(String name);
|
||||
void objectStart(boolean array);
|
||||
Object objectDone();
|
||||
|
||||
void reset();
|
||||
Object get();
|
||||
BSONCallback createBSONCallback();
|
||||
|
||||
void arrayStart();
|
||||
void arrayStart(String name);
|
||||
Object arrayDone();
|
||||
|
||||
void gotNull( String name );
|
||||
void gotUndefined( String name );
|
||||
void gotMinKey( String name );
|
||||
void gotMaxKey( String name );
|
||||
|
||||
void gotBoolean( String name , boolean v );
|
||||
void gotDouble( String name , double v );
|
||||
void gotInt( String name , int v );
|
||||
void gotLong( String name , long v );
|
||||
|
||||
void gotDate( String name , long millis );
|
||||
void gotString( String name , String v );
|
||||
void gotSymbol( String name , String v );
|
||||
void gotRegex( String name , String pattern , String flags );
|
||||
|
||||
void gotTimestamp( String name , int time , int inc );
|
||||
void gotObjectId( String name , ObjectId id );
|
||||
|
||||
/**
|
||||
* Invoked when {@link com.massivecraft.massivecore.xlib.bson.BSONDecoder} encountered a DBPointer(0x0c) type field in a byte sequence.
|
||||
*
|
||||
* @param name the name of the field
|
||||
* @param ns the namespace to which reference is pointing to
|
||||
* @param id the if of the object to which reference is pointing to
|
||||
*/
|
||||
void gotDBRef(String name, String ns, ObjectId id);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
void gotBinaryArray( String name , byte[] data );
|
||||
void gotBinary( String name , byte type , byte[] data );
|
||||
/**
|
||||
* subtype 3
|
||||
*/
|
||||
void gotUUID( String name , long part1, long part2);
|
||||
|
||||
void gotCode( String name , String code );
|
||||
void gotCodeWScope( String name , String code , Object scope );
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// BSONDecoder.java
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public interface BSONDecoder {
|
||||
|
||||
public BSONObject readObject( byte[] b );
|
||||
|
||||
public BSONObject readObject( InputStream in ) throws IOException;
|
||||
|
||||
public int decode( byte[] b , BSONCallback callback );
|
||||
|
||||
public int decode( InputStream in , BSONCallback callback ) throws IOException;
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.massivecore.xlib.bson;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.io.OutputBuffer;
|
||||
|
||||
|
||||
public interface BSONEncoder {
|
||||
public byte[] encode( BSONObject o );
|
||||
|
||||
public int putObject( BSONObject o );
|
||||
|
||||
public void done();
|
||||
|
||||
void set( OutputBuffer out );
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.massivecore.xlib.bson;
|
||||
|
||||
/**
|
||||
* A general runtime exception raised in BSON processing.
|
||||
*/
|
||||
public class BSONException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = -4415279469780082174L;
|
||||
|
||||
/**
|
||||
* @param msg The error message.
|
||||
*/
|
||||
public BSONException( final String msg ) {
|
||||
super( msg );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param errorCode The error code.
|
||||
* @param msg The error message.
|
||||
*/
|
||||
public BSONException( final int errorCode, final String msg ) {
|
||||
super( msg );
|
||||
_errorCode = errorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param msg The error message.
|
||||
* @param t The throwable cause.
|
||||
*/
|
||||
public BSONException( final String msg , final Throwable t ) {
|
||||
super( msg, t );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param errorCode The error code.
|
||||
* @param msg The error message.
|
||||
* @param t The throwable cause.
|
||||
*/
|
||||
public BSONException( final int errorCode, final String msg, final Throwable t ) {
|
||||
super( msg, t );
|
||||
_errorCode = errorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the error code.
|
||||
* @return The error code.
|
||||
*/
|
||||
public Integer getErrorCode() { return _errorCode; }
|
||||
|
||||
/**
|
||||
* Returns true if the error code is set (i.e., not null).
|
||||
*/
|
||||
public boolean hasErrorCode() { return (_errorCode != null); }
|
||||
|
||||
private Integer _errorCode = null;
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.massivecore.xlib.bson;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author antoine
|
||||
*
|
||||
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public class BSONLazyDecoder {
|
||||
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// BSONObject.java
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A key-value map that can be saved to the database.
|
||||
*/
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
public interface BSONObject {
|
||||
|
||||
/**
|
||||
* Sets a name/value pair in this object.
|
||||
* @param key Name to set
|
||||
* @param v Corresponding value
|
||||
* @return <tt>v</tt>
|
||||
*/
|
||||
public Object put( String key , Object v );
|
||||
|
||||
/**
|
||||
* Sets all key/value pairs from an object into this object
|
||||
* @param o the object
|
||||
*/
|
||||
public void putAll( BSONObject o );
|
||||
|
||||
/**
|
||||
* Sets all key/value pairs from a map into this object
|
||||
* @param m the map
|
||||
*/
|
||||
public void putAll( Map m );
|
||||
|
||||
/**
|
||||
* Gets a field from this object by a given name.
|
||||
* @param key The name of the field fetch
|
||||
* @return The field, if found
|
||||
*/
|
||||
public Object get( String key );
|
||||
|
||||
/**
|
||||
* Returns a map representing this BSONObject.
|
||||
* @return the map
|
||||
*/
|
||||
public Map toMap();
|
||||
|
||||
/**
|
||||
* Removes a field with a given name from this object.
|
||||
* @param key The name of the field to remove
|
||||
* @return The value removed from this object
|
||||
*/
|
||||
public Object removeField( String key );
|
||||
|
||||
/**
|
||||
* Deprecated
|
||||
* @param s
|
||||
* @return True if the key is present
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean containsKey( String s );
|
||||
|
||||
/**
|
||||
* Checks if this object contains a field with the given name.
|
||||
* @param s Field name for which to check
|
||||
* @return True if the field is present
|
||||
*/
|
||||
public boolean containsField(String s);
|
||||
|
||||
/**
|
||||
* Returns this object's fields' names
|
||||
* @return The names of the fields in this object
|
||||
*/
|
||||
public Set<String> keySet();
|
||||
}
|
||||
|
@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// BasicBSONCallback.java
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.types.BSONTimestamp;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.BasicBSONList;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.Binary;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.Code;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.CodeWScope;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.MaxKey;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.MinKey;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class BasicBSONCallback implements BSONCallback {
|
||||
|
||||
public BasicBSONCallback(){
|
||||
reset();
|
||||
}
|
||||
|
||||
public BSONObject create(){
|
||||
return new BasicBSONObject();
|
||||
}
|
||||
|
||||
protected BSONObject createList() {
|
||||
return new BasicBSONList();
|
||||
}
|
||||
|
||||
public BSONCallback createBSONCallback(){
|
||||
return new BasicBSONCallback();
|
||||
}
|
||||
|
||||
public BSONObject create( boolean array , List<String> path ){
|
||||
if ( array )
|
||||
return createList();
|
||||
return create();
|
||||
}
|
||||
|
||||
public void objectStart(){
|
||||
if ( _stack.size() > 0 )
|
||||
throw new IllegalStateException( "something is wrong" );
|
||||
|
||||
objectStart(false);
|
||||
}
|
||||
|
||||
public void objectStart(boolean array){
|
||||
_root = create(array, null);
|
||||
_stack.add( (BSONObject)_root );
|
||||
}
|
||||
|
||||
public void objectStart(String name){
|
||||
objectStart( false , name );
|
||||
}
|
||||
|
||||
public void objectStart(boolean array, String name){
|
||||
_nameStack.addLast( name );
|
||||
final BSONObject o = create( array , _nameStack );
|
||||
_stack.getLast().put( name , o);
|
||||
_stack.addLast( o );
|
||||
}
|
||||
|
||||
public Object objectDone(){
|
||||
final BSONObject o =_stack.removeLast();
|
||||
if ( _nameStack.size() > 0 )
|
||||
_nameStack.removeLast();
|
||||
else if ( _stack.size() > 0 )
|
||||
throw new IllegalStateException( "something is wrong" );
|
||||
|
||||
return !BSON.hasDecodeHooks() ? o : (BSONObject)BSON.applyDecodingHooks(o);
|
||||
}
|
||||
|
||||
public void arrayStart(){
|
||||
objectStart( true );
|
||||
}
|
||||
|
||||
public void arrayStart(String name){
|
||||
objectStart( true , name );
|
||||
}
|
||||
|
||||
public Object arrayDone(){
|
||||
return objectDone();
|
||||
}
|
||||
|
||||
public void gotNull( String name ){
|
||||
cur().put( name , null );
|
||||
}
|
||||
|
||||
public void gotUndefined( String name ) { }
|
||||
|
||||
public void gotMinKey( String name ){
|
||||
cur().put( name , new MinKey() );
|
||||
}
|
||||
|
||||
public void gotMaxKey( String name ){
|
||||
cur().put( name , new MaxKey() );
|
||||
}
|
||||
|
||||
public void gotBoolean( String name , boolean v ){
|
||||
_put( name , v );
|
||||
}
|
||||
|
||||
public void gotDouble( final String name , final double v ){
|
||||
_put( name , v );
|
||||
}
|
||||
|
||||
public void gotInt( final String name , final int v ){
|
||||
_put( name , v );
|
||||
}
|
||||
|
||||
public void gotLong( final String name , final long v ){
|
||||
_put( name , v );
|
||||
}
|
||||
|
||||
public void gotDate( String name , long millis ){
|
||||
_put( name , new Date( millis ) );
|
||||
}
|
||||
public void gotRegex( String name , String pattern , String flags ){
|
||||
_put( name , Pattern.compile( pattern , BSON.regexFlags( flags ) ) );
|
||||
}
|
||||
|
||||
public void gotString( final String name , final String v ){
|
||||
_put( name , v );
|
||||
}
|
||||
public void gotSymbol( String name , String v ){
|
||||
_put( name , v );
|
||||
}
|
||||
|
||||
public void gotTimestamp( String name , int time , int inc ){
|
||||
_put( name , new BSONTimestamp( time , inc ) );
|
||||
}
|
||||
public void gotObjectId( String name , ObjectId id ){
|
||||
_put( name , id );
|
||||
}
|
||||
public void gotDBRef( String name , String ns , ObjectId id ){
|
||||
_put( name , new BasicBSONObject( "$ns" , ns ).append( "$id" , id ) );
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void gotBinaryArray( String name , byte[] data ){
|
||||
gotBinary( name, BSON.B_GENERAL, data );
|
||||
}
|
||||
|
||||
public void gotBinary( String name , byte type , byte[] data ){
|
||||
if( type == BSON.B_GENERAL || type == BSON.B_BINARY )
|
||||
_put( name , data );
|
||||
else
|
||||
_put( name , new Binary( type , data ) );
|
||||
}
|
||||
|
||||
public void gotUUID( String name , long part1, long part2){
|
||||
_put( name , new UUID(part1, part2) );
|
||||
}
|
||||
|
||||
public void gotCode( String name , String code ){
|
||||
_put( name , new Code( code ) );
|
||||
}
|
||||
|
||||
public void gotCodeWScope( String name , String code , Object scope ){
|
||||
_put( name , new CodeWScope( code, (BSONObject)scope ) );
|
||||
}
|
||||
|
||||
protected void _put( final String name , final Object o ){
|
||||
cur().put( name , !BSON.hasDecodeHooks() ? o : BSON.applyDecodingHooks( o ) );
|
||||
}
|
||||
|
||||
protected BSONObject cur(){
|
||||
return _stack.getLast();
|
||||
}
|
||||
|
||||
protected String curName(){
|
||||
return (!_nameStack.isEmpty()) ? _nameStack.getLast() : null;
|
||||
}
|
||||
|
||||
public Object get(){
|
||||
return _root;
|
||||
}
|
||||
|
||||
protected void setRoot(Object o) {
|
||||
_root = o;
|
||||
}
|
||||
|
||||
protected boolean isStackEmpty() {
|
||||
return _stack.size() < 1;
|
||||
}
|
||||
|
||||
public void reset(){
|
||||
_root = null;
|
||||
_stack.clear();
|
||||
_nameStack.clear();
|
||||
}
|
||||
|
||||
private Object _root;
|
||||
private final LinkedList<BSONObject> _stack = new LinkedList<BSONObject>();
|
||||
private final LinkedList<String> _nameStack = new LinkedList<String>();
|
||||
}
|
@ -0,0 +1,639 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.massivecore.xlib.bson;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.io.PoolOutputBuffer;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.ARRAY;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.BINARY;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.BOOLEAN;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.B_BINARY;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.B_GENERAL;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.B_UUID;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.CODE;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.CODE_W_SCOPE;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.DATE;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.EOO;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.MAXKEY;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.MINKEY;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.NULL;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.NUMBER;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.NUMBER_INT;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.NUMBER_LONG;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.OBJECT;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.OID;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.REF;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.REGEX;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.STRING;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.SYMBOL;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.TIMESTAMP;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.UNDEFINED;
|
||||
|
||||
|
||||
/**
|
||||
* Basic implementation of BSONDecoder interface that creates BasicBSONObject instances.
|
||||
*
|
||||
* <h3>Migration instructions</h3>
|
||||
* In driver versions before <b>2.12</b> {@code BasicBSONDecoder} exposed several protected members to its subclasses:
|
||||
* <br/><br/>
|
||||
* <b>Fields:</b>
|
||||
* <ul>
|
||||
* <li>{@code protected BSONInput _in}</li>
|
||||
* <li>{@code protected BSONCallback _callback}</li>
|
||||
* <li>{@code protected int _len}</li>
|
||||
* <li>{@code protected int _pos}</li>
|
||||
*
|
||||
* </ul>
|
||||
* <br/>
|
||||
* <b>Methods:</b>
|
||||
* <ul>
|
||||
* <li>{@code protected void _binary(String)}</li>
|
||||
* </ul>
|
||||
* <br/>
|
||||
* <b>Nested Classes:</b>
|
||||
* <ul>
|
||||
* <li>{@code protected class BSONInput}</li>
|
||||
* </ul>
|
||||
* <br/>
|
||||
*
|
||||
*<h4>Solution 1: Custom {@link BSONCallback} implementation</h4>
|
||||
* With callbacks you can handle the process of creating objects from bytes in BSON format.
|
||||
* <p>
|
||||
* For example to get away from overriging <b>{@code BasicBSONDecoder._binary(String)}</b>
|
||||
* you can use the following piece of code:
|
||||
* </p>
|
||||
* <pre>
|
||||
* <code style="background:#eee;display:inline-block;padding:10px">public class CustomBSONCallback extends BasicBSONCallback {
|
||||
*
|
||||
* public void gotBinary(String name, byte type, byte[] data) {
|
||||
* _put(name,toHex(data));
|
||||
* }
|
||||
*
|
||||
* private static String toHex(byte[] bytes) {...}
|
||||
*}
|
||||
*</code></pre>
|
||||
*
|
||||
* This solution covers majority of the cases.
|
||||
*
|
||||
* <h4>Solution 2: Custom {@link BSONDecoder} implementation</h4>
|
||||
* If you need to customize byte-level decoding at the lowest layer you have to provide you own
|
||||
* implementation of the {@link BSONDecoder} interface.
|
||||
* <br/>
|
||||
* Please check <a href="http://bsonspec.org/">http://bsonspec.org/</a> for more information.
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class BasicBSONDecoder implements BSONDecoder {
|
||||
public BSONObject readObject( byte[] b ){
|
||||
try {
|
||||
return readObject( new ByteArrayInputStream( b ) );
|
||||
}
|
||||
catch ( IOException ioe ){
|
||||
throw new BSONException( "should be impossible" , ioe );
|
||||
}
|
||||
}
|
||||
|
||||
public BSONObject readObject( InputStream in )
|
||||
throws IOException {
|
||||
BasicBSONCallback c = new BasicBSONCallback();
|
||||
decode( in , c );
|
||||
return (BSONObject)c.get();
|
||||
}
|
||||
|
||||
public int decode( byte[] b , BSONCallback callback ){
|
||||
try {
|
||||
return _decode( new BSONInput( new ByteArrayInputStream(b) ) , callback );
|
||||
}
|
||||
catch ( IOException ioe ){
|
||||
throw new BSONException( "should be impossible" , ioe );
|
||||
}
|
||||
}
|
||||
|
||||
public int decode( InputStream in , BSONCallback callback )
|
||||
throws IOException {
|
||||
return _decode( new BSONInput( in ) , callback );
|
||||
}
|
||||
|
||||
private int _decode( BSONInput in , BSONCallback callback )
|
||||
throws IOException {
|
||||
|
||||
if ( _in != null || _callback != null )
|
||||
throw new IllegalStateException( "not ready" );
|
||||
|
||||
_in = in;
|
||||
_callback = callback;
|
||||
|
||||
if ( in.numRead() != 0 )
|
||||
throw new IllegalArgumentException( "i'm confused" );
|
||||
|
||||
try {
|
||||
|
||||
final int len = _in.readInt();
|
||||
|
||||
_in.setMax(len);
|
||||
|
||||
_callback.objectStart();
|
||||
while ( decodeElement() );
|
||||
_callback.objectDone();
|
||||
|
||||
if ( _in.numRead() != len )
|
||||
throw new IllegalArgumentException( "bad data. lengths don't match read:" + _in.numRead() + " != len:" + len );
|
||||
|
||||
return len;
|
||||
}
|
||||
finally {
|
||||
_in = null;
|
||||
_callback = null;
|
||||
}
|
||||
}
|
||||
|
||||
int decode( boolean first )
|
||||
throws IOException {
|
||||
|
||||
final int start = _in.numRead();
|
||||
|
||||
final int len = _in.readInt();
|
||||
if ( first )
|
||||
_in.setMax(len);
|
||||
|
||||
_callback.objectStart();
|
||||
while ( decodeElement() );
|
||||
_callback.objectDone();
|
||||
|
||||
final int read = _in.numRead() - start;
|
||||
|
||||
if ( read != len ){
|
||||
//throw new IllegalArgumentException( "bad data. lengths don't match " + read + " != " + len );
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
boolean decodeElement()
|
||||
throws IOException {
|
||||
|
||||
final byte type = _in.read();
|
||||
|
||||
if ( type == EOO )
|
||||
return false;
|
||||
|
||||
String name = _in.readCStr();
|
||||
|
||||
switch ( type ){
|
||||
case NULL:
|
||||
_callback.gotNull( name );
|
||||
break;
|
||||
|
||||
case UNDEFINED:
|
||||
_callback.gotUndefined( name );
|
||||
break;
|
||||
|
||||
case BOOLEAN:
|
||||
_callback.gotBoolean( name , _in.read() > 0 );
|
||||
break;
|
||||
|
||||
case NUMBER:
|
||||
_callback.gotDouble( name , _in.readDouble() );
|
||||
break;
|
||||
|
||||
case NUMBER_INT:
|
||||
_callback.gotInt( name , _in.readInt() );
|
||||
break;
|
||||
|
||||
case NUMBER_LONG:
|
||||
_callback.gotLong( name , _in.readLong() );
|
||||
break;
|
||||
|
||||
case SYMBOL:
|
||||
_callback.gotSymbol( name , _in.readUTF8String() );
|
||||
break;
|
||||
|
||||
case STRING:
|
||||
_callback.gotString(name, _in.readUTF8String() );
|
||||
break;
|
||||
|
||||
case OID:
|
||||
// OID is stored as big endian
|
||||
_callback.gotObjectId( name , new ObjectId( _in.readIntBE() , _in.readIntBE() , _in.readIntBE() ) );
|
||||
break;
|
||||
|
||||
case REF:
|
||||
_in.readInt(); // length of ctring that follows
|
||||
String ns = _in.readCStr();
|
||||
ObjectId theOID = new ObjectId( _in.readInt() , _in.readInt() , _in.readInt() );
|
||||
_callback.gotDBRef( name , ns , theOID );
|
||||
break;
|
||||
|
||||
case DATE:
|
||||
_callback.gotDate( name , _in.readLong() );
|
||||
break;
|
||||
|
||||
case REGEX:
|
||||
_callback.gotRegex( name , _in.readCStr() , _in.readCStr() );
|
||||
break;
|
||||
|
||||
case BINARY:
|
||||
_binary( name );
|
||||
break;
|
||||
|
||||
case CODE:
|
||||
_callback.gotCode( name , _in.readUTF8String() );
|
||||
break;
|
||||
|
||||
case CODE_W_SCOPE:
|
||||
_in.readInt();
|
||||
_callback.gotCodeWScope( name , _in.readUTF8String() , _readBasicObject() );
|
||||
|
||||
break;
|
||||
|
||||
case ARRAY:
|
||||
_in.readInt(); // total size - we don't care....
|
||||
|
||||
_callback.arrayStart( name );
|
||||
while ( decodeElement() );
|
||||
_callback.arrayDone();
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case OBJECT:
|
||||
_in.readInt(); // total size - we don't care....
|
||||
|
||||
_callback.objectStart( name );
|
||||
while ( decodeElement() );
|
||||
_callback.objectDone();
|
||||
|
||||
break;
|
||||
|
||||
case TIMESTAMP:
|
||||
int i = _in.readInt();
|
||||
int time = _in.readInt();
|
||||
_callback.gotTimestamp( name , time , i );
|
||||
break;
|
||||
|
||||
case MINKEY:
|
||||
_callback.gotMinKey( name );
|
||||
break;
|
||||
|
||||
case MAXKEY:
|
||||
_callback.gotMaxKey( name );
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new UnsupportedOperationException( "BSONDecoder doesn't understand type : " + type + " name: " + name );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param name the field name
|
||||
* @throws IOException
|
||||
*
|
||||
* @deprecated This method should not be a part of API.
|
||||
* Please see the class-level documentation for a migration instructions.
|
||||
*/
|
||||
@Deprecated
|
||||
protected void _binary( final String name )
|
||||
throws IOException {
|
||||
final int totalLen = _in.readInt();
|
||||
final byte bType = _in.read();
|
||||
|
||||
switch ( bType ){
|
||||
case B_GENERAL: {
|
||||
final byte[] data = new byte[totalLen];
|
||||
_in.fill( data );
|
||||
_callback.gotBinary( name, bType, data );
|
||||
return;
|
||||
}
|
||||
case B_BINARY:
|
||||
final int len = _in.readInt();
|
||||
if ( len + 4 != totalLen )
|
||||
throw new IllegalArgumentException( "bad data size subtype 2 len: " + len + " totalLen: " + totalLen );
|
||||
|
||||
final byte [] data = new byte[len];
|
||||
_in.fill( data );
|
||||
_callback.gotBinary( name , bType , data );
|
||||
return;
|
||||
case B_UUID:
|
||||
if ( totalLen != 16 )
|
||||
throw new IllegalArgumentException( "bad data size subtype 3 len: " + totalLen + " != 16");
|
||||
|
||||
final long part1 = _in.readLong();
|
||||
final long part2 = _in.readLong();
|
||||
_callback.gotUUID(name, part1, part2);
|
||||
return;
|
||||
}
|
||||
|
||||
final byte [] data = new byte[totalLen];
|
||||
_in.fill( data );
|
||||
|
||||
_callback.gotBinary( name , bType , data );
|
||||
}
|
||||
|
||||
Object _readBasicObject()
|
||||
throws IOException {
|
||||
_in.readInt();
|
||||
|
||||
final BSONCallback save = _callback;
|
||||
final BSONCallback _basic = _callback.createBSONCallback();
|
||||
_callback = _basic;
|
||||
_basic.reset();
|
||||
_basic.objectStart(false);
|
||||
|
||||
while( decodeElement() );
|
||||
_callback = save;
|
||||
return _basic.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This class should not be a part of API.
|
||||
* Please see the class-level documentation for a migration instructions.
|
||||
*/
|
||||
@Deprecated
|
||||
protected class BSONInput {
|
||||
|
||||
public BSONInput(final InputStream in){
|
||||
_raw = in;
|
||||
_read = 0;
|
||||
|
||||
_pos = 0;
|
||||
_len = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ensure that there are num bytes to read
|
||||
* _pos is where to start reading from
|
||||
* @return where to start reading from
|
||||
*/
|
||||
protected int _need( final int num )
|
||||
throws IOException {
|
||||
|
||||
//System.out.println( "p: " + _pos + " l: " + _len + " want: " + num );
|
||||
|
||||
if ( _len - _pos >= num ){
|
||||
final int ret = _pos;
|
||||
_pos += num;
|
||||
_read += num;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ( num >= _inputBuffer.length )
|
||||
throw new IllegalArgumentException( "you can't need that much" );
|
||||
|
||||
final int remaining = _len - _pos;
|
||||
if ( _pos > 0 ){
|
||||
System.arraycopy( _inputBuffer , _pos , _inputBuffer , 0 , remaining );
|
||||
|
||||
_pos = 0;
|
||||
_len = remaining;
|
||||
}
|
||||
|
||||
// read as much as possible into buffer
|
||||
int maxToRead = Math.min( _max - _read - remaining , _inputBuffer.length - _len );
|
||||
while ( maxToRead > 0 ){
|
||||
int x = _raw.read( _inputBuffer , _len , maxToRead);
|
||||
if ( x <= 0 )
|
||||
throw new IOException( "unexpected EOF" );
|
||||
maxToRead -= x;
|
||||
_len += x;
|
||||
}
|
||||
|
||||
int ret = _pos;
|
||||
_pos += num;
|
||||
_read += num;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int readInt()
|
||||
throws IOException {
|
||||
return com.massivecraft.massivecore.xlib.bson.io.Bits.readInt( _inputBuffer , _need(4) );
|
||||
}
|
||||
|
||||
public int readIntBE()
|
||||
throws IOException {
|
||||
return com.massivecraft.massivecore.xlib.bson.io.Bits.readIntBE( _inputBuffer , _need(4) );
|
||||
}
|
||||
|
||||
public long readLong()
|
||||
throws IOException {
|
||||
return com.massivecraft.massivecore.xlib.bson.io.Bits.readLong( _inputBuffer , _need(8) );
|
||||
}
|
||||
|
||||
public double readDouble()
|
||||
throws IOException {
|
||||
return Double.longBitsToDouble( readLong() );
|
||||
}
|
||||
|
||||
public byte read()
|
||||
throws IOException {
|
||||
if ( _pos < _len ){
|
||||
++_read;
|
||||
return _inputBuffer[_pos++];
|
||||
}
|
||||
return _inputBuffer[_need(1)];
|
||||
}
|
||||
|
||||
public void fill( byte b[] )
|
||||
throws IOException {
|
||||
fill( b , b.length );
|
||||
}
|
||||
|
||||
public void fill( byte b[] , int len )
|
||||
throws IOException {
|
||||
// first use what we have
|
||||
final int have = _len - _pos;
|
||||
final int tocopy = Math.min( len , have );
|
||||
System.arraycopy( _inputBuffer , _pos , b , 0 , tocopy );
|
||||
|
||||
_pos += tocopy;
|
||||
_read += tocopy;
|
||||
|
||||
len -= tocopy;
|
||||
|
||||
int off = tocopy;
|
||||
while ( len > 0 ){
|
||||
final int x = _raw.read( b , off , len );
|
||||
if (x <= 0)
|
||||
throw new IOException( "unexpected EOF" );
|
||||
_read += x;
|
||||
off += x;
|
||||
len -= x;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean _isAscii( byte b ){
|
||||
return b >=0 && b <= 127;
|
||||
}
|
||||
|
||||
public String readCStr() throws IOException {
|
||||
|
||||
boolean isAscii = true;
|
||||
|
||||
// short circuit 1 byte strings
|
||||
_random[0] = read();
|
||||
if (_random[0] == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
_random[1] = read();
|
||||
if (_random[1] == 0) {
|
||||
final String out = ONE_BYTE_STRINGS[_random[0]];
|
||||
return (out != null) ? out : new String(_random, 0, 1, DEFAULT_ENCODING);
|
||||
}
|
||||
|
||||
_stringBuffer.reset();
|
||||
_stringBuffer.write(_random, 0, 2);
|
||||
|
||||
isAscii = _isAscii(_random[0]) && _isAscii(_random[1]);
|
||||
|
||||
byte b;
|
||||
while ((b = read()) != 0) {
|
||||
_stringBuffer.write( b );
|
||||
isAscii = isAscii && _isAscii( b );
|
||||
}
|
||||
|
||||
String out = null;
|
||||
if ( isAscii ){
|
||||
out = _stringBuffer.asAscii();
|
||||
}
|
||||
else {
|
||||
try {
|
||||
out = _stringBuffer.asString( DEFAULT_ENCODING );
|
||||
}
|
||||
catch ( UnsupportedOperationException e ){
|
||||
throw new BSONException( "impossible" , e );
|
||||
}
|
||||
}
|
||||
_stringBuffer.reset();
|
||||
return out;
|
||||
}
|
||||
|
||||
public String readUTF8String()
|
||||
throws IOException {
|
||||
final int size = readInt();
|
||||
// this is just protection in case it's corrupted, to avoid huge strings
|
||||
if ( size <= 0 || size > MAX_STRING )
|
||||
throw new BSONException( "bad string size: " + size );
|
||||
|
||||
if ( size < _inputBuffer.length / 2 ){
|
||||
if ( size == 1 ){
|
||||
read();
|
||||
return "";
|
||||
}
|
||||
|
||||
return new String( _inputBuffer , _need(size) , size - 1 , DEFAULT_ENCODING );
|
||||
}
|
||||
|
||||
final byte [] b = size < _random.length ? _random : new byte[size];
|
||||
|
||||
fill( b , size );
|
||||
|
||||
try {
|
||||
return new String( b , 0 , size - 1 , DEFAULT_ENCODING );
|
||||
}
|
||||
catch ( java.io.UnsupportedEncodingException uee ){
|
||||
throw new BSONException( "impossible" , uee );
|
||||
}
|
||||
}
|
||||
|
||||
public int numRead() {
|
||||
return _read;
|
||||
}
|
||||
|
||||
public int getPos() {
|
||||
return _pos;
|
||||
}
|
||||
|
||||
public int getMax() {
|
||||
return _max;
|
||||
}
|
||||
|
||||
public void setMax(int _max) {
|
||||
this._max = _max;
|
||||
}
|
||||
|
||||
int _read;
|
||||
final InputStream _raw;
|
||||
|
||||
int _max = 4; // max number of total bytes allowed to ready
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This field should not be a part of API.
|
||||
* Please see the class-level documentation for a migration instructions.
|
||||
*/
|
||||
@Deprecated
|
||||
protected BSONInput _in;
|
||||
|
||||
/**
|
||||
* @deprecated This field should not be a part of API.
|
||||
* Please see the class-level documentation for a migration instructions.
|
||||
*/
|
||||
@Deprecated
|
||||
protected BSONCallback _callback;
|
||||
|
||||
private byte [] _random = new byte[1024]; // has to be used within a single function
|
||||
private byte [] _inputBuffer = new byte[1024];
|
||||
|
||||
private PoolOutputBuffer _stringBuffer = new PoolOutputBuffer();
|
||||
|
||||
/**
|
||||
* @deprecated This field should not be a part of API.
|
||||
* Please see the class-level documentation for a migration instructions.
|
||||
*/
|
||||
@Deprecated
|
||||
protected int _pos; // current offset into _inputBuffer
|
||||
|
||||
/**
|
||||
* @deprecated This field should not be a part of API.
|
||||
* Please see the class-level documentation for a migration instructions.
|
||||
*/
|
||||
@Deprecated
|
||||
protected int _len; // length of valid data in _inputBuffer
|
||||
|
||||
private static final int MAX_STRING = ( 32 * 1024 * 1024 );
|
||||
|
||||
private static final String DEFAULT_ENCODING = "UTF-8";
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final boolean _isAscii( final byte b ){
|
||||
return b >=0 && b <= 127;
|
||||
}
|
||||
|
||||
static final String[] ONE_BYTE_STRINGS = new String[128];
|
||||
static void _fillRange( byte min, byte max ){
|
||||
while ( min < max ){
|
||||
String s = "";
|
||||
s += (char)min;
|
||||
ONE_BYTE_STRINGS[(int)min] = s;
|
||||
min++;
|
||||
}
|
||||
}
|
||||
static {
|
||||
_fillRange( (byte)'0' , (byte)'9' );
|
||||
_fillRange( (byte)'a' , (byte)'z' );
|
||||
_fillRange( (byte)'A' , (byte)'Z' );
|
||||
}
|
||||
}
|
@ -0,0 +1,537 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// BSONEncoder.java
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.io.BasicOutputBuffer;
|
||||
import com.massivecraft.massivecore.xlib.bson.io.OutputBuffer;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.BSONTimestamp;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.Binary;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.Code;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.CodeWScope;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.MaxKey;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.MinKey;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.Symbol;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.DBRefBase;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.nio.Buffer;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.ARRAY;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.BINARY;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.BOOLEAN;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.B_BINARY;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.B_GENERAL;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.B_UUID;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.CODE;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.CODE_W_SCOPE;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.DATE;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.EOO;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.MAXKEY;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.MINKEY;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.NULL;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.NUMBER;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.NUMBER_INT;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.NUMBER_LONG;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.OBJECT;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.OID;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.REGEX;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.STRING;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.SYMBOL;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.TIMESTAMP;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.UNDEFINED;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.regexFlags;
|
||||
|
||||
/**
|
||||
* this is meant to be pooled or cached
|
||||
* there is some per instance memory for string conversion, etc...
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "deprecation", "unused"})
|
||||
public class BasicBSONEncoder implements BSONEncoder {
|
||||
|
||||
static final boolean DEBUG = false;
|
||||
|
||||
public BasicBSONEncoder(){
|
||||
|
||||
}
|
||||
|
||||
public byte[] encode( BSONObject o ){
|
||||
BasicOutputBuffer buf = new BasicOutputBuffer();
|
||||
set( buf );
|
||||
putObject( o );
|
||||
done();
|
||||
return buf.toByteArray();
|
||||
}
|
||||
|
||||
public void set( OutputBuffer out ){
|
||||
if ( _buf != null )
|
||||
throw new IllegalStateException( "in the middle of something" );
|
||||
|
||||
_buf = out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the buffer this encoder is writing to.
|
||||
*
|
||||
* @return the output buffer
|
||||
*/
|
||||
protected OutputBuffer getOutputBuffer() {
|
||||
return _buf;
|
||||
}
|
||||
|
||||
public void done(){
|
||||
_buf = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if object was handled
|
||||
*
|
||||
* @deprecated Override {@link #putSpecial(String, Object)} if you need to you need to handle custom types.
|
||||
*/
|
||||
@Deprecated
|
||||
protected boolean handleSpecialObjects( String name , BSONObject o ){
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean putSpecial( String name , Object o ){
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Encodes a <code>BSONObject</code>.
|
||||
* This is for the higher level api calls
|
||||
* @param o the object to encode
|
||||
* @return the number of characters in the encoding
|
||||
*/
|
||||
public int putObject( BSONObject o ){
|
||||
return putObject( null , o );
|
||||
}
|
||||
|
||||
/**
|
||||
* this is really for embedded objects
|
||||
*/
|
||||
protected int putObject( String name , BSONObject o ){
|
||||
|
||||
if ( o == null )
|
||||
throw new NullPointerException( "can't save a null object" );
|
||||
|
||||
if ( DEBUG ) System.out.println( "putObject : " + name + " [" + o.getClass() + "]" + " # keys " + o.keySet().size() );
|
||||
|
||||
final int start = _buf.getPosition();
|
||||
|
||||
byte myType = OBJECT;
|
||||
if ( o instanceof List )
|
||||
myType = ARRAY;
|
||||
|
||||
if ( handleSpecialObjects( name , o ) )
|
||||
return _buf.getPosition() - start;
|
||||
|
||||
if ( name != null ){
|
||||
_put( myType , name );
|
||||
}
|
||||
|
||||
final int sizePos = _buf.getPosition();
|
||||
_buf.writeInt( 0 ); // leaving space for this. set it at the end
|
||||
|
||||
List transientFields = null;
|
||||
boolean rewriteID = myType == OBJECT && name == null;
|
||||
|
||||
|
||||
if ( myType == OBJECT ) {
|
||||
if ( rewriteID && o.containsField( "_id" ) )
|
||||
_putObjectField( "_id" , o.get( "_id" ) );
|
||||
|
||||
{
|
||||
Object temp = o.get( "_transientFields" );
|
||||
if ( temp instanceof List )
|
||||
transientFields = (List)temp;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: reduce repeated code below.
|
||||
if ( o instanceof Map ){
|
||||
for ( Entry<String, Object> e : ((Map<String, Object>)o).entrySet() ){
|
||||
|
||||
if ( rewriteID && e.getKey().equals( "_id" ) )
|
||||
continue;
|
||||
|
||||
if ( transientFields != null && transientFields.contains( e.getKey() ) )
|
||||
continue;
|
||||
|
||||
_putObjectField( e.getKey() , e.getValue() );
|
||||
|
||||
}
|
||||
} else {
|
||||
for ( String s : o.keySet() ){
|
||||
|
||||
if ( rewriteID && s.equals( "_id" ) )
|
||||
continue;
|
||||
|
||||
if ( transientFields != null && transientFields.contains( s ) )
|
||||
continue;
|
||||
|
||||
Object val = o.get( s );
|
||||
|
||||
_putObjectField( s , val );
|
||||
|
||||
}
|
||||
}
|
||||
_buf.write( EOO );
|
||||
|
||||
_buf.writeInt( sizePos , _buf.getPosition() - sizePos );
|
||||
return _buf.getPosition() - start;
|
||||
}
|
||||
|
||||
protected void _putObjectField( String name , Object val ){
|
||||
|
||||
if ( name.equals( "_transientFields" ) )
|
||||
return;
|
||||
|
||||
if ( DEBUG ) System.out.println( "\t put thing : " + name );
|
||||
|
||||
if ( name.contains( "\0" ) )
|
||||
throw new IllegalArgumentException( "Document field names can't have a NULL character. (Bad Key: '" + name + "')" );
|
||||
|
||||
if ( name.equals( "$where") && val instanceof String ){
|
||||
_put( CODE , name );
|
||||
_putValueString( val.toString() );
|
||||
return;
|
||||
}
|
||||
|
||||
val = BSON.applyEncodingHooks( val );
|
||||
|
||||
if ( val == null )
|
||||
putNull(name);
|
||||
else if ( val instanceof Date )
|
||||
putDate( name , (Date)val );
|
||||
else if ( val instanceof Number )
|
||||
putNumber(name, (Number)val );
|
||||
else if ( val instanceof Character )
|
||||
putString(name, val.toString() );
|
||||
else if ( val instanceof String )
|
||||
putString(name, val.toString() );
|
||||
else if ( val instanceof ObjectId )
|
||||
putObjectId(name, (ObjectId)val );
|
||||
else if ( val instanceof BSONObject )
|
||||
putObject(name, (BSONObject)val );
|
||||
else if ( val instanceof Boolean )
|
||||
putBoolean(name, (Boolean)val );
|
||||
else if ( val instanceof Pattern )
|
||||
putPattern(name, (Pattern)val );
|
||||
else if ( val instanceof Map )
|
||||
putMap( name , (Map)val );
|
||||
else if ( val instanceof Iterable)
|
||||
putIterable( name , (Iterable)val );
|
||||
else if ( val instanceof byte[] )
|
||||
putBinary( name , (byte[])val );
|
||||
else if ( val instanceof Binary )
|
||||
putBinary( name , (Binary)val );
|
||||
else if ( val instanceof UUID )
|
||||
putUUID( name , (UUID)val );
|
||||
else if ( val.getClass().isArray() )
|
||||
putArray( name , val );
|
||||
|
||||
else if (val instanceof Symbol) {
|
||||
putSymbol(name, (Symbol) val);
|
||||
}
|
||||
else if (val instanceof BSONTimestamp) {
|
||||
putTimestamp( name , (BSONTimestamp)val );
|
||||
}
|
||||
else if (val instanceof CodeWScope) {
|
||||
putCodeWScope( name , (CodeWScope)val );
|
||||
}
|
||||
else if (val instanceof Code) {
|
||||
putCode( name , (Code)val );
|
||||
}
|
||||
else if (val instanceof DBRefBase) {
|
||||
BSONObject temp = new BasicBSONObject();
|
||||
temp.put("$ref", ((DBRefBase)val).getRef());
|
||||
temp.put("$id", ((DBRefBase)val).getId());
|
||||
putObject( name, temp );
|
||||
}
|
||||
else if ( val instanceof MinKey )
|
||||
putMinKey( name );
|
||||
else if ( val instanceof MaxKey )
|
||||
putMaxKey( name );
|
||||
else if ( putSpecial( name , val ) ){
|
||||
// no-op
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException( "can't serialize " + val.getClass() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void putArray( String name , Object array ) {
|
||||
_put( ARRAY , name );
|
||||
final int sizePos = _buf.getPosition();
|
||||
_buf.writeInt( 0 );
|
||||
|
||||
int size = Array.getLength(array);
|
||||
for ( int i = 0; i < size; i++ )
|
||||
_putObjectField( String.valueOf( i ) , Array.get( array, i ) );
|
||||
|
||||
_buf.write( EOO );
|
||||
_buf.writeInt( sizePos , _buf.getPosition() - sizePos );
|
||||
}
|
||||
|
||||
private void putIterable( String name , Iterable l ){
|
||||
_put( ARRAY , name );
|
||||
final int sizePos = _buf.getPosition();
|
||||
_buf.writeInt( 0 );
|
||||
|
||||
int i=0;
|
||||
for ( Object obj: l ) {
|
||||
_putObjectField( String.valueOf( i ) , obj );
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
_buf.write( EOO );
|
||||
_buf.writeInt( sizePos , _buf.getPosition() - sizePos );
|
||||
}
|
||||
|
||||
private void putMap( String name , Map m ){
|
||||
_put( OBJECT , name );
|
||||
final int sizePos = _buf.getPosition();
|
||||
_buf.writeInt( 0 );
|
||||
|
||||
for ( Map.Entry entry : (Set<Map.Entry>)m.entrySet() )
|
||||
_putObjectField( entry.getKey().toString() , entry.getValue() );
|
||||
|
||||
_buf.write( EOO );
|
||||
_buf.writeInt( sizePos , _buf.getPosition() - sizePos );
|
||||
}
|
||||
|
||||
|
||||
protected void putNull( String name ){
|
||||
_put( NULL , name );
|
||||
}
|
||||
|
||||
protected void putUndefined(String name){
|
||||
_put(UNDEFINED, name);
|
||||
}
|
||||
|
||||
protected void putTimestamp(String name, BSONTimestamp ts ){
|
||||
_put( TIMESTAMP , name );
|
||||
_buf.writeInt( ts.getInc() );
|
||||
_buf.writeInt( ts.getTime() );
|
||||
}
|
||||
|
||||
protected void putCodeWScope( String name , CodeWScope code ){
|
||||
_put( CODE_W_SCOPE , name );
|
||||
int temp = _buf.getPosition();
|
||||
_buf.writeInt( 0 );
|
||||
_putValueString( code.getCode() );
|
||||
putObject( code.getScope() );
|
||||
_buf.writeInt( temp , _buf.getPosition() - temp );
|
||||
}
|
||||
|
||||
protected void putCode( String name , Code code ){
|
||||
_put( CODE , name );
|
||||
int temp = _buf.getPosition();
|
||||
_putValueString( code.getCode() );
|
||||
}
|
||||
|
||||
protected void putBoolean( String name , Boolean b ){
|
||||
_put( BOOLEAN , name );
|
||||
_buf.write( b ? (byte)0x1 : (byte)0x0 );
|
||||
}
|
||||
|
||||
protected void putDate( String name , Date d ){
|
||||
_put( DATE , name );
|
||||
_buf.writeLong( d.getTime() );
|
||||
}
|
||||
|
||||
protected void putNumber( String name , Number n ){
|
||||
if ( n instanceof Integer ||
|
||||
n instanceof Short ||
|
||||
n instanceof Byte ||
|
||||
n instanceof AtomicInteger ){
|
||||
_put( NUMBER_INT , name );
|
||||
_buf.writeInt( n.intValue() );
|
||||
}
|
||||
else if ( n instanceof Long || n instanceof AtomicLong ) {
|
||||
_put( NUMBER_LONG , name );
|
||||
_buf.writeLong( n.longValue() );
|
||||
}
|
||||
else if ( n instanceof Float || n instanceof Double ) {
|
||||
_put( NUMBER , name );
|
||||
_buf.writeDouble( n.doubleValue() );
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException( "can't serialize " + n.getClass() );
|
||||
}
|
||||
}
|
||||
|
||||
protected void putBinary( String name , byte[] data ){
|
||||
putBinary( name, B_GENERAL, data );
|
||||
}
|
||||
|
||||
protected void putBinary( String name , Binary val ){
|
||||
putBinary( name, val.getType(), val.getData() );
|
||||
}
|
||||
|
||||
private void putBinary( String name , int type , byte[] data ){
|
||||
_put( BINARY , name );
|
||||
int totalLen = data.length;
|
||||
|
||||
if (type == B_BINARY)
|
||||
totalLen += 4;
|
||||
|
||||
_buf.writeInt( totalLen );
|
||||
_buf.write( type );
|
||||
if (type == B_BINARY)
|
||||
_buf.writeInt( totalLen -4 );
|
||||
int before = _buf.getPosition();
|
||||
_buf.write( data );
|
||||
int after = _buf.getPosition();
|
||||
}
|
||||
|
||||
protected void putUUID( String name , UUID val ){
|
||||
_put( BINARY , name );
|
||||
_buf.writeInt( 16 );
|
||||
_buf.write( B_UUID );
|
||||
_buf.writeLong( val.getMostSignificantBits());
|
||||
_buf.writeLong( val.getLeastSignificantBits());
|
||||
}
|
||||
|
||||
protected void putSymbol( String name , Symbol s ){
|
||||
_putString(name, s.getSymbol(), SYMBOL);
|
||||
}
|
||||
|
||||
protected void putString(String name, String s) {
|
||||
_putString(name, s, STRING);
|
||||
}
|
||||
|
||||
private void _putString( String name , String s, byte type ){
|
||||
_put( type , name );
|
||||
_putValueString( s );
|
||||
}
|
||||
|
||||
protected void putObjectId( String name , ObjectId oid ){
|
||||
_put( OID , name );
|
||||
// according to spec, values should be stored big endian
|
||||
_buf.writeIntBE( oid._time() );
|
||||
_buf.writeIntBE( oid._machine() );
|
||||
_buf.writeIntBE( oid._inc() );
|
||||
}
|
||||
|
||||
private void putPattern( String name, Pattern p ) {
|
||||
_put( REGEX , name );
|
||||
_buf.writeCString( p.pattern() );
|
||||
_buf.writeCString( regexFlags( p.flags() ) );
|
||||
}
|
||||
|
||||
private void putMinKey( String name ) {
|
||||
_put( MINKEY , name );
|
||||
}
|
||||
|
||||
private void putMaxKey( String name ) {
|
||||
_put( MAXKEY , name );
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
/**
|
||||
* Encodes the type and key.
|
||||
*
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
* Access buffer directly via {@link #getOutputBuffer()} if you need to change how BSON is written.
|
||||
*/
|
||||
@Deprecated
|
||||
protected void _put(byte type, String name) {
|
||||
_buf.write(type);
|
||||
_buf.writeCString(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
* Access buffer directly via {@link #getOutputBuffer()} if you need to change how BSON is written.
|
||||
* Otherwise override {@link #putString(String, String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
protected void _putValueString( String s ){
|
||||
_buf.writeString(s);
|
||||
}
|
||||
|
||||
void _reset( Buffer b ){
|
||||
b.position(0);
|
||||
b.limit(b.capacity());
|
||||
}
|
||||
|
||||
/**
|
||||
* puts as utf-8 string
|
||||
*
|
||||
* @deprecated Replaced by {@code getOutputBuffer().writeCString(String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
protected int _put( String str ){
|
||||
return _buf.writeCString(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes integer to underlying buffer.
|
||||
*
|
||||
* @param x the integer number
|
||||
* @deprecated Replaced by {@code getOutputBuffer().writeInt(int)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void writeInt( int x ){
|
||||
_buf.writeInt( x );
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes long to underlying buffer.
|
||||
*
|
||||
* @param x the long number
|
||||
* @deprecated Replaced by {@code getOutputBuffer().writeLong(long)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void writeLong( long x ){
|
||||
_buf.writeLong(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes C string (null-terminated string) to underlying buffer.
|
||||
*
|
||||
* @param s the string
|
||||
* @deprecated Replaced by {@code getOutputBuffer().writeCString(String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public void writeCString( String s ){
|
||||
_buf.writeCString(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Replaced by {@link #getOutputBuffer()}.
|
||||
*/
|
||||
@Deprecated
|
||||
protected OutputBuffer _buf;
|
||||
|
||||
}
|
@ -0,0 +1,399 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// BasicBSONObject.java
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson;
|
||||
|
||||
// BSON
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.types.BasicBSONList;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.util.JSONSerializers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
// Java
|
||||
|
||||
/**
|
||||
* A simple implementation of <code>DBObject</code>.
|
||||
* A <code>DBObject</code> can be created as follows, using this class:
|
||||
* <blockquote><pre>
|
||||
* DBObject obj = new BasicBSONObject();
|
||||
* obj.put( "foo", "bar" );
|
||||
* </pre></blockquote>
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "unused"})
|
||||
public class BasicBSONObject extends LinkedHashMap<String,Object> implements BSONObject {
|
||||
|
||||
private static final long serialVersionUID = -4415279469780082174L;
|
||||
|
||||
/**
|
||||
* Creates an empty object.
|
||||
*/
|
||||
public BasicBSONObject(){
|
||||
}
|
||||
|
||||
public BasicBSONObject(int size){
|
||||
super(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience CTOR
|
||||
* @param key key under which to store
|
||||
* @param value value to stor
|
||||
*/
|
||||
public BasicBSONObject(String key, Object value){
|
||||
put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DBObject from a map.
|
||||
* @param m map to convert
|
||||
*/
|
||||
public BasicBSONObject(Map m) {
|
||||
super(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a DBObject to a map.
|
||||
* @return the DBObject
|
||||
*/
|
||||
public Map toMap() {
|
||||
return new LinkedHashMap<String,Object>(this);
|
||||
}
|
||||
|
||||
/** Deletes a field from this object.
|
||||
* @param key the field name to remove
|
||||
* @return the object removed
|
||||
*/
|
||||
public Object removeField( String key ){
|
||||
return remove( key );
|
||||
}
|
||||
|
||||
/** Checks if this object contains a given field
|
||||
* @param field field name
|
||||
* @return if the field exists
|
||||
*/
|
||||
public boolean containsField( String field ){
|
||||
return super.containsKey(field);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean containsKey( String key ){
|
||||
return containsField(key);
|
||||
}
|
||||
|
||||
/** Gets a value from this object
|
||||
* @param key field name
|
||||
* @return the value
|
||||
*/
|
||||
public Object get( String key ){
|
||||
return super.get(key);
|
||||
}
|
||||
|
||||
/** Returns the value of a field as an <code>int</code>.
|
||||
* @param key the field to look for
|
||||
* @return the field value (or default)
|
||||
*/
|
||||
public int getInt( String key ){
|
||||
Object o = get(key);
|
||||
if ( o == null )
|
||||
throw new NullPointerException( "no value for: " + key );
|
||||
|
||||
return BSON.toInt(o);
|
||||
}
|
||||
|
||||
/** Returns the value of a field as an <code>int</code>.
|
||||
* @param key the field to look for
|
||||
* @param def the default to return
|
||||
* @return the field value (or default)
|
||||
*/
|
||||
public int getInt( String key , int def ){
|
||||
Object foo = get( key );
|
||||
if ( foo == null )
|
||||
return def;
|
||||
|
||||
return BSON.toInt(foo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a field as a <code>long</code>.
|
||||
*
|
||||
* @param key the field to return
|
||||
* @return the field value
|
||||
*/
|
||||
public long getLong( String key){
|
||||
Object foo = get( key );
|
||||
return ((Number)foo).longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a field as an <code>long</code>.
|
||||
* @param key the field to look for
|
||||
* @param def the default to return
|
||||
* @return the field value (or default)
|
||||
*/
|
||||
public long getLong( String key , long def ) {
|
||||
Object foo = get( key );
|
||||
if ( foo == null )
|
||||
return def;
|
||||
|
||||
return ((Number)foo).longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a field as a <code>double</code>.
|
||||
*
|
||||
* @param key the field to return
|
||||
* @return the field value
|
||||
*/
|
||||
public double getDouble( String key){
|
||||
Object foo = get( key );
|
||||
return ((Number)foo).doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a field as an <code>double</code>.
|
||||
* @param key the field to look for
|
||||
* @param def the default to return
|
||||
* @return the field value (or default)
|
||||
*/
|
||||
public double getDouble( String key , double def ) {
|
||||
Object foo = get( key );
|
||||
if ( foo == null )
|
||||
return def;
|
||||
|
||||
return ((Number)foo).doubleValue();
|
||||
}
|
||||
|
||||
/** Returns the value of a field as a string
|
||||
* @param key the field to look up
|
||||
* @return the value of the field, converted to a string
|
||||
*/
|
||||
public String getString( String key ){
|
||||
Object foo = get( key );
|
||||
if ( foo == null )
|
||||
return null;
|
||||
return foo.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a field as a string
|
||||
* @param key the field to look up
|
||||
* @param def the default to return
|
||||
* @return the value of the field, converted to a string
|
||||
*/
|
||||
public String getString( String key, final String def ) {
|
||||
Object foo = get( key );
|
||||
if ( foo == null )
|
||||
return def;
|
||||
|
||||
return foo.toString();
|
||||
}
|
||||
|
||||
/** Returns the value of a field as a boolean.
|
||||
* @param key the field to look up
|
||||
* @return the value of the field, or false if field does not exist
|
||||
*/
|
||||
public boolean getBoolean( String key ){
|
||||
return getBoolean(key, false);
|
||||
}
|
||||
|
||||
/** Returns the value of a field as a boolean
|
||||
* @param key the field to look up
|
||||
* @param def the default value in case the field is not found
|
||||
* @return the value of the field, converted to a string
|
||||
*/
|
||||
public boolean getBoolean( String key , boolean def ){
|
||||
Object foo = get( key );
|
||||
if ( foo == null )
|
||||
return def;
|
||||
if ( foo instanceof Number )
|
||||
return ((Number)foo).intValue() > 0;
|
||||
if ( foo instanceof Boolean )
|
||||
return ((Boolean)foo).booleanValue();
|
||||
throw new IllegalArgumentException( "can't coerce to bool:" + foo.getClass() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object id or null if not set.
|
||||
* @param field The field to return
|
||||
* @return The field object value or null if not found (or if null :-^).
|
||||
*/
|
||||
public ObjectId getObjectId( final String field ) {
|
||||
return (ObjectId) get( field );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object id or def if not set.
|
||||
* @param field The field to return
|
||||
* @param def the default value in case the field is not found
|
||||
* @return The field object value or def if not set.
|
||||
*/
|
||||
public ObjectId getObjectId( final String field, final ObjectId def ) {
|
||||
final Object foo = get( field );
|
||||
return (foo != null) ? (ObjectId)foo : def;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the date or null if not set.
|
||||
* @param field The field to return
|
||||
* @return The field object value or null if not found.
|
||||
*/
|
||||
public Date getDate( final String field ) {
|
||||
return (Date) get( field );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the date or def if not set.
|
||||
* @param field The field to return
|
||||
* @param def the default value in case the field is not found
|
||||
* @return The field object value or def if not set.
|
||||
*/
|
||||
public Date getDate( final String field, final Date def ) {
|
||||
final Object foo = get( field );
|
||||
return (foo != null) ? (Date)foo : def;
|
||||
}
|
||||
|
||||
/** Add a key/value pair to this object
|
||||
* @param key the field name
|
||||
* @param val the field value
|
||||
* @return the <code>val</code> parameter
|
||||
*/
|
||||
public Object put( String key , Object val ){
|
||||
return super.put( key , val );
|
||||
}
|
||||
|
||||
public void putAll( Map m ){
|
||||
for ( Map.Entry entry : (Set<Map.Entry>)m.entrySet() ){
|
||||
put( entry.getKey().toString() , entry.getValue() );
|
||||
}
|
||||
}
|
||||
|
||||
public void putAll( BSONObject o ){
|
||||
for ( String k : o.keySet() ){
|
||||
put( k , o.get( k ) );
|
||||
}
|
||||
}
|
||||
|
||||
/** Add a key/value pair to this object
|
||||
* @param key the field name
|
||||
* @param val the field value
|
||||
* @return <code>this</code>
|
||||
*/
|
||||
public BasicBSONObject append( String key , Object val ){
|
||||
put( key , val );
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Returns a JSON serialization of this object
|
||||
* @return JSON serialization
|
||||
*/
|
||||
public String toString(){
|
||||
return JSONSerializers.getStrict().serialize(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two documents according to their serialized form, ignoring the order of keys.
|
||||
*
|
||||
* @param o the document to compare to, which must be an instance of {@link com.massivecraft.massivecore.xlib.bson.BSONObject}.
|
||||
* @return true if the documents have the same serialized form, ignoring key order.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals( Object o ) {
|
||||
if (o == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! (o instanceof BSONObject)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BSONObject other = (BSONObject) o;
|
||||
|
||||
if (!keySet().equals(other.keySet())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Arrays.equals(canonicalizeBSONObject(this).encode(), canonicalizeBSONObject(other).encode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(canonicalizeBSONObject(this).encode());
|
||||
}
|
||||
|
||||
private byte[] encode() {
|
||||
return new BasicBSONEncoder().encode(this);
|
||||
}
|
||||
|
||||
private BSONObject decode(final byte[] encodedBytes) {
|
||||
return new BasicBSONDecoder().readObject(encodedBytes);
|
||||
}
|
||||
|
||||
// create a copy of "from", but with keys ordered alphabetically
|
||||
private static Object canonicalize(final Object from) {
|
||||
if (from instanceof BSONObject && !(from instanceof BasicBSONList)) {
|
||||
return canonicalizeBSONObject((BSONObject) from);
|
||||
} else if (from instanceof List) {
|
||||
return canonicalizeList((List<Object>) from);
|
||||
} else if (from instanceof Map) {
|
||||
return canonicalizeMap((Map<String, Object>) from);
|
||||
} else {
|
||||
return from;
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, Object> canonicalizeMap(final Map<String, Object> from) {
|
||||
Map<String, Object> canonicalized = new LinkedHashMap<String, Object>(from.size());
|
||||
TreeSet<String> keysInOrder = new TreeSet<String>(from.keySet());
|
||||
for (String key : keysInOrder) {
|
||||
Object val = from.get(key);
|
||||
canonicalized.put(key, canonicalize(val));
|
||||
}
|
||||
return canonicalized;
|
||||
}
|
||||
|
||||
private static BasicBSONObject canonicalizeBSONObject(final BSONObject from) {
|
||||
BasicBSONObject canonicalized = new BasicBSONObject();
|
||||
TreeSet<String> keysInOrder = new TreeSet<String>(from.keySet());
|
||||
for (String key : keysInOrder) {
|
||||
Object val = from.get(key);
|
||||
canonicalized.put(key, canonicalize(val));
|
||||
}
|
||||
return canonicalized;
|
||||
}
|
||||
|
||||
private static List canonicalizeList(final List<Object> list) {
|
||||
List<Object> canonicalized = new ArrayList<Object>(list.size());
|
||||
for (Object cur : list) {
|
||||
canonicalized.add(canonicalize(cur));
|
||||
}
|
||||
return canonicalized;
|
||||
}
|
||||
}
|
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.massivecore.xlib.bson;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
|
||||
|
||||
public class EmptyBSONCallback implements BSONCallback {
|
||||
|
||||
public void objectStart(){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void objectStart( String name ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void objectStart( boolean array ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public Object objectDone(){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public BSONCallback createBSONCallback(){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void arrayStart(){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void arrayStart( String name ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public Object arrayDone(){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void gotNull( String name ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void gotUndefined( String name ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void gotMinKey( String name ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void gotMaxKey( String name ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void gotBoolean( String name , boolean v ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void gotDouble( String name , double v ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void gotInt( String name , int v ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void gotLong( String name , long v ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void gotDate( String name , long millis ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void gotString( String name , String v ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void gotSymbol( String name , String v ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void gotRegex( String name , String pattern , String flags ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void gotTimestamp( String name , int time , int inc ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void gotObjectId( String name , ObjectId id ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void gotDBRef( String name , String ns , ObjectId id ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void gotBinaryArray( String name , byte[] data ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void gotUUID( String name , long part1 , long part2 ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void gotCode( String name , String code ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void gotCodeWScope( String name , String code , Object scope ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void reset(){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public Object get(){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void gotBinary( String name , byte type , byte[] data ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.massivecore.xlib.bson;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.io.BSONByteBuffer;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* @author brendan
|
||||
* @author scotthernandez
|
||||
*
|
||||
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public class KeyCachingLazyBSONObject extends LazyBSONObject {
|
||||
|
||||
public KeyCachingLazyBSONObject(byte[] data , LazyBSONCallback cbk) { super( data , cbk ); }
|
||||
public KeyCachingLazyBSONObject(byte[] data , int offset , LazyBSONCallback cbk) { super( data , offset , cbk ); }
|
||||
public KeyCachingLazyBSONObject( BSONByteBuffer buffer, LazyBSONCallback callback ){ super( buffer, callback ); }
|
||||
public KeyCachingLazyBSONObject( BSONByteBuffer buffer, int offset, LazyBSONCallback callback ){ super( buffer, offset, callback ); }
|
||||
|
||||
@Override
|
||||
public Object get( String key ) {
|
||||
ensureFieldList();
|
||||
return super.get( key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsField( String s ) {
|
||||
ensureFieldList();
|
||||
if (! fieldIndex.containsKey( s ) )
|
||||
return false;
|
||||
else
|
||||
return super.containsField( s );
|
||||
}
|
||||
|
||||
synchronized private void ensureFieldList() {
|
||||
//only run once
|
||||
if (fieldIndex == null) return;
|
||||
try {
|
||||
int offset = _doc_start_offset + FIRST_ELMT_OFFSET;
|
||||
|
||||
while ( !isElementEmpty( offset ) ){
|
||||
int fieldSize = sizeCString( offset );
|
||||
int elementSize = getElementBSONSize( offset++ );
|
||||
String name = _input.getCString( offset );
|
||||
ElementRecord _t_record = new ElementRecord( name, offset );
|
||||
fieldIndex.put( name, _t_record );
|
||||
offset += ( fieldSize + elementSize );
|
||||
}
|
||||
} catch (Exception e) {
|
||||
fieldIndex = new HashMap<String, ElementRecord>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private HashMap<String, ElementRecord> fieldIndex = new HashMap<String, ElementRecord>();
|
||||
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.massivecore.xlib.bson;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.LazyDBObject;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings({"rawtypes", "unused"})
|
||||
public class LazyBSONCallback extends EmptyBSONCallback {
|
||||
|
||||
public void objectStart(){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void objectStart( String name ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void objectStart( boolean array ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public Object objectDone(){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
public void reset(){
|
||||
_root = null;
|
||||
}
|
||||
|
||||
public Object get(){
|
||||
return _root;
|
||||
}
|
||||
|
||||
public void gotBinary( String name, byte type, byte[] data ){
|
||||
setRootObject( createObject( data, 0 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setRootObject( Object root ){
|
||||
_root = root;
|
||||
}
|
||||
|
||||
public Object createObject( byte[] data, int offset ){
|
||||
return new LazyDBObject( data, offset, this );
|
||||
}
|
||||
|
||||
public List createArray( byte[] data, int offset ){
|
||||
return new LazyBSONList( data, offset, this );
|
||||
}
|
||||
|
||||
public Object createDBRef( String ns, ObjectId id ){
|
||||
return new BasicBSONObject( "$ns", ns ).append( "$id", id );
|
||||
}
|
||||
|
||||
|
||||
/* public Object createObject(InputStream input, int offset) {
|
||||
try {
|
||||
return new LazyBSONObject(input, offset, this);
|
||||
}
|
||||
catch ( IOException e ) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}*/
|
||||
private Object _root;
|
||||
private static final Logger log = Logger.getLogger( "org.bson.LazyBSONCallback" );
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.massivecore.xlib.bson;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.io.Bits;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* implementation of BSONDecoder that creates LazyBSONObject instances
|
||||
*/
|
||||
public class LazyBSONDecoder implements BSONDecoder {
|
||||
static final Logger LOG = Logger.getLogger( LazyBSONDecoder.class.getName() );
|
||||
|
||||
public BSONObject readObject(byte[] b) {
|
||||
try {
|
||||
return readObject( new ByteArrayInputStream( b ) );
|
||||
}
|
||||
catch ( IOException ioe ){
|
||||
throw new BSONException( "should be impossible" , ioe );
|
||||
}
|
||||
}
|
||||
|
||||
public BSONObject readObject(InputStream in) throws IOException {
|
||||
BSONCallback c = new LazyBSONCallback();
|
||||
decode( in , c );
|
||||
return (BSONObject)c.get();
|
||||
}
|
||||
|
||||
public int decode(byte[] b, BSONCallback callback) {
|
||||
try {
|
||||
return decode( new ByteArrayInputStream( b ), callback );
|
||||
}
|
||||
catch ( IOException ioe ) {
|
||||
throw new BSONException( "should be impossible" , ioe );
|
||||
}
|
||||
}
|
||||
|
||||
public int decode(InputStream in, BSONCallback callback) throws IOException {
|
||||
byte[] objSizeBuffer = new byte[BYTES_IN_INTEGER];
|
||||
Bits.readFully(in, objSizeBuffer, 0, BYTES_IN_INTEGER);
|
||||
int objSize = Bits.readInt(objSizeBuffer);
|
||||
byte[] data = new byte[objSize];
|
||||
System.arraycopy(objSizeBuffer, 0, data, 0, BYTES_IN_INTEGER);
|
||||
|
||||
Bits.readFully(in, data, BYTES_IN_INTEGER, objSize - BYTES_IN_INTEGER);
|
||||
|
||||
// note that we are handing off ownership of the data byte array to the callback
|
||||
callback.gotBinary(null, (byte) 0, data);
|
||||
return objSize;
|
||||
}
|
||||
|
||||
private static int BYTES_IN_INTEGER = 4;
|
||||
}
|
@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.massivecore.xlib.bson;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.io.BSONByteBuffer;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
@SuppressWarnings({"rawtypes", "deprecation"})
|
||||
public class LazyBSONList extends LazyBSONObject implements List {
|
||||
|
||||
public LazyBSONList(byte[] data , LazyBSONCallback callback) { super( data , callback ); }
|
||||
public LazyBSONList(byte[] data , int offset , LazyBSONCallback callback) { super( data , offset , callback ); }
|
||||
public LazyBSONList(BSONByteBuffer buffer , LazyBSONCallback callback) { super( buffer , callback ); }
|
||||
public LazyBSONList(BSONByteBuffer buffer , int offset , LazyBSONCallback callback) { super( buffer , offset , callback ); }
|
||||
|
||||
@Override
|
||||
public boolean contains( Object arg0 ){
|
||||
return indexOf(arg0) > -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll( Collection arg0 ){
|
||||
for ( Object obj : arg0 ) {
|
||||
if ( !contains( obj ) )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get( int pos ){
|
||||
return get("" + pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator iterator(){
|
||||
return new LazyBSONListIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf( Object arg0 ){
|
||||
int pos = 0;
|
||||
Iterator it = iterator();
|
||||
while ( it.hasNext() ) {
|
||||
Object curr = it.next();
|
||||
if ( arg0.equals( curr ) )
|
||||
return pos;
|
||||
|
||||
pos++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lastIndexOf( Object arg0 ){
|
||||
int pos = 0;
|
||||
int lastFound = -1;
|
||||
|
||||
Iterator it = iterator();
|
||||
while(it.hasNext()) {
|
||||
Object curr = it.next();
|
||||
if(arg0.equals( curr ))
|
||||
lastFound = pos;
|
||||
|
||||
pos++;
|
||||
}
|
||||
|
||||
return lastFound;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size(){
|
||||
//TODO check the last one and get the key/field name to see the ordinal position in case the array is stored with missing elements.
|
||||
return getElements().size();
|
||||
}
|
||||
|
||||
public class LazyBSONListIterator implements Iterator {
|
||||
List<ElementRecord> elements;
|
||||
int pos=0;
|
||||
|
||||
public LazyBSONListIterator() {
|
||||
elements = getElements();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext(){
|
||||
return pos < elements.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object next(){
|
||||
return getElementValue(elements.get(pos++));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(){
|
||||
throw new UnsupportedOperationException( "Read Only" );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator listIterator( int arg0 ){
|
||||
throw new UnsupportedOperationException( "Not Supported" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator listIterator(){
|
||||
throw new UnsupportedOperationException( "Not Supported" );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean add( Object arg0 ){
|
||||
throw new UnsupportedOperationException( "Read Only" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add( int arg0 , Object arg1 ){
|
||||
throw new UnsupportedOperationException( "Read Only" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll( Collection arg0 ){
|
||||
throw new UnsupportedOperationException( "Read Only" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll( int arg0 , Collection arg1 ){
|
||||
throw new UnsupportedOperationException( "Read Only" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(){
|
||||
throw new UnsupportedOperationException( "Read Only" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove( Object arg0 ){
|
||||
throw new UnsupportedOperationException( "Read Only" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object remove( int arg0 ){
|
||||
throw new UnsupportedOperationException( "Read Only" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll( Collection arg0 ){
|
||||
throw new UnsupportedOperationException( "Read Only" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll( Collection arg0 ){
|
||||
throw new UnsupportedOperationException( "Read Only" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object set( int arg0 , Object arg1 ){
|
||||
throw new UnsupportedOperationException( "Read Only" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List subList( int arg0 , int arg1 ){
|
||||
throw new UnsupportedOperationException( "Not Supported" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray(){
|
||||
throw new UnsupportedOperationException( "Not Supported" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray( Object[] arg0 ){
|
||||
throw new UnsupportedOperationException( "Not Supported" );
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,744 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.massivecore.xlib.bson;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.io.BSONByteBuffer;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.BSONTimestamp;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.Code;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.CodeWScope;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.MaxKey;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.MinKey;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.Symbol;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author antoine
|
||||
* @author brendan
|
||||
* @author scotthernandez
|
||||
* @author Kilroy Wuz Here
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "unused"})
|
||||
public class LazyBSONObject implements BSONObject {
|
||||
|
||||
public LazyBSONObject( byte[] data, LazyBSONCallback callback ){
|
||||
this( BSONByteBuffer.wrap( data ), callback );
|
||||
}
|
||||
|
||||
public LazyBSONObject( byte[] data, int offset, LazyBSONCallback callback ){
|
||||
this( BSONByteBuffer.wrap( data, offset, data.length - offset ), offset, callback );
|
||||
}
|
||||
|
||||
public LazyBSONObject( BSONByteBuffer buffer, LazyBSONCallback callback ){
|
||||
this( buffer, 0, callback );
|
||||
}
|
||||
|
||||
public LazyBSONObject( BSONByteBuffer buffer, int offset, LazyBSONCallback callback ){
|
||||
_callback = callback;
|
||||
_input = buffer;
|
||||
_doc_start_offset = offset;
|
||||
}
|
||||
|
||||
|
||||
class ElementRecord {
|
||||
ElementRecord( final String name, final int offset ){
|
||||
this.name = name;
|
||||
this.offset = offset;
|
||||
this.type = getElementType( offset - 1 );
|
||||
this.fieldNameSize = sizeCString( offset );
|
||||
this.valueOffset = offset + fieldNameSize;
|
||||
}
|
||||
|
||||
final String name;
|
||||
/**
|
||||
* The offset the record begins at.
|
||||
*/
|
||||
final byte type;
|
||||
final int fieldNameSize;
|
||||
final int valueOffset;
|
||||
final int offset;
|
||||
}
|
||||
|
||||
class LazyBSONKeyIterator implements Iterator<String> {
|
||||
|
||||
public boolean hasNext(){
|
||||
return !isElementEmpty( offset );
|
||||
}
|
||||
|
||||
public String next(){
|
||||
int fieldSize = sizeCString( offset + 1);
|
||||
int elementSize = getElementBSONSize( offset );
|
||||
String key = _input.getCString( offset + 1);
|
||||
offset += fieldSize + elementSize + 1;
|
||||
return key;
|
||||
}
|
||||
|
||||
public void remove(){
|
||||
throw new UnsupportedOperationException( "Read only" );
|
||||
}
|
||||
|
||||
int offset = _doc_start_offset + FIRST_ELMT_OFFSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public class LazyBSONKeySet extends ReadOnlySet<String> {
|
||||
|
||||
/**
|
||||
* This method runs in time linear to the total size of all keys in the document.
|
||||
*
|
||||
* @return the number of keys in the document
|
||||
*/
|
||||
@Override
|
||||
public int size(){
|
||||
int size = 0;
|
||||
Iterator<String> iter = iterator();
|
||||
while(iter.hasNext()) {
|
||||
iter.next();
|
||||
++size;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty(){
|
||||
return LazyBSONObject.this.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains( Object o ){
|
||||
for ( String key : this ){
|
||||
if ( key.equals( o ) ){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<String> iterator(){
|
||||
return new LazyBSONKeyIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] toArray(){
|
||||
String[] a = new String[size()];
|
||||
return toArray(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T[] toArray(T[] a) {
|
||||
int size = size();
|
||||
|
||||
T[] localArray = a.length >= size ? a :
|
||||
(T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
|
||||
|
||||
int i = 0;
|
||||
for ( String key : this ){
|
||||
localArray[i++] = (T) key;
|
||||
}
|
||||
|
||||
if (localArray.length > i) {
|
||||
localArray[i] = null;
|
||||
}
|
||||
return localArray;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add( String e ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove( Object o ){
|
||||
throw new UnsupportedOperationException( "Not supported yet." );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll( Collection<?> collection ){
|
||||
for ( Object item : collection ){
|
||||
if ( !contains( item ) ){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class LazyBSONEntryIterator implements Iterator<Map.Entry<String, Object>> {
|
||||
|
||||
public boolean hasNext(){
|
||||
return !isElementEmpty( offset );
|
||||
}
|
||||
|
||||
public Map.Entry<String, Object> next(){
|
||||
int fieldSize = sizeCString(offset + 1);
|
||||
int elementSize = getElementBSONSize(offset);
|
||||
String key = _input.getCString(offset + 1);
|
||||
final ElementRecord nextElementRecord = new ElementRecord(key, ++offset);
|
||||
offset += fieldSize + elementSize;
|
||||
return new Map.Entry<String, Object>() {
|
||||
@Override
|
||||
public String getKey() {
|
||||
return nextElementRecord.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return getElementValue(nextElementRecord);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object setValue(Object value) {
|
||||
throw new UnsupportedOperationException("Read only");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Map.Entry))
|
||||
return false;
|
||||
Map.Entry e = (Map.Entry) o;
|
||||
return getKey().equals(e.getKey()) && getValue().equals(e.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getKey().hashCode() ^ getValue().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getKey() + "=" + getValue();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void remove(){
|
||||
throw new UnsupportedOperationException( "Read only" );
|
||||
}
|
||||
|
||||
int offset = _doc_start_offset + FIRST_ELMT_OFFSET;
|
||||
}
|
||||
|
||||
class LazyBSONEntrySet extends ReadOnlySet<Map.Entry<String, Object>> {
|
||||
@Override
|
||||
public int size() {
|
||||
return LazyBSONObject.this.keySet().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return LazyBSONObject.this.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
Iterator<Map.Entry<String, Object>> iter = iterator();
|
||||
while (iter.hasNext()) {
|
||||
if (iter.next().equals(o)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
for (Object cur : c) {
|
||||
if (!contains(cur)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Map.Entry<String, Object>> iterator() {
|
||||
return new LazyBSONEntryIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
Map.Entry[] array = new Map.Entry[size()];
|
||||
return toArray(array);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T[] toArray(T[] a) {
|
||||
int size = size();
|
||||
|
||||
T[] localArray = a.length >= size ? a :
|
||||
(T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
|
||||
|
||||
Iterator<Map.Entry<String, Object>> iter = iterator();
|
||||
int i = 0;
|
||||
while(iter.hasNext()) {
|
||||
localArray[i++] = (T) iter.next();
|
||||
}
|
||||
|
||||
if (localArray.length > i) {
|
||||
localArray[i] = null;
|
||||
}
|
||||
|
||||
return localArray;
|
||||
}
|
||||
}
|
||||
|
||||
// Base class that throws UnsupportedOperationException for any method that writes to the Set
|
||||
abstract class ReadOnlySet<E> implements Set<E> {
|
||||
|
||||
@Override
|
||||
public boolean add(E e) {
|
||||
throw new UnsupportedOperationException("Read-only Set");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
throw new UnsupportedOperationException("Read-only Set");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends E> c) {
|
||||
throw new UnsupportedOperationException("Read-only Set");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
throw new UnsupportedOperationException("Read-only Set");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
throw new UnsupportedOperationException("Read-only Set");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
throw new UnsupportedOperationException("Read-only Set");
|
||||
}
|
||||
}
|
||||
|
||||
public Object put( String key, Object v ){
|
||||
throw new UnsupportedOperationException( "Object is read only" );
|
||||
}
|
||||
|
||||
public void putAll( BSONObject o ){
|
||||
throw new UnsupportedOperationException( "Object is read only" );
|
||||
}
|
||||
|
||||
public void putAll( Map m ){
|
||||
throw new UnsupportedOperationException( "Object is read only" );
|
||||
}
|
||||
|
||||
public Object get( String key ){
|
||||
//get element up to the key
|
||||
ElementRecord element = getElement(key);
|
||||
|
||||
//no found if null/empty
|
||||
if (element == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return getElementValue(element);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the ElementRecord for the given key, or null if not found
|
||||
* @param key the field/key to find
|
||||
* @return ElementRecord for key, or null
|
||||
*/
|
||||
ElementRecord getElement(String key){
|
||||
int offset = _doc_start_offset + FIRST_ELMT_OFFSET;
|
||||
|
||||
while ( !isElementEmpty( offset ) ){
|
||||
int fieldSize = sizeCString( offset + 1 );
|
||||
int elementSize = getElementBSONSize( offset );
|
||||
String name = _input.getCString( ++offset);
|
||||
|
||||
if (name.equals(key)) {
|
||||
return new ElementRecord( name, offset );
|
||||
}
|
||||
offset += ( fieldSize + elementSize);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* returns all the ElementRecords in this document
|
||||
* @return list of ElementRecord
|
||||
*/
|
||||
List<ElementRecord> getElements(){
|
||||
int offset = _doc_start_offset + FIRST_ELMT_OFFSET;
|
||||
ArrayList<ElementRecord> elements = new ArrayList<LazyBSONObject.ElementRecord>();
|
||||
|
||||
while ( !isElementEmpty( offset ) ){
|
||||
int fieldSize = sizeCString( offset + 1 );
|
||||
int elementSize = getElementBSONSize( offset );
|
||||
String name = _input.getCString( ++offset );
|
||||
ElementRecord rec = new ElementRecord( name, offset );
|
||||
elements.add( rec );
|
||||
offset += ( fieldSize + elementSize );
|
||||
}
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
public Map toMap(){
|
||||
throw new UnsupportedOperationException( "Not Supported" );
|
||||
}
|
||||
|
||||
public Object removeField( String key ){
|
||||
throw new UnsupportedOperationException( "Object is read only" );
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean containsKey( String s ){
|
||||
return containsField( s );
|
||||
}
|
||||
|
||||
public boolean containsField( String s ){
|
||||
return keySet().contains( s );
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the set of all keys in the document
|
||||
*/
|
||||
public Set<String> keySet(){
|
||||
return new LazyBSONKeySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will be more efficient than using a combination of keySet() and get(String key)
|
||||
* @return the set of entries (key, value) in the document
|
||||
*/
|
||||
public Set<Map.Entry<String, Object>> entrySet(){
|
||||
return new LazyBSONEntrySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
protected boolean isElementEmpty( int offset ){
|
||||
return getElementType( offset ) == BSON.EOO;
|
||||
}
|
||||
|
||||
public boolean isEmpty(){
|
||||
return isElementEmpty( _doc_start_offset + FIRST_ELMT_OFFSET );
|
||||
}
|
||||
|
||||
private int getBSONSize( final int offset ){
|
||||
return _input.getInt( offset );
|
||||
}
|
||||
|
||||
public int getBSONSize(){
|
||||
return getBSONSize( _doc_start_offset );
|
||||
}
|
||||
|
||||
public int pipe(OutputStream os) throws IOException {
|
||||
os.write(_input.array(), _doc_start_offset, getBSONSize());
|
||||
return getBSONSize();
|
||||
}
|
||||
|
||||
private String getElementFieldName( final int offset ){
|
||||
return _input.getCString( offset );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
protected byte getElementType( final int offset ){
|
||||
return _input.get( offset );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
protected int getElementBSONSize( int offset ){
|
||||
int x = 0;
|
||||
byte type = getElementType( offset++ );
|
||||
int n = sizeCString( offset );
|
||||
int valueOffset = offset + n;
|
||||
switch ( type ){
|
||||
case BSON.EOO:
|
||||
case BSON.UNDEFINED:
|
||||
case BSON.NULL:
|
||||
case BSON.MAXKEY:
|
||||
case BSON.MINKEY:
|
||||
break;
|
||||
case BSON.BOOLEAN:
|
||||
x = 1;
|
||||
break;
|
||||
case BSON.NUMBER_INT:
|
||||
x = 4;
|
||||
break;
|
||||
case BSON.TIMESTAMP:
|
||||
case BSON.DATE:
|
||||
case BSON.NUMBER_LONG:
|
||||
case BSON.NUMBER:
|
||||
x = 8;
|
||||
break;
|
||||
case BSON.OID:
|
||||
x = 12;
|
||||
break;
|
||||
case BSON.SYMBOL:
|
||||
case BSON.CODE:
|
||||
case BSON.STRING:
|
||||
x = _input.getInt( valueOffset ) + 4;
|
||||
break;
|
||||
case BSON.CODE_W_SCOPE:
|
||||
x = _input.getInt( valueOffset );
|
||||
break;
|
||||
case BSON.REF:
|
||||
x = _input.getInt( valueOffset ) + 4 + 12;
|
||||
break;
|
||||
case BSON.OBJECT:
|
||||
case BSON.ARRAY:
|
||||
x = _input.getInt( valueOffset );
|
||||
break;
|
||||
case BSON.BINARY:
|
||||
x = _input.getInt( valueOffset ) + 4 + 1/*subtype*/;
|
||||
break;
|
||||
case BSON.REGEX:
|
||||
// 2 cstrs
|
||||
int part1 = sizeCString( valueOffset );
|
||||
int part2 = sizeCString( valueOffset + part1 );
|
||||
x = part1 + part2;
|
||||
break;
|
||||
default:
|
||||
throw new BSONException( "Invalid type " + type + " for field " + getElementFieldName( offset ) );
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the size of the BSON cstring at the given offset in the buffer
|
||||
* @param offset the offset into the buffer
|
||||
* @return the size of the BSON cstring, including the null terminator
|
||||
*
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
protected int sizeCString( int offset ){
|
||||
int end = offset;
|
||||
while ( true ){
|
||||
byte b = _input.get( end );
|
||||
if ( b == 0 )
|
||||
break;
|
||||
else
|
||||
end++;
|
||||
}
|
||||
return end - offset + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
protected Object getElementValue( ElementRecord record ){
|
||||
switch ( record.type ){
|
||||
case BSON.EOO:
|
||||
case BSON.UNDEFINED:
|
||||
case BSON.NULL:
|
||||
return null;
|
||||
case BSON.MAXKEY:
|
||||
return new MaxKey();
|
||||
case BSON.MINKEY:
|
||||
return new MinKey();
|
||||
case BSON.BOOLEAN:
|
||||
return ( _input.get( record.valueOffset ) != 0 );
|
||||
case BSON.NUMBER_INT:
|
||||
return _input.getInt( record.valueOffset );
|
||||
case BSON.TIMESTAMP:
|
||||
int inc = _input.getInt( record.valueOffset );
|
||||
int time = _input.getInt( record.valueOffset + 4 );
|
||||
return new BSONTimestamp( time, inc );
|
||||
case BSON.DATE:
|
||||
return new Date( _input.getLong( record.valueOffset ) );
|
||||
case BSON.NUMBER_LONG:
|
||||
return _input.getLong( record.valueOffset );
|
||||
case BSON.NUMBER:
|
||||
return Double.longBitsToDouble( _input.getLong( record.valueOffset ) );
|
||||
case BSON.OID:
|
||||
return new ObjectId( _input.getIntBE( record.valueOffset ),
|
||||
_input.getIntBE( record.valueOffset + 4 ),
|
||||
_input.getIntBE( record.valueOffset + 8 ) );
|
||||
case BSON.SYMBOL:
|
||||
return new Symbol( _input.getUTF8String( record.valueOffset ) );
|
||||
case BSON.CODE:
|
||||
return new Code( _input.getUTF8String( record.valueOffset ) );
|
||||
case BSON.STRING:
|
||||
return _input.getUTF8String( record.valueOffset );
|
||||
case BSON.CODE_W_SCOPE:
|
||||
int strsize = _input.getInt( record.valueOffset + 4 );
|
||||
String code = _input.getUTF8String( record.valueOffset + 4 );
|
||||
BSONObject scope =
|
||||
(BSONObject) _callback.createObject( _input.array(), record.valueOffset + 4 + 4 + strsize );
|
||||
return new CodeWScope( code, scope );
|
||||
case BSON.REF:
|
||||
int csize = _input.getInt( record.valueOffset );
|
||||
String ns = _input.getCString( record.valueOffset + 4 );
|
||||
int oidOffset = record.valueOffset + csize + 4;
|
||||
ObjectId oid = new ObjectId( _input.getIntBE( oidOffset ),
|
||||
_input.getIntBE( oidOffset + 4 ),
|
||||
_input.getIntBE( oidOffset + 8 ) );
|
||||
return _callback.createDBRef( ns, oid );
|
||||
case BSON.OBJECT:
|
||||
return _callback.createObject( _input.array(), record.valueOffset );
|
||||
case BSON.ARRAY:
|
||||
return _callback.createArray( _input.array(), record.valueOffset );
|
||||
case BSON.BINARY:
|
||||
return readBinary( record.valueOffset );
|
||||
case BSON.REGEX:
|
||||
int patternCStringSize = sizeCString( record.valueOffset );
|
||||
String pattern = _input.getCString( record.valueOffset );
|
||||
String flags = _input.getCString( record.valueOffset + patternCStringSize );
|
||||
return Pattern.compile( pattern, BSON.regexFlags( flags ) );
|
||||
default:
|
||||
throw new BSONException(
|
||||
"Invalid type " + record.type + " for field " + getElementFieldName( record.offset ) );
|
||||
}
|
||||
}
|
||||
|
||||
private Object readBinary( int valueOffset ){
|
||||
final int totalLen = _input.getInt( valueOffset );
|
||||
valueOffset += 4;
|
||||
final byte bType = _input.get( valueOffset );
|
||||
valueOffset += 1;
|
||||
|
||||
byte[] bin;
|
||||
switch ( bType ){
|
||||
case BSON.B_GENERAL:{
|
||||
bin = new byte[totalLen];
|
||||
for ( int n = 0; n < totalLen; n++ ){
|
||||
bin[n] = _input.get( valueOffset + n );
|
||||
}
|
||||
return bin;
|
||||
}
|
||||
case BSON.B_BINARY:
|
||||
final int len = _input.getInt( valueOffset );
|
||||
if ( len + 4 != totalLen )
|
||||
throw new IllegalArgumentException(
|
||||
"Bad Data Size; Binary Subtype 2. { actual len: " + len + " expected totalLen: " + totalLen
|
||||
+ "}" );
|
||||
valueOffset += 4;
|
||||
bin = new byte[len];
|
||||
for ( int n = 0; n < len; n++ ){
|
||||
bin[n] = _input.get( valueOffset + n );
|
||||
}
|
||||
return bin;
|
||||
case BSON.B_UUID:
|
||||
if ( totalLen != 16 )
|
||||
throw new IllegalArgumentException(
|
||||
"Bad Data Size; Binary Subtype 3 (UUID). { total length: " + totalLen + " != 16" );
|
||||
|
||||
long part1 = _input.getLong( valueOffset );
|
||||
valueOffset += 8;
|
||||
long part2 = _input.getLong( valueOffset );
|
||||
return new UUID( part1, part2 );
|
||||
}
|
||||
|
||||
bin = new byte[totalLen];
|
||||
for ( int n = 0; n < totalLen; n++ ){
|
||||
bin[n] = _input.get( valueOffset + n );
|
||||
}
|
||||
return bin;
|
||||
}
|
||||
|
||||
protected int getOffset(){
|
||||
return _doc_start_offset;
|
||||
}
|
||||
|
||||
protected byte[] getBytes() {
|
||||
return _input.array();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
LazyBSONObject that = (LazyBSONObject) o;
|
||||
|
||||
return Arrays.equals(this._input.array(), that._input.array());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(_input.array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a JSON serialization of this object
|
||||
*
|
||||
* @return JSON serialization
|
||||
*/
|
||||
public String toString(){
|
||||
return com.massivecraft.massivecore.xlib.mongodb.util.JSON.serialize( this );
|
||||
}
|
||||
|
||||
/**
|
||||
* In a "normal" (aka not embedded) doc, this will be the offset of the first element.
|
||||
*
|
||||
* In an embedded doc because we use ByteBuffers to avoid unecessary copying the offset must be manually set in
|
||||
* _doc_start_offset
|
||||
*/
|
||||
final static int FIRST_ELMT_OFFSET = 4;
|
||||
|
||||
/**
|
||||
* @deprecated Please use {@link #getOffset()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
protected final int _doc_start_offset;
|
||||
|
||||
/**
|
||||
* @deprecated Please use {@link #getBytes()} to access underlying bytes.
|
||||
*/
|
||||
@Deprecated
|
||||
protected final BSONByteBuffer _input; // TODO - Guard this with synchronicity?
|
||||
// callback is kept to create sub-objects on the fly
|
||||
|
||||
/**
|
||||
* @deprecated This field is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
protected final LazyBSONCallback _callback;
|
||||
private static final Logger log = Logger.getLogger( "org.bson.LazyBSONObject" );
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.massivecore.xlib.bson;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.io.BSONByteBuffer;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.DBObject;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.util.JSON;
|
||||
|
||||
/**
|
||||
* @author scotthernandez
|
||||
* @deprecated Please use {@link com.massivecraft.massivecore.xlib.mongodb.LazyDBList} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings({"unused"})
|
||||
public class LazyDBList extends LazyBSONList implements DBObject {
|
||||
private static final long serialVersionUID = -4415279469780082174L;
|
||||
|
||||
public LazyDBList(byte[] data, LazyBSONCallback callback) { super(data, callback); }
|
||||
public LazyDBList(byte[] data, int offset, LazyBSONCallback callback) { super(data, offset, callback); }
|
||||
public LazyDBList(BSONByteBuffer buffer, LazyBSONCallback callback) { super(buffer, callback); }
|
||||
public LazyDBList(BSONByteBuffer buffer, int offset, LazyBSONCallback callback) { super(buffer, offset, callback); }
|
||||
|
||||
/**
|
||||
* Returns a JSON serialization of this object
|
||||
* @return JSON serialization
|
||||
*/
|
||||
@Override
|
||||
public String toString(){
|
||||
return JSON.serialize( this );
|
||||
}
|
||||
|
||||
public boolean isPartialObject(){
|
||||
return _isPartialObject;
|
||||
}
|
||||
|
||||
public void markAsPartialObject(){
|
||||
_isPartialObject = true;
|
||||
}
|
||||
|
||||
private boolean _isPartialObject;
|
||||
}
|
@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.massivecore.xlib.bson;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.io.Bits;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.ARRAY;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.BINARY;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.BOOLEAN;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.B_BINARY;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.B_GENERAL;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.B_UUID;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.CODE;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.CODE_W_SCOPE;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.DATE;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.EOO;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.MAXKEY;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.MINKEY;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.NULL;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.NUMBER;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.NUMBER_INT;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.NUMBER_LONG;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.OBJECT;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.OID;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.REF;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.REGEX;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.STRING;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.SYMBOL;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.TIMESTAMP;
|
||||
import static com.massivecraft.massivecore.xlib.bson.BSON.UNDEFINED;
|
||||
|
||||
// Java
|
||||
|
||||
/**
|
||||
* A new implementation of the bson decoder.
|
||||
*
|
||||
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public class NewBSONDecoder implements BSONDecoder {
|
||||
|
||||
@Override
|
||||
public BSONObject readObject(final byte [] pData) {
|
||||
_length = pData.length;
|
||||
final BasicBSONCallback c = new BasicBSONCallback();
|
||||
decode(pData, c);
|
||||
return (BSONObject)c.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BSONObject readObject(final InputStream pIn) throws IOException {
|
||||
// Slurp in the data and convert to a byte array.
|
||||
_length = Bits.readInt(pIn);
|
||||
|
||||
if (_data == null || _data.length < _length) {
|
||||
_data = new byte[_length];
|
||||
}
|
||||
|
||||
(new DataInputStream(pIn)).readFully(_data, 4, (_length - 4));
|
||||
|
||||
return readObject(_data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int decode(final byte [] pData, final BSONCallback pCallback) {
|
||||
_data = pData;
|
||||
_pos = 4;
|
||||
_callback = pCallback;
|
||||
_decode();
|
||||
return _length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int decode(final InputStream pIn, final BSONCallback pCallback) throws IOException {
|
||||
_length = Bits.readInt(pIn);
|
||||
|
||||
if (_data == null || _data.length < _length) {
|
||||
_data = new byte[_length];
|
||||
}
|
||||
|
||||
(new DataInputStream(pIn)).readFully(_data, 4, (_length - 4));
|
||||
|
||||
return decode(_data, pCallback);
|
||||
}
|
||||
|
||||
private final void _decode() {
|
||||
_callback.objectStart();
|
||||
while (decodeElement());
|
||||
_callback.objectDone();
|
||||
}
|
||||
|
||||
private final String readCstr() {
|
||||
int length = 0;
|
||||
final int offset = _pos;
|
||||
|
||||
while (_data[_pos++] != 0) length++;
|
||||
|
||||
try {
|
||||
return new String(_data, offset, length, DEFAULT_ENCODING);
|
||||
} catch (final UnsupportedEncodingException uee) {
|
||||
return new String(_data, offset, length);
|
||||
}
|
||||
}
|
||||
|
||||
private final String readUtf8Str() {
|
||||
final int length = Bits.readInt(_data, _pos);
|
||||
_pos += 4;
|
||||
|
||||
if (length <= 0 || length > MAX_STRING) throw new BSONException("String invalid - corruption");
|
||||
|
||||
try {
|
||||
final String str = new String(_data, _pos, (length - 1), DEFAULT_ENCODING);
|
||||
_pos += length;
|
||||
return str;
|
||||
|
||||
} catch (final UnsupportedEncodingException uee) {
|
||||
throw new BSONException("What is in the db", uee);
|
||||
}
|
||||
}
|
||||
|
||||
private final Object _readBasicObject() {
|
||||
_pos += 4;
|
||||
|
||||
final BSONCallback save = _callback;
|
||||
final BSONCallback _basic = _callback.createBSONCallback();
|
||||
_callback = _basic;
|
||||
_basic.reset();
|
||||
_basic.objectStart(false);
|
||||
|
||||
while( decodeElement() );
|
||||
_callback = save;
|
||||
return _basic.get();
|
||||
}
|
||||
|
||||
private final void _binary(final String pName) {
|
||||
|
||||
final int totalLen = Bits.readInt(_data, _pos);
|
||||
_pos += 4;
|
||||
|
||||
final byte bType = _data[_pos];
|
||||
_pos += 1;
|
||||
|
||||
switch ( bType ){
|
||||
case B_GENERAL: {
|
||||
final byte [] data = new byte[totalLen];
|
||||
|
||||
System.arraycopy(_data, _pos, data, 0, totalLen);
|
||||
_pos += totalLen;
|
||||
|
||||
_callback.gotBinary(pName, bType, data);
|
||||
return;
|
||||
}
|
||||
|
||||
case B_BINARY: {
|
||||
final int len = Bits.readInt(_data, _pos);
|
||||
_pos += 4;
|
||||
|
||||
if ( len + 4 != totalLen )
|
||||
throw new IllegalArgumentException( "bad data size subtype 2 len: " + len + " totalLen: " + totalLen );
|
||||
|
||||
final byte [] data = new byte[len];
|
||||
System.arraycopy(_data, _pos, data, 0, len);
|
||||
_pos += len;
|
||||
_callback.gotBinary(pName, bType, data);
|
||||
return;
|
||||
}
|
||||
|
||||
case B_UUID: {
|
||||
if ( totalLen != 16 )
|
||||
throw new IllegalArgumentException( "bad data size subtype 3 len: " + totalLen + " != 16");
|
||||
|
||||
final long part1 = Bits.readLong(_data, _pos);
|
||||
_pos += 8;
|
||||
|
||||
final long part2 = Bits.readLong(_data, _pos);
|
||||
_pos += 8;
|
||||
|
||||
_callback.gotUUID(pName, part1, part2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final byte [] data = new byte[totalLen];
|
||||
System.arraycopy(_data, _pos, data, 0, totalLen);
|
||||
_pos += totalLen;
|
||||
|
||||
_callback.gotBinary(pName, bType, data);
|
||||
}
|
||||
|
||||
private final boolean decodeElement() {
|
||||
|
||||
final byte type = _data[_pos];
|
||||
_pos += 1;
|
||||
|
||||
if (type == EOO) return false;
|
||||
|
||||
final String name = readCstr();
|
||||
|
||||
switch (type) {
|
||||
case NULL: { _callback.gotNull(name); return true; }
|
||||
|
||||
case UNDEFINED: { _callback.gotUndefined(name); return true; }
|
||||
|
||||
case BOOLEAN: { _callback.gotBoolean(name, (_data[_pos] > 0)); _pos += 1; return true; }
|
||||
|
||||
case NUMBER: { _callback.gotDouble(name, Double.longBitsToDouble(Bits.readLong(_data, _pos))); _pos += 8; return true; }
|
||||
|
||||
case NUMBER_INT: { _callback.gotInt(name, Bits.readInt(_data, _pos)); _pos += 4; return true; }
|
||||
|
||||
case NUMBER_LONG: {
|
||||
_callback.gotLong(name, Bits.readLong(_data, _pos));
|
||||
_pos += 8;
|
||||
return true;
|
||||
}
|
||||
|
||||
case SYMBOL: { _callback.gotSymbol(name, readUtf8Str()); return true; }
|
||||
case STRING: { _callback.gotString(name, readUtf8Str()); return true; }
|
||||
|
||||
case OID: {
|
||||
// OID is stored as big endian
|
||||
|
||||
final int p1 = Bits.readIntBE(_data, _pos);
|
||||
_pos += 4;
|
||||
|
||||
final int p2 = Bits.readIntBE(_data, _pos);
|
||||
_pos += 4;
|
||||
|
||||
final int p3 = Bits.readIntBE(_data, _pos);
|
||||
_pos += 4;
|
||||
|
||||
_callback.gotObjectId(name , new ObjectId(p1, p2, p3));
|
||||
return true;
|
||||
}
|
||||
|
||||
case REF: {
|
||||
_pos += 4;
|
||||
|
||||
final String ns = readCstr();
|
||||
|
||||
final int p1 = Bits.readInt(_data, _pos);
|
||||
_pos += 4;
|
||||
|
||||
final int p2 = Bits.readInt(_data, _pos);
|
||||
_pos += 4;
|
||||
|
||||
final int p3 = Bits.readInt(_data, _pos);
|
||||
_pos += 4;
|
||||
|
||||
_callback.gotDBRef(name , ns, new ObjectId(p1, p2, p3));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case DATE: { _callback.gotDate(name , Bits.readLong(_data, _pos)); _pos += 8; return true; }
|
||||
|
||||
|
||||
case REGEX: {
|
||||
_callback.gotRegex(name, readCstr(), readCstr());
|
||||
return true;
|
||||
}
|
||||
|
||||
case BINARY: { _binary(name); return true; }
|
||||
|
||||
case CODE: { _callback.gotCode(name, readUtf8Str()); return true; }
|
||||
|
||||
case CODE_W_SCOPE: {
|
||||
_pos += 4;
|
||||
_callback.gotCodeWScope(name, readUtf8Str(), _readBasicObject());
|
||||
return true;
|
||||
}
|
||||
|
||||
case ARRAY:
|
||||
_pos += 4;
|
||||
_callback.arrayStart(name);
|
||||
while (decodeElement());
|
||||
_callback.arrayDone();
|
||||
return true;
|
||||
|
||||
case OBJECT:
|
||||
_pos += 4;
|
||||
_callback.objectStart(name);
|
||||
while (decodeElement());
|
||||
_callback.objectDone();
|
||||
return true;
|
||||
|
||||
case TIMESTAMP:
|
||||
int i = Bits.readInt(_data, _pos);
|
||||
_pos += 4;
|
||||
|
||||
int time = Bits.readInt(_data, _pos);
|
||||
_pos += 4;
|
||||
|
||||
_callback.gotTimestamp(name, time, i);
|
||||
return true;
|
||||
|
||||
case MINKEY: _callback.gotMinKey(name); return true;
|
||||
case MAXKEY: _callback.gotMaxKey(name); return true;
|
||||
|
||||
default: throw new UnsupportedOperationException( "BSONDecoder doesn't understand type : " + type + " name: " + name );
|
||||
}
|
||||
}
|
||||
|
||||
private static final int MAX_STRING = ( 32 * 1024 * 1024 );
|
||||
private static final String DEFAULT_ENCODING = "UTF-8";
|
||||
|
||||
private byte [] _data;
|
||||
private int _length;
|
||||
private int _pos = 0;
|
||||
private BSONCallback _callback;
|
||||
}
|
||||
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// Transformer.java
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson;
|
||||
|
||||
public interface Transformer {
|
||||
|
||||
/**
|
||||
* @return the new object. return passed in object if no change
|
||||
*/
|
||||
public Object transform( Object o );
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.massivecore.xlib.bson.io;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.BSONException;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
/**
|
||||
* Pseudo byte buffer, delegates as it is too hard to properly override / extend the ByteBuffer API
|
||||
*
|
||||
* @author brendan
|
||||
*/
|
||||
public class BSONByteBuffer {
|
||||
|
||||
private BSONByteBuffer( ByteBuffer buf ){
|
||||
this.buf = buf;
|
||||
buf.order( ByteOrder.LITTLE_ENDIAN );
|
||||
}
|
||||
|
||||
public static BSONByteBuffer wrap( byte[] bytes, int offset, int length ){
|
||||
return new BSONByteBuffer( ByteBuffer.wrap( bytes, offset, length ) );
|
||||
}
|
||||
|
||||
public static BSONByteBuffer wrap( byte[] bytes ){
|
||||
return new BSONByteBuffer( ByteBuffer.wrap( bytes ) );
|
||||
}
|
||||
|
||||
public byte get( int i ){
|
||||
return buf.get(i);
|
||||
}
|
||||
|
||||
public ByteBuffer get( byte[] bytes, int offset, int length ){
|
||||
return buf.get(bytes, offset, length);
|
||||
}
|
||||
|
||||
public ByteBuffer get( byte[] bytes ){
|
||||
return buf.get(bytes);
|
||||
}
|
||||
|
||||
public byte[] array(){
|
||||
return buf.array();
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public int hashCode(){
|
||||
return buf.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
BSONByteBuffer that = (BSONByteBuffer) o;
|
||||
|
||||
if (buf != null ? !buf.equals(that.buf) : that.buf != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Little Endian Integer
|
||||
*
|
||||
* @param i Index to read from
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getInt( int i ){
|
||||
return getIntLE( i );
|
||||
}
|
||||
|
||||
public int getIntLE( int i ){
|
||||
int x = 0;
|
||||
x |= ( 0xFF & buf.get( i + 0 ) ) << 0;
|
||||
x |= ( 0xFF & buf.get( i + 1 ) ) << 8;
|
||||
x |= ( 0xFF & buf.get( i + 2 ) ) << 16;
|
||||
x |= ( 0xFF & buf.get( i + 3 ) ) << 24;
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getIntBE( int i ){
|
||||
int x = 0;
|
||||
x |= ( 0xFF & buf.get( i + 0 ) ) << 24;
|
||||
x |= ( 0xFF & buf.get( i + 1 ) ) << 16;
|
||||
x |= ( 0xFF & buf.get( i + 2 ) ) << 8;
|
||||
x |= ( 0xFF & buf.get( i + 3 ) ) << 0;
|
||||
return x;
|
||||
}
|
||||
|
||||
public long getLong( int i ){
|
||||
return buf.getLong( i );
|
||||
}
|
||||
|
||||
public String getCString(int offset) {
|
||||
int end = offset;
|
||||
while (get(end) != 0) {
|
||||
++end;
|
||||
}
|
||||
int len = end - offset;
|
||||
return new String(array(), offset, len);
|
||||
}
|
||||
|
||||
public String getUTF8String(int valueOffset) {
|
||||
int size = getInt(valueOffset) - 1;
|
||||
try {
|
||||
return new String(array(), valueOffset + 4, size, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new BSONException( "Cannot decode string as UTF-8." );
|
||||
}
|
||||
}
|
||||
|
||||
public Buffer position( int i ){
|
||||
return buf.position(i);
|
||||
}
|
||||
|
||||
public Buffer reset(){
|
||||
return buf.reset();
|
||||
}
|
||||
|
||||
public int size(){
|
||||
return getInt( 0 );
|
||||
}
|
||||
|
||||
protected ByteBuffer buf;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.massivecore.xlib.bson.io;
|
||||
|
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// BasicOutputBuffer.java
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson.io;
|
||||
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
public class BasicOutputBuffer extends OutputBuffer {
|
||||
|
||||
@Override
|
||||
public void write(byte[] b){
|
||||
write( b , 0 , b.length );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len){
|
||||
_ensure( len );
|
||||
System.arraycopy( b , off , _buffer , _cur , len );
|
||||
_cur += len;
|
||||
_size = Math.max( _cur , _size );
|
||||
}
|
||||
@Override
|
||||
public void write(int b){
|
||||
_ensure(1);
|
||||
_buffer[_cur++] = (byte)(0xFF&b);
|
||||
_size = Math.max( _cur , _size );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPosition(){
|
||||
return _cur;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public void setPosition( int position ){
|
||||
_cur = position;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public void seekEnd(){
|
||||
_cur = _size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void seekStart(){
|
||||
_cur = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return size of data so far
|
||||
*/
|
||||
@Override
|
||||
public int size(){
|
||||
return _size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bytes written
|
||||
*/
|
||||
@Override
|
||||
public int pipe( OutputStream out )
|
||||
throws IOException {
|
||||
out.write( _buffer , 0 , _size );
|
||||
return _size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bytes written
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public int pipe( DataOutput out )
|
||||
throws IOException {
|
||||
out.write( _buffer , 0 , _size );
|
||||
return _size;
|
||||
}
|
||||
|
||||
|
||||
void _ensure( int more ){
|
||||
final int need = _cur + more;
|
||||
if ( need < _buffer.length )
|
||||
return;
|
||||
|
||||
int newSize = _buffer.length*2;
|
||||
if ( newSize <= need )
|
||||
newSize = need + 128;
|
||||
|
||||
byte[] n = new byte[newSize];
|
||||
System.arraycopy( _buffer , 0 , n , 0 , _size );
|
||||
_buffer = n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public String asString(){
|
||||
return new String( _buffer , 0 , _size );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public String asString( String encoding )
|
||||
throws UnsupportedEncodingException {
|
||||
return new String( _buffer , 0 , _size , encoding );
|
||||
}
|
||||
|
||||
|
||||
private int _cur;
|
||||
private int _size;
|
||||
private byte[] _buffer = new byte[512];
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// Bits.java
|
||||
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson.io;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class Bits {
|
||||
|
||||
public static void readFully( InputStream in, byte[] b )
|
||||
throws IOException {
|
||||
readFully( in , b , b.length );
|
||||
}
|
||||
|
||||
public static void readFully( InputStream in, byte[] b, int length )
|
||||
throws IOException {
|
||||
readFully(in, b, 0, length);
|
||||
}
|
||||
|
||||
public static void readFully( InputStream in, byte[] b, int startOffset, int length )
|
||||
throws IOException {
|
||||
|
||||
if (b.length < length + startOffset) {
|
||||
throw new IllegalArgumentException("Buffer is too small");
|
||||
}
|
||||
|
||||
int offset = startOffset;
|
||||
int toRead = length;
|
||||
while ( toRead > 0 ){
|
||||
int bytesRead = in.read( b, offset , toRead );
|
||||
if ( bytesRead < 0 )
|
||||
throw new EOFException();
|
||||
toRead -= bytesRead;
|
||||
offset += bytesRead;
|
||||
}
|
||||
}
|
||||
|
||||
public static int readInt( InputStream in )
|
||||
throws IOException {
|
||||
return readInt( in , new byte[4] );
|
||||
}
|
||||
|
||||
public static int readInt( InputStream in , byte[] data )
|
||||
throws IOException {
|
||||
readFully(in, data, 4);
|
||||
return readInt(data);
|
||||
}
|
||||
|
||||
public static int readInt( byte[] data ) {
|
||||
return readInt( data , 0 );
|
||||
}
|
||||
|
||||
public static int readInt( byte[] data , int offset ) {
|
||||
int x = 0;
|
||||
x |= ( 0xFF & data[offset+0] ) << 0;
|
||||
x |= ( 0xFF & data[offset+1] ) << 8;
|
||||
x |= ( 0xFF & data[offset+2] ) << 16;
|
||||
x |= ( 0xFF & data[offset+3] ) << 24;
|
||||
return x;
|
||||
}
|
||||
|
||||
public static int readIntBE( byte[] data , int offset ) {
|
||||
int x = 0;
|
||||
x |= ( 0xFF & data[offset+0] ) << 24;
|
||||
x |= ( 0xFF & data[offset+1] ) << 16;
|
||||
x |= ( 0xFF & data[offset+2] ) << 8;
|
||||
x |= ( 0xFF & data[offset+3] ) << 0;
|
||||
return x;
|
||||
}
|
||||
|
||||
public static long readLong( InputStream in )
|
||||
throws IOException {
|
||||
return readLong( in , new byte[8] );
|
||||
}
|
||||
|
||||
|
||||
public static long readLong( InputStream in , byte[] data )
|
||||
throws IOException {
|
||||
readFully(in, data, 8);
|
||||
return readLong(data);
|
||||
}
|
||||
|
||||
public static long readLong( byte[] data ) {
|
||||
return readLong( data , 0 );
|
||||
}
|
||||
|
||||
public static long readLong( byte[] data , int offset ) {
|
||||
long x = 0;
|
||||
x |= ( 0xFFL & data[offset+0] ) << 0;
|
||||
x |= ( 0xFFL & data[offset+1] ) << 8;
|
||||
x |= ( 0xFFL & data[offset+2] ) << 16;
|
||||
x |= ( 0xFFL & data[offset+3] ) << 24;
|
||||
x |= ( 0xFFL & data[offset+4] ) << 32;
|
||||
x |= ( 0xFFL & data[offset+5] ) << 40;
|
||||
x |= ( 0xFFL & data[offset+6] ) << 48;
|
||||
x |= ( 0xFFL & data[offset+7] ) << 56;
|
||||
return x;
|
||||
}
|
||||
}
|
@ -0,0 +1,291 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// OutputBuffer.java
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson.io;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.BSONException;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public abstract class OutputBuffer extends OutputStream {
|
||||
|
||||
public abstract void write(byte[] b);
|
||||
public abstract void write(byte[] b, int off, int len);
|
||||
public abstract void write(int b);
|
||||
|
||||
public abstract int getPosition();
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract void setPosition( int position );
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract void seekEnd();
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract void seekStart();
|
||||
|
||||
/**
|
||||
* @return size of data so far
|
||||
*/
|
||||
public abstract int size();
|
||||
|
||||
/**
|
||||
* @return bytes written
|
||||
*/
|
||||
public abstract int pipe( OutputStream out )
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* mostly for testing
|
||||
*/
|
||||
public byte [] toByteArray(){
|
||||
try {
|
||||
final ByteArrayOutputStream bout = new ByteArrayOutputStream( size() );
|
||||
pipe( bout );
|
||||
return bout.toByteArray();
|
||||
}
|
||||
catch ( IOException ioe ){
|
||||
throw new RuntimeException( "should be impossible" , ioe );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public String asString(){
|
||||
return new String( toByteArray() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public String asString( String encoding )
|
||||
throws UnsupportedEncodingException {
|
||||
return new String( toByteArray() , encoding );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public String hex(){
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
try {
|
||||
pipe( new OutputStream(){
|
||||
public void write( int b ){
|
||||
String s = Integer.toHexString(0xff & b);
|
||||
|
||||
if (s.length() < 2)
|
||||
buf.append("0");
|
||||
buf.append(s);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
catch ( IOException ioe ){
|
||||
throw new RuntimeException( "impossible" );
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public String md5(){
|
||||
final MessageDigest md5 ;
|
||||
try {
|
||||
md5 = MessageDigest.getInstance("MD5");
|
||||
}
|
||||
catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException("Error - this implementation of Java doesn't support MD5.");
|
||||
}
|
||||
md5.reset();
|
||||
|
||||
try {
|
||||
pipe( new OutputStream(){
|
||||
public void write( byte[] b , int off , int len ){
|
||||
md5.update( b , off , len );
|
||||
}
|
||||
|
||||
public void write( int b ){
|
||||
md5.update( (byte)(b&0xFF) );
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
catch ( IOException ioe ){
|
||||
throw new RuntimeException( "impossible" );
|
||||
}
|
||||
|
||||
return com.massivecraft.massivecore.xlib.mongodb.util.Util.toHex( md5.digest() );
|
||||
}
|
||||
|
||||
public void writeInt( int x ){
|
||||
write( x >> 0 );
|
||||
write( x >> 8 );
|
||||
write( x >> 16 );
|
||||
write( x >> 24 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public void writeIntBE( int x ){
|
||||
write( x >> 24 );
|
||||
write(x >> 16);
|
||||
write(x >> 8);
|
||||
write(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public void writeInt( int pos , int x ){
|
||||
final int save = getPosition();
|
||||
setPosition(pos);
|
||||
writeInt(x);
|
||||
setPosition(save);
|
||||
}
|
||||
|
||||
public void writeLong( long x ){
|
||||
write( (byte)(0xFFL & ( x >> 0 ) ) );
|
||||
write( (byte)(0xFFL & ( x >> 8 ) ) );
|
||||
write( (byte)(0xFFL & ( x >> 16 ) ) );
|
||||
write( (byte)(0xFFL & ( x >> 24 ) ) );
|
||||
write( (byte)(0xFFL & ( x >> 32 ) ) );
|
||||
write( (byte)(0xFFL & ( x >> 40 ) ) );
|
||||
write( (byte)(0xFFL & ( x >> 48 ) ) );
|
||||
write((byte) (0xFFL & (x >> 56)));
|
||||
}
|
||||
|
||||
public void writeDouble( double x ){
|
||||
writeLong(Double.doubleToRawLongBits(x));
|
||||
}
|
||||
|
||||
public void writeString(final String str) {
|
||||
writeInt(0); // making space for size
|
||||
final int strLen = writeCString(str, false);
|
||||
backpatchSize(strLen, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes C string (null-terminated string) to underlying buffer.
|
||||
*
|
||||
* @param str the string
|
||||
* @return number of bytes written
|
||||
*/
|
||||
public int writeCString(final String str) {
|
||||
return writeCString(str, true);
|
||||
|
||||
}
|
||||
|
||||
private int writeCString(final String str, final boolean checkForNullCharacters) {
|
||||
|
||||
final int len = str.length();
|
||||
int total = 0;
|
||||
|
||||
for (int i = 0; i < len;/*i gets incremented*/) {
|
||||
final int c = Character.codePointAt(str, i);
|
||||
|
||||
if (checkForNullCharacters && c == 0x0) {
|
||||
throw new BSONException(
|
||||
String.format("BSON cstring '%s' is not valid because it contains a null character at index %d", str, i));
|
||||
}
|
||||
if (c < 0x80) {
|
||||
write((byte) c);
|
||||
total += 1;
|
||||
} else if (c < 0x800) {
|
||||
write((byte) (0xc0 + (c >> 6)));
|
||||
write((byte) (0x80 + (c & 0x3f)));
|
||||
total += 2;
|
||||
} else if (c < 0x10000) {
|
||||
write((byte) (0xe0 + (c >> 12)));
|
||||
write((byte) (0x80 + ((c >> 6) & 0x3f)));
|
||||
write((byte) (0x80 + (c & 0x3f)));
|
||||
total += 3;
|
||||
} else {
|
||||
write((byte) (0xf0 + (c >> 18)));
|
||||
write((byte) (0x80 + ((c >> 12) & 0x3f)));
|
||||
write((byte) (0x80 + ((c >> 6) & 0x3f)));
|
||||
write((byte) (0x80 + (c & 0x3f)));
|
||||
total += 4;
|
||||
}
|
||||
|
||||
i += Character.charCount(c);
|
||||
}
|
||||
|
||||
write((byte) 0);
|
||||
total++;
|
||||
return total;
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
return getClass().getName() + " size: " + size() + " pos: " + getPosition() ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Backpatches the size of a document or string by writing the size into the four bytes starting at getPosition() -
|
||||
* size.
|
||||
*
|
||||
* @param size the size of the document/string
|
||||
*/
|
||||
public void backpatchSize(final int size) {
|
||||
writeInt(getPosition() - size, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Backpatches the size of a document or string by writing the size into the four bytes starting at {@code getPosition() - size -
|
||||
* additionalOffset}.
|
||||
*
|
||||
* @param size the size of the document/string
|
||||
* @param additionalOffset the offset from the current position to write the size
|
||||
*/
|
||||
protected void backpatchSize(final int size, final int additionalOffset) {
|
||||
writeInt(getPosition() - size - additionalOffset, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncates the buffer to the given new position, which must be greater than or equal to zero and less than or equal to the current
|
||||
* size of this buffer.
|
||||
*
|
||||
* @param newPosition the position to truncate this buffer to
|
||||
*/
|
||||
public void truncateToPosition(int newPosition) {
|
||||
setPosition(newPosition);
|
||||
}
|
||||
}
|
@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// PoolOutputBuffer.java
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public class PoolOutputBuffer extends OutputBuffer {
|
||||
|
||||
public static final int BUF_SIZE = 1024 * 16;
|
||||
|
||||
public PoolOutputBuffer(){
|
||||
reset();
|
||||
}
|
||||
|
||||
public void reset(){
|
||||
_cur.reset();
|
||||
_end.reset();
|
||||
|
||||
for ( int i=0; i<_fromPool.size(); i++ )
|
||||
_extra.done( _fromPool.get(i) );
|
||||
_fromPool.clear();
|
||||
}
|
||||
|
||||
public int getPosition(){
|
||||
return _cur.pos();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setPosition( int position ){
|
||||
_cur.reset( position );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public void seekEnd(){
|
||||
_cur.reset( _end );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public void seekStart(){
|
||||
_cur.reset();
|
||||
}
|
||||
|
||||
|
||||
public int size(){
|
||||
return _end.pos();
|
||||
}
|
||||
|
||||
public void write(byte[] b){
|
||||
write( b , 0 , b.length );
|
||||
}
|
||||
|
||||
public void write(byte[] b, int off, int len){
|
||||
while ( len > 0 ){
|
||||
byte[] bs = _cur();
|
||||
int space = Math.min( bs.length - _cur.y , len );
|
||||
System.arraycopy( b , off , bs , _cur.y , space );
|
||||
_cur.inc( space );
|
||||
len -= space;
|
||||
off += space;
|
||||
_afterWrite();
|
||||
}
|
||||
}
|
||||
|
||||
public void write(int b){
|
||||
byte[] bs = _cur();
|
||||
bs[_cur.getAndInc()] = (byte)(b&0xFF);
|
||||
_afterWrite();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void truncateToPosition(final int newPosition) {
|
||||
setPosition(newPosition);
|
||||
_end.reset(_cur);
|
||||
}
|
||||
|
||||
void _afterWrite(){
|
||||
|
||||
if ( _cur.pos() < _end.pos() ){
|
||||
// we're in the middle of the total space
|
||||
// just need to make sure we're not at the end of a buffer
|
||||
if ( _cur.y == BUF_SIZE )
|
||||
_cur.nextBuffer();
|
||||
return;
|
||||
}
|
||||
|
||||
_end.reset( _cur );
|
||||
|
||||
if ( _end.y < BUF_SIZE )
|
||||
return;
|
||||
|
||||
_fromPool.add( _extra.get() );
|
||||
_end.nextBuffer();
|
||||
_cur.reset( _end );
|
||||
}
|
||||
|
||||
byte[] _cur(){
|
||||
return _get( _cur.x );
|
||||
}
|
||||
|
||||
byte[] _get( int z ){
|
||||
if ( z < 0 )
|
||||
return _mine;
|
||||
return _fromPool.get(z);
|
||||
}
|
||||
|
||||
public int pipe( final OutputStream out )
|
||||
throws IOException {
|
||||
|
||||
if ( out == null )
|
||||
throw new NullPointerException( "out is null" );
|
||||
|
||||
int total = 0;
|
||||
|
||||
for ( int i=-1; i<_fromPool.size(); i++ ){
|
||||
final byte[] b = _get( i );
|
||||
final int amt = _end.len( i );
|
||||
if (amt == 0) {
|
||||
break;
|
||||
}
|
||||
out.write( b , 0 , amt );
|
||||
total += amt;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
static class Position {
|
||||
Position(){
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset(){
|
||||
x = -1;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
void reset( Position other ){
|
||||
x = other.x;
|
||||
y = other.y;
|
||||
}
|
||||
|
||||
void reset( int pos ){
|
||||
x = ( pos / BUF_SIZE ) - 1;
|
||||
y = pos % BUF_SIZE;
|
||||
}
|
||||
|
||||
int pos(){
|
||||
return ( ( x + 1 ) * BUF_SIZE ) + y;
|
||||
}
|
||||
|
||||
int getAndInc(){
|
||||
return y++;
|
||||
}
|
||||
|
||||
void inc( int amt ){
|
||||
y += amt;
|
||||
if ( y > BUF_SIZE )
|
||||
throw new IllegalArgumentException( "something is wrong" );
|
||||
}
|
||||
|
||||
void nextBuffer(){
|
||||
if ( y != BUF_SIZE )
|
||||
throw new IllegalArgumentException( "broken" );
|
||||
x++;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
int len( int which ){
|
||||
if ( which < x )
|
||||
return BUF_SIZE;
|
||||
else if (which == x)
|
||||
return y;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
return x + "," + y;
|
||||
}
|
||||
|
||||
int x; // which buffer -1 == _mine
|
||||
int y; // position in buffer
|
||||
}
|
||||
|
||||
public String asAscii(){
|
||||
if ( _fromPool.size() > 0 )
|
||||
return super.asString();
|
||||
|
||||
final int m = size();
|
||||
final char c[] = m < _chars.length ? _chars : new char[m];
|
||||
|
||||
for ( int i=0; i<m; i++ )
|
||||
c[i] = (char)_mine[i];
|
||||
|
||||
return new String( c , 0 , m );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public String asString( String encoding )
|
||||
throws UnsupportedEncodingException {
|
||||
|
||||
|
||||
if ( _fromPool.size() > 0 )
|
||||
return super.asString( encoding );
|
||||
|
||||
if ( encoding.equals( DEFAULT_ENCODING_1 ) || encoding.equals( DEFAULT_ENCODING_2) ){
|
||||
try {
|
||||
return _encoding.decode( _mine , 0 , size() );
|
||||
}
|
||||
catch ( IOException ioe ){
|
||||
// we failed, fall back
|
||||
}
|
||||
}
|
||||
return new String( _mine , 0 , size() , encoding );
|
||||
}
|
||||
|
||||
final byte[] _mine = new byte[BUF_SIZE];
|
||||
final char[] _chars = new char[BUF_SIZE];
|
||||
final List<byte[]> _fromPool = new ArrayList<byte[]>();
|
||||
final UTF8Encoding _encoding = new UTF8Encoding();
|
||||
|
||||
private static final String DEFAULT_ENCODING_1 = "UTF-8";
|
||||
private static final String DEFAULT_ENCODING_2 = "UTF8";
|
||||
|
||||
private final Position _cur = new Position();
|
||||
private final Position _end = new Position();
|
||||
|
||||
private static com.massivecraft.massivecore.xlib.bson.util.SimplePool<byte[]> _extra =
|
||||
new com.massivecraft.massivecore.xlib.bson.util.SimplePool<byte[]>( ( 1024 * 1024 * 10 ) / BUF_SIZE ){
|
||||
|
||||
protected byte[] createNew(){
|
||||
return new byte[BUF_SIZE];
|
||||
}
|
||||
|
||||
};
|
||||
}
|
@ -0,0 +1,201 @@
|
||||
// UTF8Encoding.java
|
||||
|
||||
/**
|
||||
* from postgresql jdbc driver:
|
||||
* postgresql-jdbc-9.0-801.src
|
||||
|
||||
|
||||
Copyright (c) 1997-2008, PostgreSQL Global Development Group
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the PostgreSQL Global Development Group nor the names
|
||||
of its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2003-2008, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
*
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
//package org.postgresql.core;
|
||||
package com.massivecraft.massivecore.xlib.bson.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
class UTF8Encoding {
|
||||
|
||||
private static final int MIN_2_BYTES = 0x80;
|
||||
private static final int MIN_3_BYTES = 0x800;
|
||||
private static final int MIN_4_BYTES = 0x10000;
|
||||
private static final int MAX_CODE_POINT = 0x10ffff;
|
||||
|
||||
private char[] decoderArray = new char[1024];
|
||||
|
||||
// helper for decode
|
||||
private final static void checkByte(int ch, int pos, int len) throws IOException {
|
||||
if ((ch & 0xc0) != 0x80)
|
||||
throw new IOException(MessageFormat.format("Illegal UTF-8 sequence: byte {0} of {1} byte sequence is not 10xxxxxx: {2}",
|
||||
new Object[] { new Integer(pos), new Integer(len), new Integer(ch) }));
|
||||
}
|
||||
|
||||
private final static void checkMinimal(int ch, int minValue) throws IOException {
|
||||
if (ch >= minValue)
|
||||
return;
|
||||
|
||||
int actualLen;
|
||||
switch (minValue) {
|
||||
case MIN_2_BYTES:
|
||||
actualLen = 2;
|
||||
break;
|
||||
case MIN_3_BYTES:
|
||||
actualLen = 3;
|
||||
break;
|
||||
case MIN_4_BYTES:
|
||||
actualLen = 4;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("unexpected minValue passed to checkMinimal: " + minValue);
|
||||
}
|
||||
|
||||
int expectedLen;
|
||||
if (ch < MIN_2_BYTES)
|
||||
expectedLen = 1;
|
||||
else if (ch < MIN_3_BYTES)
|
||||
expectedLen = 2;
|
||||
else if (ch < MIN_4_BYTES)
|
||||
expectedLen = 3;
|
||||
else
|
||||
throw new IllegalArgumentException("unexpected ch passed to checkMinimal: " + ch);
|
||||
|
||||
throw new IOException(MessageFormat.format("Illegal UTF-8 sequence: {0} bytes used to encode a {1} byte value: {2}",
|
||||
new Object[] { new Integer(actualLen), new Integer(expectedLen), new Integer(ch) }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom byte[] -> String conversion routine for UTF-8 only.
|
||||
* This is about twice as fast as using the String(byte[],int,int,String)
|
||||
* ctor, at least under JDK 1.4.2. The extra checks for illegal representations
|
||||
* add about 10-15% overhead, but they seem worth it given the number of SQL_ASCII
|
||||
* databases out there.
|
||||
*
|
||||
* @param data the array containing UTF8-encoded data
|
||||
* @param offset the offset of the first byte in <code>data</code> to decode from
|
||||
* @param length the number of bytes to decode
|
||||
* @return a decoded string
|
||||
* @throws IOException if something goes wrong
|
||||
*/
|
||||
public synchronized String decode(byte[] data, int offset, int length) throws IOException {
|
||||
char[] cdata = decoderArray;
|
||||
if (cdata.length < length)
|
||||
cdata = decoderArray = new char[length];
|
||||
|
||||
int in = offset;
|
||||
int out = 0;
|
||||
int end = length + offset;
|
||||
|
||||
try
|
||||
{
|
||||
while (in < end)
|
||||
{
|
||||
int ch = data[in++] & 0xff;
|
||||
|
||||
// Convert UTF-8 to 21-bit codepoint.
|
||||
if (ch < 0x80) {
|
||||
// 0xxxxxxx -- length 1.
|
||||
} else if (ch < 0xc0) {
|
||||
// 10xxxxxx -- illegal!
|
||||
throw new IOException(MessageFormat.format("Illegal UTF-8 sequence: initial byte is {0}: {1}",
|
||||
new Object[] { "10xxxxxx", new Integer(ch) }));
|
||||
} else if (ch < 0xe0) {
|
||||
// 110xxxxx 10xxxxxx
|
||||
ch = ((ch & 0x1f) << 6);
|
||||
checkByte(data[in], 2, 2);
|
||||
ch = ch | (data[in++] & 0x3f);
|
||||
checkMinimal(ch, MIN_2_BYTES);
|
||||
} else if (ch < 0xf0) {
|
||||
// 1110xxxx 10xxxxxx 10xxxxxx
|
||||
ch = ((ch & 0x0f) << 12);
|
||||
checkByte(data[in], 2, 3);
|
||||
ch = ch | ((data[in++] & 0x3f) << 6);
|
||||
checkByte(data[in], 3, 3);
|
||||
ch = ch | (data[in++] & 0x3f);
|
||||
checkMinimal(ch, MIN_3_BYTES);
|
||||
} else if (ch < 0xf8) {
|
||||
// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
ch = ((ch & 0x07) << 18);
|
||||
checkByte(data[in], 2, 4);
|
||||
ch = ch | ((data[in++] & 0x3f) << 12);
|
||||
checkByte(data[in], 3, 4);
|
||||
ch = ch | ((data[in++] & 0x3f) << 6);
|
||||
checkByte(data[in], 4, 4);
|
||||
ch = ch | (data[in++] & 0x3f);
|
||||
checkMinimal(ch, MIN_4_BYTES);
|
||||
} else {
|
||||
throw new IOException(MessageFormat.format("Illegal UTF-8 sequence: initial byte is {0}: {1}",
|
||||
new Object[] { "11111xxx", new Integer(ch) }));
|
||||
}
|
||||
|
||||
if (ch > MAX_CODE_POINT)
|
||||
throw new IOException(MessageFormat.format("Illegal UTF-8 sequence: final value is out of range: {0}",
|
||||
new Integer(ch)));
|
||||
|
||||
// Convert 21-bit codepoint to Java chars:
|
||||
// 0..ffff are represented directly as a single char
|
||||
// 10000..10ffff are represented as a "surrogate pair" of two chars
|
||||
// See: http://java.sun.com/developer/technicalArticles/Intl/Supplementary/
|
||||
|
||||
if (ch > 0xffff) {
|
||||
// Use a surrogate pair to represent it.
|
||||
ch -= 0x10000; // ch is now 0..fffff (20 bits)
|
||||
cdata[out++] = (char) (0xd800 + (ch >> 10)); // top 10 bits
|
||||
cdata[out++] = (char) (0xdc00 + (ch & 0x3ff)); // bottom 10 bits
|
||||
} else if (ch >= 0xd800 && ch < 0xe000) {
|
||||
// Not allowed to encode the surrogate range directly.
|
||||
throw new IOException(MessageFormat.format("Illegal UTF-8 sequence: final value is a surrogate value: {0}",
|
||||
new Integer(ch)));
|
||||
} else {
|
||||
// Normal case.
|
||||
cdata[out++] = (char) ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ArrayIndexOutOfBoundsException a)
|
||||
{
|
||||
throw new IOException("Illegal UTF-8 sequence: multibyte sequence was truncated");
|
||||
}
|
||||
|
||||
// Check if we ran past the end without seeing an exception.
|
||||
if (in > end)
|
||||
throw new IOException("Illegal UTF-8 sequence: multibyte sequence was truncated");
|
||||
|
||||
return new String(cdata, 0, out);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<!--
|
||||
~ Copyright (c) 2008-2014 MongoDB, 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.
|
||||
-->
|
||||
<body>
|
||||
<p>Contains classes implementing I/O operations used by BSON objects.</p>
|
||||
</body>
|
@ -0,0 +1,18 @@
|
||||
<!--
|
||||
~ Copyright (c) 2008-2014 MongoDB, 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.
|
||||
-->
|
||||
<body>
|
||||
<p>Contains the base BSON classes and Encoder/Decoder.</p>
|
||||
</body>
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// BSONTimestamp.java
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson.types;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* this is used for internal increment values.
|
||||
* for storing normal dates in MongoDB, you should use java.util.Date
|
||||
* <b>time</b> is seconds since epoch
|
||||
* <b>inc<b> is an ordinal
|
||||
*/
|
||||
public class BSONTimestamp implements Comparable<BSONTimestamp>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = -3268482672267936464L;
|
||||
|
||||
static final boolean D = Boolean.getBoolean( "DEBUG.DBTIMESTAMP" );
|
||||
|
||||
public BSONTimestamp(){
|
||||
_inc = 0;
|
||||
_time = null;
|
||||
}
|
||||
|
||||
public BSONTimestamp(int time, int inc ){
|
||||
_time = new Date( time * 1000L );
|
||||
_inc = inc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return get time in seconds since epoch
|
||||
*/
|
||||
public int getTime(){
|
||||
if ( _time == null )
|
||||
return 0;
|
||||
return (int)(_time.getTime() / 1000);
|
||||
}
|
||||
|
||||
public int getInc(){
|
||||
return _inc;
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
return "TS time:" + _time + " inc:" + _inc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(BSONTimestamp ts) {
|
||||
if(getTime() != ts.getTime()) {
|
||||
return getTime() - ts.getTime();
|
||||
}
|
||||
else{
|
||||
return getInc() - ts.getInc();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + _inc;
|
||||
result = prime * result + getTime();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this)
|
||||
return true;
|
||||
if (obj instanceof BSONTimestamp) {
|
||||
BSONTimestamp t2 = (BSONTimestamp) obj;
|
||||
return getTime() == t2.getTime() && getInc() == t2.getInc();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
final int _inc;
|
||||
final Date _time;
|
||||
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// BasicBSONList.java
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson.types;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.BSONObject;
|
||||
import com.massivecraft.massivecore.xlib.bson.util.StringRangeSet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Utility class to allow array <code>DBObject</code>s to be created.
|
||||
* <p>
|
||||
* Note: MongoDB will also create arrays from <code>java.util.List</code>s.
|
||||
* </p>
|
||||
* <p>
|
||||
* <blockquote><pre>
|
||||
* DBObject obj = new BasicBSONList();
|
||||
* obj.put( "0", value1 );
|
||||
* obj.put( "4", value2 );
|
||||
* obj.put( 2, value3 );
|
||||
* </pre></blockquote>
|
||||
* This simulates the array [ value1, null, value3, null, value2 ] by creating the
|
||||
* <code>DBObject</code> <code>{ "0" : value1, "1" : null, "2" : value3, "3" : null, "4" : value2 }</code>.
|
||||
* </p>
|
||||
* <p>
|
||||
* BasicBSONList only supports numeric keys. Passing strings that cannot be converted to ints will cause an
|
||||
* IllegalArgumentException.
|
||||
* <blockquote><pre>
|
||||
* BasicBSONList list = new BasicBSONList();
|
||||
* list.put("1", "bar"); // ok
|
||||
* list.put("1E1", "bar"); // throws exception
|
||||
* </pre></blockquote>
|
||||
* </p>
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class BasicBSONList extends ArrayList<Object> implements BSONObject {
|
||||
|
||||
private static final long serialVersionUID = -4415279469780082174L;
|
||||
|
||||
public BasicBSONList() { }
|
||||
|
||||
/**
|
||||
* Puts a value at an index.
|
||||
* For interface compatibility. Must be passed a String that is parsable to an int.
|
||||
* @param key the index at which to insert the value
|
||||
* @param v the value to insert
|
||||
* @return the value
|
||||
* @throws IllegalArgumentException if <code>key</code> cannot be parsed into an <code>int</code>
|
||||
*/
|
||||
public Object put( String key , Object v ){
|
||||
return put(_getInt( key ), v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a value at an index.
|
||||
* This will fill any unset indexes less than <code>index</code> with <code>null</code>.
|
||||
* @param key the index at which to insert the value
|
||||
* @param v the value to insert
|
||||
* @return the value
|
||||
*/
|
||||
public Object put( int key, Object v ) {
|
||||
while ( key >= size() )
|
||||
add( null );
|
||||
set( key , v );
|
||||
return v;
|
||||
}
|
||||
|
||||
public void putAll( Map m ){
|
||||
for ( Map.Entry entry : (Set<Map.Entry>)m.entrySet() ){
|
||||
put( entry.getKey().toString() , entry.getValue() );
|
||||
}
|
||||
}
|
||||
|
||||
public void putAll( BSONObject o ){
|
||||
for ( String k : o.keySet() ){
|
||||
put( k , o.get( k ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value at an index.
|
||||
* For interface compatibility. Must be passed a String that is parsable to an int.
|
||||
* @param key the index
|
||||
* @return the value, if found, or null
|
||||
* @throws IllegalArgumentException if <code>key</code> cannot be parsed into an <code>int</code>
|
||||
*/
|
||||
public Object get( String key ){
|
||||
int i = _getInt( key );
|
||||
if ( i < 0 )
|
||||
return null;
|
||||
if ( i >= size() )
|
||||
return null;
|
||||
return get( i );
|
||||
}
|
||||
|
||||
public Object removeField( String key ){
|
||||
int i = _getInt( key );
|
||||
if ( i < 0 )
|
||||
return null;
|
||||
if ( i >= size() )
|
||||
return null;
|
||||
return remove( i );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean containsKey( String key ){
|
||||
return containsField(key);
|
||||
}
|
||||
|
||||
public boolean containsField( String key ){
|
||||
int i = _getInt( key , false );
|
||||
if ( i < 0 )
|
||||
return false;
|
||||
return i >= 0 && i < size();
|
||||
}
|
||||
|
||||
public Set<String> keySet(){
|
||||
return new StringRangeSet(size());
|
||||
}
|
||||
|
||||
public Map toMap() {
|
||||
Map m = new HashMap();
|
||||
Iterator i = this.keySet().iterator();
|
||||
while (i.hasNext()) {
|
||||
Object s = i.next();
|
||||
m.put(s, this.get(String.valueOf(s)));
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
int _getInt( String s ){
|
||||
return _getInt( s , true );
|
||||
}
|
||||
|
||||
int _getInt( String s , boolean err ){
|
||||
try {
|
||||
return Integer.parseInt( s );
|
||||
}
|
||||
catch ( Exception e ){
|
||||
if ( err )
|
||||
throw new IllegalArgumentException( "BasicBSONList can only work with numeric keys, not: [" + s + "]" );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// Binary.java
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson.types;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.BSON;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* generic binary holder
|
||||
*/
|
||||
public class Binary implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 7902997490338209467L;
|
||||
|
||||
/**
|
||||
* Creates a Binary object with the default binary type of 0
|
||||
*
|
||||
* @param data raw data
|
||||
*/
|
||||
public Binary(byte[] data) {
|
||||
this(BSON.B_GENERAL, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Binary object
|
||||
*
|
||||
* @param type type of the field as encoded in BSON
|
||||
* @param data raw data
|
||||
*/
|
||||
public Binary(byte type, byte[] data) {
|
||||
_type = type;
|
||||
_data = data;
|
||||
}
|
||||
|
||||
public byte getType() {
|
||||
return _type;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return _data;
|
||||
}
|
||||
|
||||
public int length() {
|
||||
return _data.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof Binary)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Binary binary = (Binary) o;
|
||||
|
||||
if (_type != binary._type) {
|
||||
return false;
|
||||
}
|
||||
if (!Arrays.equals(_data, binary._data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = (int) _type;
|
||||
result = 31 * result + (_data != null ? Arrays.hashCode(_data) : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
final byte _type;
|
||||
final byte[] _data;
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// Code.java
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson.types;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* for using the Code type
|
||||
*/
|
||||
public class Code implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 475535263314046697L;
|
||||
|
||||
public Code( String code ){
|
||||
_code = code;
|
||||
}
|
||||
|
||||
public String getCode(){
|
||||
return _code;
|
||||
}
|
||||
|
||||
public boolean equals( Object o ){
|
||||
if ( ! ( o instanceof Code ) )
|
||||
return false;
|
||||
|
||||
Code c = (Code)o;
|
||||
return _code.equals( c._code );
|
||||
}
|
||||
|
||||
public int hashCode(){
|
||||
return _code.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getCode();
|
||||
}
|
||||
|
||||
final String _code;
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// CodeWScope.java
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson.types;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.BSONObject;
|
||||
|
||||
/**
|
||||
* for using the CodeWScope type
|
||||
*/
|
||||
public class CodeWScope extends Code {
|
||||
|
||||
private static final long serialVersionUID = -6284832275113680002L;
|
||||
|
||||
public CodeWScope( String code , BSONObject scope ){
|
||||
super( code );
|
||||
_scope = scope;
|
||||
}
|
||||
|
||||
public BSONObject getScope(){
|
||||
return _scope;
|
||||
}
|
||||
|
||||
public boolean equals( Object o ){
|
||||
if ( ! ( o instanceof CodeWScope ) )
|
||||
return false;
|
||||
|
||||
CodeWScope c = (CodeWScope)o;
|
||||
return _code.equals( c._code ) && _scope.equals( c._scope );
|
||||
}
|
||||
|
||||
public int hashCode(){
|
||||
return _code.hashCode() ^ _scope.hashCode();
|
||||
}
|
||||
|
||||
final BSONObject _scope;
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.massivecore.xlib.bson.types;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Represent the maximum key value regardless of the key's type
|
||||
*/
|
||||
public class MaxKey implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 5123414776151687185L;
|
||||
|
||||
public MaxKey() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof MaxKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MaxKey";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.massivecore.xlib.bson.types;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Represent the minimum key value regardless of the key's type
|
||||
*/
|
||||
public class MinKey implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 4075901136671855684L;
|
||||
|
||||
public MinKey() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof MinKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MinKey";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,592 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// ObjectId.java
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson.types;
|
||||
|
||||
import java.net.NetworkInterface;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* A globally unique identifier for objects.
|
||||
* <p>Consists of 12 bytes, divided as follows:
|
||||
* <blockquote><pre>
|
||||
* <table border="1">
|
||||
* <tr><td>0</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td>
|
||||
* <td>7</td><td>8</td><td>9</td><td>10</td><td>11</td></tr>
|
||||
* <tr><td colspan="4">time</td><td colspan="3">machine</td>
|
||||
* <td colspan="2">pid</td><td colspan="3">inc</td></tr>
|
||||
* </table>
|
||||
* </pre></blockquote>
|
||||
*
|
||||
* @dochub objectids
|
||||
*/
|
||||
public class ObjectId implements Comparable<ObjectId> , java.io.Serializable {
|
||||
|
||||
private static final long serialVersionUID = -4415279469780082174L;
|
||||
|
||||
static final Logger LOGGER = Logger.getLogger( "org.bson.ObjectId" );
|
||||
|
||||
/** Gets a new object id.
|
||||
* @return the new id
|
||||
*/
|
||||
public static ObjectId get(){
|
||||
return new ObjectId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ObjectId using time, machine and inc values. The Java driver has done it this way for a long time, but it
|
||||
* does not match the <a href="http://docs.mongodb.org/manual/reference/object-id/">ObjectId specification</a>,
|
||||
* which requires four values, not three. The next major release of the Java driver will conform to this specification,
|
||||
* but will still need to support clients that are relying on the current behavior. To that end,
|
||||
* the constructors that takes these three arguments are now deprecated in favor of this more explicit factory method,
|
||||
* and in the next major release those constructors will be removed.
|
||||
* <p>
|
||||
* NOTE: This will not break any application that use ObjectIds. The 12-byte representation will be round-trippable from old to new
|
||||
* driver releases.
|
||||
*
|
||||
* </p>
|
||||
*
|
||||
* @param time time in seconds
|
||||
* @param machine machine ID
|
||||
* @param inc incremental value
|
||||
* @see com.massivecraft.massivecore.xlib.bson.types.ObjectId#ObjectId(int, int, int)
|
||||
* @since 2.12.0
|
||||
*/
|
||||
public static ObjectId createFromLegacyFormat(final int time, final int machine, final int inc) {
|
||||
return new ObjectId(time, machine, inc);
|
||||
}
|
||||
|
||||
|
||||
/** Checks if a string could be an <code>ObjectId</code>.
|
||||
* @return whether the string could be an object id
|
||||
*/
|
||||
public static boolean isValid( String s ){
|
||||
if ( s == null )
|
||||
return false;
|
||||
|
||||
final int len = s.length();
|
||||
if ( len != 24 )
|
||||
return false;
|
||||
|
||||
for ( int i=0; i<len; i++ ){
|
||||
char c = s.charAt( i );
|
||||
if ( c >= '0' && c <= '9' )
|
||||
continue;
|
||||
if ( c >= 'a' && c <= 'f' )
|
||||
continue;
|
||||
if ( c >= 'A' && c <= 'F' )
|
||||
continue;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Turn an object into an <code>ObjectId</code>, if possible.
|
||||
* Strings will be converted into <code>ObjectId</code>s, if possible, and <code>ObjectId</code>s will
|
||||
* be cast and returned. Passing in <code>null</code> returns <code>null</code>.
|
||||
* @param o the object to convert
|
||||
* @return an <code>ObjectId</code> if it can be massaged, null otherwise
|
||||
*
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public static ObjectId massageToObjectId( Object o ){
|
||||
if ( o == null )
|
||||
return null;
|
||||
|
||||
if ( o instanceof ObjectId )
|
||||
return (ObjectId)o;
|
||||
|
||||
if ( o instanceof String ){
|
||||
String s = o.toString();
|
||||
if ( isValid( s ) )
|
||||
return new ObjectId( s );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ObjectId( Date time ){
|
||||
this(time, _genmachine, _nextInc.getAndIncrement());
|
||||
}
|
||||
|
||||
public ObjectId( Date time , int inc ){
|
||||
this( time , _genmachine , inc );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an ObjectId using time, machine and inc values. The Java driver has done it this way for a long time, but it
|
||||
* does not match the <a href="http://docs.mongodb.org/manual/reference/object-id/">ObjectId specification</a>,
|
||||
* which requires four values, not three. The next major release of the Java driver will conform to this specification,
|
||||
* but will still need to support clients that are relying on the current behavior. To that end,
|
||||
* this constructor is now deprecated in favor of the more explicit factory method ObjectId#createFromLegacyFormat(int, int, int)},
|
||||
* and in the next major release this constructor will be removed.
|
||||
*
|
||||
* @see ObjectId#createFromLegacyFormat(int, int, int)
|
||||
* @deprecated {@code ObjectId}'s constructed this way do not conform to
|
||||
* the <a href="http://docs.mongodb.org/manual/reference/object-id/">ObjectId specification</a>.
|
||||
* Please use {@link com.massivecraft.massivecore.xlib.bson.types.ObjectId#ObjectId(byte[])} or
|
||||
* {@link ObjectId#createFromLegacyFormat(int, int, int)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public ObjectId( Date time , int machine , int inc ){
|
||||
_time = (int)(time.getTime() / 1000);
|
||||
_machine = machine;
|
||||
_inc = inc;
|
||||
_new = false;
|
||||
}
|
||||
|
||||
/** Creates a new instance from a string.
|
||||
* @param s the string to convert
|
||||
* @throws IllegalArgumentException if the string is not a valid id
|
||||
*/
|
||||
public ObjectId( String s ){
|
||||
this( s , false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of {@code ObjectId} from a string.
|
||||
* @param s the string representation of ObjectId. Can contains only [0-9]|[a-f]|[A-F] characters.
|
||||
* @param babble if {@code true} - convert to 'babble' objectId format
|
||||
*
|
||||
* @deprecated 'babble' format is deprecated. Please use {@link #ObjectId(String)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public ObjectId( String s , boolean babble ){
|
||||
|
||||
if ( ! isValid( s ) )
|
||||
throw new IllegalArgumentException( "invalid ObjectId [" + s + "]" );
|
||||
|
||||
if ( babble )
|
||||
s = babbleToMongod( s );
|
||||
|
||||
byte b[] = new byte[12];
|
||||
for ( int i=0; i<b.length; i++ ){
|
||||
b[i] = (byte)Integer.parseInt( s.substring( i*2 , i*2 + 2) , 16 );
|
||||
}
|
||||
ByteBuffer bb = ByteBuffer.wrap( b );
|
||||
_time = bb.getInt();
|
||||
_machine = bb.getInt();
|
||||
_inc = bb.getInt();
|
||||
_new = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an ObjectId given its 12-byte binary representation.
|
||||
* @param b a byte array of length 12
|
||||
*/
|
||||
public ObjectId( byte[] b ){
|
||||
if ( b.length != 12 )
|
||||
throw new IllegalArgumentException( "need 12 bytes" );
|
||||
ByteBuffer bb = ByteBuffer.wrap( b );
|
||||
_time = bb.getInt();
|
||||
_machine = bb.getInt();
|
||||
_inc = bb.getInt();
|
||||
_new = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an ObjectId using time, machine and inc values. The Java driver has done it this way for a long time, but it
|
||||
* does not match the <a href="http://docs.mongodb.org/manual/reference/object-id/">ObjectId specification</a>,
|
||||
* which requires four values, not three. The next major release of the Java driver will conform to this specification,
|
||||
* but we will still need to support clients that are relying on the current behavior. To that end,
|
||||
* this constructor is now deprecated in favor of the more explicit factory method ObjectId#createFromLegacyFormat(int, int, int)},
|
||||
* and in the next major release this constructor will be removed.
|
||||
*
|
||||
* @param time time in seconds
|
||||
* @param machine machine ID
|
||||
* @param inc incremental value
|
||||
* @see ObjectId#createFromLegacyFormat(int, int, int)
|
||||
* @deprecated {@code ObjectId}'s constructed this way do not conform to
|
||||
* the <a href="http://docs.mongodb.org/manual/reference/object-id/">ObjectId specification</a>.
|
||||
* Please use {@link com.massivecraft.massivecore.xlib.bson.types.ObjectId#ObjectId(byte[])} or
|
||||
* {@link ObjectId#createFromLegacyFormat(int, int, int)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public ObjectId(int time, int machine, int inc) {
|
||||
_time = time;
|
||||
_machine = machine;
|
||||
_inc = inc;
|
||||
_new = false;
|
||||
}
|
||||
|
||||
/** Create a new object id.
|
||||
*/
|
||||
public ObjectId(){
|
||||
_time = (int) (System.currentTimeMillis() / 1000);
|
||||
_machine = _genmachine;
|
||||
_inc = _nextInc.getAndIncrement();
|
||||
_new = true;
|
||||
}
|
||||
|
||||
public int hashCode(){
|
||||
int x = _time;
|
||||
x += ( _machine * 111 );
|
||||
x += ( _inc * 17 );
|
||||
return x;
|
||||
}
|
||||
|
||||
public boolean equals( Object o ){
|
||||
|
||||
if ( this == o )
|
||||
return true;
|
||||
|
||||
ObjectId other = massageToObjectId( o );
|
||||
if ( other == null )
|
||||
return false;
|
||||
|
||||
return
|
||||
_time == other._time &&
|
||||
_machine == other._machine &&
|
||||
_inc == other._inc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 'babble' format is deprecated. Please use {@link #toHexString()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public String toStringBabble(){
|
||||
return babbleToMongod( toStringMongod() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this instance into a 24-byte hexadecimal string representation.
|
||||
*
|
||||
* @return a string representation of the ObjectId in hexadecimal format
|
||||
*/
|
||||
public String toHexString() {
|
||||
final StringBuilder buf = new StringBuilder(24);
|
||||
|
||||
for (final byte b : toByteArray()) {
|
||||
buf.append(String.format("%02x", b & 0xff));
|
||||
}
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a string representation of the ObjectId in hexadecimal format
|
||||
*
|
||||
* @deprecated Please use {@link #toHexString()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public String toStringMongod(){
|
||||
byte b[] = toByteArray();
|
||||
|
||||
StringBuilder buf = new StringBuilder(24);
|
||||
|
||||
for ( int i=0; i<b.length; i++ ){
|
||||
int x = b[i] & 0xFF;
|
||||
String s = Integer.toHexString( x );
|
||||
if ( s.length() == 1 )
|
||||
buf.append( "0" );
|
||||
buf.append( s );
|
||||
}
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public byte[] toByteArray(){
|
||||
byte b[] = new byte[12];
|
||||
ByteBuffer bb = ByteBuffer.wrap( b );
|
||||
// by default BB is big endian like we need
|
||||
bb.putInt( _time );
|
||||
bb.putInt( _machine );
|
||||
bb.putInt( _inc );
|
||||
return b;
|
||||
}
|
||||
|
||||
static String _pos( String s , int p ){
|
||||
return s.substring( p * 2 , ( p * 2 ) + 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public static String babbleToMongod( String b ){
|
||||
if ( ! isValid( b ) )
|
||||
throw new IllegalArgumentException( "invalid object id: " + b );
|
||||
|
||||
StringBuilder buf = new StringBuilder( 24 );
|
||||
for ( int i=7; i>=0; i-- )
|
||||
buf.append( _pos( b , i ) );
|
||||
for ( int i=11; i>=8; i-- )
|
||||
buf.append( _pos( b , i ) );
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
return toStringMongod();
|
||||
}
|
||||
|
||||
int _compareUnsigned( int i , int j ){
|
||||
long li = 0xFFFFFFFFL;
|
||||
li = i & li;
|
||||
long lj = 0xFFFFFFFFL;
|
||||
lj = j & lj;
|
||||
long diff = li - lj;
|
||||
if (diff < Integer.MIN_VALUE)
|
||||
return Integer.MIN_VALUE;
|
||||
if (diff > Integer.MAX_VALUE)
|
||||
return Integer.MAX_VALUE;
|
||||
return (int) diff;
|
||||
}
|
||||
|
||||
public int compareTo( ObjectId id ){
|
||||
if ( id == null )
|
||||
return -1;
|
||||
|
||||
int x = _compareUnsigned( _time , id._time );
|
||||
if ( x != 0 )
|
||||
return x;
|
||||
|
||||
x = _compareUnsigned( _machine , id._machine );
|
||||
if ( x != 0 )
|
||||
return x;
|
||||
|
||||
return _compareUnsigned( _inc , id._inc );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the timestamp (number of seconds since the Unix epoch).
|
||||
*
|
||||
* @return the timestamp
|
||||
*/
|
||||
public int getTimestamp() {
|
||||
return _time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the timestamp as a {@code Date} instance.
|
||||
*
|
||||
* @return the Date
|
||||
*/
|
||||
public Date getDate() {
|
||||
return new Date(_time * 1000L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the time of this ID, in milliseconds
|
||||
*
|
||||
* @deprecated Please use {@link #getDate()} ()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public long getTime(){
|
||||
return _time * 1000L;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the time of this ID, in seconds.
|
||||
* @deprecated Please use {@link #getTimestamp()} ()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public int getTimeSecond() {
|
||||
return _time;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the counter.
|
||||
*
|
||||
* @return the counter
|
||||
* @deprecated Please use the {@link #toByteArray()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public int getInc() {
|
||||
return _inc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the timestamp.
|
||||
*
|
||||
* @return the timestamp
|
||||
* @deprecated Please use {@link #getTimestamp()} ()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public int _time(){
|
||||
return _time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the machine identifier.
|
||||
*
|
||||
* @return the machine identifier
|
||||
* @see #createFromLegacyFormat(int, int, int)
|
||||
* @deprecated Please use {@code #toByteArray()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public int getMachine() {
|
||||
return _machine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the machine identifier.
|
||||
*
|
||||
* @return the machine identifier
|
||||
* @see #createFromLegacyFormat(int, int, int)
|
||||
* @deprecated Please use {@link #toByteArray()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public int _machine(){
|
||||
return _machine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the counter.
|
||||
*
|
||||
* @return the counter
|
||||
* @see #createFromLegacyFormat(int, int, int)
|
||||
* @deprecated Please use {@link #toByteArray()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public int _inc(){
|
||||
return _inc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 'new' flag breaks the immutability of the {@code ObjectId} class
|
||||
* and will be dropped in 3.x versions of the driver
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isNew() {
|
||||
return _new;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 'new' flag breaks the immutability of the {@code ObjectId} class
|
||||
* and will be dropped in 3.x versions of the driver
|
||||
*/
|
||||
@Deprecated
|
||||
public void notNew(){
|
||||
_new = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the machine identifier.
|
||||
*
|
||||
* @return the machine identifier
|
||||
* @see #createFromLegacyFormat(int, int, int)
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public static int getGenMachineId() {
|
||||
return _genmachine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current value of the auto-incrementing counter.
|
||||
*/
|
||||
public static int getCurrentCounter() {
|
||||
return _nextInc.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current value of the auto-incrementing counter.
|
||||
*
|
||||
* @deprecated Please use {@link #getCurrentCounter()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static int getCurrentInc() {
|
||||
return _nextInc.get();
|
||||
}
|
||||
|
||||
final int _time;
|
||||
final int _machine;
|
||||
final int _inc;
|
||||
|
||||
boolean _new;
|
||||
|
||||
/**
|
||||
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public static int _flip( int x ){
|
||||
int z = 0;
|
||||
z |= ( ( x << 24 ) & 0xFF000000 );
|
||||
z |= ( ( x << 8 ) & 0x00FF0000 );
|
||||
z |= ( ( x >> 8 ) & 0x0000FF00 );
|
||||
z |= ( ( x >> 24 ) & 0x000000FF );
|
||||
return z;
|
||||
}
|
||||
|
||||
private static AtomicInteger _nextInc = new AtomicInteger( (new java.util.Random()).nextInt() );
|
||||
|
||||
private static final int _genmachine;
|
||||
static {
|
||||
|
||||
try {
|
||||
// build a 2-byte machine piece based on NICs info
|
||||
int machinePiece;
|
||||
{
|
||||
try {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();
|
||||
while ( e.hasMoreElements() ){
|
||||
NetworkInterface ni = e.nextElement();
|
||||
sb.append( ni.toString() );
|
||||
}
|
||||
machinePiece = sb.toString().hashCode() << 16;
|
||||
} catch (Throwable e) {
|
||||
// exception sometimes happens with IBM JVM, use random
|
||||
LOGGER.log(Level.WARNING, e.getMessage(), e);
|
||||
machinePiece = (new Random().nextInt()) << 16;
|
||||
}
|
||||
LOGGER.fine( "machine piece post: " + Integer.toHexString( machinePiece ) );
|
||||
}
|
||||
|
||||
// add a 2 byte process piece. It must represent not only the JVM but the class loader.
|
||||
// Since static var belong to class loader there could be collisions otherwise
|
||||
final int processPiece;
|
||||
{
|
||||
int processId = new java.util.Random().nextInt();
|
||||
try {
|
||||
processId = java.lang.management.ManagementFactory.getRuntimeMXBean().getName().hashCode();
|
||||
}
|
||||
catch ( Throwable t ){
|
||||
}
|
||||
|
||||
ClassLoader loader = ObjectId.class.getClassLoader();
|
||||
int loaderId = loader != null ? System.identityHashCode(loader) : 0;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(Integer.toHexString(processId));
|
||||
sb.append(Integer.toHexString(loaderId));
|
||||
processPiece = sb.toString().hashCode() & 0xFFFF;
|
||||
LOGGER.fine( "process piece: " + Integer.toHexString( processPiece ) );
|
||||
}
|
||||
|
||||
_genmachine = machinePiece | processPiece;
|
||||
LOGGER.fine( "machine : " + Integer.toHexString( _genmachine ) );
|
||||
}
|
||||
catch ( Exception e ){
|
||||
throw new RuntimeException( e );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// Symbol.java
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson.types;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Class to hold a BSON symbol object, which is an interned string in Ruby
|
||||
*/
|
||||
public class Symbol implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1326269319883146072L;
|
||||
|
||||
public Symbol(String s) {
|
||||
_symbol = s;
|
||||
}
|
||||
|
||||
public String getSymbol(){
|
||||
return _symbol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will compare equal to a String that is equal to the String that this holds
|
||||
* @param o
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null) return false;
|
||||
|
||||
String otherSymbol;
|
||||
if (o instanceof Symbol) {
|
||||
otherSymbol = ((Symbol) o)._symbol;
|
||||
}
|
||||
else if (o instanceof String) {
|
||||
otherSymbol = (String) o;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_symbol != null ? !_symbol.equals(otherSymbol) : otherSymbol != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return _symbol != null ? _symbol.hashCode() : 0;
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
return _symbol;
|
||||
}
|
||||
|
||||
private final String _symbol;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<!--
|
||||
~ Copyright (c) 2008-2014 MongoDB, 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.
|
||||
-->
|
||||
<body>
|
||||
<p>Contains classes implementing various BSON types.</p>
|
||||
</body>
|
@ -0,0 +1,632 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Atlassian Pty Ltd
|
||||
*
|
||||
* 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.massivecore.xlib.bson.util;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.util.annotations.GuardedBy;
|
||||
import com.massivecraft.massivecore.xlib.bson.util.annotations.ThreadSafe;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import static com.massivecraft.massivecore.xlib.bson.util.Assertions.notNull;
|
||||
import static java.util.Collections.unmodifiableCollection;
|
||||
import static java.util.Collections.unmodifiableSet;
|
||||
|
||||
/**
|
||||
* Abstract base class for COW {@link Map} implementations that delegate to an
|
||||
* internal map.
|
||||
*
|
||||
* @param <K> The key type
|
||||
* @param <V> The value type
|
||||
* @param <M> the internal {@link Map} or extension for things like sorted and
|
||||
* navigable maps.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@ThreadSafe
|
||||
abstract class AbstractCopyOnWriteMap<K, V, M extends Map<K, V>> implements ConcurrentMap<K, V>, Serializable {
|
||||
private static final long serialVersionUID = 4508989182041753878L;
|
||||
|
||||
@GuardedBy("lock")
|
||||
private volatile M delegate;
|
||||
|
||||
// import edu.umd.cs.findbugs.annotations.@SuppressWarnings
|
||||
private final transient Lock lock = new ReentrantLock();
|
||||
|
||||
// private final transient EntrySet entrySet = new EntrySet();
|
||||
// private final transient KeySet keySet = new KeySet();
|
||||
// private final transient Values values = new Values();
|
||||
// private final View.Type viewType;
|
||||
private final View<K, V> view;
|
||||
|
||||
/**
|
||||
* Create a new {@link CopyOnWriteMap} with the supplied {@link Map} to
|
||||
* initialize the values.
|
||||
*
|
||||
* @param map the initial map to initialize with
|
||||
* @param viewType for writable or read-only key, value and entrySet views
|
||||
*/
|
||||
protected <N extends Map<? extends K, ? extends V>> AbstractCopyOnWriteMap(final N map, final View.Type viewType) {
|
||||
this.delegate = notNull("delegate", copy(notNull("map", map)));
|
||||
this.view = notNull("viewType", viewType).get(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy function, implemented by sub-classes.
|
||||
*
|
||||
* @param <N> the map to copy and return.
|
||||
* @param map the initial values of the newly created map.
|
||||
* @return a new map. Will never be modified after construction.
|
||||
*/
|
||||
@GuardedBy("lock")
|
||||
abstract <N extends Map<? extends K, ? extends V>> M copy(N map);
|
||||
|
||||
//
|
||||
// mutable operations
|
||||
//
|
||||
|
||||
public final void clear() {
|
||||
lock.lock();
|
||||
try {
|
||||
set(copy(Collections.<K, V> emptyMap()));
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public final V remove(final Object key) {
|
||||
lock.lock();
|
||||
try {
|
||||
// short circuit if key doesn't exist
|
||||
if (!delegate.containsKey(key)) {
|
||||
return null;
|
||||
}
|
||||
final M map = copy();
|
||||
try {
|
||||
return map.remove(key);
|
||||
} finally {
|
||||
set(map);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean remove(final Object key, final Object value) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (delegate.containsKey(key) && equals(value, delegate.get(key))) {
|
||||
final M map = copy();
|
||||
map.remove(key);
|
||||
set(map);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean replace(final K key, final V oldValue, final V newValue) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (!delegate.containsKey(key) || !equals(oldValue, delegate.get(key))) {
|
||||
return false;
|
||||
}
|
||||
final M map = copy();
|
||||
map.put(key, newValue);
|
||||
set(map);
|
||||
return true;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public V replace(final K key, final V value) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (!delegate.containsKey(key)) {
|
||||
return null;
|
||||
}
|
||||
final M map = copy();
|
||||
try {
|
||||
return map.put(key, value);
|
||||
} finally {
|
||||
set(map);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public final V put(final K key, final V value) {
|
||||
lock.lock();
|
||||
try {
|
||||
final M map = copy();
|
||||
try {
|
||||
return map.put(key, value);
|
||||
} finally {
|
||||
set(map);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public V putIfAbsent(final K key, final V value) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (!delegate.containsKey(key)) {
|
||||
final M map = copy();
|
||||
try {
|
||||
return map.put(key, value);
|
||||
} finally {
|
||||
set(map);
|
||||
}
|
||||
}
|
||||
return delegate.get(key);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public final void putAll(final Map<? extends K, ? extends V> t) {
|
||||
lock.lock();
|
||||
try {
|
||||
final M map = copy();
|
||||
map.putAll(t);
|
||||
set(map);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
protected M copy() {
|
||||
lock.lock();
|
||||
try {
|
||||
return copy(delegate);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("lock")
|
||||
protected void set(final M map) {
|
||||
delegate = map;
|
||||
}
|
||||
|
||||
//
|
||||
// Collection views
|
||||
//
|
||||
|
||||
public final Set<Map.Entry<K, V>> entrySet() {
|
||||
return view.entrySet();
|
||||
}
|
||||
|
||||
public final Set<K> keySet() {
|
||||
return view.keySet();
|
||||
}
|
||||
|
||||
public final Collection<V> values() {
|
||||
return view.values();
|
||||
}
|
||||
|
||||
//
|
||||
// delegate operations
|
||||
//
|
||||
|
||||
public final boolean containsKey(final Object key) {
|
||||
return delegate.containsKey(key);
|
||||
}
|
||||
|
||||
public final boolean containsValue(final Object value) {
|
||||
return delegate.containsValue(value);
|
||||
}
|
||||
|
||||
public final V get(final Object key) {
|
||||
return delegate.get(key);
|
||||
}
|
||||
|
||||
public final boolean isEmpty() {
|
||||
return delegate.isEmpty();
|
||||
}
|
||||
|
||||
public final int size() {
|
||||
return delegate.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(final Object o) {
|
||||
return delegate.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return delegate.hashCode();
|
||||
}
|
||||
|
||||
protected final M getDelegate() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return delegate.toString();
|
||||
}
|
||||
|
||||
//
|
||||
// inner classes
|
||||
//
|
||||
|
||||
private class KeySet extends CollectionView<K> implements Set<K> {
|
||||
|
||||
@Override
|
||||
Collection<K> getDelegate() {
|
||||
return delegate.keySet();
|
||||
}
|
||||
|
||||
//
|
||||
// mutable operations
|
||||
//
|
||||
|
||||
public void clear() {
|
||||
lock.lock();
|
||||
try {
|
||||
final M map = copy();
|
||||
map.keySet().clear();
|
||||
set(map);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean remove(final Object o) {
|
||||
return AbstractCopyOnWriteMap.this.remove(o) != null;
|
||||
}
|
||||
|
||||
public boolean removeAll(final Collection<?> c) {
|
||||
lock.lock();
|
||||
try {
|
||||
final M map = copy();
|
||||
try {
|
||||
return map.keySet().removeAll(c);
|
||||
} finally {
|
||||
set(map);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean retainAll(final Collection<?> c) {
|
||||
lock.lock();
|
||||
try {
|
||||
final M map = copy();
|
||||
try {
|
||||
return map.keySet().retainAll(c);
|
||||
} finally {
|
||||
set(map);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class Values extends CollectionView<V> {
|
||||
|
||||
@Override
|
||||
Collection<V> getDelegate() {
|
||||
return delegate.values();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
lock.lock();
|
||||
try {
|
||||
final M map = copy();
|
||||
map.values().clear();
|
||||
set(map);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean remove(final Object o) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (!contains(o)) {
|
||||
return false;
|
||||
}
|
||||
final M map = copy();
|
||||
try {
|
||||
return map.values().remove(o);
|
||||
} finally {
|
||||
set(map);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean removeAll(final Collection<?> c) {
|
||||
lock.lock();
|
||||
try {
|
||||
final M map = copy();
|
||||
try {
|
||||
return map.values().removeAll(c);
|
||||
} finally {
|
||||
set(map);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean retainAll(final Collection<?> c) {
|
||||
lock.lock();
|
||||
try {
|
||||
final M map = copy();
|
||||
try {
|
||||
return map.values().retainAll(c);
|
||||
} finally {
|
||||
set(map);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class EntrySet extends CollectionView<Entry<K, V>> implements Set<Map.Entry<K, V>> {
|
||||
|
||||
@Override
|
||||
Collection<java.util.Map.Entry<K, V>> getDelegate() {
|
||||
return delegate.entrySet();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
lock.lock();
|
||||
try {
|
||||
final M map = copy();
|
||||
map.entrySet().clear();
|
||||
set(map);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean remove(final Object o) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (!contains(o)) {
|
||||
return false;
|
||||
}
|
||||
final M map = copy();
|
||||
try {
|
||||
return map.entrySet().remove(o);
|
||||
} finally {
|
||||
set(map);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean removeAll(final Collection<?> c) {
|
||||
lock.lock();
|
||||
try {
|
||||
final M map = copy();
|
||||
try {
|
||||
return map.entrySet().removeAll(c);
|
||||
} finally {
|
||||
set(map);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean retainAll(final Collection<?> c) {
|
||||
lock.lock();
|
||||
try {
|
||||
final M map = copy();
|
||||
try {
|
||||
return map.entrySet().retainAll(c);
|
||||
} finally {
|
||||
set(map);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class UnmodifiableIterator<T> implements Iterator<T> {
|
||||
private final Iterator<T> delegate;
|
||||
|
||||
public UnmodifiableIterator(final Iterator<T> delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return delegate.hasNext();
|
||||
}
|
||||
|
||||
public T next() {
|
||||
return delegate.next();
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
protected static abstract class CollectionView<E> implements Collection<E> {
|
||||
|
||||
abstract Collection<E> getDelegate();
|
||||
|
||||
//
|
||||
// delegate operations
|
||||
//
|
||||
|
||||
public final boolean contains(final Object o) {
|
||||
return getDelegate().contains(o);
|
||||
}
|
||||
|
||||
public final boolean containsAll(final Collection<?> c) {
|
||||
return getDelegate().containsAll(c);
|
||||
}
|
||||
|
||||
public final Iterator<E> iterator() {
|
||||
return new UnmodifiableIterator<E>(getDelegate().iterator());
|
||||
}
|
||||
|
||||
public final boolean isEmpty() {
|
||||
return getDelegate().isEmpty();
|
||||
}
|
||||
|
||||
public final int size() {
|
||||
return getDelegate().size();
|
||||
}
|
||||
|
||||
public final Object[] toArray() {
|
||||
return getDelegate().toArray();
|
||||
}
|
||||
|
||||
public final <T> T[] toArray(final T[] a) {
|
||||
return getDelegate().toArray(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getDelegate().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
return getDelegate().equals(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getDelegate().toString();
|
||||
}
|
||||
|
||||
//
|
||||
// unsupported operations
|
||||
//
|
||||
|
||||
public final boolean add(final E o) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public final boolean addAll(final Collection<? extends E> c) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean equals(final Object o1, final Object o2) {
|
||||
if (o1 == null) {
|
||||
return o2 == null;
|
||||
}
|
||||
return o1.equals(o2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides access to the views of the underlying key, value and entry
|
||||
* collections.
|
||||
*/
|
||||
public static abstract class View<K, V> {
|
||||
View() {}
|
||||
|
||||
abstract Set<K> keySet();
|
||||
|
||||
abstract Set<Entry<K, V>> entrySet();
|
||||
|
||||
abstract Collection<V> values();
|
||||
|
||||
/**
|
||||
* The different types of {@link View} available
|
||||
*/
|
||||
public enum Type {
|
||||
STABLE {
|
||||
@Override
|
||||
<K, V, M extends Map<K, V>> View<K, V> get(final AbstractCopyOnWriteMap<K, V, M> host) {
|
||||
return host.new Immutable();
|
||||
}
|
||||
},
|
||||
LIVE {
|
||||
@Override
|
||||
<K, V, M extends Map<K, V>> View<K, V> get(final AbstractCopyOnWriteMap<K, V, M> host) {
|
||||
return host.new Mutable();
|
||||
}
|
||||
};
|
||||
abstract <K, V, M extends Map<K, V>> View<K, V> get(AbstractCopyOnWriteMap<K, V, M> host);
|
||||
}
|
||||
}
|
||||
|
||||
final class Immutable extends View<K, V> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -4158727180429303818L;
|
||||
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
return unmodifiableSet(delegate.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
return unmodifiableSet(delegate.entrySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<V> values() {
|
||||
return unmodifiableCollection(delegate.values());
|
||||
}
|
||||
}
|
||||
|
||||
final class Mutable extends View<K, V> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1624520291194797634L;
|
||||
|
||||
private final transient KeySet keySet = new KeySet();
|
||||
private final transient EntrySet entrySet = new EntrySet();
|
||||
private final transient Values values = new Values();
|
||||
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
return keySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
return entrySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<V> values() {
|
||||
return values;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, Inc.
|
||||
* Copyright (c) 2008 Atlassian Pty Ltd
|
||||
*
|
||||
* 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.massivecore.xlib.bson.util;
|
||||
|
||||
/**
|
||||
* Design by contract assertions.
|
||||
*
|
||||
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public class Assertions {
|
||||
public static <T> T notNull(final String name, final T notNull) throws IllegalArgumentException {
|
||||
if (notNull == null) {
|
||||
throw new NullArgumentException(name);
|
||||
}
|
||||
return notNull;
|
||||
}
|
||||
|
||||
public static void isTrue(final String name, final boolean check) throws IllegalArgumentException {
|
||||
if (!check) {
|
||||
throw new IllegalStateException(name);
|
||||
}
|
||||
}
|
||||
|
||||
public static void isTrueArgument(final String name, final boolean check) {
|
||||
if (!check) {
|
||||
throw new IllegalArgumentException("state should be: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
// /CLOVER:OFF
|
||||
private Assertions() {}
|
||||
|
||||
// /CLOVER:ON
|
||||
|
||||
static class NullArgumentException extends IllegalArgumentException {
|
||||
private static final long serialVersionUID = 6178592463723624585L;
|
||||
|
||||
NullArgumentException(final String name) {
|
||||
super(name + " should not be null!");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.massivecore.xlib.bson.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import static com.massivecraft.massivecore.xlib.bson.util.CopyOnWriteMap.newHashMap;
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
|
||||
class ClassAncestry {
|
||||
|
||||
/**
|
||||
* getAncestry
|
||||
*
|
||||
* Walks superclass and interface graph, superclasses first, then
|
||||
* interfaces, to compute an ancestry list. Supertypes are visited left to
|
||||
* right. Duplicates are removed such that no Class will appear in the list
|
||||
* before one of its subtypes.
|
||||
*
|
||||
* Does not need to be synchronized, races are harmless as the Class graph
|
||||
* does not change at runtime.
|
||||
*/
|
||||
public static <T> List<Class<?>> getAncestry(Class<T> c) {
|
||||
final ConcurrentMap<Class<?>, List<Class<?>>> cache = getClassAncestryCache();
|
||||
while (true) {
|
||||
List<Class<?>> cachedResult = cache.get(c);
|
||||
if (cachedResult != null) {
|
||||
return cachedResult;
|
||||
}
|
||||
cache.putIfAbsent(c, computeAncestry(c));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* computeAncestry, starting with children and going back to parents
|
||||
*/
|
||||
private static List<Class<?>> computeAncestry(Class<?> c) {
|
||||
final List<Class<?>> result = new ArrayList<Class<?>>();
|
||||
result.add(Object.class);
|
||||
computeAncestry(c, result);
|
||||
Collections.reverse(result);
|
||||
return unmodifiableList(new ArrayList<Class<?>>(result));
|
||||
}
|
||||
|
||||
private static <T> void computeAncestry(Class<T> c, List<Class<?>> result) {
|
||||
if ((c == null) || (c == Object.class)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// first interfaces (looks backwards but is not)
|
||||
Class<?>[] interfaces = c.getInterfaces();
|
||||
for (int i = interfaces.length - 1; i >= 0; i--) {
|
||||
computeAncestry(interfaces[i], result);
|
||||
}
|
||||
|
||||
// next superclass
|
||||
computeAncestry(c.getSuperclass(), result);
|
||||
|
||||
if (!result.contains(c))
|
||||
result.add(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* classAncestryCache
|
||||
*/
|
||||
private static ConcurrentMap<Class<?>, List<Class<?>>> getClassAncestryCache() {
|
||||
return (_ancestryCache);
|
||||
}
|
||||
|
||||
private static final ConcurrentMap<Class<?>, List<Class<?>>> _ancestryCache = newHashMap();
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// ClassMap.java
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson.util;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Maps Class objects to values. A ClassMap is different from a regular Map in
|
||||
* that get(c) does not only look to see if 'c' is a key in the Map, but also
|
||||
* walks the up superclass and interface graph of 'c' to find matches. Derived
|
||||
* matches of this sort are then "cached" in the registry so that matches are
|
||||
* faster on future gets.
|
||||
*
|
||||
* This is a very useful class for Class based registries.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ClassMap<String> m = new ClassMap<String>(); m.put(Animal.class, "Animal");
|
||||
* m.put(Fox.class, "Fox"); m.Fox.class) --> "Fox" m.get(Dog.class) --> "Animal"
|
||||
*
|
||||
* (assuming Dog.class < Animal.class)
|
||||
*/
|
||||
public class ClassMap<T> {
|
||||
/**
|
||||
* Walks superclass and interface graph, superclasses first, then
|
||||
* interfaces, to compute an ancestry list. Supertypes are visited left to
|
||||
* right. Duplicates are removed such that no Class will appear in the list
|
||||
* before one of its subtypes.
|
||||
*/
|
||||
public static <T> List<Class<?>> getAncestry(Class<T> c) {
|
||||
return ClassAncestry.getAncestry(c);
|
||||
}
|
||||
|
||||
private final class ComputeFunction implements Function<Class<?>, T> {
|
||||
@Override
|
||||
public T apply(Class<?> a) {
|
||||
for (Class<?> cls : getAncestry(a)) {
|
||||
T result = map.get(cls);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
private final Map<Class<?>, T> map = CopyOnWriteMap.newHashMap();
|
||||
private final Map<Class<?>, T> cache = ComputingMap.create(new ComputeFunction());
|
||||
|
||||
|
||||
public T get(Object key) {
|
||||
return cache.get(key);
|
||||
}
|
||||
|
||||
public T put(Class<?> key, T value) {
|
||||
try {
|
||||
return map.put(key, value);
|
||||
} finally {
|
||||
cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public T remove(Object key) {
|
||||
try {
|
||||
return map.remove(key);
|
||||
} finally {
|
||||
cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
map.clear();
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
}
|
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.massivecore.xlib.bson.util;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import static com.massivecraft.massivecore.xlib.bson.util.Assertions.notNull;
|
||||
|
||||
@SuppressWarnings({"unchecked", "deprecation"})
|
||||
final class ComputingMap<K, V> implements Map<K, V>, Function<K, V> {
|
||||
|
||||
public static <K, V> Map<K, V> create(Function<K, V> function) {
|
||||
return new ComputingMap<K, V>(CopyOnWriteMap.<K, V> newHashMap(), function);
|
||||
}
|
||||
|
||||
private final ConcurrentMap<K, V> map;
|
||||
private final Function<K, V> function;
|
||||
|
||||
ComputingMap(ConcurrentMap<K, V> map, Function<K, V> function) {
|
||||
this.map = notNull("map", map);
|
||||
this.function = notNull("function", function);
|
||||
}
|
||||
|
||||
public V get(Object key) {
|
||||
while (true) {
|
||||
V v = map.get(key);
|
||||
if (v != null)
|
||||
return v;
|
||||
K k = (K) key;
|
||||
V value = function.apply(k);
|
||||
if (value == null)
|
||||
return null;
|
||||
map.putIfAbsent(k, value);
|
||||
}
|
||||
}
|
||||
|
||||
public V apply(K k) {
|
||||
return get(k);
|
||||
}
|
||||
|
||||
public V putIfAbsent(K key, V value) {
|
||||
return map.putIfAbsent(key, value);
|
||||
}
|
||||
|
||||
public boolean remove(Object key, Object value) {
|
||||
return map.remove(key, value);
|
||||
}
|
||||
|
||||
public boolean replace(K key, V oldValue, V newValue) {
|
||||
return map.replace(key, oldValue, newValue);
|
||||
}
|
||||
|
||||
public V replace(K key, V value) {
|
||||
return map.replace(key, value);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
public boolean containsKey(Object key) {
|
||||
return map.containsKey(key);
|
||||
}
|
||||
|
||||
public boolean containsValue(Object value) {
|
||||
return map.containsValue(value);
|
||||
}
|
||||
|
||||
public V put(K key, V value) {
|
||||
return map.put(key, value);
|
||||
}
|
||||
|
||||
public V remove(Object key) {
|
||||
return map.remove(key);
|
||||
}
|
||||
|
||||
public void putAll(Map<? extends K, ? extends V> m) {
|
||||
map.putAll(m);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
map.clear();
|
||||
}
|
||||
|
||||
public Set<K> keySet() {
|
||||
return map.keySet();
|
||||
}
|
||||
|
||||
public Collection<V> values() {
|
||||
return map.values();
|
||||
}
|
||||
|
||||
public Set<java.util.Map.Entry<K, V>> entrySet() {
|
||||
return map.entrySet();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return map.equals(o);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return map.hashCode();
|
||||
}
|
||||
}
|
@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Atlassian Pty Ltd
|
||||
*
|
||||
* 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.massivecore.xlib.bson.util;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.util.AbstractCopyOnWriteMap.View.Type;
|
||||
import com.massivecraft.massivecore.xlib.bson.util.annotations.GuardedBy;
|
||||
import com.massivecraft.massivecore.xlib.bson.util.annotations.ThreadSafe;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
/**
|
||||
* A thread-safe variant of {@link Map} in which all mutative operations (the
|
||||
* "destructive" operations described by {@link Map} put, remove and so on) are
|
||||
* implemented by making a fresh copy of the underlying map.
|
||||
* <p>
|
||||
* This is ordinarily too costly, but may be <em>more</em> efficient than
|
||||
* alternatives when traversal operations vastly out-number mutations, and is
|
||||
* useful when you cannot or don't want to synchronize traversals, yet need to
|
||||
* preclude interference among concurrent threads. The "snapshot" style
|
||||
* iterators on the collections returned by {@link #entrySet()},
|
||||
* {@link #keySet()} and {@link #values()} use a reference to the internal map
|
||||
* at the point that the iterator was created. This map never changes during the
|
||||
* lifetime of the iterator, so interference is impossible and the iterator is
|
||||
* guaranteed not to throw <tt>ConcurrentModificationException</tt>. The
|
||||
* iterators will not reflect additions, removals, or changes to the list since
|
||||
* the iterator was created. Removing elements via these iterators is not
|
||||
* supported. The mutable operations on these collections (remove, retain etc.)
|
||||
* are supported but as with the {@link Map} interface, add and addAll are not
|
||||
* and throw {@link UnsupportedOperationException}.
|
||||
* <p>
|
||||
* The actual copy is performed by an abstract {@link #copy(Map)} method. The
|
||||
* method is responsible for the underlying Map implementation (for instance a
|
||||
* {@link HashMap}, {@link TreeMap}, {@link LinkedHashMap} etc.) and therefore
|
||||
* the semantics of what this map will cope with as far as null keys and values,
|
||||
* iteration ordering etc. See the note below about suitable candidates for
|
||||
* underlying Map implementations
|
||||
* <p>
|
||||
* There are supplied implementations for the common j.u.c {@link Map}
|
||||
* implementations via the {@link CopyOnWriteMap} static {@link Builder}.
|
||||
* <p>
|
||||
* Collection views of the keys, values and entries are optionally
|
||||
* {@link View.Type.LIVE live} or {@link View.Type.STABLE stable}. Live views
|
||||
* are modifiable will cause a copy if a modifying method is called on them.
|
||||
* Methods on these will reflect the current state of the collection, although
|
||||
* iterators will be snapshot style. If the collection views are stable they are
|
||||
* unmodifiable, and will be a snapshot of the state of the map at the time the
|
||||
* collection was asked for.
|
||||
* <p>
|
||||
* <strong>Please note</strong> that the thread-safety guarantees are limited to
|
||||
* the thread-safety of the non-mutative (non-destructive) operations of the
|
||||
* underlying map implementation. For instance some implementations such as
|
||||
* {@link WeakHashMap} and {@link LinkedHashMap} with access ordering are
|
||||
* actually structurally modified by the {@link #get(Object)} method and are
|
||||
* therefore not suitable candidates as delegates for this class.
|
||||
*
|
||||
* @param <K> the key type
|
||||
* @param <V> the value type
|
||||
* @author Jed Wesley-Smith
|
||||
*/
|
||||
@ThreadSafe
|
||||
@SuppressWarnings({"deprecation"})
|
||||
abstract class CopyOnWriteMap<K, V> extends AbstractCopyOnWriteMap<K, V, Map<K, V>> {
|
||||
private static final long serialVersionUID = 7935514534647505917L;
|
||||
|
||||
/**
|
||||
* Get a {@link Builder} for a {@link CopyOnWriteMap} instance.
|
||||
*
|
||||
* @param <K> key type
|
||||
* @param <V> value type
|
||||
* @return a fresh builder
|
||||
*/
|
||||
public static <K, V> Builder<K, V> builder() {
|
||||
return new Builder<K, V>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a {@link CopyOnWriteMap} and specify all the options.
|
||||
*
|
||||
* @param <K> key type
|
||||
* @param <V> value type
|
||||
*/
|
||||
public static class Builder<K, V> {
|
||||
private View.Type viewType = View.Type.STABLE;
|
||||
private final Map<K, V> initialValues = new HashMap<K, V>();
|
||||
|
||||
Builder() {}
|
||||
|
||||
/**
|
||||
* Views are stable (fixed in time) and unmodifiable.
|
||||
*/
|
||||
public Builder<K, V> stableViews() {
|
||||
viewType = View.Type.STABLE;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Views are live (reflecting concurrent updates) and mutator methods
|
||||
* are supported.
|
||||
*/
|
||||
public Builder<K, V> addAll(final Map<? extends K, ? extends V> values) {
|
||||
initialValues.putAll(values);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Views are live (reflecting concurrent updates) and mutator methods
|
||||
* are supported.
|
||||
*/
|
||||
public Builder<K, V> liveViews() {
|
||||
viewType = View.Type.LIVE;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CopyOnWriteMap<K, V> newHashMap() {
|
||||
return new Hash<K, V>(initialValues, viewType);
|
||||
}
|
||||
|
||||
public CopyOnWriteMap<K, V> newLinkedMap() {
|
||||
return new Linked<K, V>(initialValues, viewType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link CopyOnWriteMap} with an underlying {@link HashMap}.
|
||||
* <p>
|
||||
* This map has {@link View.Type.STABLE stable} views.
|
||||
*/
|
||||
public static <K, V> CopyOnWriteMap<K, V> newHashMap() {
|
||||
final Builder<K, V> builder = builder();
|
||||
return builder.newHashMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link CopyOnWriteMap} with an underlying {@link HashMap}
|
||||
* using the supplied map as the initial values.
|
||||
* <p>
|
||||
* This map has {@link View.Type.STABLE stable} views.
|
||||
*/
|
||||
public static <K, V> CopyOnWriteMap<K, V> newHashMap(final Map<? extends K, ? extends V> map) {
|
||||
final Builder<K, V> builder = builder();
|
||||
return builder.addAll(map).newHashMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link CopyOnWriteMap} with an underlying
|
||||
* {@link LinkedHashMap}. Iterators for this map will be return elements in
|
||||
* insertion order.
|
||||
* <p>
|
||||
* This map has {@link View.Type.STABLE stable} views.
|
||||
*/
|
||||
public static <K, V> CopyOnWriteMap<K, V> newLinkedMap() {
|
||||
final Builder<K, V> builder = builder();
|
||||
return builder.newLinkedMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link CopyOnWriteMap} with an underlying
|
||||
* {@link LinkedHashMap} using the supplied map as the initial values.
|
||||
* Iterators for this map will be return elements in insertion order.
|
||||
* <p>
|
||||
* This map has {@link View.Type.STABLE stable} views.
|
||||
*/
|
||||
public static <K, V> CopyOnWriteMap<K, V> newLinkedMap(final Map<? extends K, ? extends V> map) {
|
||||
final Builder<K, V> builder = builder();
|
||||
return builder.addAll(map).newLinkedMap();
|
||||
}
|
||||
|
||||
//
|
||||
// constructors
|
||||
//
|
||||
|
||||
/**
|
||||
* Create a new {@link CopyOnWriteMap} with the supplied {@link Map} to
|
||||
* initialize the values.
|
||||
*
|
||||
* @param map the initial map to initialize with
|
||||
* @deprecated since 0.0.12 use the versions that explicitly specify
|
||||
* View.Type
|
||||
*/
|
||||
@Deprecated
|
||||
protected CopyOnWriteMap(final Map<? extends K, ? extends V> map) {
|
||||
this(map, View.Type.LIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new empty {@link CopyOnWriteMap}.
|
||||
*
|
||||
* @deprecated since 0.0.12 use the versions that explicitly specify
|
||||
* View.Type
|
||||
*/
|
||||
@Deprecated
|
||||
protected CopyOnWriteMap() {
|
||||
this(Collections.<K, V> emptyMap(), View.Type.LIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link CopyOnWriteMap} with the supplied {@link Map} to
|
||||
* initialize the values. This map may be optionally modified using any of
|
||||
* the key, entry or value views
|
||||
*
|
||||
* @param map the initial map to initialize with
|
||||
*/
|
||||
protected CopyOnWriteMap(final Map<? extends K, ? extends V> map, final View.Type viewType) {
|
||||
super(map, viewType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new empty {@link CopyOnWriteMap}. This map may be optionally
|
||||
* modified using any of the key, entry or value views
|
||||
*/
|
||||
protected CopyOnWriteMap(final View.Type viewType) {
|
||||
super(Collections.<K, V> emptyMap(), viewType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@GuardedBy("internal-lock")
|
||||
protected abstract <N extends Map<? extends K, ? extends V>> Map<K, V> copy(N map);
|
||||
|
||||
//
|
||||
// inner classes
|
||||
//
|
||||
|
||||
/**
|
||||
* Uses {@link HashMap} instances as its internal storage.
|
||||
*/
|
||||
static class Hash<K, V> extends CopyOnWriteMap<K, V> {
|
||||
private static final long serialVersionUID = 5221824943734164497L;
|
||||
|
||||
Hash(final Map<? extends K, ? extends V> map, final Type viewType) {
|
||||
super(map, viewType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <N extends Map<? extends K, ? extends V>> Map<K, V> copy(final N map) {
|
||||
return new HashMap<K, V>(map);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses {@link LinkedHashMap} instances as its internal storage.
|
||||
*/
|
||||
static class Linked<K, V> extends CopyOnWriteMap<K, V> {
|
||||
private static final long serialVersionUID = -8659999465009072124L;
|
||||
|
||||
Linked(final Map<? extends K, ? extends V> map, final Type viewType) {
|
||||
super(map, viewType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <N extends Map<? extends K, ? extends V>> Map<K, V> copy(final N map) {
|
||||
return new LinkedHashMap<K, V>(map);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.massivecore.xlib.bson.util;
|
||||
|
||||
interface Function<A, B> {
|
||||
B apply(A a);
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.
|
||||
*/
|
||||
|
||||
// SimplePool.java
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson.util;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
/**
|
||||
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class SimplePool<T> {
|
||||
|
||||
public SimplePool( int max ){
|
||||
_max = max;
|
||||
}
|
||||
|
||||
public SimplePool(){
|
||||
_max = 1000;
|
||||
}
|
||||
|
||||
protected abstract T createNew();
|
||||
|
||||
protected boolean ok( T t ){
|
||||
return true;
|
||||
}
|
||||
|
||||
public T get(){
|
||||
T t = _stored.poll();
|
||||
if ( t != null )
|
||||
return t;
|
||||
return createNew();
|
||||
}
|
||||
|
||||
public void done( T t ){
|
||||
if ( ! ok( t ) )
|
||||
return;
|
||||
|
||||
if ( _stored.size() > _max )
|
||||
return;
|
||||
_stored.add( t );
|
||||
}
|
||||
|
||||
final int _max;
|
||||
private Queue<T> _stored = new ConcurrentLinkedQueue<T>();
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2014 MongoDB, 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.massivecore.xlib.bson.util;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
public class StringRangeSet implements Set<String> {
|
||||
|
||||
private final int size;
|
||||
|
||||
private final static int NUMSTR_LEN = 100;
|
||||
private final static String[] NUMSTRS = new String[100];
|
||||
static {
|
||||
for (int i = 0; i < NUMSTR_LEN; ++i)
|
||||
NUMSTRS[i] = String.valueOf(i);
|
||||
}
|
||||
|
||||
public StringRangeSet(int size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public Iterator<String> iterator() {
|
||||
return new Iterator<String>() {
|
||||
|
||||
int index = 0;
|
||||
|
||||
public boolean hasNext() {
|
||||
return index < size;
|
||||
}
|
||||
|
||||
public String next() {
|
||||
if (index < NUMSTR_LEN)
|
||||
return NUMSTRS[index++];
|
||||
return String.valueOf(index++);
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(String e) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends String> c) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
int t = Integer.parseInt(String.valueOf(o));
|
||||
return t >= 0 && t < size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
for (Object o : c) {
|
||||
if (!contains(o)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
String[] array = new String[size()];
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (i < NUMSTR_LEN) {
|
||||
array[i] = NUMSTRS[i];
|
||||
} else {
|
||||
array[i] = String.valueOf(i);
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T[] toArray(T[] a) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Brian Goetz and Tim Peierls
|
||||
* Released under the Creative Commons Attribution License
|
||||
* (http://creativecommons.org/licenses/by/2.5)
|
||||
* Official home: http://www.jcip.net
|
||||
*
|
||||
* Any republication or derived work distributed in source code form
|
||||
* must include this copyright and license notice.
|
||||
*/
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson.util.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* The field or method to which this annotation is applied can only be accessed
|
||||
* when holding a particular lock, which may be a built-in (synchronization) lock,
|
||||
* or may be an explicit java.util.concurrent.Lock.
|
||||
*
|
||||
* The argument determines which lock guards the annotated field or method:
|
||||
* <ul>
|
||||
* <li>
|
||||
* <code>this</code> : The intrinsic lock of the object in whose class the field is defined.
|
||||
* </li>
|
||||
* <li>
|
||||
* <code>class-name.this</code> : For inner classes, it may be necessary to disambiguate 'this';
|
||||
* the <em>class-name.this</em> designation allows you to specify which 'this' reference is intended
|
||||
* </li>
|
||||
* <li>
|
||||
* <code>itself</code> : For reference fields only; the object to which the field refers.
|
||||
* </li>
|
||||
* <li>
|
||||
* <code>field-name</code> : The lock object is referenced by the (instance or static) field
|
||||
* specified by <em>field-name</em>.
|
||||
* </li>
|
||||
* <li>
|
||||
* <code>class-name.field-name</code> : The lock object is reference by the static field specified
|
||||
* by <em>class-name.field-name</em>.
|
||||
* </li>
|
||||
* <li>
|
||||
* <code>method-name()</code> : The lock object is returned by calling the named nil-ary method.
|
||||
* </li>
|
||||
* <li>
|
||||
* <code>class-name.class</code> : The Class object for the specified class should be used as the lock object.
|
||||
* </li>
|
||||
*
|
||||
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Deprecated
|
||||
public @interface GuardedBy {
|
||||
String value();
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Brian Goetz and Tim Peierls
|
||||
* Released under the Creative Commons Attribution License
|
||||
* (http://creativecommons.org/licenses/by/2.5)
|
||||
* Official home: http://www.jcip.net
|
||||
*
|
||||
* Any republication or derived work distributed in source code form
|
||||
* must include this copyright and license notice.
|
||||
*/
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson.util.annotations;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* The class to which this annotation is applied is immutable. This means that
|
||||
* its state cannot be seen to change by callers, which implies that
|
||||
* <ul>
|
||||
* <li> all public fields are final, </li>
|
||||
* <li> all public final reference fields refer to other immutable objects, and </li>
|
||||
* <li> constructors and methods do not publish references to any internal state
|
||||
* which is potentially mutable by the implementation. </li>
|
||||
* </ul>
|
||||
* Immutable objects may still have internal mutable state for purposes of performance
|
||||
* optimization; some state variables may be lazily computed, so long as they are computed
|
||||
* from immutable state and that callers cannot tell the difference.
|
||||
* <p>
|
||||
* Immutable objects are inherently thread-safe; they may be passed between threads or
|
||||
* published without synchronization.
|
||||
*
|
||||
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Documented
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Deprecated
|
||||
public @interface Immutable {
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Brian Goetz and Tim Peierls
|
||||
* Released under the Creative Commons Attribution License
|
||||
* (http://creativecommons.org/licenses/by/2.5)
|
||||
* Official home: http://www.jcip.net
|
||||
*
|
||||
* Any republication or derived work distributed in source code form
|
||||
* must include this copyright and license notice.
|
||||
*/
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson.util.annotations;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
|
||||
/**
|
||||
* The class to which this annotation is applied is not thread-safe.
|
||||
* This annotation primarily exists for clarifying the non-thread-safety of a class
|
||||
* that might otherwise be assumed to be thread-safe, despite the fact that it is a bad
|
||||
* idea to assume a class is thread-safe without good reason.
|
||||
* @see ThreadSafe
|
||||
*
|
||||
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Documented
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Deprecated
|
||||
public @interface NotThreadSafe {
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Brian Goetz and Tim Peierls
|
||||
* Released under the Creative Commons Attribution License
|
||||
* (http://creativecommons.org/licenses/by/2.5)
|
||||
* Official home: http://www.jcip.net
|
||||
*
|
||||
* Any republication or derived work distributed in source code form
|
||||
* must include this copyright and license notice.
|
||||
*/
|
||||
|
||||
package com.massivecraft.massivecore.xlib.bson.util.annotations;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
|
||||
/**
|
||||
* The class to which this annotation is applied is thread-safe. This means that
|
||||
* no sequences of accesses (reads and writes to public fields, calls to public methods)
|
||||
* may put the object into an invalid state, regardless of the interleaving of those actions
|
||||
* by the runtime, and without requiring any additional synchronization or coordination on the
|
||||
* part of the caller.
|
||||
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
|
||||
*/
|
||||
@Documented
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Deprecated
|
||||
public @interface ThreadSafe {
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<!--
|
||||
~ Copyright (c) 2008-2014 MongoDB, 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.
|
||||
-->
|
||||
<body>
|
||||
<p>Misc utils used by BSON.</p>
|
||||
</body>
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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.massivecore.xlib.gson;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* This type adapter supports three subclasses of date: Date, Timestamp, and
|
||||
* java.sql.Date.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
final class DefaultDateTypeAdapter implements JsonSerializer<Date>, JsonDeserializer<Date> {
|
||||
|
||||
// TODO: migrate to streaming adapter
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
@ -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.massivecore.xlib.gson;
|
||||
|
||||
/**
|
||||
* 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 true then that class or field type
|
||||
* will not be part of the JSON output. For deserialization, if {@link #shouldSkipClass(Class)}
|
||||
* returns true, then it will not be set as part of the Java object structure.
|
||||
*
|
||||
* <p>The following are a few examples that shows how you can use this exclusion mechanism.
|
||||
*
|
||||
* <p><strong>Exclude fields and objects based on a particular class type:</strong>
|
||||
* <pre class="code">
|
||||
* private static class SpecificClassExclusionStrategy implements ExclusionStrategy {
|
||||
* private final Class<?> excludedThisClass;
|
||||
*
|
||||
* public SpecificClassExclusionStrategy(Class<?> excludedThisClass) {
|
||||
* this.excludedThisClass = excludedThisClass;
|
||||
* }
|
||||
*
|
||||
* public boolean shouldSkipClass(Class<?> clazz) {
|
||||
* return excludedThisClass.equals(clazz);
|
||||
* }
|
||||
*
|
||||
* public boolean shouldSkipField(FieldAttributes f) {
|
||||
* return excludedThisClass.equals(f.getDeclaredClass());
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p><strong>Excludes fields and objects based on a particular annotation:</strong>
|
||||
* <pre class="code">
|
||||
* 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;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>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:
|
||||
* <pre class="code">
|
||||
* ExclusionStrategy excludeStrings = new UserDefinedExclusionStrategy(String.class);
|
||||
* Gson gson = new GsonBuilder()
|
||||
* .setExclusionStrategies(excludeStrings)
|
||||
* .create();
|
||||
* </pre>
|
||||
*
|
||||
* <p>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:
|
||||
* <pre class="code">
|
||||
* ExclusionStrategy excludeStrings = new UserDefinedExclusionStrategy(String.class);
|
||||
* Gson gson = new GsonBuilder()
|
||||
* .addDeserializationExclusionStrategy(excludeStrings)
|
||||
* .create();
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* 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.massivecore.xlib.gson;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.$Gson$Preconditions;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A data object that stores attributes of a field.
|
||||
*
|
||||
* <p>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 final Field field;
|
||||
|
||||
/**
|
||||
* Constructs a Field Attributes object from the {@code f}.
|
||||
*
|
||||
* @param f the field to pull attributes from
|
||||
*/
|
||||
public FieldAttributes(Field f) {
|
||||
$Gson$Preconditions.checkNotNull(f);
|
||||
this.field = f;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the declaring class that contains this field
|
||||
*/
|
||||
public Class<?> getDeclaringClass() {
|
||||
return field.getDeclaringClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name of the field
|
||||
*/
|
||||
public String getName() {
|
||||
return field.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>For example, assume the following class definition:
|
||||
* <pre class="code">
|
||||
* public class Foo {
|
||||
* private String bar;
|
||||
* private List<String> red;
|
||||
* }
|
||||
*
|
||||
* Type listParmeterizedType = new TypeToken<List<String>>() {}.getType();
|
||||
* </pre>
|
||||
*
|
||||
* <p>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() {
|
||||
return field.getGenericType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@code Class} object that was declared for this field.
|
||||
*
|
||||
* <p>For example, assume the following class definition:
|
||||
* <pre class="code">
|
||||
* public class Foo {
|
||||
* private String bar;
|
||||
* private List<String> red;
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>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 field.getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 extends Annotation> T getAnnotation(Class<T> annotation) {
|
||||
return field.getAnnotation(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<Annotation> getAnnotations() {
|
||||
return Arrays.asList(field.getAnnotations());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the field is defined with the {@code modifier}.
|
||||
*
|
||||
* <p>This method is meant to be called as:
|
||||
* <pre class="code">
|
||||
* boolean hasPublicModifier = fieldAttribute.hasModifier(java.lang.reflect.Modifier.PUBLIC);
|
||||
* </pre>
|
||||
*
|
||||
* @see java.lang.reflect.Modifier
|
||||
*/
|
||||
public boolean hasModifier(int modifier) {
|
||||
return (field.getModifiers() & 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 field.isSynthetic();
|
||||
}
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* 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.massivecore.xlib.gson;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* An enumeration that defines a few standard naming conventions for JSON field names.
|
||||
* This enumeration should be used in conjunction with {@link com.massivecraft.massivecore.xlib.gson.GsonBuilder}
|
||||
* to configure a {@link com.massivecraft.massivecore.xlib.gson.Gson} instance to properly translate Java field
|
||||
* names into the desired JSON field names.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
public enum FieldNamingPolicy implements FieldNamingStrategy {
|
||||
|
||||
/**
|
||||
* Using this naming policy with Gson will ensure that the field name is
|
||||
* unchanged.
|
||||
*/
|
||||
IDENTITY() {
|
||||
public String translateName(Field f) {
|
||||
return f.getName();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
|
||||
* <ul>
|
||||
* <li>someFieldName ---> SomeFieldName</li>
|
||||
* <li>_someFieldName ---> _SomeFieldName</li>
|
||||
* </ul>
|
||||
*/
|
||||
UPPER_CAMEL_CASE() {
|
||||
public String translateName(Field f) {
|
||||
return upperCaseFirstLetter(f.getName());
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
|
||||
* <ul>
|
||||
* <li>someFieldName ---> Some Field Name</li>
|
||||
* <li>_someFieldName ---> _Some Field Name</li>
|
||||
* </ul>
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
UPPER_CAMEL_CASE_WITH_SPACES() {
|
||||
public String translateName(Field f) {
|
||||
return upperCaseFirstLetter(separateCamelCase(f.getName(), " "));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 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 (_).
|
||||
*
|
||||
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
|
||||
* <ul>
|
||||
* <li>someFieldName ---> some_field_name</li>
|
||||
* <li>_someFieldName ---> _some_field_name</li>
|
||||
* <li>aStringField ---> a_string_field</li>
|
||||
* <li>aURL ---> a_u_r_l</li>
|
||||
* </ul>
|
||||
*/
|
||||
LOWER_CASE_WITH_UNDERSCORES() {
|
||||
public String translateName(Field f) {
|
||||
return separateCamelCase(f.getName(), "_").toLowerCase();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 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 (-).
|
||||
*
|
||||
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
|
||||
* <ul>
|
||||
* <li>someFieldName ---> some-field-name</li>
|
||||
* <li>_someFieldName ---> _some-field-name</li>
|
||||
* <li>aStringField ---> a-string-field</li>
|
||||
* <li>aURL ---> a-u-r-l</li>
|
||||
* </ul>
|
||||
* 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() {
|
||||
public String translateName(Field f) {
|
||||
return separateCamelCase(f.getName(), "-").toLowerCase();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts the field name that uses camel-case define word separation into
|
||||
* separate words that are separated by the provided {@code separatorString}.
|
||||
*/
|
||||
private static String separateCamelCase(String name, String separator) {
|
||||
StringBuilder translation = new StringBuilder();
|
||||
for (int i = 0; i < name.length(); i++) {
|
||||
char character = name.charAt(i);
|
||||
if (Character.isUpperCase(character) && translation.length() != 0) {
|
||||
translation.append(separator);
|
||||
}
|
||||
translation.append(character);
|
||||
}
|
||||
return translation.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the JSON field names begins with an upper case letter.
|
||||
*/
|
||||
private static String upperCaseFirstLetter(String name) {
|
||||
StringBuilder fieldNameBuilder = new StringBuilder();
|
||||
int index = 0;
|
||||
char firstCharacter = name.charAt(index);
|
||||
|
||||
while (index < name.length() - 1) {
|
||||
if (Character.isLetter(firstCharacter)) {
|
||||
break;
|
||||
}
|
||||
|
||||
fieldNameBuilder.append(firstCharacter);
|
||||
firstCharacter = name.charAt(++index);
|
||||
}
|
||||
|
||||
if (index == name.length()) {
|
||||
return fieldNameBuilder.toString();
|
||||
}
|
||||
|
||||
if (!Character.isUpperCase(firstCharacter)) {
|
||||
String modifiedTarget = modifyString(Character.toUpperCase(firstCharacter), name, ++index);
|
||||
return fieldNameBuilder.append(modifiedTarget).toString();
|
||||
} else {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
private static String modifyString(char firstCharacter, String srcString, int indexOfSubstring) {
|
||||
return (indexOfSubstring < srcString.length())
|
||||
? firstCharacter + srcString.substring(indexOfSubstring)
|
||||
: String.valueOf(firstCharacter);
|
||||
}
|
||||
}
|
@ -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.massivecore.xlib.gson;
|
||||
|
||||
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);
|
||||
}
|
908
src/main/java/com/massivecraft/massivecore/xlib/gson/Gson.java
Normal file
908
src/main/java/com/massivecraft/massivecore/xlib/gson/Gson.java
Normal file
@ -0,0 +1,908 @@
|
||||
/*
|
||||
* 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.massivecore.xlib.gson;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.ConstructorConstructor;
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.Excluder;
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.Primitives;
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.Streams;
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.bind.ArrayTypeAdapter;
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.bind.CollectionTypeAdapterFactory;
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.bind.DateTypeAdapter;
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.bind.JsonAdapterAnnotationTypeAdapterFactory;
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.bind.JsonTreeReader;
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.bind.JsonTreeWriter;
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.bind.MapTypeAdapterFactory;
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.bind.ObjectTypeAdapter;
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.bind.ReflectiveTypeAdapterFactory;
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.bind.SqlDateTypeAdapter;
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.bind.TimeTypeAdapter;
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.bind.TypeAdapters;
|
||||
import com.massivecraft.massivecore.xlib.gson.reflect.TypeToken;
|
||||
import com.massivecraft.massivecore.xlib.gson.stream.JsonReader;
|
||||
import com.massivecraft.massivecore.xlib.gson.stream.JsonToken;
|
||||
import com.massivecraft.massivecore.xlib.gson.stream.JsonWriter;
|
||||
import com.massivecraft.massivecore.xlib.gson.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.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
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.
|
||||
*
|
||||
* <p>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.</p>
|
||||
*
|
||||
* <p>Here is an example of how Gson is used for a simple Class:
|
||||
*
|
||||
* <pre>
|
||||
* 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
|
||||
* </pre></p>
|
||||
*
|
||||
* <p>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}:
|
||||
*
|
||||
* <pre>
|
||||
* Type listType = new TypeToken<List<String>>() {}.getType();
|
||||
* List<String> target = new LinkedList<String>();
|
||||
* target.add("blah");
|
||||
*
|
||||
* Gson gson = new Gson();
|
||||
* String json = gson.toJson(target, listType);
|
||||
* List<String> target2 = gson.fromJson(json, listType);
|
||||
* </pre></p>
|
||||
*
|
||||
* <p>See the <a href="https://sites.google.com/site/gson/gson-user-guide">Gson User Guide</a>
|
||||
* for a more complete set of examples.</p>
|
||||
*
|
||||
* @see com.massivecraft.massivecore.xlib.gson.reflect.TypeToken
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
* @author Jesse Wilson
|
||||
*/
|
||||
public final class Gson {
|
||||
static final boolean DEFAULT_JSON_NON_EXECUTABLE = false;
|
||||
|
||||
private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n";
|
||||
|
||||
/**
|
||||
* This thread local guards against reentrant calls to getAdapter(). In
|
||||
* certain object graphs, creating an adapter for a type may recursively
|
||||
* require an adapter for the same type! Without intervention, the recursive
|
||||
* lookup would stack overflow. We cheat by returning a proxy type adapter.
|
||||
* The proxy is wired up once the initial adapter has been created.
|
||||
*/
|
||||
private final ThreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>> calls
|
||||
= new ThreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>>();
|
||||
|
||||
private final Map<TypeToken<?>, TypeAdapter<?>> typeTokenCache
|
||||
= Collections.synchronizedMap(new HashMap<TypeToken<?>, TypeAdapter<?>>());
|
||||
|
||||
private final List<TypeAdapterFactory> factories;
|
||||
private final ConstructorConstructor constructorConstructor;
|
||||
|
||||
private final boolean serializeNulls;
|
||||
private final boolean htmlSafe;
|
||||
private final boolean generateNonExecutableJson;
|
||||
private final boolean prettyPrinting;
|
||||
|
||||
final JsonDeserializationContext deserializationContext = new JsonDeserializationContext() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T deserialize(JsonElement json, Type typeOfT) throws JsonParseException {
|
||||
return (T) fromJson(json, typeOfT);
|
||||
}
|
||||
};
|
||||
|
||||
final JsonSerializationContext serializationContext = new JsonSerializationContext() {
|
||||
public JsonElement serialize(Object src) {
|
||||
return toJsonTree(src);
|
||||
}
|
||||
public JsonElement serialize(Object src, Type typeOfSrc) {
|
||||
return toJsonTree(src, typeOfSrc);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs a Gson object with default configuration. The default configuration has the
|
||||
* following settings:
|
||||
* <ul>
|
||||
* <li>The JSON generated by <code>toJson</code> methods is in compact representation. This
|
||||
* means that all the unneeded white-space is removed. You can change this behavior with
|
||||
* {@link GsonBuilder#setPrettyPrinting()}. </li>
|
||||
* <li>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()}.</li>
|
||||
* <li>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)}. </li>
|
||||
* <li>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)}. </li>
|
||||
* <li>By default, Gson ignores the {@link com.massivecraft.massivecore.xlib.gson.annotations.Expose} annotation.
|
||||
* You can enable Gson to serialize/deserialize only those fields marked with this annotation
|
||||
* through {@link GsonBuilder#excludeFieldsWithoutExposeAnnotation()}. </li>
|
||||
* <li>By default, Gson ignores the {@link com.massivecraft.massivecore.xlib.gson.annotations.Since} annotation. You
|
||||
* can enable Gson to use this annotation through {@link GsonBuilder#setVersion(double)}.</li>
|
||||
* <li>The default field naming policy for the output Json is same as in Java. So, a Java class
|
||||
* field <code>versionNumber</code> will be output as <code>"versionNumber"</code> 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)}.</li>
|
||||
* <li>By default, Gson excludes <code>transient</code> or <code>static</code> fields from
|
||||
* consideration for serialization and deserialization. You can change this behavior through
|
||||
* {@link GsonBuilder#excludeFieldsWithModifiers(int...)}.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public Gson() {
|
||||
this(Excluder.DEFAULT, FieldNamingPolicy.IDENTITY,
|
||||
Collections.<Type, InstanceCreator<?>>emptyMap(), false, false, DEFAULT_JSON_NON_EXECUTABLE,
|
||||
true, false, false, LongSerializationPolicy.DEFAULT,
|
||||
Collections.<TypeAdapterFactory>emptyList());
|
||||
}
|
||||
|
||||
Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingPolicy,
|
||||
final Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
|
||||
boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
|
||||
boolean prettyPrinting, boolean serializeSpecialFloatingPointValues,
|
||||
LongSerializationPolicy longSerializationPolicy,
|
||||
List<TypeAdapterFactory> typeAdapterFactories) {
|
||||
this.constructorConstructor = new ConstructorConstructor(instanceCreators);
|
||||
this.serializeNulls = serializeNulls;
|
||||
this.generateNonExecutableJson = generateNonExecutableGson;
|
||||
this.htmlSafe = htmlSafe;
|
||||
this.prettyPrinting = prettyPrinting;
|
||||
|
||||
List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
|
||||
|
||||
// built-in type adapters that cannot be overridden
|
||||
factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
|
||||
factories.add(ObjectTypeAdapter.FACTORY);
|
||||
|
||||
// the excluder must precede all adapters that handle user-defined types
|
||||
factories.add(excluder);
|
||||
|
||||
// user's type adapters
|
||||
factories.addAll(typeAdapterFactories);
|
||||
|
||||
// type adapters for basic platform types
|
||||
factories.add(TypeAdapters.STRING_FACTORY);
|
||||
factories.add(TypeAdapters.INTEGER_FACTORY);
|
||||
factories.add(TypeAdapters.BOOLEAN_FACTORY);
|
||||
factories.add(TypeAdapters.BYTE_FACTORY);
|
||||
factories.add(TypeAdapters.SHORT_FACTORY);
|
||||
factories.add(TypeAdapters.newFactory(long.class, Long.class,
|
||||
longAdapter(longSerializationPolicy)));
|
||||
factories.add(TypeAdapters.newFactory(double.class, Double.class,
|
||||
doubleAdapter(serializeSpecialFloatingPointValues)));
|
||||
factories.add(TypeAdapters.newFactory(float.class, Float.class,
|
||||
floatAdapter(serializeSpecialFloatingPointValues)));
|
||||
factories.add(TypeAdapters.NUMBER_FACTORY);
|
||||
factories.add(TypeAdapters.CHARACTER_FACTORY);
|
||||
factories.add(TypeAdapters.STRING_BUILDER_FACTORY);
|
||||
factories.add(TypeAdapters.STRING_BUFFER_FACTORY);
|
||||
factories.add(TypeAdapters.newFactory(BigDecimal.class, TypeAdapters.BIG_DECIMAL));
|
||||
factories.add(TypeAdapters.newFactory(BigInteger.class, TypeAdapters.BIG_INTEGER));
|
||||
factories.add(TypeAdapters.URL_FACTORY);
|
||||
factories.add(TypeAdapters.URI_FACTORY);
|
||||
factories.add(TypeAdapters.UUID_FACTORY);
|
||||
factories.add(TypeAdapters.LOCALE_FACTORY);
|
||||
factories.add(TypeAdapters.INET_ADDRESS_FACTORY);
|
||||
factories.add(TypeAdapters.BIT_SET_FACTORY);
|
||||
factories.add(DateTypeAdapter.FACTORY);
|
||||
factories.add(TypeAdapters.CALENDAR_FACTORY);
|
||||
factories.add(TimeTypeAdapter.FACTORY);
|
||||
factories.add(SqlDateTypeAdapter.FACTORY);
|
||||
factories.add(TypeAdapters.TIMESTAMP_FACTORY);
|
||||
factories.add(ArrayTypeAdapter.FACTORY);
|
||||
factories.add(TypeAdapters.ENUM_FACTORY);
|
||||
factories.add(TypeAdapters.CLASS_FACTORY);
|
||||
|
||||
// type adapters for composite and user-defined types
|
||||
factories.add(new CollectionTypeAdapterFactory(constructorConstructor));
|
||||
factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));
|
||||
factories.add(new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor));
|
||||
factories.add(new ReflectiveTypeAdapterFactory(
|
||||
constructorConstructor, fieldNamingPolicy, excluder));
|
||||
|
||||
this.factories = Collections.unmodifiableList(factories);
|
||||
}
|
||||
|
||||
private TypeAdapter<Number> doubleAdapter(boolean serializeSpecialFloatingPointValues) {
|
||||
if (serializeSpecialFloatingPointValues) {
|
||||
return TypeAdapters.DOUBLE;
|
||||
}
|
||||
return new TypeAdapter<Number>() {
|
||||
@Override public Double read(JsonReader in) throws IOException {
|
||||
if (in.peek() == JsonToken.NULL) {
|
||||
in.nextNull();
|
||||
return null;
|
||||
}
|
||||
return in.nextDouble();
|
||||
}
|
||||
@Override public void write(JsonWriter out, Number value) throws IOException {
|
||||
if (value == null) {
|
||||
out.nullValue();
|
||||
return;
|
||||
}
|
||||
double doubleValue = value.doubleValue();
|
||||
checkValidFloatingPoint(doubleValue);
|
||||
out.value(value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private TypeAdapter<Number> floatAdapter(boolean serializeSpecialFloatingPointValues) {
|
||||
if (serializeSpecialFloatingPointValues) {
|
||||
return TypeAdapters.FLOAT;
|
||||
}
|
||||
return new TypeAdapter<Number>() {
|
||||
@Override public Float read(JsonReader in) throws IOException {
|
||||
if (in.peek() == JsonToken.NULL) {
|
||||
in.nextNull();
|
||||
return null;
|
||||
}
|
||||
return (float) in.nextDouble();
|
||||
}
|
||||
@Override public void write(JsonWriter out, Number value) throws IOException {
|
||||
if (value == null) {
|
||||
out.nullValue();
|
||||
return;
|
||||
}
|
||||
float floatValue = value.floatValue();
|
||||
checkValidFloatingPoint(floatValue);
|
||||
out.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.serializeSpecialFloatingPointValues() method.");
|
||||
}
|
||||
}
|
||||
|
||||
private TypeAdapter<Number> longAdapter(LongSerializationPolicy longSerializationPolicy) {
|
||||
if (longSerializationPolicy == LongSerializationPolicy.DEFAULT) {
|
||||
return TypeAdapters.LONG;
|
||||
}
|
||||
return new TypeAdapter<Number>() {
|
||||
@Override public Number read(JsonReader in) throws IOException {
|
||||
if (in.peek() == JsonToken.NULL) {
|
||||
in.nextNull();
|
||||
return null;
|
||||
}
|
||||
return in.nextLong();
|
||||
}
|
||||
@Override public void write(JsonWriter out, Number value) throws IOException {
|
||||
if (value == null) {
|
||||
out.nullValue();
|
||||
return;
|
||||
}
|
||||
out.value(value.toString());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type adapter for {@code} type.
|
||||
*
|
||||
* @throws IllegalArgumentException if this GSON cannot serialize and
|
||||
* deserialize {@code type}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
|
||||
TypeAdapter<?> cached = typeTokenCache.get(type);
|
||||
if (cached != null) {
|
||||
return (TypeAdapter<T>) cached;
|
||||
}
|
||||
|
||||
Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();
|
||||
boolean requiresThreadLocalCleanup = false;
|
||||
if (threadCalls == null) {
|
||||
threadCalls = new HashMap<TypeToken<?>, FutureTypeAdapter<?>>();
|
||||
calls.set(threadCalls);
|
||||
requiresThreadLocalCleanup = true;
|
||||
}
|
||||
|
||||
// the key and value type parameters always agree
|
||||
FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type);
|
||||
if (ongoingCall != null) {
|
||||
return ongoingCall;
|
||||
}
|
||||
|
||||
try {
|
||||
FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
|
||||
threadCalls.put(type, call);
|
||||
|
||||
for (TypeAdapterFactory factory : factories) {
|
||||
TypeAdapter<T> candidate = factory.create(this, type);
|
||||
if (candidate != null) {
|
||||
call.setDelegate(candidate);
|
||||
typeTokenCache.put(type, candidate);
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("GSON cannot handle " + type);
|
||||
} finally {
|
||||
threadCalls.remove(type);
|
||||
|
||||
if (requiresThreadLocalCleanup) {
|
||||
calls.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to get an alternate type adapter for the specified type. This is used
|
||||
* to access a type adapter that is overridden by a {@link TypeAdapterFactory} that you
|
||||
* may have registered. This features is typically used when you want to register a type
|
||||
* adapter that does a little bit of work but then delegates further processing to the Gson
|
||||
* default type adapter. Here is an example:
|
||||
* <p>Let's say we want to write a type adapter that counts the number of objects being read
|
||||
* from or written to JSON. We can achieve this by writing a type adapter factory that uses
|
||||
* the <code>getDelegateAdapter</code> method:
|
||||
* <pre> {@code
|
||||
* class StatsTypeAdapterFactory implements TypeAdapterFactory {
|
||||
* public int numReads = 0;
|
||||
* public int numWrites = 0;
|
||||
* public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
|
||||
* final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
|
||||
* return new TypeAdapter<T>() {
|
||||
* public void write(JsonWriter out, T value) throws IOException {
|
||||
* ++numWrites;
|
||||
* delegate.write(out, value);
|
||||
* }
|
||||
* public T read(JsonReader in) throws IOException {
|
||||
* ++numReads;
|
||||
* return delegate.read(in);
|
||||
* }
|
||||
* };
|
||||
* }
|
||||
* }
|
||||
* } </pre>
|
||||
* This factory can now be used like this:
|
||||
* <pre> {@code
|
||||
* StatsTypeAdapterFactory stats = new StatsTypeAdapterFactory();
|
||||
* Gson gson = new GsonBuilder().registerTypeAdapterFactory(stats).create();
|
||||
* // Call gson.toJson() and fromJson methods on objects
|
||||
* System.out.println("Num JSON reads" + stats.numReads);
|
||||
* System.out.println("Num JSON writes" + stats.numWrites);
|
||||
* }</pre>
|
||||
* Note that since you can not override type adapter factories for String and Java primitive
|
||||
* types, our stats factory will not count the number of String or primitives that will be
|
||||
* read or written.
|
||||
* @param skipPast The type adapter factory that needs to be skipped while searching for
|
||||
* a matching type adapter. In most cases, you should just pass <i>this</i> (the type adapter
|
||||
* factory from where {@link #getDelegateAdapter} method is being invoked).
|
||||
* @param type Type for which the delegate adapter is being searched for.
|
||||
*
|
||||
* @since 2.2
|
||||
*/
|
||||
public <T> TypeAdapter<T> getDelegateAdapter(TypeAdapterFactory skipPast, TypeToken<T> type) {
|
||||
boolean skipPastFound = false;
|
||||
|
||||
for (TypeAdapterFactory factory : factories) {
|
||||
if (!skipPastFound) {
|
||||
if (factory == skipPast) {
|
||||
skipPastFound = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
TypeAdapter<T> candidate = factory.create(this, type);
|
||||
if (candidate != null) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("GSON cannot serialize " + type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type adapter for {@code} type.
|
||||
*
|
||||
* @throws IllegalArgumentException if this GSON cannot serialize and
|
||||
* deserialize {@code type}.
|
||||
*/
|
||||
public <T> TypeAdapter<T> getAdapter(Class<T> type) {
|
||||
return getAdapter(TypeToken.get(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.massivecore.xlib.gson.reflect.TypeToken} class. For example,
|
||||
* to get the type for {@code Collection<Foo>}, you should use:
|
||||
* <pre>
|
||||
* Type typeOfSrc = new TypeToken<Collection<Foo>>(){}.getType();
|
||||
* </pre>
|
||||
* @return Json representation of {@code src}
|
||||
* @since 1.4
|
||||
*/
|
||||
public JsonElement toJsonTree(Object src, Type typeOfSrc) {
|
||||
JsonTreeWriter writer = new JsonTreeWriter();
|
||||
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.massivecore.xlib.gson.reflect.TypeToken} class. For example,
|
||||
* to get the type for {@code Collection<Foo>}, you should use:
|
||||
* <pre>
|
||||
* Type typeOfSrc = new TypeToken<Collection<Foo>>(){}.getType();
|
||||
* </pre>
|
||||
* @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.massivecore.xlib.gson.reflect.TypeToken} class. For example,
|
||||
* to get the type for {@code Collection<Foo>}, you should use:
|
||||
* <pre>
|
||||
* Type typeOfSrc = new TypeToken<Collection<Foo>>(){}.getType();
|
||||
* </pre>
|
||||
* @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 = 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<Object>) adapter).write(writer, src);
|
||||
} catch (IOException e) {
|
||||
throw new JsonIOException(e);
|
||||
} finally {
|
||||
writer.setLenient(oldLenient);
|
||||
writer.setHtmlSafe(oldHtmlSafe);
|
||||
writer.setSerializeNulls(oldSerializeNulls);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a tree of {@link JsonElement}s into its equivalent JSON representation.
|
||||
*
|
||||
* @param jsonElement root of a tree of {@link JsonElement}s
|
||||
* @return JSON String representation of the tree
|
||||
* @since 1.4
|
||||
*/
|
||||
public String toJson(JsonElement jsonElement) {
|
||||
StringWriter writer = new StringWriter();
|
||||
toJson(jsonElement, writer);
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes out the equivalent JSON for a tree of {@link JsonElement}s.
|
||||
*
|
||||
* @param jsonElement root of a tree of {@link JsonElement}s
|
||||
* @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.4
|
||||
*/
|
||||
public void toJson(JsonElement jsonElement, Appendable writer) throws JsonIOException {
|
||||
try {
|
||||
JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer));
|
||||
toJson(jsonElement, jsonWriter);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new JSON writer configured for this GSON and with the non-execute
|
||||
* prefix if that is configured.
|
||||
*/
|
||||
private JsonWriter newJsonWriter(Writer writer) throws IOException {
|
||||
if (generateNonExecutableJson) {
|
||||
writer.write(JSON_NON_EXECUTABLE_PREFIX);
|
||||
}
|
||||
JsonWriter jsonWriter = new JsonWriter(writer);
|
||||
if (prettyPrinting) {
|
||||
jsonWriter.setIndent(" ");
|
||||
}
|
||||
jsonWriter.setSerializeNulls(serializeNulls);
|
||||
return jsonWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the JSON for {@code jsonElement} to {@code writer}.
|
||||
* @throws JsonIOException if there was a problem writing to the writer
|
||||
*/
|
||||
public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOException {
|
||||
boolean oldLenient = writer.isLenient();
|
||||
writer.setLenient(true);
|
||||
boolean oldHtmlSafe = writer.isHtmlSafe();
|
||||
writer.setHtmlSafe(htmlSafe);
|
||||
boolean oldSerializeNulls = writer.getSerializeNulls();
|
||||
writer.setSerializeNulls(serializeNulls);
|
||||
try {
|
||||
Streams.write(jsonElement, writer);
|
||||
} catch (IOException e) {
|
||||
throw new JsonIOException(e);
|
||||
} finally {
|
||||
writer.setLenient(oldLenient);
|
||||
writer.setHtmlSafe(oldHtmlSafe);
|
||||
writer.setSerializeNulls(oldSerializeNulls);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method deserializes the specified Json into an object of the specified class. It is not
|
||||
* suitable to use if the specified class is a generic type since it will not have the generic
|
||||
* type information because of the Type Erasure feature of Java. Therefore, this method should not
|
||||
* be used if the desired type is a generic type. Note that this method works fine if the any of
|
||||
* the fields of the specified object are generics, just the object itself should not be a
|
||||
* generic type. For the cases when the object is of generic type, invoke
|
||||
* {@link #fromJson(String, Type)}. If you have the Json in a {@link Reader} instead of
|
||||
* a String, use {@link #fromJson(Reader, Class)} instead.
|
||||
*
|
||||
* @param <T> the type of the desired object
|
||||
* @param json the string from which the object is to be deserialized
|
||||
* @param classOfT the class of T
|
||||
* @return an object of type T from the string. Returns {@code null} if {@code json} is {@code null}.
|
||||
* @throws JsonSyntaxException if json is not a valid representation for an object of type
|
||||
* classOfT
|
||||
*/
|
||||
public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
|
||||
Object object = fromJson(json, (Type) classOfT);
|
||||
return Primitives.wrap(classOfT).cast(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method deserializes the specified Json into an object of the specified type. This method
|
||||
* is useful if the specified object is a generic type. For non-generic objects, use
|
||||
* {@link #fromJson(String, Class)} instead. If you have the Json in a {@link Reader} instead of
|
||||
* a String, use {@link #fromJson(Reader, Type)} instead.
|
||||
*
|
||||
* @param <T> the type of the desired object
|
||||
* @param json the string from which the object is to be deserialized
|
||||
* @param typeOfT The specific genericized type of src. You can obtain this type by using the
|
||||
* {@link com.massivecraft.massivecore.xlib.gson.reflect.TypeToken} class. For example, to get the type for
|
||||
* {@code Collection<Foo>}, you should use:
|
||||
* <pre>
|
||||
* Type typeOfT = new TypeToken<Collection<Foo>>(){}.getType();
|
||||
* </pre>
|
||||
* @return an object of type T from the string. Returns {@code null} if {@code json} is {@code null}.
|
||||
* @throws JsonParseException if json is not a valid representation for an object of type typeOfT
|
||||
* @throws JsonSyntaxException if json is not a valid representation for an object of type
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
|
||||
if (json == null) {
|
||||
return null;
|
||||
}
|
||||
StringReader reader = new StringReader(json);
|
||||
T target = (T) fromJson(reader, typeOfT);
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method deserializes the Json read from the specified reader into an object of the
|
||||
* specified class. It is not suitable to use if the specified class is a generic type since it
|
||||
* will not have the generic type information because of the Type Erasure feature of Java.
|
||||
* Therefore, this method should not be used if the desired type is a generic type. Note that
|
||||
* this method works fine if the any of the fields of the specified object are generics, just the
|
||||
* object itself should not be a generic type. For the cases when the object is of generic type,
|
||||
* invoke {@link #fromJson(Reader, Type)}. If you have the Json in a String form instead of a
|
||||
* {@link Reader}, use {@link #fromJson(String, Class)} instead.
|
||||
*
|
||||
* @param <T> the type of the desired object
|
||||
* @param json the reader producing the Json from which the object is to be deserialized.
|
||||
* @param classOfT the class of T
|
||||
* @return an object of type T from the string. Returns {@code null} if {@code json} is at EOF.
|
||||
* @throws JsonIOException if there was a problem reading from the Reader
|
||||
* @throws JsonSyntaxException if json is not a valid representation for an object of type
|
||||
* @since 1.2
|
||||
*/
|
||||
public <T> T fromJson(Reader json, Class<T> classOfT) throws JsonSyntaxException, JsonIOException {
|
||||
JsonReader jsonReader = new JsonReader(json);
|
||||
Object object = fromJson(jsonReader, classOfT);
|
||||
assertFullConsumption(object, jsonReader);
|
||||
return Primitives.wrap(classOfT).cast(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method deserializes the Json read from the specified reader into an object of the
|
||||
* specified type. This method is useful if the specified object is a generic type. For
|
||||
* non-generic objects, use {@link #fromJson(Reader, Class)} instead. If you have the Json in a
|
||||
* String form instead of a {@link Reader}, use {@link #fromJson(String, Type)} instead.
|
||||
*
|
||||
* @param <T> the type of the desired object
|
||||
* @param json the reader producing Json from which the object is to be deserialized
|
||||
* @param typeOfT The specific genericized type of src. You can obtain this type by using the
|
||||
* {@link com.massivecraft.massivecore.xlib.gson.reflect.TypeToken} class. For example, to get the type for
|
||||
* {@code Collection<Foo>}, you should use:
|
||||
* <pre>
|
||||
* Type typeOfT = new TypeToken<Collection<Foo>>(){}.getType();
|
||||
* </pre>
|
||||
* @return an object of type T from the json. Returns {@code null} if {@code json} is at EOF.
|
||||
* @throws JsonIOException if there was a problem reading from the Reader
|
||||
* @throws JsonSyntaxException if json is not a valid representation for an object of type
|
||||
* @since 1.2
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
|
||||
JsonReader jsonReader = new JsonReader(json);
|
||||
T object = (T) fromJson(jsonReader, typeOfT);
|
||||
assertFullConsumption(object, jsonReader);
|
||||
return object;
|
||||
}
|
||||
|
||||
private static void assertFullConsumption(Object obj, JsonReader reader) {
|
||||
try {
|
||||
if (obj != null && reader.peek() != JsonToken.END_DOCUMENT) {
|
||||
throw new JsonIOException("JSON document was not fully consumed.");
|
||||
}
|
||||
} catch (MalformedJsonException e) {
|
||||
throw new JsonSyntaxException(e);
|
||||
} catch (IOException e) {
|
||||
throw new JsonIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the next JSON value from {@code reader} and convert it to an object
|
||||
* of type {@code typeOfT}. Returns {@code null}, if the {@code reader} is at EOF.
|
||||
* Since Type is not parameterized by T, this method is type unsafe and should be used carefully
|
||||
*
|
||||
* @throws JsonIOException if there was a problem writing to the Reader
|
||||
* @throws JsonSyntaxException if json is not a valid representation for an object of type
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
|
||||
boolean isEmpty = true;
|
||||
boolean oldLenient = reader.isLenient();
|
||||
reader.setLenient(true);
|
||||
try {
|
||||
reader.peek();
|
||||
isEmpty = false;
|
||||
TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
|
||||
TypeAdapter<T> typeAdapter = getAdapter(typeToken);
|
||||
T object = typeAdapter.read(reader);
|
||||
return object;
|
||||
} catch (EOFException e) {
|
||||
/*
|
||||
* For compatibility with JSON 1.5 and earlier, we return null for empty
|
||||
* documents instead of throwing.
|
||||
*/
|
||||
if (isEmpty) {
|
||||
return null;
|
||||
}
|
||||
throw new JsonSyntaxException(e);
|
||||
} catch (IllegalStateException e) {
|
||||
throw new JsonSyntaxException(e);
|
||||
} catch (IOException e) {
|
||||
// TODO(inder): Figure out whether it is indeed right to rethrow this as JsonSyntaxException
|
||||
throw new JsonSyntaxException(e);
|
||||
} finally {
|
||||
reader.setLenient(oldLenient);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method deserializes the Json read from the specified parse tree into an object of the
|
||||
* specified type. It is not suitable to use if the specified class is a generic type since it
|
||||
* will not have the generic type information because of the Type Erasure feature of Java.
|
||||
* Therefore, this method should not be used if the desired type is a generic type. Note that
|
||||
* this method works fine if the any of the fields of the specified object are generics, just the
|
||||
* object itself should not be a generic type. For the cases when the object is of generic type,
|
||||
* invoke {@link #fromJson(JsonElement, Type)}.
|
||||
* @param <T> the type of the desired object
|
||||
* @param json the root of the parse tree of {@link JsonElement}s from which the object is to
|
||||
* be deserialized
|
||||
* @param classOfT The class of T
|
||||
* @return an object of type T from the json. Returns {@code null} if {@code json} is {@code null}.
|
||||
* @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
|
||||
* @since 1.3
|
||||
*/
|
||||
public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException {
|
||||
Object object = fromJson(json, (Type) classOfT);
|
||||
return Primitives.wrap(classOfT).cast(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method deserializes the Json read from the specified parse tree into an object of the
|
||||
* specified type. This method is useful if the specified object is a generic type. For
|
||||
* non-generic objects, use {@link #fromJson(JsonElement, Class)} instead.
|
||||
*
|
||||
* @param <T> the type of the desired object
|
||||
* @param json the root of the parse tree of {@link JsonElement}s from which the object is to
|
||||
* be deserialized
|
||||
* @param typeOfT The specific genericized type of src. You can obtain this type by using the
|
||||
* {@link com.massivecraft.massivecore.xlib.gson.reflect.TypeToken} class. For example, to get the type for
|
||||
* {@code Collection<Foo>}, you should use:
|
||||
* <pre>
|
||||
* Type typeOfT = new TypeToken<Collection<Foo>>(){}.getType();
|
||||
* </pre>
|
||||
* @return an object of type T from the json. Returns {@code null} if {@code json} is {@code null}.
|
||||
* @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
|
||||
* @since 1.3
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException {
|
||||
if (json == null) {
|
||||
return null;
|
||||
}
|
||||
return (T) fromJson(new JsonTreeReader(json), typeOfT);
|
||||
}
|
||||
|
||||
static class FutureTypeAdapter<T> extends TypeAdapter<T> {
|
||||
private TypeAdapter<T> delegate;
|
||||
|
||||
public void setDelegate(TypeAdapter<T> typeAdapter) {
|
||||
if (delegate != null) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
delegate = typeAdapter;
|
||||
}
|
||||
|
||||
@Override public T read(JsonReader in) throws IOException {
|
||||
if (delegate == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return delegate.read(in);
|
||||
}
|
||||
|
||||
@Override public void write(JsonWriter out, T value) throws IOException {
|
||||
if (delegate == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
delegate.write(out, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder("{serializeNulls:")
|
||||
.append(serializeNulls)
|
||||
.append("factories:").append(factories)
|
||||
.append(",instanceCreators:").append(constructorConstructor)
|
||||
.append("}")
|
||||
.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,566 @@
|
||||
/*
|
||||
* 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.massivecore.xlib.gson;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.$Gson$Preconditions;
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.Excluder;
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.bind.TypeAdapters;
|
||||
import com.massivecraft.massivecore.xlib.gson.reflect.TypeToken;
|
||||
|
||||
/**
|
||||
* <p>Use this builder to construct a {@link Gson} instance when you need to set configuration
|
||||
* options other than the default. For {@link Gson} with default configuration, it is simpler to
|
||||
* use {@code new Gson()}. {@code GsonBuilder} is best used by creating it, and then invoking its
|
||||
* various configuration methods, and finally calling create.</p>
|
||||
*
|
||||
* <p>The following is an example shows how to use the {@code GsonBuilder} to construct a Gson
|
||||
* instance:
|
||||
*
|
||||
* <pre>
|
||||
* Gson gson = new GsonBuilder()
|
||||
* .registerTypeAdapter(Id.class, new IdTypeAdapter())
|
||||
* .enableComplexMapKeySerialization()
|
||||
* .serializeNulls()
|
||||
* .setDateFormat(DateFormat.LONG)
|
||||
* .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
|
||||
* .setPrettyPrinting()
|
||||
* .setVersion(1.0)
|
||||
* .create();
|
||||
* </pre></p>
|
||||
*
|
||||
* <p>NOTES:
|
||||
* <ul>
|
||||
* <li> the order of invocation of configuration methods does not matter.</li>
|
||||
* <li> 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.</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
* @author Jesse Wilson
|
||||
*/
|
||||
public final class GsonBuilder {
|
||||
private Excluder excluder = Excluder.DEFAULT;
|
||||
private LongSerializationPolicy longSerializationPolicy = LongSerializationPolicy.DEFAULT;
|
||||
private FieldNamingStrategy fieldNamingPolicy = FieldNamingPolicy.IDENTITY;
|
||||
private final Map<Type, InstanceCreator<?>> instanceCreators
|
||||
= new HashMap<Type, InstanceCreator<?>>();
|
||||
private final List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
|
||||
/** tree-style hierarchy factories. These come after factories for backwards compatibility. */
|
||||
private final List<TypeAdapterFactory> hierarchyFactories = new ArrayList<TypeAdapterFactory>();
|
||||
private boolean serializeNulls;
|
||||
private String datePattern;
|
||||
private int dateStyle = DateFormat.DEFAULT;
|
||||
private int timeStyle = DateFormat.DEFAULT;
|
||||
private boolean complexMapKeySerialization;
|
||||
private boolean serializeSpecialFloatingPointValues;
|
||||
private boolean escapeHtmlChars = true;
|
||||
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() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
excluder = excluder.withVersion(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) {
|
||||
excluder = excluder.withModifiers(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
|
||||
* <a href="http://code.google.com/p/google-gson/issues/detail?id=42">Gson Issue 42</a>
|
||||
* 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.massivecore.xlib.gson.annotations.Expose} annotation.
|
||||
*
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
*/
|
||||
public GsonBuilder excludeFieldsWithoutExposeAnnotation() {
|
||||
excluder = excluder.excludeFieldsWithoutExposeAnnotation();
|
||||
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 <strong>serialized</strong> 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:
|
||||
*
|
||||
* <h3>Maps as JSON objects</h3>
|
||||
* 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}.
|
||||
*
|
||||
* <p>Below is an example:
|
||||
* <pre> {@code
|
||||
* Gson gson = new GsonBuilder()
|
||||
* .register(Point.class, new MyPointTypeAdapter())
|
||||
* .enableComplexMapKeySerialization()
|
||||
* .create();
|
||||
*
|
||||
* Map<Point, String> original = new LinkedHashMap<Point, String>();
|
||||
* original.put(new Point(5, 6), "a");
|
||||
* original.put(new Point(8, 8), "b");
|
||||
* System.out.println(gson.toJson(original, type));
|
||||
* }</pre>
|
||||
* The above code prints this JSON object:<pre> {@code
|
||||
* {
|
||||
* "(5,6)": "a",
|
||||
* "(8,8)": "b"
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* <h3>Maps as JSON arrays</h3>
|
||||
* 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}}.
|
||||
*
|
||||
* <p>Given the assumption above, a {@code Map<Point, String>} will be
|
||||
* serialize as an array of arrays (can be viewed as an entry set of pairs).
|
||||
*
|
||||
* <p>Below is an example of serializing complex types as JSON arrays:
|
||||
* <pre> {@code
|
||||
* Gson gson = new GsonBuilder()
|
||||
* .enableComplexMapKeySerialization()
|
||||
* .create();
|
||||
*
|
||||
* Map<Point, String> original = new LinkedHashMap<Point, String>();
|
||||
* 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:
|
||||
* <pre> {@code
|
||||
* [
|
||||
* [
|
||||
* {
|
||||
* "x": 5,
|
||||
* "y": 6
|
||||
* },
|
||||
* "a"
|
||||
* ],
|
||||
* [
|
||||
* {
|
||||
* "x": 8,
|
||||
* "y": 8
|
||||
* },
|
||||
* "b"
|
||||
* ]
|
||||
* ]
|
||||
* }</pre>
|
||||
*
|
||||
* @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() {
|
||||
excluder = excluder.disableInnerClassSerialization();
|
||||
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) {
|
||||
this.fieldNamingPolicy = namingConvention;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
this.fieldNamingPolicy = 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) {
|
||||
for (ExclusionStrategy strategy : strategies) {
|
||||
excluder = excluder.withExclusionStrategy(strategy, true, true);
|
||||
}
|
||||
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) {
|
||||
excluder = excluder.withExclusionStrategy(strategy, true, false);
|
||||
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) {
|
||||
excluder = excluder.withExclusionStrategy(strategy, false, true);
|
||||
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.
|
||||
*
|
||||
* <p>The date format will be used to serialize and deserialize {@link java.util.Date}, {@link
|
||||
* java.sql.Timestamp} and {@link java.sql.Date}.
|
||||
*
|
||||
* <p>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.</p>
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* <p>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.</p>
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* <p>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.</p>
|
||||
*
|
||||
* @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 TypeAdapter}, {@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 a type adapter was
|
||||
* previously registered for the specified {@code type}, it is overwritten.
|
||||
*
|
||||
* <p>This registers the type specified and no other types: you must manually register related
|
||||
* types! For example, applications registering {@code boolean.class} should also register {@code
|
||||
* Boolean.class}.
|
||||
*
|
||||
* @param type the type definition for the type adapter being registered
|
||||
* @param typeAdapter This object must implement at least one of the {@link TypeAdapter},
|
||||
* {@link InstanceCreator}, {@link JsonSerializer}, and a {@link JsonDeserializer} interfaces.
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
|
||||
$Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
|
||||
|| typeAdapter instanceof JsonDeserializer<?>
|
||||
|| typeAdapter instanceof InstanceCreator<?>
|
||||
|| typeAdapter instanceof TypeAdapter<?>);
|
||||
if (typeAdapter instanceof InstanceCreator<?>) {
|
||||
instanceCreators.put(type, (InstanceCreator) typeAdapter);
|
||||
}
|
||||
if (typeAdapter instanceof JsonSerializer<?> || typeAdapter instanceof JsonDeserializer<?>) {
|
||||
TypeToken<?> typeToken = TypeToken.get(type);
|
||||
factories.add(TreeTypeAdapter.newFactoryWithMatchRawType(typeToken, typeAdapter));
|
||||
}
|
||||
if (typeAdapter instanceof TypeAdapter<?>) {
|
||||
factories.add(TypeAdapters.newFactory(TypeToken.get(type), (TypeAdapter)typeAdapter));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a factory for type adapters. Registering a factory is useful when the type
|
||||
* adapter needs to be configured based on the type of the field being processed. Gson
|
||||
* is designed to handle a large number of factories, so you should consider registering
|
||||
* them to be at par with registering an individual type adapter.
|
||||
*
|
||||
* @since 2.1
|
||||
*/
|
||||
public GsonBuilder registerTypeAdapterFactory(TypeAdapterFactory factory) {
|
||||
factories.add(factory);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson for custom serialization or deserialization for an inheritance type hierarchy.
|
||||
* This method combines the registration of a {@link TypeAdapter}, {@link JsonSerializer} and
|
||||
* a {@link JsonDeserializer}. If a type adapter was previously registered for the specified
|
||||
* type hierarchy, it is overridden. If a type adapter 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 {@link TypeAdapter},
|
||||
* {@link JsonSerializer} or {@link JsonDeserializer} interfaces.
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
* @since 1.7
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public GsonBuilder registerTypeHierarchyAdapter(Class<?> baseType, Object typeAdapter) {
|
||||
$Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
|
||||
|| typeAdapter instanceof JsonDeserializer<?>
|
||||
|| typeAdapter instanceof TypeAdapter<?>);
|
||||
if (typeAdapter instanceof JsonDeserializer || typeAdapter instanceof JsonSerializer) {
|
||||
hierarchyFactories.add(0,
|
||||
TreeTypeAdapter.newTypeHierarchyFactory(baseType, typeAdapter));
|
||||
}
|
||||
if (typeAdapter instanceof TypeAdapter<?>) {
|
||||
factories.add(TypeAdapters.newTypeHierarchyFactory(baseType, (TypeAdapter)typeAdapter));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Section 2.4 of <a href="http://www.ietf.org/rfc/rfc4627.txt">JSON specification</a> disallows
|
||||
* special double values (NaN, Infinity, -Infinity). However,
|
||||
* <a href="http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf">Javascript
|
||||
* specification</a> (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.
|
||||
*
|
||||
* <p>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<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
|
||||
factories.addAll(this.factories);
|
||||
Collections.reverse(factories);
|
||||
factories.addAll(this.hierarchyFactories);
|
||||
addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, factories);
|
||||
|
||||
return new Gson(excluder, fieldNamingPolicy, instanceCreators,
|
||||
serializeNulls, complexMapKeySerialization,
|
||||
generateNonExecutableJson, escapeHtmlChars, prettyPrinting,
|
||||
serializeSpecialFloatingPointValues, longSerializationPolicy, factories);
|
||||
}
|
||||
|
||||
private void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle,
|
||||
List<TypeAdapterFactory> factories) {
|
||||
DefaultDateTypeAdapter dateTypeAdapter;
|
||||
if (datePattern != null && !"".equals(datePattern.trim())) {
|
||||
dateTypeAdapter = new DefaultDateTypeAdapter(datePattern);
|
||||
} else if (dateStyle != DateFormat.DEFAULT && timeStyle != DateFormat.DEFAULT) {
|
||||
dateTypeAdapter = new DefaultDateTypeAdapter(dateStyle, timeStyle);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
factories.add(TreeTypeAdapter.newFactory(TypeToken.get(Date.class), dateTypeAdapter));
|
||||
factories.add(TreeTypeAdapter.newFactory(TypeToken.get(Timestamp.class), dateTypeAdapter));
|
||||
factories.add(TreeTypeAdapter.newFactory(TypeToken.get(java.sql.Date.class), dateTypeAdapter));
|
||||
}
|
||||
}
|
@ -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.massivecore.xlib.gson;
|
||||
|
||||
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.
|
||||
* <p>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.</p>
|
||||
*
|
||||
* <pre>
|
||||
* 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;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>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:</p>
|
||||
*
|
||||
* <pre>
|
||||
* private Id() {
|
||||
* this(Object.class, 0L);
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>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}:</p>
|
||||
*
|
||||
* <pre>
|
||||
* class IdInstanceCreator implements InstanceCreator<Id> {
|
||||
* public Id createInstance(Type type) {
|
||||
* return new Id(Object.class, 0L);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>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
|
||||
* <i>new</i> 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:</p>
|
||||
*
|
||||
* <pre>
|
||||
* Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdInstanceCreator()).create();
|
||||
* </pre>
|
||||
*
|
||||
* @param <T> the type of object that will be created by this implementation.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*/
|
||||
public interface InstanceCreator<T> {
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
@ -0,0 +1,337 @@
|
||||
/*
|
||||
* 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.massivecore.xlib.gson;
|
||||
|
||||
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<JsonElement> {
|
||||
private final List<JsonElement> elements;
|
||||
|
||||
/**
|
||||
* Creates an empty JsonArray.
|
||||
*/
|
||||
public JsonArray() {
|
||||
elements = new ArrayList<JsonElement>();
|
||||
}
|
||||
|
||||
@Override
|
||||
JsonArray deepCopy() {
|
||||
JsonArray result = new JsonArray();
|
||||
for (JsonElement element : elements) {
|
||||
result.add(element.deepCopy());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the element at the specified position in this array with the specified element.
|
||||
* Element can be null.
|
||||
* @param index index of the element to replace
|
||||
* @param element element to be stored at the specified position
|
||||
* @return the element previously at the specified position
|
||||
* @throws IndexOutOfBoundsException if the specified index is outside the array bounds
|
||||
*/
|
||||
public JsonElement set(int index, JsonElement element) {
|
||||
return elements.set(index, element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the first occurrence of the specified element from this array, if it is present.
|
||||
* If the array does not contain the element, it is unchanged.
|
||||
* @param element element to be removed from this array, if present
|
||||
* @return true if this array contained the specified element, false otherwise
|
||||
* @since 2.3
|
||||
*/
|
||||
public boolean remove(JsonElement element) {
|
||||
return elements.remove(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the element at the specified position in this array. Shifts any subsequent elements
|
||||
* to the left (subtracts one from their indices). Returns the element that was removed from
|
||||
* the array.
|
||||
* @param index index the index of the element to be removed
|
||||
* @return the element previously at the specified position
|
||||
* @throws IndexOutOfBoundsException if the specified index is outside the array bounds
|
||||
* @since 2.3
|
||||
*/
|
||||
public JsonElement remove(int index) {
|
||||
return elements.remove(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this array contains the specified element.
|
||||
* @return true if this array contains the specified element.
|
||||
* @param element whose presence in this array is to be tested
|
||||
* @since 2.3
|
||||
*/
|
||||
public boolean contains(JsonElement element) {
|
||||
return elements.contains(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<JsonElement> 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();
|
||||
}
|
||||
}
|
@ -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.massivecore.xlib.gson;
|
||||
|
||||
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 <T> 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> T deserialize(JsonElement json, Type typeOfT) throws JsonParseException;
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.massivecore.xlib.gson;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* <p>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)}.</p>
|
||||
*
|
||||
* <p>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}.</p>
|
||||
*
|
||||
* <pre>
|
||||
* 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;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>The default deserialization of {@code Id(com.foo.MyObject.class, 20L)} will require the
|
||||
* Json string to be <code>{"clazz":com.foo.MyObject,"value":20}</code>. 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:</p>
|
||||
*
|
||||
* <pre>
|
||||
* class IdDeserializer implements JsonDeserializer<Id>() {
|
||||
* public Id deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
* throws JsonParseException {
|
||||
* return new Id((Class)typeOfT, id.getValue());
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>You will also need to register {@code IdDeserializer} with Gson as follows:</p>
|
||||
*
|
||||
* <pre>
|
||||
* Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdDeserializer()).create();
|
||||
* </pre>
|
||||
*
|
||||
* <p>New applications should prefer {@link TypeAdapter}, whose streaming API
|
||||
* is more efficient than this interface's tree API.
|
||||
*
|
||||
* @author Inderjeet Singh
|
||||
* @author Joel Leitch
|
||||
*
|
||||
* @param <T> 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<T> {
|
||||
|
||||
/**
|
||||
* Gson invokes this call-back method during deserialization when it encounters a field of the
|
||||
* specified type.
|
||||
* <p>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;
|
||||
}
|
@ -0,0 +1,331 @@
|
||||
/*
|
||||
* 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.massivecore.xlib.gson;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.Streams;
|
||||
import com.massivecraft.massivecore.xlib.gson.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 {
|
||||
/**
|
||||
* Returns a deep copy of this element. Immutable elements like primitives
|
||||
* and nulls are not copied.
|
||||
*/
|
||||
abstract JsonElement deepCopy();
|
||||
|
||||
/**
|
||||
* 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 IllegalStateException} 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 IllegalStateException} 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 IllegalStateException} 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 IllegalStateException} 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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.massivecore.xlib.gson;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.massivecore.xlib.gson;
|
||||
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
|
||||
@Override
|
||||
JsonNull deepCopy() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* 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.massivecore.xlib.gson;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.LinkedTreeMap;
|
||||
|
||||
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 {
|
||||
private final LinkedTreeMap<String, JsonElement> members =
|
||||
new LinkedTreeMap<String, JsonElement>();
|
||||
|
||||
@Override
|
||||
JsonObject deepCopy() {
|
||||
JsonObject result = new JsonObject();
|
||||
for (Map.Entry<String, JsonElement> entry : members.entrySet()) {
|
||||
result.add(entry.getKey(), entry.getValue().deepCopy());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(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<Map.Entry<String, JsonElement>> 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) {
|
||||
return members.get(memberName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
@ -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.massivecore.xlib.gson;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* <p>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}.</p>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.massivecore.xlib.gson;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.gson.internal.Streams;
|
||||
import com.massivecraft.massivecore.xlib.gson.stream.JsonReader;
|
||||
import com.massivecraft.massivecore.xlib.gson.stream.JsonToken;
|
||||
import com.massivecraft.massivecore.xlib.gson.stream.MalformedJsonException;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
} finally {
|
||||
json.setLenient(lenient);
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user