Shade in GSON, BSON and MongoDB.
This commit is contained in:
parent
2e589a195e
commit
e0656ab9ea
97
dependency-reduced-pom.xml
Normal file
97
dependency-reduced-pom.xml
Normal file
@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.massivecraft</groupId>
|
||||
<artifactId>MassiveCore</artifactId>
|
||||
<name>MassiveCore</name>
|
||||
<version>7.5.0</version>
|
||||
<build>
|
||||
<sourceDirectory>src</sourceDirectory>
|
||||
<defaultGoal>clean package install</defaultGoal>
|
||||
<resources>
|
||||
<resource>
|
||||
<targetPath>.</targetPath>
|
||||
<filtering>true</filtering>
|
||||
<directory>.</directory>
|
||||
<includes>
|
||||
<include>*.yml</include>
|
||||
<include>*.md</include>
|
||||
<include>*.txt</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
<finalName>MassiveCore</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<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>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>bukkit-repo</id>
|
||||
<url>http://repo.bukkit.org/content/groups/public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>vault-repo</id>
|
||||
<url>http://nexus.theyeticave.net/content/repositories/pub_releases</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<version>1.7.9-R0.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.milkbowl.vault</groupId>
|
||||
<artifactId>Vault</artifactId>
|
||||
<version>1.4.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
</project>
|
||||
|
14
pom.xml
14
pom.xml
@ -50,6 +50,7 @@
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<include>com.google.code.gson:gson</include>
|
||||
<include>org.mongodb:mongo-java-driver</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
@ -57,6 +58,14 @@
|
||||
<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>
|
||||
@ -82,6 +91,11 @@
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.2.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mongodb</groupId>
|
||||
<artifactId>mongo-java-driver</artifactId>
|
||||
<version>2.12.3</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<repositories>
|
||||
|
@ -4,8 +4,8 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.massivecraft.massivecore.store.Entity;
|
||||
import com.massivecraft.massivecore.xlib.gson.annotations.SerializedName;
|
||||
|
||||
public class Aspect extends Entity<Aspect>
|
||||
{
|
||||
|
@ -7,11 +7,18 @@ 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;
|
||||
@ -36,13 +43,6 @@ 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.bson.types.ObjectId;
|
||||
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
|
||||
{
|
||||
|
@ -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.massivecraft.massivecore.xlib.mongodb.WriteConcern;
|
||||
import com.mongodb.WriteConcern;
|
||||
|
||||
public class MassiveCoreMConf extends Entity<MassiveCoreMConf>
|
||||
{
|
||||
|
@ -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.massivecraft.massivecore.xlib.gson.Gson;
|
||||
import com.massivecraft.massivecore.xlib.gson.GsonBuilder;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
public abstract class MassivePlugin extends JavaPlugin implements Listener
|
||||
{
|
||||
|
@ -6,7 +6,7 @@ import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.massivecraft.massivecore.store.accessor.Accessor;
|
||||
import com.massivecraft.massivecore.util.DiscUtil;
|
||||
import com.massivecraft.massivecore.xlib.gson.Gson;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class SimpleConfig
|
||||
{
|
||||
|
@ -11,10 +11,10 @@ import org.bukkit.FireworkEffect;
|
||||
import org.bukkit.FireworkEffect.Type;
|
||||
|
||||
import com.massivecraft.massivecore.util.MUtil;
|
||||
import com.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;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
|
||||
public class FireworkEffectAdapter
|
||||
{
|
||||
|
@ -8,14 +8,14 @@ import org.bukkit.inventory.PlayerInventory;
|
||||
|
||||
import com.massivecraft.massivecore.MassiveCore;
|
||||
import com.massivecraft.massivecore.mixin.Mixin;
|
||||
import com.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;
|
||||
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;
|
||||
|
||||
/**
|
||||
* This is my Gson adapter for Inventories.
|
||||
|
@ -26,15 +26,15 @@ import org.bukkit.inventory.meta.Repairable;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import com.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;
|
||||
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;
|
||||
|
||||
/**
|
||||
* This is a GSON serializer/deserializer for the Bukkit ItemStack. Why not use
|
||||
|
@ -2,12 +2,12 @@ package com.massivecraft.massivecore.adapter;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import com.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;
|
||||
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;
|
||||
|
||||
public class JsonElementAdapter implements JsonDeserializer<JsonElement>, JsonSerializer<JsonElement>
|
||||
{
|
||||
|
@ -1,13 +1,13 @@
|
||||
package com.massivecraft.massivecore.adapter;
|
||||
|
||||
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 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 java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
@ -2,14 +2,15 @@ package com.massivecraft.massivecore.adapter;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
|
||||
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;
|
||||
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>
|
||||
{
|
||||
|
@ -4,12 +4,12 @@ import java.lang.reflect.Type;
|
||||
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
public class PlayerInventoryAdapter implements JsonDeserializer<PlayerInventory>, JsonSerializer<PlayerInventory>
|
||||
{
|
||||
|
@ -2,15 +2,15 @@ package com.massivecraft.massivecore.adapter;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
public class PolymorphicAdapter<T> implements JsonDeserializer<T>, JsonSerializer<T>
|
||||
{
|
||||
|
@ -3,8 +3,8 @@ package com.massivecraft.massivecore.adapter;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonObject;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class PotionEffectAdapter
|
||||
|
@ -3,13 +3,13 @@ package com.massivecraft.massivecore.adapter;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.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;
|
||||
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 UUIDAdapter implements JsonDeserializer<UUID>, JsonSerializer<UUID>
|
||||
{
|
||||
|
@ -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.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
public class CmdMassiveCoreStoreCopydb extends MassiveCommand
|
||||
{
|
||||
|
@ -15,9 +15,9 @@ import com.massivecraft.massivecore.Aspect;
|
||||
import com.massivecraft.massivecore.MassiveCore;
|
||||
import com.massivecraft.massivecore.Multiverse;
|
||||
import com.massivecraft.massivecore.util.MUtil;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonObject;
|
||||
import com.massivecraft.massivecore.xlib.gson.annotations.SerializedName;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* # Introduction
|
||||
|
@ -2,10 +2,10 @@ package com.massivecraft.massivecore.ps;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
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.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
|
||||
public class PSAdapter implements JsonDeserializer<PS>
|
||||
{
|
||||
|
@ -22,9 +22,9 @@ import com.massivecraft.massivecore.NaturalOrderComparator;
|
||||
import com.massivecraft.massivecore.Predictate;
|
||||
import com.massivecraft.massivecore.store.accessor.Accessor;
|
||||
import com.massivecraft.massivecore.util.Txt;
|
||||
import com.massivecraft.massivecore.xlib.gson.Gson;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonObject;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public class Coll<E> implements CollInterface<E>
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.massivecraft.massivecore.store;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.mongodb.DB;
|
||||
import com.mongodb.DB;
|
||||
|
||||
public class DbMongo extends DbAbstract
|
||||
{
|
||||
|
@ -5,7 +5,7 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
public interface Driver
|
||||
{
|
||||
|
@ -12,8 +12,8 @@ import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.massivecraft.massivecore.util.DiscUtil;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonParser;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
public class DriverFlatfile extends DriverAbstract
|
||||
{
|
||||
|
@ -10,13 +10,13 @@ import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.massivecraft.massivecore.MassiveCoreMConf;
|
||||
import com.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;
|
||||
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;
|
||||
|
||||
public class DriverMongo extends DriverAbstract
|
||||
{
|
||||
|
@ -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.massivecraft.massivecore.xlib.gson.Gson;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonObject;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* Usage of this class is highly optional. You may persist anything. If you are
|
||||
|
@ -3,10 +3,10 @@ package com.massivecraft.massivecore.store;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.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.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonNull;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public class GsonCloner
|
||||
{
|
||||
|
@ -4,12 +4,12 @@ import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
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.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;
|
||||
|
||||
public class GsonEqualsChecker
|
||||
{
|
||||
|
@ -3,17 +3,17 @@ package com.massivecraft.massivecore.store;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import com.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;
|
||||
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;
|
||||
|
||||
public final class GsonMongoConverter
|
||||
{
|
||||
|
@ -7,7 +7,7 @@ import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.massivecraft.massivecore.ConfServer;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
import com.google.gson.JsonElement;
|
||||
|
||||
public class MStore
|
||||
{
|
||||
|
@ -37,7 +37,7 @@ import com.massivecraft.massivecore.mixin.Mixin;
|
||||
import com.massivecraft.massivecore.store.Coll;
|
||||
import com.massivecraft.massivecore.store.SenderColl;
|
||||
import com.massivecraft.massivecore.store.SenderEntity;
|
||||
import com.massivecraft.massivecore.xlib.gson.reflect.TypeToken;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
/**
|
||||
* Identification of a CommandSender can be done in 4 different ways.
|
||||
|
@ -1,346 +0,0 @@
|
||||
// BSON.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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 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;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.util.ClassMap;
|
||||
|
||||
@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>>();
|
||||
|
||||
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" );
|
||||
}
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
// BSONCallback.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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 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 );
|
||||
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 );
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
// BSONDecoder.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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 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;
|
||||
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2008 - 2011 10gen, Inc. <http://10gen.com>
|
||||
*
|
||||
* 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.*;
|
||||
|
||||
|
||||
public interface BSONEncoder {
|
||||
public byte[] encode( BSONObject o );
|
||||
|
||||
public int putObject( BSONObject o );
|
||||
|
||||
public void done();
|
||||
|
||||
void set( OutputBuffer out );
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2011, 10gen 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;
|
||||
}
|
||||
|
@ -1,24 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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
|
||||
*/
|
||||
public class BSONLazyDecoder {
|
||||
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
// BSONObject.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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 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();
|
||||
}
|
||||
|
@ -1,206 +0,0 @@
|
||||
// BasicBSONCallback.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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 java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.types.*;
|
||||
|
||||
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>();
|
||||
}
|
@ -1,527 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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 static com.massivecraft.massivecore.xlib.bson.BSON.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.io.PoolOutputBuffer;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
|
||||
|
||||
|
||||
/**
|
||||
* Basic implementation of BSONDecoder interface that creates BasicBSONObject instances
|
||||
*/
|
||||
@SuppressWarnings({"unused"})
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
protected BSONInput _in;
|
||||
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();
|
||||
|
||||
protected int _pos; // current offset into _inputBuffer
|
||||
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";
|
||||
|
||||
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' );
|
||||
}
|
||||
}
|
@ -1,524 +0,0 @@
|
||||
// BSONEncoder.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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 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;
|
||||
|
||||
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 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;
|
||||
|
||||
/**
|
||||
* this is meant to be pooled or cached
|
||||
* there is some per instance memory for string conversion, etc...
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "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;
|
||||
}
|
||||
|
||||
public void done(){
|
||||
_buf = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if object was handled
|
||||
*/
|
||||
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.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();
|
||||
com.massivecraft.massivecore.xlib.mongodb.util.MyAsserts.assertEquals( after - before , data.length );
|
||||
}
|
||||
|
||||
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 );
|
||||
_put( p.pattern() );
|
||||
_put( regexFlags( p.flags() ) );
|
||||
}
|
||||
|
||||
private void putMinKey( String name ) {
|
||||
_put( MINKEY , name );
|
||||
}
|
||||
|
||||
private void putMaxKey( String name ) {
|
||||
_put( MAXKEY , name );
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
/**
|
||||
* Encodes the type and key.
|
||||
*
|
||||
*/
|
||||
protected void _put( byte type , String name ){
|
||||
_buf.write( type );
|
||||
_put( name );
|
||||
}
|
||||
|
||||
protected void _putValueString( String s ){
|
||||
int lenPos = _buf.getPosition();
|
||||
_buf.writeInt( 0 ); // making space for size
|
||||
int strLen = _put( s );
|
||||
_buf.writeInt( lenPos , strLen );
|
||||
}
|
||||
|
||||
void _reset( Buffer b ){
|
||||
b.position(0);
|
||||
b.limit( b.capacity() );
|
||||
}
|
||||
|
||||
/**
|
||||
* puts as utf-8 string
|
||||
*/
|
||||
protected int _put( String str ){
|
||||
|
||||
final int len = str.length();
|
||||
int total = 0;
|
||||
|
||||
for ( int i=0; i<len; ){
|
||||
int c = Character.codePointAt( str , i );
|
||||
|
||||
if ( c < 0x80 ){
|
||||
_buf.write( (byte)c );
|
||||
total += 1;
|
||||
}
|
||||
else if ( c < 0x800 ){
|
||||
_buf.write( (byte)(0xc0 + (c >> 6) ) );
|
||||
_buf.write( (byte)(0x80 + (c & 0x3f) ) );
|
||||
total += 2;
|
||||
}
|
||||
else if (c < 0x10000){
|
||||
_buf.write( (byte)(0xe0 + (c >> 12) ) );
|
||||
_buf.write( (byte)(0x80 + ((c >> 6) & 0x3f) ) );
|
||||
_buf.write( (byte)(0x80 + (c & 0x3f) ) );
|
||||
total += 3;
|
||||
}
|
||||
else {
|
||||
_buf.write( (byte)(0xf0 + (c >> 18)) );
|
||||
_buf.write( (byte)(0x80 + ((c >> 12) & 0x3f)) );
|
||||
_buf.write( (byte)(0x80 + ((c >> 6) & 0x3f)) );
|
||||
_buf.write( (byte)(0x80 + (c & 0x3f)) );
|
||||
total += 4;
|
||||
}
|
||||
|
||||
i += Character.charCount(c);
|
||||
}
|
||||
|
||||
_buf.write( (byte)0 );
|
||||
total++;
|
||||
return total;
|
||||
}
|
||||
|
||||
public void writeInt( int x ){
|
||||
_buf.writeInt( x );
|
||||
}
|
||||
|
||||
public void writeLong( long x ){
|
||||
_buf.writeLong( x );
|
||||
}
|
||||
|
||||
public void writeCString( String s ){
|
||||
_put( s );
|
||||
}
|
||||
|
||||
protected OutputBuffer _buf;
|
||||
|
||||
}
|
@ -1,354 +0,0 @@
|
||||
// BasicBSONObject.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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;
|
||||
|
||||
// BSON
|
||||
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
|
||||
|
||||
|
||||
// Java
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 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"})
|
||||
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 com.massivecraft.massivecore.xlib.mongodb.util.JSON.serialize( this );
|
||||
}
|
||||
|
||||
public boolean equals( Object o ){
|
||||
if ( ! ( o instanceof BSONObject ) )
|
||||
return false;
|
||||
|
||||
BSONObject other = (BSONObject)o;
|
||||
if ( ! keySet().equals( other.keySet() ) )
|
||||
return false;
|
||||
|
||||
for ( String key : keySet() ){
|
||||
Object a = get( key );
|
||||
Object b = other.get( key );
|
||||
|
||||
if ( a == null ){
|
||||
if ( b != null )
|
||||
return false;
|
||||
}
|
||||
if ( b == null ){
|
||||
if ( a != null )
|
||||
return false;
|
||||
}
|
||||
else if ( a instanceof Number && b instanceof Number ){
|
||||
if ( ((Number)a).doubleValue() !=
|
||||
((Number)b).doubleValue() )
|
||||
return false;
|
||||
}
|
||||
else if ( a instanceof Pattern && b instanceof Pattern ){
|
||||
Pattern p1 = (Pattern) a;
|
||||
Pattern p2 = (Pattern) b;
|
||||
if (!p1.pattern().equals(p2.pattern()) || p1.flags() != p2.flags())
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if ( ! a.equals( b ) )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,143 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2011 10gen 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." );
|
||||
}
|
||||
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2011 10gen 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 java.util.HashMap;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.io.BSONByteBuffer;
|
||||
|
||||
/**
|
||||
* @author brendan
|
||||
* @author scotthernandez
|
||||
*/
|
||||
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>();
|
||||
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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 java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.LazyDBObject;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@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 ) );
|
||||
}
|
||||
|
||||
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 LazyDBList( 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" );
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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;
|
||||
}
|
@ -1,177 +0,0 @@
|
||||
package com.massivecraft.massivecore.xlib.bson;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.io.BSONByteBuffer;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@SuppressWarnings( "rawtypes" )
|
||||
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" );
|
||||
}
|
||||
|
||||
}
|
@ -1,685 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2008-2011 10gen 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.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.*;
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
protected byte getElementType( final int offset ){
|
||||
return _input.get( offset );
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
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 + 1 );
|
||||
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;
|
||||
}
|
||||
|
||||
@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;
|
||||
|
||||
protected final int _doc_start_offset;
|
||||
|
||||
protected final BSONByteBuffer _input; // TODO - Guard this with synchronicity?
|
||||
// callback is kept to create sub-objects on the fly
|
||||
protected final LazyBSONCallback _callback;
|
||||
private static final Logger log = Logger.getLogger( "org.bson.LazyBSONObject" );
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
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
|
||||
*
|
||||
*/
|
||||
@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;
|
||||
}
|
@ -1,305 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2012 10gen 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 static com.massivecraft.massivecore.xlib.bson.BSON.*;
|
||||
|
||||
|
||||
// Java
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
/**
|
||||
* A new implementation of the bson decoder.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
@ -1,27 +0,0 @@
|
||||
// Transformer.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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;
|
||||
|
||||
public interface Transformer {
|
||||
|
||||
/**
|
||||
* @return the new object. return passed in object if no change
|
||||
*/
|
||||
public Object transform( Object o );
|
||||
}
|
@ -1,143 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2008-2011 10gen 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.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.*;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
// BasicOutputBuffer.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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 java.io.*;
|
||||
|
||||
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;
|
||||
}
|
||||
@Override
|
||||
public void setPosition( int position ){
|
||||
_cur = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seekEnd(){
|
||||
_cur = _size;
|
||||
}
|
||||
@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
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString(){
|
||||
return new String( _buffer , 0 , _size );
|
||||
}
|
||||
|
||||
@Override
|
||||
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];
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
// Bits.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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 java.io.*;
|
||||
|
||||
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 - startOffset > length) {
|
||||
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;
|
||||
}
|
||||
}
|
@ -1,159 +0,0 @@
|
||||
// OutputBuffer.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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 java.io.*;
|
||||
import java.security.*;
|
||||
|
||||
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();
|
||||
public abstract void setPosition( int position );
|
||||
|
||||
public abstract void seekEnd();
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
public String asString(){
|
||||
return new String( toByteArray() );
|
||||
}
|
||||
|
||||
public String asString( String encoding )
|
||||
throws UnsupportedEncodingException {
|
||||
return new String( toByteArray() , encoding );
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
public void writeIntBE( int x ){
|
||||
write( x >> 24 );
|
||||
write( x >> 16 );
|
||||
write( x >> 8 );
|
||||
write( x );
|
||||
}
|
||||
|
||||
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 String toString(){
|
||||
return getClass().getName() + " size: " + size() + " pos: " + getPosition() ;
|
||||
}
|
||||
}
|
@ -1,238 +0,0 @@
|
||||
// PoolOutputBuffer.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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 java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
public void setPosition( int position ){
|
||||
_cur.reset( position );
|
||||
}
|
||||
|
||||
public void seekEnd(){
|
||||
_cur.reset( _end );
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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 );
|
||||
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;
|
||||
return y;
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
};
|
||||
}
|
@ -1,202 +0,0 @@
|
||||
// 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);
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
<body>
|
||||
<p>Contains classes implementing I/O operations used by BSON objects.</p>
|
||||
</body>
|
@ -1,3 +0,0 @@
|
||||
<body>
|
||||
<p>Contains the base BSON classes and Encoder/Decoder.</p>
|
||||
</body>
|
@ -1,96 +0,0 @@
|
||||
// BSONTimestamp.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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;
|
||||
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;
|
||||
|
||||
}
|
@ -1,164 +0,0 @@
|
||||
// BasicBSONList.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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 com.massivecraft.massivecore.xlib.bson.*;
|
||||
import com.massivecraft.massivecore.xlib.bson.util.StringRangeSet;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
// Binary.java
|
||||
|
||||
/**
|
||||
* See the NOTICE.txt file distributed with this work for
|
||||
* information regarding copyright ownership.
|
||||
*
|
||||
* The authors license this file to you under the
|
||||
* Apache License, Version 2.0 (the "License"); you may not use
|
||||
* this file except in compliance with the License. You may
|
||||
* obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package com.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;
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
// Code.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
}
|
||||
|
@ -1,53 +0,0 @@
|
||||
// CodeWScope.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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 com.massivecraft.massivecore.xlib.bson.*;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
@ -1,47 +0,0 @@
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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";
|
||||
}
|
||||
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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";
|
||||
}
|
||||
|
||||
}
|
@ -1,401 +0,0 @@
|
||||
// ObjectId.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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.net.*;
|
||||
import java.nio.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.*;
|
||||
import java.util.logging.*;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
/** 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
|
||||
*/
|
||||
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 );
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ObjectId
|
||||
* @param time time in seconds
|
||||
* @param machine machine ID
|
||||
* @param inc incremental value
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
public String toStringBabble(){
|
||||
return babbleToMongod( toStringMongod() );
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
public int getMachine(){
|
||||
return _machine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the time of this ID, in milliseconds
|
||||
*/
|
||||
public long getTime(){
|
||||
return _time * 1000L;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the time of this ID, in seconds
|
||||
*/
|
||||
public int getTimeSecond(){
|
||||
return _time;
|
||||
}
|
||||
|
||||
public int getInc(){
|
||||
return _inc;
|
||||
}
|
||||
|
||||
public int _time(){
|
||||
return _time;
|
||||
}
|
||||
public int _machine(){
|
||||
return _machine;
|
||||
}
|
||||
public int _inc(){
|
||||
return _inc;
|
||||
}
|
||||
|
||||
public boolean isNew(){
|
||||
return _new;
|
||||
}
|
||||
|
||||
public void notNew(){
|
||||
_new = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the generated machine ID, identifying the machine / process / class loader
|
||||
*/
|
||||
public static int getGenMachineId() {
|
||||
return _genmachine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current value of the auto increment
|
||||
*/
|
||||
public static int getCurrentInc() {
|
||||
return _nextInc.get();
|
||||
}
|
||||
|
||||
final int _time;
|
||||
final int _machine;
|
||||
final int _inc;
|
||||
|
||||
boolean _new;
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,74 +0,0 @@
|
||||
// Symbol.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2009 10gen 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
<body>
|
||||
<p>Contains classes implementing various BSON types.</p>
|
||||
</body>
|
@ -1,631 +0,0 @@
|
||||
/**
|
||||
* Copyright 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 static com.massivecraft.massivecore.xlib.bson.util.Assertions.notNull;
|
||||
import static java.util.Collections.unmodifiableCollection;
|
||||
import static java.util.Collections.unmodifiableSet;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@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;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/**
|
||||
* Copyright 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.
|
||||
*/
|
||||
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 IllegalArgumentException(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!");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
package com.massivecraft.massivecore.xlib.bson.util;
|
||||
|
||||
import static com.massivecraft.massivecore.xlib.bson.util.CopyOnWriteMap.newHashMap;
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
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();
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
// ClassMap.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Maps Class objects to values. A ClassMap is different from a regular Map in
|
||||
* that get(c) does not only look to see if 'c' is a key in the Map, but also
|
||||
* walks the up superclass and interface graph of 'c' to find matches. Derived
|
||||
* matches of this sort are then "cached" in the registry so that matches are
|
||||
* faster on future gets.
|
||||
*
|
||||
* This is a very useful class for Class based registries.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ClassMap<String> m = new ClassMap<String>(); m.put(Animal.class, "Animal");
|
||||
* m.put(Fox.class, "Fox"); m.Fox.class) --> "Fox" m.get(Dog.class) --> "Animal"
|
||||
*
|
||||
* (assuming Dog.class < Animal.class)
|
||||
*/
|
||||
public class ClassMap<T> {
|
||||
/**
|
||||
* Walks superclass and interface graph, superclasses first, then
|
||||
* interfaces, to compute an ancestry list. Supertypes are visited left to
|
||||
* right. Duplicates are removed such that no Class will appear in the list
|
||||
* before one of its subtypes.
|
||||
*/
|
||||
public static <T> List<Class<?>> getAncestry(Class<T> c) {
|
||||
return ClassAncestry.getAncestry(c);
|
||||
}
|
||||
|
||||
private final class ComputeFunction implements Function<Class<?>, T> {
|
||||
@Override
|
||||
public T apply(Class<?> a) {
|
||||
for (Class<?> cls : getAncestry(a)) {
|
||||
T result = map.get(cls);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
private final Map<Class<?>, T> map = CopyOnWriteMap.newHashMap();
|
||||
private final Map<Class<?>, T> cache = ComputingMap.create(new ComputeFunction());
|
||||
|
||||
|
||||
public T get(Object key) {
|
||||
return cache.get(key);
|
||||
}
|
||||
|
||||
public T put(Class<?> key, T value) {
|
||||
try {
|
||||
return map.put(key, value);
|
||||
} finally {
|
||||
cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public T remove(Object key) {
|
||||
try {
|
||||
return map.remove(key);
|
||||
} finally {
|
||||
cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
map.clear();
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
package com.massivecraft.massivecore.xlib.bson.util;
|
||||
|
||||
import static com.massivecraft.massivecore.xlib.bson.util.Assertions.notNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
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;
|
||||
@SuppressWarnings("unchecked")
|
||||
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();
|
||||
}
|
||||
}
|
@ -1,272 +0,0 @@
|
||||
/**
|
||||
* Copyright 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 java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
package com.massivecraft.massivecore.xlib.bson.util;
|
||||
|
||||
interface Function<A, B> {
|
||||
B apply(A a);
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
// SimplePool.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
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>();
|
||||
}
|
@ -1,130 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2010 10gen 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();
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
*/
|
||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface GuardedBy {
|
||||
String value();
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* 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.*;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@Documented
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Immutable {
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* 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.*;
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@Documented
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface NotThreadSafe {
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* 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.*;
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@Documented
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ThreadSafe {
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
<body>
|
||||
<p>Misc utils used by BSON.</p>
|
||||
</body>
|
@ -1,58 +0,0 @@
|
||||
package com.massivecraft.massivecore.xlib.mongodb;
|
||||
|
||||
public class AggregationOutput {
|
||||
|
||||
/**
|
||||
* returns an iterator to the results of the aggregation
|
||||
* @return
|
||||
*/
|
||||
public Iterable<DBObject> results() {
|
||||
return _resultSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the command result of the aggregation
|
||||
* @return
|
||||
*/
|
||||
public CommandResult getCommandResult(){
|
||||
return _commandResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the original aggregation command
|
||||
* @return
|
||||
*/
|
||||
public DBObject getCommand() {
|
||||
return _cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the address of the server used to execute the aggregation
|
||||
* @return
|
||||
*/
|
||||
public ServerAddress getServerUsed() {
|
||||
return _commandResult.getServerUsed();
|
||||
}
|
||||
|
||||
/**
|
||||
* string representation of the aggregation command
|
||||
*/
|
||||
public String toString(){
|
||||
return _commandResult.toString();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public AggregationOutput(DBObject cmd, CommandResult raw) {
|
||||
_commandResult = raw;
|
||||
_cmd = cmd;
|
||||
|
||||
if(raw.containsField("result"))
|
||||
_resultSet = (Iterable<DBObject>) raw.get( "result" );
|
||||
else
|
||||
throw new IllegalArgumentException("result undefined");
|
||||
}
|
||||
|
||||
protected final CommandResult _commandResult;
|
||||
protected final DBObject _cmd;
|
||||
protected final Iterable<DBObject> _resultSet;
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
// BasicDBList.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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.mongodb;
|
||||
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.types.BasicBSONList;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.util.JSON;
|
||||
|
||||
/**
|
||||
* a basic implementation of bson list that is mongo specific
|
||||
* @author antoine
|
||||
*/
|
||||
public class BasicDBList extends BasicBSONList implements DBObject {
|
||||
|
||||
private static final long serialVersionUID = -4415279469780082174L;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
public Object copy() {
|
||||
// copy field values into new object
|
||||
BasicDBList newobj = new BasicDBList();
|
||||
// need to clone the sub obj
|
||||
for (int i = 0; i < size(); ++i) {
|
||||
Object val = get(i);
|
||||
if (val instanceof BasicDBObject) {
|
||||
val = ((BasicDBObject)val).copy();
|
||||
} else if (val instanceof BasicDBList) {
|
||||
val = ((BasicDBList)val).copy();
|
||||
}
|
||||
newobj.add(val);
|
||||
}
|
||||
return newobj;
|
||||
}
|
||||
|
||||
private boolean _isPartialObject;
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
// BasicDBObject.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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.mongodb;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.BasicBSONObject;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.util.JSON;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* a basic implementation of bson object that is mongo specific.
|
||||
* A <code>DBObject</code> can be created as follows, using this class:
|
||||
* <blockquote><pre>
|
||||
* DBObject obj = new BasicDBObject();
|
||||
* obj.put( "foo", "bar" );
|
||||
* </pre></blockquote>
|
||||
*/
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
public class BasicDBObject extends BasicBSONObject implements DBObject {
|
||||
|
||||
private static final long serialVersionUID = -4415279469780082174L;
|
||||
|
||||
/**
|
||||
* Creates an empty object.
|
||||
*/
|
||||
public BasicDBObject(){
|
||||
}
|
||||
|
||||
/**
|
||||
* creates an empty object
|
||||
* @param size an estimate of number of fields that will be inserted
|
||||
*/
|
||||
public BasicDBObject(int size){
|
||||
super(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* creates an object with the given key/value
|
||||
* @param key key under which to store
|
||||
* @param value value to stor
|
||||
*/
|
||||
public BasicDBObject(String key, Object value){
|
||||
super(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an object from a map.
|
||||
* @param m map to convert
|
||||
*/
|
||||
public BasicDBObject(Map m) {
|
||||
super(m);
|
||||
}
|
||||
|
||||
public boolean isPartialObject(){
|
||||
return _isPartialObject;
|
||||
}
|
||||
|
||||
public void markAsPartialObject(){
|
||||
_isPartialObject = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a JSON serialization of this object
|
||||
* @return JSON serialization
|
||||
*/
|
||||
@Override
|
||||
public String toString(){
|
||||
return JSON.serialize( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicDBObject append( String key , Object val ){
|
||||
put( key , val );
|
||||
return this;
|
||||
}
|
||||
|
||||
public Object copy() {
|
||||
// copy field values into new object
|
||||
BasicDBObject newobj = new BasicDBObject(this.toMap());
|
||||
// need to clone the sub obj
|
||||
for (String field : keySet()) {
|
||||
Object val = get(field);
|
||||
if (val instanceof BasicDBObject) {
|
||||
newobj.put(field, ((BasicDBObject)val).copy());
|
||||
} else if (val instanceof BasicDBList) {
|
||||
newobj.put(field, ((BasicDBList)val).copy());
|
||||
}
|
||||
}
|
||||
return newobj;
|
||||
}
|
||||
|
||||
private boolean _isPartialObject;
|
||||
}
|
@ -1,142 +0,0 @@
|
||||
// BasicDBObjectBuilder.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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.mongodb;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* utility for building complex objects
|
||||
* example:
|
||||
* BasicDBObjectBuilder.start().add( "name" , "eliot" ).add( "number" , 17 ).get()
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public class BasicDBObjectBuilder {
|
||||
|
||||
/**
|
||||
* creates an empty object
|
||||
*/
|
||||
public BasicDBObjectBuilder(){
|
||||
_stack = new LinkedList<DBObject>();
|
||||
_stack.add( new BasicDBObject() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty object
|
||||
* @return The new empty builder
|
||||
*/
|
||||
public static BasicDBObjectBuilder start(){
|
||||
return new BasicDBObjectBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* creates an object with the given key/value
|
||||
* @param k The field name
|
||||
* @param val The value
|
||||
*/
|
||||
public static BasicDBObjectBuilder start( String k , Object val ){
|
||||
return (new BasicDBObjectBuilder()).add( k , val );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an object builder from an existing map.
|
||||
* @param m map to use
|
||||
* @return the new builder
|
||||
*/
|
||||
public static BasicDBObjectBuilder start(Map m){
|
||||
BasicDBObjectBuilder b = new BasicDBObjectBuilder();
|
||||
Iterator<Map.Entry> i = m.entrySet().iterator();
|
||||
while (i.hasNext()) {
|
||||
Map.Entry entry = i.next();
|
||||
b.add(entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* appends the key/value to the active object
|
||||
* @param key
|
||||
* @param val
|
||||
* @return returns itself so you can chain
|
||||
*/
|
||||
public BasicDBObjectBuilder append( String key , Object val ){
|
||||
_cur().put( key , val );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* same as appends
|
||||
* @see #append(String, Object)
|
||||
* @param key
|
||||
* @param val
|
||||
* @return returns itself so you can chain
|
||||
*/
|
||||
public BasicDBObjectBuilder add( String key , Object val ){
|
||||
return append( key, val );
|
||||
}
|
||||
|
||||
/**
|
||||
* creates an new empty object and inserts it into the current object with the given key.
|
||||
* The new child object becomes the active one.
|
||||
* @param key
|
||||
* @return returns itself so you can chain
|
||||
*/
|
||||
public BasicDBObjectBuilder push( String key ){
|
||||
BasicDBObject o = new BasicDBObject();
|
||||
_cur().put( key , o );
|
||||
_stack.addLast( o );
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* pops the active object, which means that the parent object becomes active
|
||||
* @return returns itself so you can chain
|
||||
*/
|
||||
public BasicDBObjectBuilder pop(){
|
||||
if ( _stack.size() <= 1 )
|
||||
throw new IllegalArgumentException( "can't pop last element" );
|
||||
_stack.removeLast();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the base object
|
||||
* @return The base object
|
||||
*/
|
||||
public DBObject get(){
|
||||
return _stack.getFirst();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true if no key/value was inserted into base object
|
||||
* @return True if empty
|
||||
*/
|
||||
public boolean isEmpty(){
|
||||
return ((BasicDBObject) _stack.getFirst()).size() == 0;
|
||||
}
|
||||
|
||||
private DBObject _cur(){
|
||||
return _stack.getLast();
|
||||
}
|
||||
|
||||
private final LinkedList<DBObject> _stack;
|
||||
|
||||
}
|
@ -1,227 +0,0 @@
|
||||
// Bytes.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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.mongodb;
|
||||
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.BSON;
|
||||
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.ObjectId;
|
||||
|
||||
/**
|
||||
* Class that hold definitions of the wire protocol
|
||||
* @author antoine
|
||||
*/
|
||||
public class Bytes extends BSON {
|
||||
|
||||
static final Logger LOGGER = Logger.getLogger( "com.mongodb" );
|
||||
|
||||
static final boolean D = Boolean.getBoolean( "DEBUG.MONGO" );
|
||||
|
||||
static {
|
||||
if ( LOGGER.getLevel() == null ){
|
||||
if ( D )
|
||||
LOGGER.setLevel( Level.ALL );
|
||||
else
|
||||
LOGGER.setLevel( Level.WARNING );
|
||||
}
|
||||
}
|
||||
|
||||
/** Little-endian */
|
||||
public static final ByteOrder ORDER = ByteOrder.LITTLE_ENDIAN;
|
||||
|
||||
/** this size is set low to 4MB, but just serves as safe default */
|
||||
static final int MAX_OBJECT_SIZE = 1024 * 1024 * 4;
|
||||
|
||||
/** default target size of an insert batch */
|
||||
static final int BATCH_INSERT_SIZE = 1024 * 1024 * 8;
|
||||
|
||||
static final int CONNECTIONS_PER_HOST = Integer.parseInt( System.getProperty( "MONGO.POOLSIZE" , "10" ) );
|
||||
|
||||
|
||||
// --- network protocol options
|
||||
|
||||
/**
|
||||
* Tailable means cursor is not closed when the last data is retrieved.
|
||||
* Rather, the cursor marks the final object's position.
|
||||
* You can resume using the cursor later, from where it was located, if more data were received.
|
||||
* Like any "latent cursor", the cursor may become invalid at some point (CursorNotFound) – for example if the final object it references were deleted.
|
||||
*/
|
||||
public static final int QUERYOPTION_TAILABLE = 1 << 1;
|
||||
/**
|
||||
* When turned on, read queries will be directed to slave servers instead of the primary server.
|
||||
*/
|
||||
public static final int QUERYOPTION_SLAVEOK = 1 << 2;
|
||||
/**
|
||||
* Internal replication use only - driver should not set
|
||||
*/
|
||||
public static final int QUERYOPTION_OPLOGREPLAY = 1 << 3;
|
||||
/**
|
||||
* The server normally times out idle cursors after an inactivity period (10 minutes) to prevent excess memory use.
|
||||
* Set this option to prevent that.
|
||||
*/
|
||||
public static final int QUERYOPTION_NOTIMEOUT = 1 << 4;
|
||||
|
||||
/**
|
||||
* Use with TailableCursor.
|
||||
* If we are at the end of the data, block for a while rather than returning no data.
|
||||
* After a timeout period, we do return as normal.
|
||||
*/
|
||||
public static final int QUERYOPTION_AWAITDATA = 1 << 5;
|
||||
|
||||
/**
|
||||
* Stream the data down full blast in multiple "more" packages, on the assumption that the client will fully read all data queried.
|
||||
* Faster when you are pulling a lot of data and know you want to pull it all down.
|
||||
* Note: the client is not allowed to not read all the data unless it closes the connection.
|
||||
*/
|
||||
public static final int QUERYOPTION_EXHAUST = 1 << 6;
|
||||
|
||||
/**
|
||||
* Use with sharding (mongos).
|
||||
* Allows partial results from a sharded system if any shards are down/missing from the cluster. If not used an error will be returned
|
||||
* from the mongos server.
|
||||
*/
|
||||
public static final int QUERYOPTION_PARTIAL = 1 << 7;
|
||||
|
||||
/**
|
||||
* Set when getMore is called but the cursor id is not valid at the server.
|
||||
* Returned with zero results.
|
||||
*/
|
||||
public static final int RESULTFLAG_CURSORNOTFOUND = 1;
|
||||
/**
|
||||
* Set when query failed.
|
||||
* Results consist of one document containing an "$err" field describing the failure.
|
||||
*/
|
||||
public static final int RESULTFLAG_ERRSET = 2;
|
||||
/**
|
||||
* Drivers should ignore this.
|
||||
* Only mongos will ever see this set, in which case, it needs to update config from the server.
|
||||
*/
|
||||
public static final int RESULTFLAG_SHARDCONFIGSTALE = 4;
|
||||
/**
|
||||
* Set when the server supports the AwaitData Query option.
|
||||
* If it doesn't, a client should sleep a little between getMore's of a Tailable cursor.
|
||||
* Mongod version 1.6 supports AwaitData and thus always sets AwaitCapable.
|
||||
*/
|
||||
public static final int RESULTFLAG_AWAITCAPABLE = 8;
|
||||
|
||||
|
||||
static class OptionHolder {
|
||||
OptionHolder( OptionHolder parent ){
|
||||
_parent = parent;
|
||||
}
|
||||
|
||||
void set( int options ){
|
||||
_options = options;
|
||||
_hasOptions = true;
|
||||
}
|
||||
|
||||
int get(){
|
||||
if ( _hasOptions )
|
||||
return _options;
|
||||
if ( _parent == null )
|
||||
return 0;
|
||||
return _parent.get();
|
||||
}
|
||||
|
||||
void add( int option ){
|
||||
set( get() | option );
|
||||
}
|
||||
|
||||
void reset(){
|
||||
_hasOptions = false;
|
||||
}
|
||||
|
||||
final OptionHolder _parent;
|
||||
|
||||
int _options = 0;
|
||||
boolean _hasOptions = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type byte for a given object.
|
||||
* @param o the object
|
||||
* @return the byte value associated with the type, or -1 if no type is matched
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public static byte getType( Object o ){
|
||||
if ( o == null )
|
||||
return NULL;
|
||||
|
||||
if ( o instanceof DBPointer )
|
||||
return REF;
|
||||
|
||||
if (o instanceof Integer
|
||||
|| o instanceof Short
|
||||
|| o instanceof Byte
|
||||
|| o instanceof AtomicInteger) {
|
||||
return NUMBER_INT;
|
||||
}
|
||||
|
||||
if (o instanceof Long || o instanceof AtomicLong) {
|
||||
return NUMBER_LONG;
|
||||
}
|
||||
|
||||
if ( o instanceof Number )
|
||||
return NUMBER;
|
||||
|
||||
if ( o instanceof String )
|
||||
return STRING;
|
||||
|
||||
if ( o instanceof java.util.List )
|
||||
return ARRAY;
|
||||
|
||||
if ( o instanceof byte[] )
|
||||
return BINARY;
|
||||
|
||||
if ( o instanceof ObjectId )
|
||||
return OID;
|
||||
|
||||
if ( o instanceof Boolean )
|
||||
return BOOLEAN;
|
||||
|
||||
if ( o instanceof java.util.Date )
|
||||
return DATE;
|
||||
|
||||
if ( o instanceof BSONTimestamp )
|
||||
return TIMESTAMP;
|
||||
|
||||
if ( o instanceof java.util.regex.Pattern )
|
||||
return REGEX;
|
||||
|
||||
if ( o instanceof DBObject || o instanceof DBRefBase )
|
||||
return OBJECT;
|
||||
|
||||
if ( o instanceof Code )
|
||||
return CODE;
|
||||
|
||||
if ( o instanceof CodeWScope )
|
||||
return CODE_W_SCOPE;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static final ObjectId COLLECTION_REF_ID = new ObjectId( -1 , -1 , -1 );
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2008 - 2013 10gen, Inc. <http://10gen.com>
|
||||
*
|
||||
* 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.mongodb;
|
||||
|
||||
/**
|
||||
* An exception indicating a failed command.
|
||||
*/
|
||||
public class CommandFailureException extends MongoException {
|
||||
private static final long serialVersionUID = -1180715413196161037L;
|
||||
private final CommandResult commandResult;
|
||||
|
||||
/**
|
||||
* Construct a new instance with the CommandResult from a failed command
|
||||
*
|
||||
* @param commandResult the result
|
||||
*/
|
||||
public CommandFailureException(CommandResult commandResult){
|
||||
super(ServerError.getCode(commandResult), commandResult.toString());
|
||||
this.commandResult = commandResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the getlasterror command result document.
|
||||
*
|
||||
* @return the command result
|
||||
*/
|
||||
public CommandResult getCommandResult() {
|
||||
return commandResult;
|
||||
}
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
// CommandResult.java
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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.mongodb;
|
||||
|
||||
|
||||
/**
|
||||
* A simple wrapper for the result of getLastError() calls and other commands
|
||||
*/
|
||||
public class CommandResult extends BasicDBObject {
|
||||
|
||||
CommandResult(ServerAddress srv) {
|
||||
if (srv == null) {
|
||||
throw new IllegalArgumentException("server address is null");
|
||||
}
|
||||
_host = srv;
|
||||
//so it is shown in toString/debug
|
||||
put("serverUsed", srv.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the "ok" field which is the result of the command
|
||||
* @return True if ok
|
||||
*/
|
||||
public boolean ok(){
|
||||
Object o = get( "ok" );
|
||||
if ( o == null )
|
||||
throw new IllegalArgumentException( "'ok' should never be null..." );
|
||||
|
||||
if ( o instanceof Boolean )
|
||||
return (Boolean) o;
|
||||
|
||||
if ( o instanceof Number )
|
||||
return ((Number)o).intValue() == 1;
|
||||
|
||||
throw new IllegalArgumentException( "can't figure out what to do with: " + o.getClass().getName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the "errmsg" field which holds the error message
|
||||
* @return The error message or null
|
||||
*/
|
||||
public String getErrorMessage(){
|
||||
Object errorMessage = get( "errmsg" );
|
||||
if ( errorMessage == null )
|
||||
return null;
|
||||
return errorMessage.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* utility method to create an exception with the command name
|
||||
* @return The mongo exception or null
|
||||
*/
|
||||
public MongoException getException() {
|
||||
if ( !ok() ) { // check for command failure
|
||||
return new CommandFailureException( this );
|
||||
} else if ( hasErr() ) { // check for errors reported by getlasterror command
|
||||
if (getCode() == 11000 || getCode() == 11001 || getCode() == 12582) {
|
||||
return new MongoException.DuplicateKey(this);
|
||||
}
|
||||
else {
|
||||
return new WriteConcernException(this);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the "code" field, as an int
|
||||
* @return -1 if there is no code
|
||||
*/
|
||||
int getCode() {
|
||||
int code = -1;
|
||||
if ( get( "code" ) instanceof Number )
|
||||
code = ((Number)get("code")).intValue();
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* check the "err" field
|
||||
* @return if it has it, and isn't null
|
||||
*/
|
||||
boolean hasErr(){
|
||||
Object o = get( "err" );
|
||||
return (o != null && ( (String) o ).length() > 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* throws an exception containing the cmd name, in case the command failed, or the "err/code" information
|
||||
* @throws MongoException
|
||||
*/
|
||||
public void throwOnError() {
|
||||
if ( !ok() || hasErr() ){
|
||||
throw getException();
|
||||
}
|
||||
}
|
||||
|
||||
public ServerAddress getServerUsed() {
|
||||
return _host;
|
||||
}
|
||||
|
||||
private final ServerAddress _host;
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
@ -1,252 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2008 - 2012 10gen, Inc. <http://10gen.com>
|
||||
* <p/>
|
||||
* 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
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* 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.mongodb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Base class for classes that manage connections to mongo instances as background tasks.
|
||||
*/
|
||||
abstract class ConnectionStatus {
|
||||
|
||||
ConnectionStatus(List<ServerAddress> mongosAddresses, Mongo mongo) {
|
||||
_mongoOptions = mongoOptionsDefaults.copy();
|
||||
_mongoOptions.socketFactory = mongo._options.socketFactory;
|
||||
this._mongosAddresses = new ArrayList<ServerAddress>(mongosAddresses);
|
||||
this._mongo = mongo;
|
||||
}
|
||||
|
||||
protected BackgroundUpdater _updater;
|
||||
protected final Mongo _mongo;
|
||||
protected final List<ServerAddress> _mongosAddresses;
|
||||
protected volatile boolean _closed;
|
||||
protected final MongoOptions _mongoOptions;
|
||||
|
||||
protected static int updaterIntervalMS;
|
||||
protected static int updaterIntervalNoMasterMS;
|
||||
@SuppressWarnings("deprecation")
|
||||
protected static final MongoOptions mongoOptionsDefaults = new MongoOptions();
|
||||
protected static final float latencySmoothFactor;
|
||||
protected static final DBObject isMasterCmd = new BasicDBObject("ismaster", 1);
|
||||
|
||||
/**
|
||||
* Start the updater if there is one
|
||||
*/
|
||||
void start() {
|
||||
if (_updater != null) {
|
||||
_updater.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the updater if there is one
|
||||
*/
|
||||
void close() {
|
||||
_closed = true;
|
||||
if (_updater != null) {
|
||||
_updater.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of addresses for this connection.
|
||||
*/
|
||||
abstract List<ServerAddress> getServerAddressList();
|
||||
|
||||
|
||||
/**
|
||||
* Whether there is least one server up.
|
||||
*/
|
||||
abstract boolean hasServerUp();
|
||||
|
||||
/**
|
||||
* Ensures that we have the current master, if there is one. If the current snapshot of the replica set
|
||||
* has no master, this method waits one cycle to find a new master, and returns it if found, or null if not.
|
||||
*
|
||||
* @return address of the current master, or null if there is none
|
||||
*/
|
||||
abstract Node ensureMaster();
|
||||
|
||||
/**
|
||||
* Whether this connection has been closed.
|
||||
*/
|
||||
void checkClosed() {
|
||||
if (_closed)
|
||||
throw new IllegalStateException("ReplicaSetStatus closed");
|
||||
}
|
||||
|
||||
static {
|
||||
updaterIntervalMS = Integer.parseInt(System.getProperty("com.mongodb.updaterIntervalMS", "5000"));
|
||||
updaterIntervalNoMasterMS = Integer.parseInt(System.getProperty("com.mongodb.updaterIntervalNoMasterMS", "10"));
|
||||
mongoOptionsDefaults.connectTimeout = Integer.parseInt(System.getProperty("com.mongodb.updaterConnectTimeoutMS", "20000"));
|
||||
mongoOptionsDefaults.socketTimeout = Integer.parseInt(System.getProperty("com.mongodb.updaterSocketTimeoutMS", "20000"));
|
||||
latencySmoothFactor = Float.parseFloat(System.getProperty("com.mongodb.latencySmoothFactor", "4"));
|
||||
}
|
||||
|
||||
static class Node {
|
||||
|
||||
Node(float pingTime, ServerAddress addr, int maxBsonObjectSize, boolean ok) {
|
||||
this._pingTime = pingTime;
|
||||
this._addr = addr;
|
||||
this._maxBsonObjectSize = maxBsonObjectSize;
|
||||
this._ok = ok;
|
||||
}
|
||||
|
||||
public boolean isOk() {
|
||||
return _ok;
|
||||
}
|
||||
|
||||
public int getMaxBsonObjectSize() {
|
||||
return _maxBsonObjectSize;
|
||||
}
|
||||
|
||||
public ServerAddress getServerAddress() {
|
||||
return _addr;
|
||||
}
|
||||
|
||||
protected final ServerAddress _addr;
|
||||
protected final float _pingTime;
|
||||
protected final boolean _ok;
|
||||
protected final int _maxBsonObjectSize;
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
final Node node = (Node) o;
|
||||
|
||||
if (_maxBsonObjectSize != node._maxBsonObjectSize) return false;
|
||||
if (_ok != node._ok) return false;
|
||||
if (Float.compare(node._pingTime, _pingTime) != 0) return false;
|
||||
if (!_addr.equals(node._addr)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = _addr.hashCode();
|
||||
result = 31 * result + (_pingTime != +0.0f ? Float.floatToIntBits(_pingTime) : 0);
|
||||
result = 31 * result + (_ok ? 1 : 0);
|
||||
result = 31 * result + _maxBsonObjectSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
public String toJSON() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("{");
|
||||
buf.append("address:'").append(_addr).append("', ");
|
||||
buf.append("ok:").append(_ok).append(", ");
|
||||
buf.append("ping:").append(_pingTime).append(", ");
|
||||
buf.append("maxBsonObjectSize:").append(_maxBsonObjectSize).append(", ");
|
||||
buf.append("}");
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
||||
static class BackgroundUpdater extends Thread {
|
||||
public BackgroundUpdater(final String name) {
|
||||
super(name);
|
||||
setDaemon(true);
|
||||
}
|
||||
}
|
||||
|
||||
static abstract class UpdatableNode {
|
||||
UpdatableNode(final ServerAddress addr, Mongo mongo, MongoOptions mongoOptions) {
|
||||
this._addr = addr;
|
||||
this._mongo = mongo;
|
||||
this._mongoOptions = mongoOptions;
|
||||
this._port = new DBPort(addr, null, mongoOptions);
|
||||
}
|
||||
|
||||
public CommandResult update() {
|
||||
CommandResult res = null;
|
||||
try {
|
||||
long start = System.nanoTime();
|
||||
res = _port.runCommand(_mongo.getDB("admin"), isMasterCmd);
|
||||
long end = System.nanoTime();
|
||||
float newPingMS = (end - start) / 1000000F;
|
||||
if (!successfullyContacted)
|
||||
_pingTimeMS = newPingMS;
|
||||
else
|
||||
_pingTimeMS = _pingTimeMS + ((newPingMS - _pingTimeMS) / latencySmoothFactor);
|
||||
|
||||
getLogger().log(Level.FINE, "Latency to " + _addr + " actual=" + newPingMS + " smoothed=" + _pingTimeMS);
|
||||
|
||||
successfullyContacted = true;
|
||||
|
||||
if (res == null) {
|
||||
throw new MongoInternalException("Invalid null value returned from isMaster");
|
||||
}
|
||||
|
||||
if (!_ok) {
|
||||
getLogger().log(Level.INFO, "Server seen up: " + _addr);
|
||||
}
|
||||
_ok = true;
|
||||
|
||||
// max size was added in 1.8
|
||||
if (res.containsField("maxBsonObjectSize")) {
|
||||
_maxBsonObjectSize = (Integer) res.get("maxBsonObjectSize");
|
||||
} else {
|
||||
_maxBsonObjectSize = Bytes.MAX_OBJECT_SIZE;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (!((_ok) ? true : (Math.random() > 0.1))) {
|
||||
return res;
|
||||
}
|
||||
|
||||
final StringBuilder logError = (new StringBuilder("Server seen down: ")).append(_addr);
|
||||
|
||||
if (e instanceof IOException) {
|
||||
|
||||
logError.append(" - ").append(IOException.class.getName());
|
||||
|
||||
if (e.getMessage() != null) {
|
||||
logError.append(" - message: ").append(e.getMessage());
|
||||
}
|
||||
|
||||
getLogger().log(Level.WARNING, logError.toString());
|
||||
|
||||
} else {
|
||||
getLogger().log(Level.WARNING, logError.toString(), e);
|
||||
}
|
||||
_ok = false;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
protected abstract Logger getLogger();
|
||||
|
||||
final ServerAddress _addr;
|
||||
final MongoOptions _mongoOptions;
|
||||
final Mongo _mongo;
|
||||
|
||||
DBPort _port; // we have our own port so we can set different socket options and don't have to worry about the pool
|
||||
|
||||
boolean successfullyContacted = false;
|
||||
boolean _ok = false;
|
||||
float _pingTimeMS = 0;
|
||||
int _maxBsonObjectSize;
|
||||
}
|
||||
|
||||
}
|
@ -1,822 +0,0 @@
|
||||
// DB.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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.mongodb;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.BSONObject;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.DBApiLayer.Result;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.util.Util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* an abstract class that represents a logical database on a server
|
||||
* @dochub databases
|
||||
*/
|
||||
public abstract class DB {
|
||||
|
||||
private static final Set<String> _obedientCommands = new HashSet<String>();
|
||||
|
||||
static {
|
||||
_obedientCommands.add("group");
|
||||
_obedientCommands.add("aggregate");
|
||||
_obedientCommands.add("collstats");
|
||||
_obedientCommands.add("dbstats");
|
||||
_obedientCommands.add("count");
|
||||
_obedientCommands.add("distinct");
|
||||
_obedientCommands.add("geonear");
|
||||
_obedientCommands.add("geosearch");
|
||||
_obedientCommands.add("geowalk");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mongo the mongo instance
|
||||
* @param name the database name
|
||||
*/
|
||||
public DB( Mongo mongo , String name ){
|
||||
_mongo = mongo;
|
||||
_name = name;
|
||||
_options = new Bytes.OptionHolder( _mongo._netOptions );
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the read preference that should be used for the given command.
|
||||
* @param command the <code>DBObject</code> representing the command
|
||||
* @param requestedPreference the preference requested by the client.
|
||||
* @return the read preference to use for the given command. It will never return null.
|
||||
* @see com.massivecraft.massivecore.xlib.mongodb.ReadPreference
|
||||
*/
|
||||
ReadPreference getCommandReadPreference(DBObject command, ReadPreference requestedPreference){
|
||||
String comString = command.keySet().iterator().next();
|
||||
|
||||
if (comString.equals("getnonce") || comString.equals("authenticate")) {
|
||||
return ReadPreference.primaryPreferred();
|
||||
}
|
||||
|
||||
boolean primaryRequired;
|
||||
|
||||
// explicitly check mapreduce commands are inline
|
||||
if(comString.equals("mapreduce")) {
|
||||
Object out = command.get("out");
|
||||
if (out instanceof BSONObject ){
|
||||
BSONObject outMap = (BSONObject) out;
|
||||
primaryRequired = outMap.get("inline") == null;
|
||||
}
|
||||
else
|
||||
primaryRequired = true;
|
||||
} else {
|
||||
primaryRequired = !_obedientCommands.contains(comString.toLowerCase());
|
||||
}
|
||||
|
||||
if (primaryRequired) {
|
||||
return ReadPreference.primary();
|
||||
} else if (requestedPreference == null) {
|
||||
return ReadPreference.primary();
|
||||
} else {
|
||||
return requestedPreference;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* starts a new "consistent request".
|
||||
* Following this call and until requestDone() is called, all db operations should use the same underlying connection.
|
||||
* This is useful to ensure that operations happen in a certain order with predictable results.
|
||||
*/
|
||||
public abstract void requestStart();
|
||||
|
||||
/**
|
||||
* ends the current "consistent request"
|
||||
*/
|
||||
public abstract void requestDone();
|
||||
|
||||
/**
|
||||
* ensure that a connection is assigned to the current "consistent request" (from primary pool, if connected to a replica set)
|
||||
*/
|
||||
public abstract void requestEnsureConnection();
|
||||
|
||||
/**
|
||||
* Returns the collection represented by the string <dbName>.<collectionName>.
|
||||
* @param name the name of the collection
|
||||
* @return the collection
|
||||
*/
|
||||
protected abstract DBCollection doGetCollection( String name );
|
||||
|
||||
/**
|
||||
* Gets a collection with a given name.
|
||||
* If the collection does not exist, a new collection is created.
|
||||
* @param name the name of the collection to return
|
||||
* @return the collection
|
||||
*/
|
||||
public DBCollection getCollection( String name ){
|
||||
DBCollection c = doGetCollection( name );
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a collection with a given name and options.
|
||||
* If the collection does not exist, a new collection is created.
|
||||
* Note that if the options parameter is null, the creation will be deferred to when the collection is written to.
|
||||
* Possible options:
|
||||
* <dl>
|
||||
* <dt>capped</dt><dd><i>boolean</i>: if the collection is capped</dd>
|
||||
* <dt>size</dt><dd><i>int</i>: collection size (in bytes)</dd>
|
||||
* <dt>max</dt><dd><i>int</i>: max number of documents</dd>
|
||||
* </dl>
|
||||
* @param name the name of the collection to return
|
||||
* @param options options
|
||||
* @return the collection
|
||||
* @throws MongoException
|
||||
*/
|
||||
public DBCollection createCollection( String name, DBObject options ){
|
||||
if ( options != null ){
|
||||
DBObject createCmd = new BasicDBObject("create", name);
|
||||
createCmd.putAll(options);
|
||||
CommandResult result = command(createCmd);
|
||||
result.throwOnError();
|
||||
}
|
||||
return getCollection(name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a collection matching a given string.
|
||||
* @param s the name of the collection
|
||||
* @return the collection
|
||||
*/
|
||||
public DBCollection getCollectionFromString( String s ){
|
||||
DBCollection foo = null;
|
||||
|
||||
int idx = s.indexOf( "." );
|
||||
while ( idx >= 0 ){
|
||||
String b = s.substring( 0 , idx );
|
||||
s = s.substring( idx + 1 );
|
||||
if ( foo == null )
|
||||
foo = getCollection( b );
|
||||
else
|
||||
foo = foo.getCollection( b );
|
||||
idx = s.indexOf( "." );
|
||||
}
|
||||
|
||||
if ( foo != null )
|
||||
return foo.getCollection( s );
|
||||
return getCollection( s );
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a database command.
|
||||
* This method calls {@link DB#command(com.massivecraft.massivecore.xlib.mongodb.DBObject, int) } with 0 as query option.
|
||||
* @see <a href="http://mongodb.onconfluence.com/display/DOCS/List+of+Database+Commands">List of Commands</a>
|
||||
* @param cmd dbobject representing the command to execute
|
||||
* @return result of command from the database
|
||||
* @throws MongoException
|
||||
* @dochub commands
|
||||
*/
|
||||
public CommandResult command( DBObject cmd ){
|
||||
return command( cmd, 0 );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Executes a database command.
|
||||
* This method calls {@link DB#command(com.massivecraft.massivecore.xlib.mongodb.DBObject, int, com.massivecraft.massivecore.xlib.mongodb.DBEncoder) } with 0 as query option.
|
||||
* @see <a href="http://mongodb.onconfluence.com/display/DOCS/List+of+Database+Commands">List of Commands</a>
|
||||
* @param cmd dbobject representing the command to execute
|
||||
* @param encoder
|
||||
* @return result of command from the database
|
||||
* @throws MongoException
|
||||
* @dochub commands
|
||||
*/
|
||||
public CommandResult command( DBObject cmd, DBEncoder encoder ){
|
||||
return command( cmd, 0, encoder );
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a database command.
|
||||
* This method calls {@link DB#command(com.massivecraft.massivecore.xlib.mongodb.DBObject, int, com.massivecraft.massivecore.xlib.mongodb.ReadPreference, com.massivecraft.massivecore.xlib.mongodb.DBEncoder) } with a null readPrefs.
|
||||
* @see <a href="http://mongodb.onconfluence.com/display/DOCS/List+of+Database+Commands">List of Commands</a>
|
||||
* @param cmd dbobject representing the command to execute
|
||||
* @param options query options to use
|
||||
* @param encoder
|
||||
* @return result of command from the database
|
||||
* @throws MongoException
|
||||
* @dochub commands
|
||||
*/
|
||||
public CommandResult command( DBObject cmd , int options, DBEncoder encoder ){
|
||||
return command(cmd, options, getReadPreference(), encoder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a database command.
|
||||
* This method calls {@link DB#command(com.massivecraft.massivecore.xlib.mongodb.DBObject, int, com.massivecraft.massivecore.xlib.mongodb.ReadPreference, com.massivecraft.massivecore.xlib.mongodb.DBEncoder) } with a default encoder.
|
||||
* @see <a href="http://mongodb.onconfluence.com/display/DOCS/List+of+Database+Commands">List of Commands</a>
|
||||
* @param cmd dbobject representing the command to execute
|
||||
* @param options query options to use
|
||||
* @param readPrefs ReadPreferences for this command (nodes selection is the biggest part of this)
|
||||
* @return result of command from the database
|
||||
* @throws MongoException
|
||||
* @dochub commands
|
||||
*/
|
||||
public CommandResult command( DBObject cmd , int options, ReadPreference readPrefs ){
|
||||
return command(cmd, options, readPrefs, DefaultDBEncoder.FACTORY.create());
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a database command.
|
||||
* @see <a href="http://mongodb.onconfluence.com/display/DOCS/List+of+Database+Commands">List of Commands</a>
|
||||
* @param cmd dbobject representing the command to execute
|
||||
* @param options query options to use
|
||||
* @param readPrefs ReadPreferences for this command (nodes selection is the biggest part of this)
|
||||
* @param encoder
|
||||
* @return result of command from the database
|
||||
* @throws MongoException
|
||||
* @dochub commands
|
||||
*/
|
||||
public CommandResult command( DBObject cmd , int options, ReadPreference readPrefs, DBEncoder encoder ){
|
||||
readPrefs = getCommandReadPreference(cmd, readPrefs);
|
||||
cmd = wrapCommand(cmd, readPrefs);
|
||||
|
||||
Iterator<DBObject> i =
|
||||
getCollection("$cmd").__find(cmd, new BasicDBObject(), 0, -1, 0, options, readPrefs ,
|
||||
DefaultDBDecoder.FACTORY.create(), encoder);
|
||||
if ( i == null || ! i.hasNext() )
|
||||
return null;
|
||||
|
||||
DBObject res = i.next();
|
||||
ServerAddress sa = (i instanceof Result) ? ((Result) i).getServerAddress() : null;
|
||||
CommandResult cr = new CommandResult(sa);
|
||||
cr.putAll( res );
|
||||
return cr;
|
||||
}
|
||||
|
||||
// Only append $readPreference meta-operator if connected to a mongos, read preference is not primary
|
||||
// or secondary preferred,
|
||||
// and command is an instance of BasicDBObject. The last condition is unfortunate, but necessary in case
|
||||
// the encoder is not capable of encoding a BasicDBObject
|
||||
// Due to issues with compatibility between different versions of mongos, also wrap the command in a
|
||||
// $query field, so that the $readPreference is not rejected
|
||||
private DBObject wrapCommand(DBObject cmd, final ReadPreference readPrefs) {
|
||||
if (getMongo().isMongosConnection() &&
|
||||
!(ReadPreference.primary().equals(readPrefs) || ReadPreference.secondaryPreferred().equals(readPrefs)) &&
|
||||
cmd instanceof BasicDBObject) {
|
||||
cmd = new BasicDBObject("$query", cmd)
|
||||
.append(QueryOpBuilder.READ_PREFERENCE_META_OPERATOR, readPrefs.toDBObject());
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a database command.
|
||||
* @see <a href="http://mongodb.onconfluence.com/display/DOCS/List+of+Database+Commands">List of Commands</a>
|
||||
* @param cmd dbobject representing the command to execute
|
||||
* @param options query options to use
|
||||
* @return result of command from the database
|
||||
* @throws MongoException
|
||||
* @dochub commands
|
||||
*/
|
||||
public CommandResult command( DBObject cmd , int options ){
|
||||
return command(cmd, options, getReadPreference());
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a database command.
|
||||
* This method constructs a simple dbobject and calls {@link DB#command(com.massivecraft.massivecore.xlib.mongodb.DBObject) }
|
||||
* @see <a href="http://mongodb.onconfluence.com/display/DOCS/List+of+Database+Commands">List of Commands</a>
|
||||
* @param cmd command to execute
|
||||
* @return result of command from the database
|
||||
* @throws MongoException
|
||||
* @dochub commands
|
||||
*/
|
||||
public CommandResult command( String cmd ){
|
||||
return command( new BasicDBObject( cmd , Boolean.TRUE ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a database command.
|
||||
* This method constructs a simple dbobject and calls {@link DB#command(com.massivecraft.massivecore.xlib.mongodb.DBObject, int) }
|
||||
* @see <a href="http://mongodb.onconfluence.com/display/DOCS/List+of+Database+Commands">List of Commands</a>
|
||||
* @param cmd command to execute
|
||||
* @param options query options to use
|
||||
* @return result of command from the database
|
||||
* @throws MongoException
|
||||
* @dochub commands
|
||||
*/
|
||||
public CommandResult command( String cmd, int options ){
|
||||
return command( new BasicDBObject( cmd , Boolean.TRUE ), options );
|
||||
}
|
||||
|
||||
/**
|
||||
* evaluates a function on the database.
|
||||
* This is useful if you need to touch a lot of data lightly, in which case network transfer could be a bottleneck.
|
||||
* @param code the function in javascript code
|
||||
* @param args arguments to be passed to the function
|
||||
* @return The command result
|
||||
* @throws MongoException
|
||||
*/
|
||||
public CommandResult doEval( String code , Object ... args ){
|
||||
|
||||
return command( BasicDBObjectBuilder.start()
|
||||
.add( "$eval" , code )
|
||||
.add( "args" , args )
|
||||
.get() );
|
||||
}
|
||||
|
||||
/**
|
||||
* calls {@link DB#doEval(java.lang.String, java.lang.Object[]) }.
|
||||
* If the command is successful, the "retval" field is extracted and returned.
|
||||
* Otherwise an exception is thrown.
|
||||
* @param code the function in javascript code
|
||||
* @param args arguments to be passed to the function
|
||||
* @return The object
|
||||
* @throws MongoException
|
||||
*/
|
||||
public Object eval( String code , Object ... args ){
|
||||
|
||||
CommandResult res = doEval( code , args );
|
||||
res.throwOnError();
|
||||
return res.get( "retval" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of "dbstats" command
|
||||
* @return
|
||||
* @throws MongoException
|
||||
*/
|
||||
public CommandResult getStats() {
|
||||
return command("dbstats");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this database.
|
||||
* @return the name
|
||||
*/
|
||||
public String getName(){
|
||||
return _name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes this database read-only.
|
||||
* Important note: this is a convenience setting that is only known on the client side and not persisted.
|
||||
* @param b if the database should be read-only
|
||||
*/
|
||||
public void setReadOnly( Boolean b ){
|
||||
_readOnly = b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set containing the names of all collections in this database.
|
||||
* @return the names of collections in this database
|
||||
* @throws MongoException
|
||||
*/
|
||||
public Set<String> getCollectionNames(){
|
||||
|
||||
DBCollection namespaces = getCollection("system.namespaces");
|
||||
if (namespaces == null)
|
||||
throw new RuntimeException("this is impossible");
|
||||
|
||||
Iterator<DBObject> i = namespaces.__find(new BasicDBObject(), null, 0, 0, 0, getOptions(), getReadPreference(), null);
|
||||
if (i == null)
|
||||
return new HashSet<String>();
|
||||
|
||||
List<String> tables = new ArrayList<String>();
|
||||
|
||||
for (; i.hasNext();) {
|
||||
DBObject o = i.next();
|
||||
if ( o.get( "name" ) == null ){
|
||||
throw new MongoException( "how is name null : " + o );
|
||||
}
|
||||
String n = o.get("name").toString();
|
||||
int idx = n.indexOf(".");
|
||||
|
||||
String root = n.substring(0, idx);
|
||||
if (!root.equals(_name))
|
||||
continue;
|
||||
|
||||
if (n.indexOf("$") >= 0)
|
||||
continue;
|
||||
|
||||
String table = n.substring(idx + 1);
|
||||
|
||||
tables.add(table);
|
||||
}
|
||||
|
||||
Collections.sort(tables);
|
||||
|
||||
return new LinkedHashSet<String>(tables);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a collection by name %lt;name> exists.
|
||||
* @param collectionName The collection to test for existence
|
||||
* @return false if no collection by that name exists, true if a match to an existing collection was found
|
||||
* @throws MongoException
|
||||
*/
|
||||
public boolean collectionExists(String collectionName)
|
||||
{
|
||||
if (collectionName == null || "".equals(collectionName))
|
||||
return false;
|
||||
|
||||
Set<String> collections = getCollectionNames();
|
||||
if (collections.isEmpty())
|
||||
return false;
|
||||
|
||||
for (String collection : collections)
|
||||
{
|
||||
if (collectionName.equalsIgnoreCase(collection))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of this database.
|
||||
* @return the name
|
||||
*/
|
||||
@Override
|
||||
public String toString(){
|
||||
return _name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the the error (if there is one) from the previous operation on this connection.
|
||||
* The result of this command will look like
|
||||
*
|
||||
* <pre>
|
||||
* { "err" : errorMessage , "ok" : 1.0 }
|
||||
* </pre>
|
||||
*
|
||||
* The value for errorMessage will be null if no error occurred, or a description otherwise.
|
||||
*
|
||||
* Important note: when calling this method directly, it is undefined which connection "getLastError" is called on.
|
||||
* You may need to explicitly use a "consistent Request", see {@link DB#requestStart()}
|
||||
* For most purposes it is better not to call this method directly but instead use {@link WriteConcern}
|
||||
*
|
||||
* @return DBObject with error and status information
|
||||
* @throws MongoException
|
||||
*/
|
||||
public CommandResult getLastError(){
|
||||
return command(new BasicDBObject("getlasterror", 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see {@link DB#getLastError() }
|
||||
* @param concern the concern associated with "getLastError" call
|
||||
* @return
|
||||
* @throws MongoException
|
||||
*/
|
||||
public CommandResult getLastError( com.massivecraft.massivecore.xlib.mongodb.WriteConcern concern ){
|
||||
return command( concern.getCommand() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see {@link DB#getLastError(com.massivecraft.massivecore.xlib.mongodb.WriteConcern) }
|
||||
* @param w
|
||||
* @param wtimeout
|
||||
* @param fsync
|
||||
* @return The command result
|
||||
* @throws MongoException
|
||||
*/
|
||||
public CommandResult getLastError( int w , int wtimeout , boolean fsync ){
|
||||
return command( (new com.massivecraft.massivecore.xlib.mongodb.WriteConcern( w, wtimeout , fsync )).getCommand() );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the write concern for this database. It Will be used for
|
||||
* writes to any collection in this database. See the
|
||||
* documentation for {@link WriteConcern} for more information.
|
||||
* @param concern write concern to use
|
||||
*/
|
||||
public void setWriteConcern( com.massivecraft.massivecore.xlib.mongodb.WriteConcern concern ){
|
||||
if (concern == null) throw new IllegalArgumentException();
|
||||
_concern = concern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the write concern for this database.
|
||||
* @return
|
||||
*/
|
||||
public com.massivecraft.massivecore.xlib.mongodb.WriteConcern getWriteConcern(){
|
||||
if ( _concern != null )
|
||||
return _concern;
|
||||
return _mongo.getWriteConcern();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the read preference for this database. Will be used as default for
|
||||
* reads from any collection in this database. See the
|
||||
* documentation for {@link ReadPreference} for more information.
|
||||
*
|
||||
* @param preference Read Preference to use
|
||||
*/
|
||||
public void setReadPreference( ReadPreference preference ){
|
||||
_readPref = preference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default read preference
|
||||
* @return
|
||||
*/
|
||||
public ReadPreference getReadPreference(){
|
||||
if ( _readPref != null )
|
||||
return _readPref;
|
||||
return _mongo.getReadPreference();
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops this database. Removes all data on disk. Use with caution.
|
||||
* @throws MongoException
|
||||
*/
|
||||
public void dropDatabase(){
|
||||
|
||||
CommandResult res = command(new BasicDBObject("dropDatabase", 1));
|
||||
res.throwOnError();
|
||||
_mongo._dbs.remove(this.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a user has been authenticated
|
||||
*
|
||||
* @return true if authenticated, false otherwise
|
||||
* @dochub authenticate
|
||||
*/
|
||||
public boolean isAuthenticated() {
|
||||
return getAuthenticationCredentials() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticates to db with the given credentials. If this method (or {@code authenticateCommand} has already been
|
||||
* called with the same credentials and the authentication test succeeded, this method will return true. If this method
|
||||
* has already been called with different credentials and the authentication test succeeded,
|
||||
* this method will throw an {@code IllegalStateException}. If this method has already been called with any credentials
|
||||
* and the authentication test failed, this method will re-try the authentication test with the
|
||||
* given credentials.
|
||||
*
|
||||
* @param username name of user for this database
|
||||
* @param password password of user for this database
|
||||
* @return true if authenticated, false otherwise
|
||||
* @throws MongoException if authentication failed due to invalid user/pass, or other exceptions like I/O
|
||||
* @throws IllegalStateException if authentiation test has already succeeded with different credentials
|
||||
* @see #authenticateCommand(String, char[])
|
||||
* @dochub authenticate
|
||||
*/
|
||||
public boolean authenticate(String username, char[] password ){
|
||||
return authenticateCommandHelper(username, password).failure == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticates to db with the given credentials. If this method (or {@code authenticate} has already been
|
||||
* called with the same credentials and the authentication test succeeded, this method will return true. If this method
|
||||
* has already been called with different credentials and the authentication test succeeded,
|
||||
* this method will throw an {@code IllegalStateException}. If this method has already been called with any credentials
|
||||
* and the authentication test failed, this method will re-try the authentication test with the
|
||||
* given credentials.
|
||||
*
|
||||
*
|
||||
* @param username name of user for this database
|
||||
* @param password password of user for this database
|
||||
* @return the CommandResult from authenticate command
|
||||
* @throws MongoException if authentication failed due to invalid user/pass, or other exceptions like I/O
|
||||
* @throws IllegalStateException if authentiation test has already succeeded with different credentials
|
||||
* @see #authenticate(String, char[])
|
||||
* @dochub authenticate
|
||||
*/
|
||||
public synchronized CommandResult authenticateCommand(String username, char[] password ){
|
||||
CommandResultPair commandResultPair = authenticateCommandHelper(username, password);
|
||||
if (commandResultPair.failure != null) {
|
||||
throw commandResultPair.failure;
|
||||
}
|
||||
return commandResultPair.result;
|
||||
}
|
||||
|
||||
private CommandResultPair authenticateCommandHelper(String username, char[] password) {
|
||||
MongoCredential credentials =
|
||||
MongoCredential.createMongoCRCredential(username, getName(), password);
|
||||
if (getAuthenticationCredentials() != null) {
|
||||
if (getAuthenticationCredentials().equals(credentials)) {
|
||||
if (authenticationTestCommandResult != null) {
|
||||
return new CommandResultPair(authenticationTestCommandResult);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException("can't authenticate twice on the same database");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
authenticationTestCommandResult = doAuthenticate(credentials);
|
||||
return new CommandResultPair(authenticationTestCommandResult);
|
||||
} catch (CommandFailureException commandFailureException) {
|
||||
return new CommandResultPair(commandFailureException);
|
||||
}
|
||||
}
|
||||
|
||||
class CommandResultPair {
|
||||
CommandResult result;
|
||||
CommandFailureException failure;
|
||||
|
||||
public CommandResultPair(final CommandResult result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public CommandResultPair(final CommandFailureException failure) {
|
||||
this.failure = failure;
|
||||
}
|
||||
}
|
||||
|
||||
abstract CommandResult doAuthenticate(MongoCredential credentials);
|
||||
|
||||
/**
|
||||
* Adds a new user for this db
|
||||
* @param username
|
||||
* @param passwd
|
||||
* @throws MongoException
|
||||
*/
|
||||
public WriteResult addUser( String username , char[] passwd ){
|
||||
return addUser(username, passwd, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new user for this db
|
||||
* @param username
|
||||
* @param passwd
|
||||
* @param readOnly if true, user will only be able to read
|
||||
* @throws MongoException
|
||||
*/
|
||||
public WriteResult addUser( String username , char[] passwd, boolean readOnly ){
|
||||
DBCollection c = getCollection( "system.users" );
|
||||
DBObject o = c.findOne( new BasicDBObject( "user" , username ) );
|
||||
if ( o == null )
|
||||
o = new BasicDBObject( "user" , username );
|
||||
o.put( "pwd" , _hash( username , passwd ) );
|
||||
o.put( "readOnly" , readOnly );
|
||||
return c.save( o );
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a user for this db
|
||||
* @param username
|
||||
* @throws MongoException
|
||||
*/
|
||||
public WriteResult removeUser( String username ){
|
||||
DBCollection c = getCollection( "system.users" );
|
||||
return c.remove(new BasicDBObject( "user" , username ));
|
||||
}
|
||||
|
||||
String _hash( String username , char[] passwd ){
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream( username.length() + 20 + passwd.length );
|
||||
try {
|
||||
bout.write( username.getBytes() );
|
||||
bout.write( ":mongo:".getBytes() );
|
||||
for ( int i=0; i<passwd.length; i++ ){
|
||||
if ( passwd[i] >= 128 )
|
||||
throw new IllegalArgumentException( "can't handle non-ascii passwords yet" );
|
||||
bout.write( (byte)passwd[i] );
|
||||
}
|
||||
}
|
||||
catch ( IOException ioe ){
|
||||
throw new RuntimeException( "impossible" , ioe );
|
||||
}
|
||||
return Util.hexMD5( bout.toByteArray() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last error that occurred since start of database or a call to <code>resetError()</code>
|
||||
*
|
||||
* The return object will look like
|
||||
*
|
||||
* <pre>
|
||||
* { err : errorMessage, nPrev : countOpsBack, ok : 1 }
|
||||
* </pre>
|
||||
*
|
||||
* The value for errorMessage will be null of no error has occurred, otherwise the error message.
|
||||
* The value of countOpsBack will be the number of operations since the error occurred.
|
||||
*
|
||||
* Care must be taken to ensure that calls to getPreviousError go to the same connection as that
|
||||
* of the previous operation.
|
||||
* See {@link DB#requestStart()} for more information.
|
||||
*
|
||||
* @return DBObject with error and status information
|
||||
* @throws MongoException
|
||||
*/
|
||||
public CommandResult getPreviousError(){
|
||||
return command(new BasicDBObject("getpreverror", 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the error memory for this database.
|
||||
* Used to clear all errors such that {@link DB#getPreviousError()} will return no error.
|
||||
* @throws MongoException
|
||||
*/
|
||||
public void resetError(){
|
||||
command(new BasicDBObject("reseterror", 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* For testing purposes only - this method forces an error to help test error handling
|
||||
* @throws MongoException
|
||||
*/
|
||||
public void forceError(){
|
||||
command(new BasicDBObject("forceerror", 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Mongo instance
|
||||
* @return
|
||||
*/
|
||||
public Mongo getMongo(){
|
||||
return _mongo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets another database on same server
|
||||
* @param name name of the database
|
||||
* @return
|
||||
*/
|
||||
public DB getSisterDB( String name ){
|
||||
return _mongo.getDB( name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes it possible to execute "read" queries on a slave node
|
||||
*
|
||||
* @deprecated Replaced with {@code ReadPreference.secondaryPreferred()}
|
||||
* @see ReadPreference#secondaryPreferred()
|
||||
*/
|
||||
@Deprecated
|
||||
public void slaveOk(){
|
||||
addOption( Bytes.QUERYOPTION_SLAVEOK );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the give option
|
||||
* @param option
|
||||
*/
|
||||
public void addOption( int option ){
|
||||
_options.add( option );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the query options
|
||||
* @param options
|
||||
*/
|
||||
public void setOptions( int options ){
|
||||
_options.set( options );
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the query options
|
||||
*/
|
||||
public void resetOptions(){
|
||||
_options.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the query options
|
||||
* @return
|
||||
*/
|
||||
public int getOptions(){
|
||||
return _options.get();
|
||||
}
|
||||
|
||||
public abstract void cleanCursors( boolean force );
|
||||
|
||||
MongoCredential getAuthenticationCredentials() {
|
||||
return getMongo().getAuthority().getCredentialsStore().get(getName());
|
||||
}
|
||||
|
||||
final Mongo _mongo;
|
||||
final String _name;
|
||||
|
||||
protected boolean _readOnly = false;
|
||||
private com.massivecraft.massivecore.xlib.mongodb.WriteConcern _concern;
|
||||
private com.massivecraft.massivecore.xlib.mongodb.ReadPreference _readPref;
|
||||
final Bytes.OptionHolder _options;
|
||||
|
||||
// cached authentication command result, to return in case of multiple calls to authenticateCommand with the
|
||||
// same credentials
|
||||
private volatile CommandResult authenticationTestCommandResult;
|
||||
}
|
@ -1,187 +0,0 @@
|
||||
// DBAddress.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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.mongodb;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
/**
|
||||
* Represents a database address
|
||||
*/
|
||||
public class DBAddress extends ServerAddress {
|
||||
|
||||
/** Creates a new address
|
||||
* Accepts as the parameter format:
|
||||
* <table border="1">
|
||||
* <tr>
|
||||
* <td><i>name</i></td>
|
||||
* <td>"mydb"</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><i><host>/name</i></td>
|
||||
* <td>"127.0.0.1/mydb"</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><i><host>:<port>/name</i></td>
|
||||
* <td>"127.0.0.1:8080/mydb"</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
* @param urlFormat
|
||||
* @throws UnknownHostException
|
||||
*/
|
||||
public DBAddress( String urlFormat )
|
||||
throws UnknownHostException {
|
||||
super( _getHostSection( urlFormat ) );
|
||||
|
||||
_check( urlFormat , "urlFormat" );
|
||||
_db = _fixName( _getDBSection( urlFormat ) );
|
||||
|
||||
_check( _host , "host" );
|
||||
_check( _db , "db" );
|
||||
}
|
||||
|
||||
static String _getHostSection( String urlFormat ){
|
||||
if ( urlFormat == null )
|
||||
throw new NullPointerException( "urlFormat can't be null" );
|
||||
int idx = urlFormat.indexOf( "/" );
|
||||
if ( idx >= 0 )
|
||||
return urlFormat.substring( 0 , idx );
|
||||
return null;
|
||||
}
|
||||
|
||||
static String _getDBSection( String urlFormat ){
|
||||
if ( urlFormat == null )
|
||||
throw new NullPointerException( "urlFormat can't be null" );
|
||||
int idx = urlFormat.indexOf( "/" );
|
||||
if ( idx >= 0 )
|
||||
return urlFormat.substring( idx + 1 );
|
||||
return urlFormat;
|
||||
}
|
||||
|
||||
static String _fixName( String name ){
|
||||
name = name.replace( '.' , '-' );
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param other an existing <code>DBAddress</code> that gives the host and port
|
||||
* @param dbname the database to which to connect
|
||||
* @throws UnknownHostException
|
||||
*/
|
||||
public DBAddress( DBAddress other , String dbname )
|
||||
throws UnknownHostException {
|
||||
this( other._host , other._port , dbname );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param host host name
|
||||
* @param dbname database name
|
||||
* @throws UnknownHostException
|
||||
*/
|
||||
public DBAddress( String host , String dbname )
|
||||
throws UnknownHostException {
|
||||
this( host , DBPort.PORT , dbname );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param host host name
|
||||
* @param port database port
|
||||
* @param dbname database name
|
||||
* @throws UnknownHostException
|
||||
*/
|
||||
public DBAddress( String host , int port , String dbname )
|
||||
throws UnknownHostException {
|
||||
super( host , port );
|
||||
_db = dbname.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param addr host address
|
||||
* @param port database port
|
||||
* @param dbname database name
|
||||
*/
|
||||
public DBAddress( InetAddress addr , int port , String dbname ){
|
||||
super( addr , port );
|
||||
_check( dbname , "name" );
|
||||
_db = dbname.trim();
|
||||
}
|
||||
|
||||
static void _check( String thing , String name ){
|
||||
if ( thing == null )
|
||||
throw new NullPointerException( name + " can't be null " );
|
||||
|
||||
thing = thing.trim();
|
||||
if ( thing.length() == 0 )
|
||||
throw new IllegalArgumentException( name + " can't be empty" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode(){
|
||||
return super.hashCode() + _db.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals( Object other ){
|
||||
if ( other instanceof DBAddress ){
|
||||
DBAddress a = (DBAddress)other;
|
||||
return
|
||||
a._port == _port &&
|
||||
a._db.equals( _db ) &&
|
||||
a._host.equals( _host );
|
||||
} else if ( other instanceof ServerAddress ){
|
||||
return other.equals(this);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* creates a DBAddress pointing to a different database on the same server
|
||||
* @param name database name
|
||||
* @return
|
||||
* @throws MongoException
|
||||
*/
|
||||
public DBAddress getSister( String name ){
|
||||
try {
|
||||
return new DBAddress( _host , _port , name );
|
||||
}
|
||||
catch ( UnknownHostException uh ){
|
||||
throw new MongoInternalException( "shouldn't be possible" , uh );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the database name
|
||||
* @return
|
||||
*/
|
||||
public String getDBName(){
|
||||
return _db;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets a String representation of address as host:port/dbname.
|
||||
* @return this address
|
||||
*/
|
||||
@Override
|
||||
public String toString(){
|
||||
return super.toString() + "/" + _db;
|
||||
}
|
||||
|
||||
final String _db;
|
||||
}
|
@ -1,556 +0,0 @@
|
||||
// DBApiLayer.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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.mongodb;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.BSONObject;
|
||||
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
|
||||
import com.massivecraft.massivecore.xlib.mongodb.util.JSON;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
/** Database API
|
||||
* This cannot be directly instantiated, but the functions are available
|
||||
* through instances of Mongo.
|
||||
*/
|
||||
public class DBApiLayer extends DB {
|
||||
|
||||
/** The maximum number of cursors allowed */
|
||||
static final int NUM_CURSORS_BEFORE_KILL = 100;
|
||||
static final int NUM_CURSORS_PER_BATCH = 20000;
|
||||
|
||||
// --- show
|
||||
|
||||
static final Logger TRACE_LOGGER = Logger.getLogger( "com.mongodb.TRACE" );
|
||||
static final Level TRACE_LEVEL = Boolean.getBoolean( "DB.TRACE" ) ? Level.INFO : Level.FINEST;
|
||||
|
||||
static boolean willTrace(){
|
||||
return TRACE_LOGGER.isLoggable( TRACE_LEVEL );
|
||||
}
|
||||
|
||||
static void trace( String s ){
|
||||
TRACE_LOGGER.log( TRACE_LEVEL , s );
|
||||
}
|
||||
|
||||
static int chooseBatchSize(int batchSize, int limit, int fetched) {
|
||||
int bs = Math.abs(batchSize);
|
||||
int remaining = limit > 0 ? limit - fetched : 0;
|
||||
int res;
|
||||
if (bs == 0 && remaining > 0)
|
||||
res = remaining;
|
||||
else if (bs > 0 && remaining == 0)
|
||||
res = bs;
|
||||
else
|
||||
res = Math.min(bs, remaining);
|
||||
|
||||
if (batchSize < 0) {
|
||||
// force close
|
||||
res = -res;
|
||||
}
|
||||
|
||||
if (res == 1) {
|
||||
// optimization: use negative batchsize to close cursor
|
||||
res = -1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mongo the Mongo instance
|
||||
* @param name the database name
|
||||
* @param connector the connector
|
||||
*/
|
||||
protected DBApiLayer( Mongo mongo, String name , DBConnector connector ){
|
||||
super( mongo, name );
|
||||
|
||||
if ( connector == null )
|
||||
throw new IllegalArgumentException( "need a connector: " + name );
|
||||
|
||||
_root = name;
|
||||
_rootPlusDot = _root + ".";
|
||||
|
||||
_connector = connector;
|
||||
}
|
||||
|
||||
public void requestStart(){
|
||||
_connector.requestStart();
|
||||
}
|
||||
|
||||
public void requestDone(){
|
||||
_connector.requestDone();
|
||||
}
|
||||
|
||||
public void requestEnsureConnection(){
|
||||
_connector.requestEnsureConnection();
|
||||
}
|
||||
|
||||
protected MyCollection doGetCollection( String name ){
|
||||
MyCollection c = _collections.get( name );
|
||||
if ( c != null )
|
||||
return c;
|
||||
|
||||
c = new MyCollection( name );
|
||||
MyCollection old = _collections.putIfAbsent(name, c);
|
||||
return old != null ? old : c;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param force true if should clean regardless of number of dead cursors
|
||||
* @throws MongoException
|
||||
*/
|
||||
public void cleanCursors( boolean force ){
|
||||
|
||||
int sz = _deadCursorIds.size();
|
||||
|
||||
if ( sz == 0 || ( ! force && sz < NUM_CURSORS_BEFORE_KILL))
|
||||
return;
|
||||
|
||||
Bytes.LOGGER.info( "going to kill cursors : " + sz );
|
||||
|
||||
Map<ServerAddress,List<Long>> m = new HashMap<ServerAddress,List<Long>>();
|
||||
DeadCursor c;
|
||||
while (( c = _deadCursorIds.poll()) != null ){
|
||||
List<Long> x = m.get( c.host );
|
||||
if ( x == null ){
|
||||
x = new LinkedList<Long>();
|
||||
m.put( c.host , x );
|
||||
}
|
||||
x.add( c.id );
|
||||
}
|
||||
|
||||
for ( Map.Entry<ServerAddress,List<Long>> e : m.entrySet() ){
|
||||
try {
|
||||
killCursors( e.getKey() , e.getValue() );
|
||||
}
|
||||
catch ( Throwable t ){
|
||||
Bytes.LOGGER.log( Level.WARNING , "can't clean cursors" , t );
|
||||
for ( Long x : e.getValue() )
|
||||
_deadCursorIds.add( new DeadCursor( x , e.getKey() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void killCursors( ServerAddress addr , List<Long> all ){
|
||||
if ( all == null || all.size() == 0 )
|
||||
return;
|
||||
|
||||
OutMessage om = OutMessage.killCursors(_mongo, Math.min( NUM_CURSORS_PER_BATCH , all.size()));
|
||||
|
||||
int soFar = 0;
|
||||
int totalSoFar = 0;
|
||||
for (Long l : all) {
|
||||
om.writeLong(l);
|
||||
|
||||
totalSoFar++;
|
||||
soFar++;
|
||||
|
||||
if ( soFar >= NUM_CURSORS_PER_BATCH ){
|
||||
_connector.say( this , om ,com.massivecraft.massivecore.xlib.mongodb.WriteConcern.NONE );
|
||||
om = OutMessage.killCursors(_mongo, Math.min( NUM_CURSORS_PER_BATCH , all.size() - totalSoFar));
|
||||
soFar = 0;
|
||||
}
|
||||
}
|
||||
|
||||
_connector.say( this , om ,com.massivecraft.massivecore.xlib.mongodb.WriteConcern.NONE , addr );
|
||||
}
|
||||
|
||||
@Override
|
||||
CommandResult doAuthenticate(MongoCredential credentials) {
|
||||
return _connector.authenticate(credentials);
|
||||
}
|
||||
|
||||
class MyCollection extends DBCollection {
|
||||
MyCollection( String name ){
|
||||
super( DBApiLayer.this , name );
|
||||
_fullNameSpace = _root + "." + name;
|
||||
}
|
||||
|
||||
public void doapply( DBObject o ){
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drop(){
|
||||
_collections.remove(getName());
|
||||
super.drop();
|
||||
}
|
||||
|
||||
public WriteResult insert(List<DBObject> list, com.massivecraft.massivecore.xlib.mongodb.WriteConcern concern, DBEncoder encoder ){
|
||||
|
||||
if (concern == null) {
|
||||
throw new IllegalArgumentException("Write concern can not be null");
|
||||
}
|
||||
|
||||
return insert(list, true, concern, encoder);
|
||||
}
|
||||
|
||||
protected WriteResult insert(List<DBObject> list, boolean shouldApply , com.massivecraft.massivecore.xlib.mongodb.WriteConcern concern, DBEncoder encoder ){
|
||||
|
||||
if (encoder == null)
|
||||
encoder = DefaultDBEncoder.FACTORY.create();
|
||||
|
||||
if ( willTrace() ) {
|
||||
for (DBObject o : list) {
|
||||
trace( "save: " + _fullNameSpace + " " + JSON.serialize( o ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( shouldApply ){
|
||||
for (DBObject o : list) {
|
||||
apply(o);
|
||||
_checkObject(o, false, false);
|
||||
Object id = o.get("_id");
|
||||
if (id instanceof ObjectId) {
|
||||
((ObjectId) id).notNew();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WriteResult last = null;
|
||||
|
||||
int cur = 0;
|
||||
int maxsize = _mongo.getMaxBsonObjectSize();
|
||||
while ( cur < list.size() ) {
|
||||
|
||||
OutMessage om = OutMessage.insert( this , encoder, concern );
|
||||
|
||||
for ( ; cur < list.size(); cur++ ){
|
||||
DBObject o = list.get(cur);
|
||||
om.putObject( o );
|
||||
|
||||
// limit for batch insert is 4 x maxbson on server, use 2 x to be safe
|
||||
if ( om.size() > 2 * maxsize ){
|
||||
cur++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
last = _connector.say( _db , om , concern );
|
||||
}
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
public WriteResult remove( DBObject o , com.massivecraft.massivecore.xlib.mongodb.WriteConcern concern, DBEncoder encoder ){
|
||||
|
||||
if (concern == null) {
|
||||
throw new IllegalArgumentException("Write concern can not be null");
|
||||
}
|
||||
|
||||
if (encoder == null)
|
||||
encoder = DefaultDBEncoder.FACTORY.create();
|
||||
|
||||
if ( willTrace() ) trace( "remove: " + _fullNameSpace + " " + JSON.serialize( o ) );
|
||||
|
||||
OutMessage om = OutMessage.remove(this, encoder, o);
|
||||
|
||||
return _connector.say( _db , om , concern );
|
||||
}
|
||||
|
||||
@Override
|
||||
Iterator<DBObject> __find( DBObject ref , DBObject fields , int numToSkip , int batchSize, int limit , int options, ReadPreference readPref, DBDecoder decoder ){
|
||||
|
||||
return __find(ref, fields, numToSkip, batchSize, limit, options, readPref, decoder, DefaultDBEncoder.FACTORY.create());
|
||||
}
|
||||
|
||||
@Override
|
||||
Iterator<DBObject> __find( DBObject ref , DBObject fields , int numToSkip , int batchSize , int limit, int options,
|
||||
ReadPreference readPref, DBDecoder decoder, DBEncoder encoder ){
|
||||
|
||||
if ( ref == null )
|
||||
ref = new BasicDBObject();
|
||||
|
||||
if ( willTrace() ) trace( "find: " + _fullNameSpace + " " + JSON.serialize( ref ) );
|
||||
|
||||
OutMessage query = OutMessage.query( this , options , numToSkip , chooseBatchSize(batchSize, limit, 0) , ref , fields, readPref,
|
||||
encoder);
|
||||
|
||||
Response res = _connector.call( _db , this , query , null , 2, readPref, decoder );
|
||||
|
||||
if ( res.size() == 1 ){
|
||||
BSONObject foo = res.get(0);
|
||||
MongoException e = MongoException.parse( foo );
|
||||
if ( e != null && ! _name.equals( "$cmd" ) )
|
||||
throw e;
|
||||
}
|
||||
|
||||
return new Result( this , res , batchSize, limit , options, decoder );
|
||||
}
|
||||
|
||||
@Override
|
||||
public WriteResult update( DBObject query , DBObject o , boolean upsert , boolean multi , com.massivecraft.massivecore.xlib.mongodb.WriteConcern concern, DBEncoder encoder ){
|
||||
|
||||
if (o == null) {
|
||||
throw new IllegalArgumentException("update can not be null");
|
||||
}
|
||||
|
||||
if (concern == null) {
|
||||
throw new IllegalArgumentException("Write concern can not be null");
|
||||
}
|
||||
|
||||
if (encoder == null)
|
||||
encoder = DefaultDBEncoder.FACTORY.create();
|
||||
|
||||
if (!o.keySet().isEmpty()) {
|
||||
// if 1st key doesn't start with $, then object will be inserted as is, need to check it
|
||||
String key = o.keySet().iterator().next();
|
||||
if (!key.startsWith("$"))
|
||||
_checkObject(o, false, false);
|
||||
}
|
||||
|
||||
if ( willTrace() ) {
|
||||
trace( "update: " + _fullNameSpace + " " + JSON.serialize( query ) + " " + JSON.serialize( o ) );
|
||||
}
|
||||
|
||||
OutMessage om = OutMessage.update(this, encoder, upsert, multi, query, o);
|
||||
|
||||
return _connector.say( _db , om , concern );
|
||||
}
|
||||
|
||||
public void createIndex( final DBObject keys, final DBObject options, DBEncoder encoder ){
|
||||
|
||||
if (encoder == null)
|
||||
encoder = DefaultDBEncoder.FACTORY.create();
|
||||
|
||||
DBObject full = new BasicDBObject();
|
||||
for ( String k : options.keySet() )
|
||||
full.put( k , options.get( k ) );
|
||||
full.put( "key" , keys );
|
||||
|
||||
MyCollection idxs = DBApiLayer.this.doGetCollection( "system.indexes" );
|
||||
//query first, maybe we should do an update w/upsert? -- need to test performance and lock behavior
|
||||
if ( idxs.findOne( full ) == null )
|
||||
idxs.insert(Arrays.asList(full), false, WriteConcern.SAFE, encoder);
|
||||
}
|
||||
|
||||
final String _fullNameSpace;
|
||||
}
|
||||
|
||||
class Result implements Iterator<DBObject> {
|
||||
|
||||
Result( MyCollection coll , Response res , int batchSize, int limit , int options, DBDecoder decoder ){
|
||||
_collection = coll;
|
||||
_batchSize = batchSize;
|
||||
_limit = limit;
|
||||
_options = options;
|
||||
_host = res._host;
|
||||
_decoder = decoder;
|
||||
init( res );
|
||||
// Only enable finalizer if cursor finalization is enabled and there is actually a cursor that needs killing
|
||||
_optionalFinalizer = _mongo.getMongoOptions().isCursorFinalizerEnabled() && res.cursor() != 0 ?
|
||||
new OptionalFinalizer() : null;
|
||||
}
|
||||
|
||||
private void init( Response res ){
|
||||
if ( ( res._flags & Bytes.RESULTFLAG_CURSORNOTFOUND ) > 0 ){
|
||||
throw new MongoException.CursorNotFound(_curResult.cursor(), res.serverUsed());
|
||||
}
|
||||
|
||||
_totalBytes += res._len;
|
||||
_curResult = res;
|
||||
_cur = res.iterator();
|
||||
_sizes.add( res.size() );
|
||||
_numFetched += res.size();
|
||||
|
||||
if (res._cursor != 0 && _limit > 0 && _limit - _numFetched <= 0) {
|
||||
// fetched all docs within limit, close cursor server-side
|
||||
killCursor();
|
||||
}
|
||||
}
|
||||
|
||||
public DBObject next(){
|
||||
if ( _cur.hasNext() ) {
|
||||
return _cur.next();
|
||||
}
|
||||
|
||||
if ( ! _curResult.hasGetMore( _options ) )
|
||||
throw new NoSuchElementException("no more");
|
||||
|
||||
_advance();
|
||||
return next();
|
||||
}
|
||||
|
||||
public boolean hasNext(){
|
||||
boolean hasNext = _cur.hasNext();
|
||||
while ( !hasNext ) {
|
||||
if ( ! _curResult.hasGetMore( _options ) )
|
||||
return false;
|
||||
|
||||
_advance();
|
||||
hasNext = _cur.hasNext();
|
||||
|
||||
if (!hasNext) {
|
||||
if ( ( _options & Bytes.QUERYOPTION_AWAITDATA ) == 0 ) {
|
||||
// dont block waiting for data if no await
|
||||
return false;
|
||||
} else {
|
||||
// if await, driver should block until data is available
|
||||
// if server does not support await, driver must sleep to avoid busy loop
|
||||
if ((_curResult._flags & Bytes.RESULTFLAG_AWAITCAPABLE) == 0) {
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
throw new MongoInterruptedException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return hasNext;
|
||||
}
|
||||
|
||||
private void _advance(){
|
||||
|
||||
if ( _curResult.cursor() <= 0 )
|
||||
throw new RuntimeException( "can't advance a cursor <= 0" );
|
||||
|
||||
OutMessage m = OutMessage.getMore(_collection, _curResult.cursor(),
|
||||
chooseBatchSize(_batchSize, _limit, _numFetched));
|
||||
|
||||
Response res = _connector.call( DBApiLayer.this , _collection , m , _host, _decoder );
|
||||
_numGetMores++;
|
||||
init( res );
|
||||
}
|
||||
|
||||
public void remove(){
|
||||
throw new RuntimeException( "can't remove this way" );
|
||||
}
|
||||
|
||||
public int getBatchSize(){
|
||||
return _batchSize;
|
||||
}
|
||||
|
||||
public void setBatchSize(int size){
|
||||
_batchSize = size;
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
return "DBCursor";
|
||||
}
|
||||
|
||||
public long totalBytes(){
|
||||
return _totalBytes;
|
||||
}
|
||||
|
||||
public long getCursorId(){
|
||||
if ( _curResult == null )
|
||||
return 0;
|
||||
return _curResult._cursor;
|
||||
}
|
||||
|
||||
int numGetMores(){
|
||||
return _numGetMores;
|
||||
}
|
||||
|
||||
List<Integer> getSizes(){
|
||||
return Collections.unmodifiableList( _sizes );
|
||||
}
|
||||
|
||||
void close(){
|
||||
// not perfectly thread safe here, may need to use an atomicBoolean
|
||||
if (_curResult != null) {
|
||||
killCursor();
|
||||
_curResult = null;
|
||||
_cur = null;
|
||||
}
|
||||
}
|
||||
|
||||
void killCursor() {
|
||||
if (_curResult == null)
|
||||
return;
|
||||
long curId = _curResult.cursor();
|
||||
if (curId == 0)
|
||||
return;
|
||||
|
||||
List<Long> l = new ArrayList<Long>();
|
||||
l.add(curId);
|
||||
|
||||
try {
|
||||
killCursors(_host, l);
|
||||
} catch (Throwable t) {
|
||||
Bytes.LOGGER.log(Level.WARNING, "can't clean 1 cursor", t);
|
||||
_deadCursorIds.add(new DeadCursor(curId, _host));
|
||||
}
|
||||
_curResult._cursor = 0;
|
||||
}
|
||||
|
||||
public ServerAddress getServerAddress() {
|
||||
return _host;
|
||||
}
|
||||
|
||||
boolean hasFinalizer() {
|
||||
return _optionalFinalizer != null;
|
||||
}
|
||||
|
||||
Response _curResult;
|
||||
Iterator<DBObject> _cur;
|
||||
int _batchSize;
|
||||
int _limit;
|
||||
final DBDecoder _decoder;
|
||||
final MyCollection _collection;
|
||||
final int _options;
|
||||
final ServerAddress _host; // host where first went. all subsequent have to go there
|
||||
|
||||
private long _totalBytes = 0;
|
||||
private int _numGetMores = 0;
|
||||
private List<Integer> _sizes = new ArrayList<Integer>();
|
||||
private int _numFetched = 0;
|
||||
|
||||
// This allows us to easily enable/disable finalizer for cleaning up un-closed cursors
|
||||
private final OptionalFinalizer _optionalFinalizer;
|
||||
|
||||
private class OptionalFinalizer {
|
||||
@Override
|
||||
protected void finalize() {
|
||||
if (_curResult != null) {
|
||||
long curId = _curResult.cursor();
|
||||
_curResult = null;
|
||||
_cur = null;
|
||||
if (curId != 0) {
|
||||
_deadCursorIds.add(new DeadCursor(curId, _host));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // class Result
|
||||
|
||||
static class DeadCursor {
|
||||
|
||||
DeadCursor( long a , ServerAddress b ){
|
||||
id = a;
|
||||
host = b;
|
||||
}
|
||||
|
||||
final long id;
|
||||
final ServerAddress host;
|
||||
}
|
||||
|
||||
final String _root;
|
||||
final String _rootPlusDot;
|
||||
final DBConnector _connector;
|
||||
final ConcurrentHashMap<String,MyCollection> _collections = new ConcurrentHashMap<String,MyCollection>();
|
||||
|
||||
ConcurrentLinkedQueue<DeadCursor> _deadCursorIds = new ConcurrentLinkedQueue<DeadCursor>();
|
||||
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
// DBCallback.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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.mongodb;
|
||||
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.BSONCallback;
|
||||
|
||||
/**
|
||||
* The DB callback interface.
|
||||
*/
|
||||
public interface DBCallback extends BSONCallback {
|
||||
|
||||
}
|
||||
|
@ -1,27 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2011 10gen 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.mongodb;
|
||||
|
||||
/**
|
||||
* The DBCallback factory interface.
|
||||
*/
|
||||
public interface DBCallbackFactory {
|
||||
|
||||
public DBCallback create( DBCollection collection );
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,116 +0,0 @@
|
||||
// DBConnector.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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.mongodb;
|
||||
|
||||
|
||||
/**
|
||||
* Interface that provides the ability to exchange request/response with the database
|
||||
*/
|
||||
public interface DBConnector {
|
||||
|
||||
/**
|
||||
* initiates a "consistent request" on the thread.
|
||||
* Once this has been called, the connector will ensure that the same underlying connection is always used for a given thread.
|
||||
* This happens until requestStop() is called.
|
||||
*/
|
||||
public void requestStart();
|
||||
/**
|
||||
* terminates the "consistent request".
|
||||
*/
|
||||
public void requestDone();
|
||||
/**
|
||||
* Ensures that a connection exists for the "consistent request"
|
||||
*/
|
||||
public void requestEnsureConnection();
|
||||
|
||||
/**
|
||||
* does a write operation
|
||||
* @param db the database
|
||||
* @param m the request message
|
||||
* @param concern the write concern
|
||||
* @return the write result
|
||||
* @throws MongoException
|
||||
*/
|
||||
public WriteResult say( DB db , OutMessage m , WriteConcern concern );
|
||||
/**
|
||||
* does a write operation
|
||||
* @param db the database
|
||||
* @param m the request message
|
||||
* @param concern the write concern
|
||||
* @param hostNeeded specific server to connect to
|
||||
* @return the write result
|
||||
* @throws MongoException
|
||||
*/
|
||||
public WriteResult say( DB db , OutMessage m , WriteConcern concern , ServerAddress hostNeeded );
|
||||
|
||||
/**
|
||||
* does a read operation on the database
|
||||
* @param db the database
|
||||
* @param coll the collection
|
||||
* @param m the request message
|
||||
* @param hostNeeded specific server to connect to
|
||||
* @param decoder the decoder to use
|
||||
* @return the read result
|
||||
* @throws MongoException
|
||||
*/
|
||||
public Response call( DB db , DBCollection coll , OutMessage m ,
|
||||
ServerAddress hostNeeded , DBDecoder decoder );
|
||||
/**
|
||||
*
|
||||
* does a read operation on the database
|
||||
* @param db the database
|
||||
* @param coll the collection
|
||||
* @param m the request message
|
||||
* @param hostNeeded specific server to connect to
|
||||
* @param retries the number of retries in case of an error
|
||||
* @return the read result
|
||||
* @throws MongoException
|
||||
*/
|
||||
public Response call( DB db , DBCollection coll , OutMessage m , ServerAddress hostNeeded , int retries );
|
||||
|
||||
/**
|
||||
* does a read operation on the database
|
||||
* @param db the database
|
||||
* @param coll the collection
|
||||
* @param m the request message
|
||||
* @param hostNeeded specific server to connect to
|
||||
* @param retries number of retries in case of error
|
||||
* @param readPref the read preferences
|
||||
* @param decoder the decoder to use
|
||||
* @return the read result
|
||||
* @throws MongoException
|
||||
*/
|
||||
public Response call( DB db , DBCollection coll , OutMessage m , ServerAddress hostNeeded , int retries , ReadPreference readPref , DBDecoder decoder );
|
||||
|
||||
/**
|
||||
* returns true if the connector is in a usable state
|
||||
* @return
|
||||
*/
|
||||
public boolean isOpen();
|
||||
|
||||
/**
|
||||
* Authenticate using the given credentials.
|
||||
*
|
||||
* @param credentials the credentials.
|
||||
* @return the result of the authentication command, if successful
|
||||
* @throws CommandFailureException if the authentication failed
|
||||
* @since 2.11.0
|
||||
*/
|
||||
public CommandResult authenticate(MongoCredential credentials);
|
||||
}
|
@ -1,730 +0,0 @@
|
||||
// DBCursor.java
|
||||
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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.mongodb;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.mongodb.DBApiLayer.Result;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/** An iterator over database results.
|
||||
* Doing a <code>find()</code> query on a collection returns a
|
||||
* <code>DBCursor</code> thus
|
||||
*
|
||||
* <blockquote><pre>
|
||||
* DBCursor cursor = collection.find( query );
|
||||
* if( cursor.hasNext() )
|
||||
* DBObject obj = cursor.next();
|
||||
* </pre></blockquote>
|
||||
*
|
||||
* <p><b>Warning:</b> Calling <code>toArray</code> or <code>length</code> on
|
||||
* a DBCursor will irrevocably turn it into an array. This
|
||||
* means that, if the cursor was iterating over ten million results
|
||||
* (which it was lazily fetching from the database), suddenly there will
|
||||
* be a ten-million element array in memory. Before converting to an array,
|
||||
* make sure that there are a reasonable number of results using
|
||||
* <code>skip()</code> and <code>limit()</code>.
|
||||
* <p>For example, to get an array of the 1000-1100th elements of a cursor, use
|
||||
*
|
||||
* <blockquote><pre>
|
||||
* List<DBObject> obj = collection.find( query ).skip( 1000 ).limit( 100 ).toArray();
|
||||
* </pre></blockquote>
|
||||
*
|
||||
* @dochub cursors
|
||||
*/
|
||||
public class DBCursor implements Iterator<DBObject> , Iterable<DBObject>, Closeable {
|
||||
|
||||
/**
|
||||
* Initializes a new database cursor
|
||||
* @param collection collection to use
|
||||
* @param q query to perform
|
||||
* @param k keys to return from the query
|
||||
* @param preference the Read Preference for this query
|
||||
*/
|
||||
public DBCursor( DBCollection collection , DBObject q , DBObject k, ReadPreference preference ){
|
||||
if (collection == null) {
|
||||
throw new IllegalArgumentException("collection is null");
|
||||
}
|
||||
_collection = collection;
|
||||
_query = q == null ? new BasicDBObject() : q;
|
||||
_keysWanted = k;
|
||||
_options = _collection.getOptions();
|
||||
_readPref = preference;
|
||||
_decoderFact = collection.getDBDecoderFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Types of cursors: iterator or array.
|
||||
*/
|
||||
static enum CursorType { ITERATOR , ARRAY };
|
||||
|
||||
/**
|
||||
* Creates a copy of an existing database cursor.
|
||||
* The new cursor is an iterator, even if the original
|
||||
* was an array.
|
||||
*
|
||||
* @return the new cursor
|
||||
*/
|
||||
public DBCursor copy() {
|
||||
DBCursor c = new DBCursor(_collection, _query, _keysWanted, _readPref);
|
||||
c._orderBy = _orderBy;
|
||||
c._hint = _hint;
|
||||
c._hintDBObj = _hintDBObj;
|
||||
c._limit = _limit;
|
||||
c._skip = _skip;
|
||||
c._options = _options;
|
||||
c._batchSize = _batchSize;
|
||||
c._snapshot = _snapshot;
|
||||
c._explain = _explain;
|
||||
if ( _specialFields != null )
|
||||
c._specialFields = new BasicDBObject( _specialFields.toMap() );
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a copy of this cursor object that can be iterated.
|
||||
* Note:
|
||||
* - you can iterate the DBCursor itself without calling this method
|
||||
* - no actual data is getting copied.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Iterator<DBObject> iterator(){
|
||||
return this.copy();
|
||||
}
|
||||
|
||||
// ---- querty modifiers --------
|
||||
|
||||
/**
|
||||
* Sorts this cursor's elements.
|
||||
* This method must be called before getting any object from the cursor.
|
||||
* @param orderBy the fields by which to sort
|
||||
* @return a cursor pointing to the first element of the sorted results
|
||||
*/
|
||||
public DBCursor sort( DBObject orderBy ){
|
||||
if ( _it != null )
|
||||
throw new IllegalStateException( "can't sort after executing query" );
|
||||
|
||||
_orderBy = orderBy;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* adds a special operator like $maxScan or $returnKey
|
||||
* e.g. addSpecial( "$returnKey" , 1 )
|
||||
* e.g. addSpecial( "$maxScan" , 100 )
|
||||
* @param name
|
||||
* @param o
|
||||
* @return
|
||||
* @dochub specialOperators
|
||||
*/
|
||||
public DBCursor addSpecial( String name , Object o ){
|
||||
if ( _specialFields == null )
|
||||
_specialFields = new BasicDBObject();
|
||||
_specialFields.put( name , o );
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Informs the database of indexed fields of the collection in order to improve performance.
|
||||
* @param indexKeys a <code>DBObject</code> with fields and direction
|
||||
* @return same DBCursor for chaining operations
|
||||
*/
|
||||
public DBCursor hint( DBObject indexKeys ){
|
||||
if ( _it != null )
|
||||
throw new IllegalStateException( "can't hint after executing query" );
|
||||
|
||||
_hintDBObj = indexKeys;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Informs the database of an indexed field of the collection in order to improve performance.
|
||||
* @param indexName the name of an index
|
||||
* @return same DBCursor for chaining operations
|
||||
*/
|
||||
public DBCursor hint( String indexName ){
|
||||
if ( _it != null )
|
||||
throw new IllegalStateException( "can't hint after executing query" );
|
||||
|
||||
_hint = indexName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use snapshot mode for the query. Snapshot mode assures no duplicates are
|
||||
* returned, or objects missed, which were present at both the start and end
|
||||
* of the query's execution (if an object is new during the query, or deleted
|
||||
* during the query, it may or may not be returned, even with snapshot mode).
|
||||
* Note that short query responses (less than 1MB) are always effectively snapshotted.
|
||||
* Currently, snapshot mode may not be used with sorting or explicit hints.
|
||||
* @return same DBCursor for chaining operations
|
||||
*/
|
||||
public DBCursor snapshot() {
|
||||
if (_it != null)
|
||||
throw new IllegalStateException("can't snapshot after executing the query");
|
||||
|
||||
_snapshot = true;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object containing basic information about the
|
||||
* execution of the query that created this cursor
|
||||
* This creates a <code>DBObject</code> with the key/value pairs:
|
||||
* "cursor" : cursor type
|
||||
* "nScanned" : number of records examined by the database for this query
|
||||
* "n" : the number of records that the database returned
|
||||
* "millis" : how long it took the database to execute the query
|
||||
* @return a <code>DBObject</code>
|
||||
* @throws MongoException
|
||||
* @dochub explain
|
||||
*/
|
||||
public DBObject explain(){
|
||||
DBCursor c = copy();
|
||||
c._explain = true;
|
||||
if (c._limit > 0) {
|
||||
// need to pass a negative batchSize as limit for explain
|
||||
c._batchSize = c._limit * -1;
|
||||
c._limit = 0;
|
||||
}
|
||||
return c.next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Limits the number of elements returned.
|
||||
* Note: parameter <tt>n</tt> should be positive, although a negative value is supported for legacy reason.
|
||||
* Passing a negative value will call {@link DBCursor#batchSize(int)} which is the preferred method.
|
||||
* @param n the number of elements to return
|
||||
* @return a cursor to iterate the results
|
||||
* @dochub limit
|
||||
*/
|
||||
public DBCursor limit( int n ){
|
||||
if ( _it != null )
|
||||
throw new IllegalStateException( "can't set limit after executing query" );
|
||||
|
||||
if (n > 0)
|
||||
_limit = n;
|
||||
else if (n < 0)
|
||||
batchSize(n);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limits the number of elements returned in one batch.
|
||||
* A cursor typically fetches a batch of result objects and store them locally.
|
||||
*
|
||||
* If <tt>batchSize</tt> is positive, it represents the size of each batch of objects retrieved.
|
||||
* It can be adjusted to optimize performance and limit data transfer.
|
||||
*
|
||||
* If <tt>batchSize</tt> is negative, it will limit of number objects returned, that fit within the max batch size limit (usually 4MB), and cursor will be closed.
|
||||
* For example if <tt>batchSize</tt> is -10, then the server will return a maximum of 10 documents and as many as can fit in 4MB, then close the cursor.
|
||||
* Note that this feature is different from limit() in that documents must fit within a maximum size, and it removes the need to send a request to close the cursor server-side.
|
||||
*
|
||||
* The batch size can be changed even after a cursor is iterated, in which case the setting will apply on the next batch retrieval.
|
||||
*
|
||||
* @param n the number of elements to return in a batch
|
||||
* @return
|
||||
*/
|
||||
public DBCursor batchSize( int n ){
|
||||
// check for special case, used to have server bug with 1
|
||||
if ( n == 1 )
|
||||
n = 2;
|
||||
|
||||
if ( _it != null ) {
|
||||
if (_it instanceof DBApiLayer.Result)
|
||||
((DBApiLayer.Result)_it).setBatchSize(n);
|
||||
}
|
||||
|
||||
_batchSize = n;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discards a given number of elements at the beginning of the cursor.
|
||||
* @param n the number of elements to skip
|
||||
* @return a cursor pointing to the new first element of the results
|
||||
* @throws IllegalStateException if the cursor has started to be iterated through
|
||||
*/
|
||||
public DBCursor skip( int n ){
|
||||
if ( _it != null )
|
||||
throw new IllegalStateException( "can't set skip after executing query" );
|
||||
_skip = n;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the cursor id.
|
||||
* @return the cursor id, or 0 if there is no active cursor.
|
||||
*/
|
||||
public long getCursorId() {
|
||||
if ( _it instanceof Result )
|
||||
return ((Result)_it).getCursorId();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* kills the current cursor on the server.
|
||||
*/
|
||||
public void close() {
|
||||
if ( _it instanceof Result )
|
||||
((Result)_it).close();
|
||||
}
|
||||
|
||||
/**
|
||||
* makes this query ok to run on a slave node
|
||||
*
|
||||
* @return a copy of the same cursor (for chaining)
|
||||
*
|
||||
* @deprecated Replaced with {@code ReadPreference.secondaryPreferred()}
|
||||
* @see ReadPreference#secondaryPreferred()
|
||||
*/
|
||||
@Deprecated
|
||||
public DBCursor slaveOk(){
|
||||
return addOption( Bytes.QUERYOPTION_SLAVEOK );
|
||||
}
|
||||
|
||||
/**
|
||||
* adds a query option - see Bytes.QUERYOPTION_* for list
|
||||
* @param option
|
||||
* @return
|
||||
*/
|
||||
public DBCursor addOption( int option ){
|
||||
if ( option == Bytes.QUERYOPTION_EXHAUST )
|
||||
throw new IllegalArgumentException("The exhaust option is not user settable.");
|
||||
|
||||
_options |= option;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the query option - see Bytes.QUERYOPTION_* for list
|
||||
* @param options
|
||||
*/
|
||||
public DBCursor setOptions( int options ){
|
||||
_options = options;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* resets the query options
|
||||
*/
|
||||
public DBCursor resetOptions(){
|
||||
_options = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the query options
|
||||
* @return
|
||||
*/
|
||||
public int getOptions(){
|
||||
return _options;
|
||||
}
|
||||
|
||||
// ---- internal stuff ------
|
||||
|
||||
private void _check() {
|
||||
if (_it != null)
|
||||
return;
|
||||
|
||||
_lookForHints();
|
||||
|
||||
QueryOpBuilder builder = new QueryOpBuilder()
|
||||
.addQuery(_query)
|
||||
.addOrderBy(_orderBy)
|
||||
.addHint(_hintDBObj)
|
||||
.addHint(_hint)
|
||||
.addExplain(_explain)
|
||||
.addSnapshot(_snapshot)
|
||||
.addSpecialFields(_specialFields);
|
||||
|
||||
if (_collection.getDB().getMongo().isMongosConnection()) {
|
||||
builder.addReadPreference(_readPref.toDBObject());
|
||||
}
|
||||
|
||||
_it = _collection.__find(builder.get(), _keysWanted, _skip, _batchSize, _limit,
|
||||
_options, _readPref, getDecoder());
|
||||
}
|
||||
|
||||
// Only create a new decoder if there is a decoder factory explicitly set on the collection. Otherwise return null
|
||||
// so that the collection can use a cached decoder
|
||||
private DBDecoder getDecoder() {
|
||||
return _decoderFact != null ? _decoderFact.create() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* if there is a hint to use, use it
|
||||
*/
|
||||
private void _lookForHints(){
|
||||
|
||||
if ( _hint != null ) // if someone set a hint, then don't do this
|
||||
return;
|
||||
|
||||
if ( _collection._hintFields == null )
|
||||
return;
|
||||
|
||||
Set<String> mykeys = _query.keySet();
|
||||
|
||||
for ( DBObject o : _collection._hintFields ){
|
||||
|
||||
Set<String> hintKeys = o.keySet();
|
||||
|
||||
if ( ! mykeys.containsAll( hintKeys ) )
|
||||
continue;
|
||||
|
||||
hint( o );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void _checkType( CursorType type ){
|
||||
if ( _cursorType == null ){
|
||||
_cursorType = type;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( type == _cursorType )
|
||||
return;
|
||||
|
||||
throw new IllegalArgumentException( "can't switch cursor access methods" );
|
||||
}
|
||||
|
||||
private DBObject _next() {
|
||||
if ( _cursorType == null )
|
||||
_checkType( CursorType.ITERATOR );
|
||||
|
||||
_check();
|
||||
|
||||
_cur = _it.next();
|
||||
_num++;
|
||||
|
||||
if ( _keysWanted != null && _keysWanted.keySet().size() > 0 ){
|
||||
_cur.markAsPartialObject();
|
||||
//throw new UnsupportedOperationException( "need to figure out partial" );
|
||||
}
|
||||
|
||||
if ( _cursorType == CursorType.ARRAY ){
|
||||
_all.add( _cur );
|
||||
}
|
||||
|
||||
return _cur;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the number of times, so far, that the cursor retrieved a batch from the database
|
||||
* @return
|
||||
*/
|
||||
public int numGetMores(){
|
||||
if ( _it instanceof DBApiLayer.Result )
|
||||
return ((DBApiLayer.Result)_it).numGetMores();
|
||||
|
||||
throw new IllegalArgumentException("_it not a real result" );
|
||||
}
|
||||
|
||||
/**
|
||||
* gets a list containing the number of items received in each batch
|
||||
* @return
|
||||
*/
|
||||
public List<Integer> getSizes(){
|
||||
if ( _it instanceof DBApiLayer.Result )
|
||||
return ((DBApiLayer.Result)_it).getSizes();
|
||||
|
||||
throw new IllegalArgumentException("_it not a real result" );
|
||||
}
|
||||
|
||||
private boolean _hasNext() {
|
||||
_check();
|
||||
|
||||
if ( _limit > 0 && _num >= _limit )
|
||||
return false;
|
||||
|
||||
return _it.hasNext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of objects through which the cursor has iterated.
|
||||
* @return the number of objects seen
|
||||
*/
|
||||
public int numSeen(){
|
||||
return _num;
|
||||
}
|
||||
|
||||
// ----- iterator api -----
|
||||
|
||||
/**
|
||||
* Checks if there is another object available
|
||||
* @return
|
||||
* @throws MongoException
|
||||
*/
|
||||
public boolean hasNext() {
|
||||
_checkType( CursorType.ITERATOR );
|
||||
return _hasNext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object the cursor is at and moves the cursor ahead by one.
|
||||
* @return the next element
|
||||
* @throws MongoException
|
||||
*/
|
||||
public DBObject next() {
|
||||
_checkType( CursorType.ITERATOR );
|
||||
return _next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the element the cursor is at.
|
||||
* @return the current element
|
||||
*/
|
||||
public DBObject curr(){
|
||||
_checkType( CursorType.ITERATOR );
|
||||
return _cur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not implemented.
|
||||
*/
|
||||
public void remove(){
|
||||
throw new UnsupportedOperationException( "can't remove from a cursor" );
|
||||
}
|
||||
|
||||
|
||||
// ---- array api -----
|
||||
|
||||
void _fill( int n ){
|
||||
_checkType( CursorType.ARRAY );
|
||||
while ( n >= _all.size() && _hasNext() )
|
||||
_next();
|
||||
}
|
||||
|
||||
/**
|
||||
* pulls back all items into an array and returns the number of objects.
|
||||
* Note: this can be resource intensive
|
||||
* @see #count()
|
||||
* @see #size()
|
||||
* @return the number of elements in the array
|
||||
* @throws MongoException
|
||||
*/
|
||||
public int length() {
|
||||
_checkType( CursorType.ARRAY );
|
||||
_fill( Integer.MAX_VALUE );
|
||||
return _all.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this cursor to an array.
|
||||
* @return an array of elements
|
||||
* @throws MongoException
|
||||
*/
|
||||
public List<DBObject> toArray(){
|
||||
return toArray( Integer.MAX_VALUE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this cursor to an array.
|
||||
* @param max the maximum number of objects to return
|
||||
* @return an array of objects
|
||||
* @throws MongoException
|
||||
*/
|
||||
public List<DBObject> toArray( int max ) {
|
||||
_checkType( CursorType.ARRAY );
|
||||
_fill( max - 1 );
|
||||
return _all;
|
||||
}
|
||||
|
||||
/**
|
||||
* for testing only!
|
||||
* Iterates cursor and counts objects
|
||||
* @see #count()
|
||||
* @return num objects
|
||||
* @throws MongoException
|
||||
*/
|
||||
public int itcount(){
|
||||
int n = 0;
|
||||
while ( this.hasNext() ){
|
||||
this.next();
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the number of objects matching the query
|
||||
* This does not take limit/skip into consideration
|
||||
* @see #size()
|
||||
* @return the number of objects
|
||||
* @throws MongoException
|
||||
*/
|
||||
public int count() {
|
||||
if ( _collection == null )
|
||||
throw new IllegalArgumentException( "why is _collection null" );
|
||||
if ( _collection._db == null )
|
||||
throw new IllegalArgumentException( "why is _collection._db null" );
|
||||
|
||||
return (int)_collection.getCount(this._query, this._keysWanted, getReadPreference());
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the number of objects matching the query
|
||||
* this does take limit/skip into consideration
|
||||
* @see #count()
|
||||
* @return the number of objects
|
||||
* @throws MongoException
|
||||
*/
|
||||
public int size() {
|
||||
if ( _collection == null )
|
||||
throw new IllegalArgumentException( "why is _collection null" );
|
||||
if ( _collection._db == null )
|
||||
throw new IllegalArgumentException( "why is _collection._db null" );
|
||||
|
||||
return (int)_collection.getCount(this._query, this._keysWanted, this._limit, this._skip, getReadPreference() );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gets the fields to be returned
|
||||
* @return
|
||||
*/
|
||||
public DBObject getKeysWanted(){
|
||||
return _keysWanted;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the query
|
||||
* @return
|
||||
*/
|
||||
public DBObject getQuery(){
|
||||
return _query;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the collection
|
||||
* @return
|
||||
*/
|
||||
public DBCollection getCollection(){
|
||||
return _collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Server Address of the server that data is pulled from.
|
||||
* Note that this information may not be available until hasNext() or next() is called.
|
||||
* @return
|
||||
*/
|
||||
public ServerAddress getServerAddress() {
|
||||
if (_it != null && _it instanceof DBApiLayer.Result)
|
||||
return ((DBApiLayer.Result)_it).getServerAddress();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the read preference for this cursor.
|
||||
* See the * documentation for {@link ReadPreference}
|
||||
* for more information.
|
||||
*
|
||||
* @param preference Read Preference to use
|
||||
*/
|
||||
public DBCursor setReadPreference( ReadPreference preference ){
|
||||
_readPref = preference;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default read preference
|
||||
* @return
|
||||
*/
|
||||
public ReadPreference getReadPreference(){
|
||||
return _readPref;
|
||||
}
|
||||
|
||||
public DBCursor setDecoderFactory(DBDecoderFactory fact){
|
||||
_decoderFact = fact;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DBDecoderFactory getDecoderFactory(){
|
||||
return _decoderFact;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Cursor id=").append(getCursorId());
|
||||
sb.append(", ns=").append(getCollection().getFullName());
|
||||
sb.append(", query=").append(getQuery());
|
||||
if (getKeysWanted() != null)
|
||||
sb.append(", fields=").append(getKeysWanted());
|
||||
sb.append(", numIterated=").append(_num);
|
||||
if (_skip != 0)
|
||||
sb.append(", skip=").append(_skip);
|
||||
if (_limit != 0)
|
||||
sb.append(", limit=").append(_limit);
|
||||
if (_batchSize != 0)
|
||||
sb.append(", batchSize=").append(_batchSize);
|
||||
|
||||
ServerAddress addr = getServerAddress();
|
||||
if (addr != null)
|
||||
sb.append(", addr=").append(addr);
|
||||
|
||||
if (_readPref != null)
|
||||
sb.append(", readPreference=").append( _readPref.toString() );
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
boolean hasFinalizer() {
|
||||
if (_it == null || ! (_it instanceof Result)) {
|
||||
return false;
|
||||
}
|
||||
return ((Result) _it).hasFinalizer();
|
||||
}
|
||||
|
||||
// ---- query setup ----
|
||||
private final DBCollection _collection;
|
||||
private final DBObject _query;
|
||||
private final DBObject _keysWanted;
|
||||
|
||||
private DBObject _orderBy = null;
|
||||
private String _hint = null;
|
||||
private DBObject _hintDBObj = null;
|
||||
private boolean _explain = false;
|
||||
private int _limit = 0;
|
||||
private int _batchSize = 0;
|
||||
private int _skip = 0;
|
||||
private boolean _snapshot = false;
|
||||
private int _options = 0;
|
||||
private ReadPreference _readPref;
|
||||
private DBDecoderFactory _decoderFact;
|
||||
|
||||
private DBObject _specialFields;
|
||||
|
||||
// ---- result info ----
|
||||
private Iterator<DBObject> _it = null;
|
||||
|
||||
private CursorType _cursorType = null;
|
||||
private DBObject _cur = null;
|
||||
private int _num = 0;
|
||||
|
||||
private final ArrayList<DBObject> _all = new ArrayList<DBObject>();
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2008 10gen 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.mongodb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import com.massivecraft.massivecore.xlib.bson.BSONDecoder;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public interface DBDecoder extends BSONDecoder {
|
||||
public DBCallback getDBCallback(DBCollection collection);
|
||||
|
||||
public DBObject decode( byte[] b, DBCollection collection );
|
||||
|
||||
public DBObject decode( InputStream in, DBCollection collection ) throws IOException;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user