Sorry could not shade. m2eclipse does not handle it well enough.

This commit is contained in:
Olof Larsson 2014-09-13 10:24:26 +02:00
parent e1d92aa421
commit b732a26a9e
368 changed files with 57439 additions and 236 deletions

47
pom.xml
View File

@ -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>

View File

@ -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>
{

View File

@ -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())

View File

@ -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()
{

View File

@ -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
{

View File

@ -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
{

View File

@ -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
{

View File

@ -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.

View File

@ -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

View File

@ -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>
{

View File

@ -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;

View File

@ -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());
}
}

View File

@ -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>
{

View File

@ -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>
{

View File

@ -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

View File

@ -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)

View File

@ -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
{

View File

@ -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

View File

@ -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>
{

View File

@ -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>
{

View File

@ -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
{

View File

@ -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
{

View File

@ -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
{

View File

@ -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);

View File

@ -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

View File

@ -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
{

View File

@ -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
{

View File

@ -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
{

View File

@ -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
{

View File

@ -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.

View 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" );
}
}

View File

@ -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 );
}

View File

@ -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;
}

View File

@ -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 );
}

View File

@ -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;
}

View File

@ -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 {
}

View File

@ -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();
}

View File

@ -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>();
}

View File

@ -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' );
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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." );
}
}

View File

@ -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>();
}

View File

@ -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" );
}

View File

@ -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;
}

View File

@ -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" );
}
}

View File

@ -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" );
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 );
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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];
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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];
}
};
}

View File

@ -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);
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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;
}

View File

@ -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;
}
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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";
}
}

View File

@ -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";
}
}

View File

@ -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 );
}
}
}

View File

@ -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;
}

View File

@ -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>

View File

@ -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;
}
}
}

View File

@ -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!");
}
}
}

View File

@ -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();
}

View File

@ -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 &lt; 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();
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}

View File

@ -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>();
}

View File

@ -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();
}
}

View File

@ -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();
}

View File

@ -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 {
}

View File

@ -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 {
}

View File

@ -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 {
}

View File

@ -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>

View File

@ -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();
}
}

View File

@ -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&lt;?&gt; excludedThisClass;
*
* public SpecificClassExclusionStrategy(Class&lt;?&gt; excludedThisClass) {
* this.excludedThisClass = excludedThisClass;
* }
*
* public boolean shouldSkipClass(Class&lt;?&gt; 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 &#64interface FooAnnotation {
* // some implementation here
* }
*
* // Excludes any field (or class) that is tagged with an "&#64FooAnnotation"
* private static class FooAnnotationExclusionStrategy implements ExclusionStrategy {
* public boolean shouldSkipClass(Class&lt;?&gt; 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);
}

View File

@ -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&lt;String&gt; red;
* }
*
* Type listParmeterizedType = new TypeToken&lt;List&lt;String&gt;&gt;() {}.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&lt;String&gt; 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();
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View 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&lt;List&lt;String&gt;&gt;() {}.getType();
* List&lt;String&gt; target = new LinkedList&lt;String&gt;();
* target.add("blah");
*
* Gson gson = new Gson();
* String json = gson.toJson(target, listType);
* List&lt;String&gt; 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>&quot;versionNumber&quot;</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 &lt;T&gt; TypeAdapter&lt;T&gt; create(Gson gson, TypeToken&lt;T&gt; type) {
* final TypeAdapter&lt;T&gt; delegate = gson.getDelegateAdapter(this, type);
* return new TypeAdapter&lt;T&gt;() {
* 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&lt;Collection&lt;Foo&gt;&gt;(){}.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&lt;Collection&lt;Foo&gt;&gt;(){}.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&lt;Collection&lt;Foo&gt;&gt;(){}.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&lt;Collection&lt;Foo&gt;&gt;(){}.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&lt;Collection&lt;Foo&gt;&gt;(){}.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&lt;Collection&lt;Foo&gt;&gt;(){}.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();
}
}

View File

@ -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 &lt; &gt; 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));
}
}

View File

@ -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&lt;T&gt; {
* private final Class&lt;T&gt; clazz;
* private final long value;
* public Id(Class&lt;T&gt; 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&lt;Id&gt; {
* 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);
}

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -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&lt;T&gt; {
* private final Class&lt;T&gt; clazz;
* private final long value;
* public Id(Class&lt;T&gt; 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&lt;Id&gt;() {
* 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;
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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