Use MassiveXlib shaded artifact

This commit is contained in:
Olof Larsson 2017-12-17 09:14:02 +01:00
parent 1d02942085
commit 7babdf910c
339 changed files with 5 additions and 58051 deletions

View File

@ -21,6 +21,11 @@
<!-- Dependencies --> <!-- Dependencies -->
<dependencies> <dependencies>
<!-- MassiveXlib -->
<dependency>
<groupId>com.massivecraft.massivecore</groupId>
<artifactId>MassiveXlib</artifactId>
</dependency>
<!-- Spigot --> <!-- Spigot -->
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>

View File

@ -1,350 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// BSON.java
package com.massivecraft.massivecore.xlib.bson;
import com.massivecraft.massivecore.xlib.bson.util.ClassMap;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Logger;
import java.util.regex.Pattern;
@SuppressWarnings({"rawtypes"})
public class BSON {
static final Logger LOGGER = Logger.getLogger( "org.bson.BSON" );
// ---- basics ----
public static final byte EOO = 0;
public static final byte NUMBER = 1;
public static final byte STRING = 2;
public static final byte OBJECT = 3;
public static final byte ARRAY = 4;
public static final byte BINARY = 5;
public static final byte UNDEFINED = 6;
public static final byte OID = 7;
public static final byte BOOLEAN = 8;
public static final byte DATE = 9;
public static final byte NULL = 10;
public static final byte REGEX = 11;
public static final byte REF = 12;
public static final byte CODE = 13;
public static final byte SYMBOL = 14;
public static final byte CODE_W_SCOPE = 15;
public static final byte NUMBER_INT = 16;
public static final byte TIMESTAMP = 17;
public static final byte NUMBER_LONG = 18;
public static final byte MINKEY = -1;
public static final byte MAXKEY = 127;
// --- binary types
/*
these are binary types
so the format would look like
<BINARY><name><BINARY_TYPE><...>
*/
public static final byte B_GENERAL = 0;
public static final byte B_FUNC = 1;
public static final byte B_BINARY = 2;
public static final byte B_UUID = 3;
// ---- regular expression handling ----
/** Converts a string of regular expression flags from the database in Java regular
* expression flags.
* @param flags flags from database
* @return the Java flags
*/
public static int regexFlags( String flags ){
int fint = 0;
if ( flags == null || flags.length() == 0 )
return fint;
flags = flags.toLowerCase();
for( int i=0; i<flags.length(); i++ ) {
RegexFlag flag = RegexFlag.getByCharacter( flags.charAt( i ) );
if( flag != null ) {
fint |= flag.javaFlag;
if( flag.unsupported != null )
_warnUnsupportedRegex( flag.unsupported );
}
else {
throw new IllegalArgumentException( "unrecognized flag ["+flags.charAt( i ) + "] " + (int)flags.charAt(i) );
}
}
return fint;
}
public static int regexFlag( char c ){
RegexFlag flag = RegexFlag.getByCharacter( c );
if ( flag == null )
throw new IllegalArgumentException( "unrecognized flag [" + c + "]" );
if ( flag.unsupported != null ){
_warnUnsupportedRegex( flag.unsupported );
return 0;
}
return flag.javaFlag;
}
/** Converts Java regular expression flags into a string of flags for the database
* @param flags Java flags
* @return the flags for the database
*/
public static String regexFlags( int flags ){
StringBuilder buf = new StringBuilder();
for( RegexFlag flag : RegexFlag.values() ) {
if( ( flags & flag.javaFlag ) > 0 ) {
buf.append( flag.flagChar );
flags -= flag.javaFlag;
}
}
if( flags > 0 )
throw new IllegalArgumentException( "some flags could not be recognized." );
return buf.toString();
}
private 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<>();
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<>();
_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<>();
_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<>();
static ClassMap<List<Transformer>> _decodingHooks =
new ClassMap<>();
/**
* @deprecated Use {@link Charset#forName(String)} to create UTF-8 charset.
*/
@Deprecated
static protected Charset _utf8 = Charset.forName( "UTF-8" );
// ----- static encode/decode -----
public static byte[] encode( BSONObject o ){
BSONEncoder e = _staticEncoder.get();
try {
return e.encode( o );
}
finally {
e.done();
}
}
public static BSONObject decode( byte[] b ){
BSONDecoder d = _staticDecoder.get();
return d.readObject( b );
}
static ThreadLocal<BSONEncoder> _staticEncoder = new ThreadLocal<BSONEncoder>(){
protected BSONEncoder initialValue(){
return new BasicBSONEncoder();
}
};
static ThreadLocal<BSONDecoder> _staticDecoder = new ThreadLocal<BSONDecoder>(){
protected BSONDecoder initialValue(){
return new BasicBSONDecoder();
}
};
// --- coercing ---
public static int toInt( Object o ){
if ( o == null )
throw new NullPointerException( "can't be null" );
if ( o instanceof Number )
return ((Number)o).intValue();
if ( o instanceof Boolean )
return ((Boolean)o) ? 1 : 0;
throw new IllegalArgumentException( "can't convert: " + o.getClass().getName() + " to int" );
}
}

View File

@ -1,78 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// BSONCallback.java
package com.massivecraft.massivecore.xlib.bson;
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
public interface BSONCallback {
void objectStart();
void objectStart(String name);
void objectStart(boolean array);
Object objectDone();
void reset();
Object get();
BSONCallback createBSONCallback();
void arrayStart();
void arrayStart(String name);
Object arrayDone();
void gotNull( String name );
void gotUndefined( String name );
void gotMinKey( String name );
void gotMaxKey( String name );
void gotBoolean( String name , boolean v );
void gotDouble( String name , double v );
void gotInt( String name , int v );
void gotLong( String name , long v );
void gotDate( String name , long millis );
void gotString( String name , String v );
void gotSymbol( String name , String v );
void gotRegex( String name , String pattern , String flags );
void gotTimestamp( String name , int time , int inc );
void gotObjectId( String name , ObjectId id );
/**
* Invoked when {@link com.massivecraft.massivecore.xlib.bson.BSONDecoder} encountered a DBPointer(0x0c) type field in a byte sequence.
*
* @param name the name of the field
* @param ns the namespace to which reference is pointing to
* @param id the if of the object to which reference is pointing to
*/
void gotDBRef(String name, String ns, ObjectId id);
/**
*
*/
@Deprecated
void gotBinaryArray( String name , byte[] data );
void gotBinary( String name , byte type , byte[] data );
/**
* subtype 3
*/
void gotUUID( String name , long part1, long part2);
void gotCode( String name , String code );
void gotCodeWScope( String name , String code , Object scope );
}

View File

@ -1,34 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// BSONDecoder.java
package com.massivecraft.massivecore.xlib.bson;
import java.io.IOException;
import java.io.InputStream;
public interface BSONDecoder {
BSONObject readObject(byte[] b);
BSONObject readObject(InputStream in) throws IOException;
int decode(byte[] b, BSONCallback callback);
int decode(InputStream in, BSONCallback callback) throws IOException;
}

View File

@ -1,30 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson;
import com.massivecraft.massivecore.xlib.bson.io.OutputBuffer;
public interface BSONEncoder {
byte[] encode(BSONObject o);
int putObject(BSONObject o);
void done();
void set( OutputBuffer out );
}

View File

@ -1,73 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson;
/**
* A general runtime exception raised in BSON processing.
*/
public class BSONException extends RuntimeException {
private static final long serialVersionUID = -4415279469780082174L;
/**
* @param msg The error message.
*/
public BSONException( final String msg ) {
super( msg );
}
/**
* @param errorCode The error code.
* @param msg The error message.
*/
public BSONException( final int errorCode, final String msg ) {
super( msg );
_errorCode = errorCode;
}
/**
* @param msg The error message.
* @param t The throwable cause.
*/
public BSONException( final String msg , final Throwable t ) {
super( msg, t );
}
/**
* @param errorCode The error code.
* @param msg The error message.
* @param t The throwable cause.
*/
public BSONException( final int errorCode, final String msg, final Throwable t ) {
super( msg, t );
_errorCode = errorCode;
}
/**
* Returns the error code.
* @return The error code.
*/
public Integer getErrorCode() { return _errorCode; }
/**
* Returns true if the error code is set (i.e., not null).
*/
public boolean hasErrorCode() { return (_errorCode != null); }
private Integer _errorCode = null;
}

View File

@ -1,28 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson;
/**
*
* @author antoine
*
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public class BSONLazyDecoder {
}

View File

@ -1,92 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// BSONObject.java
package com.massivecraft.massivecore.xlib.bson;
import java.util.Map;
import java.util.Set;
/**
* A key-value map that can be saved to the database.
*/
@SuppressWarnings({"rawtypes"})
public interface BSONObject {
/**
* Sets a name/value pair in this object.
* @param key Name to set
* @param v Corresponding value
* @return <tt>v</tt>
*/
Object put(String key, Object v);
/**
* Sets all key/value pairs from an object into this object
* @param o the object
*/
void putAll(BSONObject o);
/**
* Sets all key/value pairs from a map into this object
* @param m the map
*/
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
*/
Object get(String key);
/**
* Returns a map representing this BSONObject.
* @return the map
*/
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
*/
Object removeField(String key);
/**
* Deprecated
* @param s
* @return True if the key is present
* @deprecated
*/
@Deprecated
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
*/
boolean containsField(String s);
/**
* Returns this object's fields' names
* @return The names of the fields in this object
*/
Set<String> keySet();
}

View File

@ -1,216 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// BasicBSONCallback.java
package com.massivecraft.massivecore.xlib.bson;
import com.massivecraft.massivecore.xlib.bson.types.BSONTimestamp;
import com.massivecraft.massivecore.xlib.bson.types.BasicBSONList;
import com.massivecraft.massivecore.xlib.bson.types.Binary;
import com.massivecraft.massivecore.xlib.bson.types.Code;
import com.massivecraft.massivecore.xlib.bson.types.CodeWScope;
import com.massivecraft.massivecore.xlib.bson.types.MaxKey;
import com.massivecraft.massivecore.xlib.bson.types.MinKey;
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern;
public class BasicBSONCallback implements BSONCallback {
public BasicBSONCallback(){
reset();
}
public BSONObject create(){
return new BasicBSONObject();
}
protected BSONObject createList() {
return new BasicBSONList();
}
public BSONCallback createBSONCallback(){
return new BasicBSONCallback();
}
public BSONObject create( boolean array , List<String> path ){
if ( array )
return createList();
return create();
}
public void objectStart(){
if ( _stack.size() > 0 )
throw new IllegalStateException( "something is wrong" );
objectStart(false);
}
public void objectStart(boolean array){
_root = create(array, null);
_stack.add( (BSONObject)_root );
}
public void objectStart(String name){
objectStart( false , name );
}
public void objectStart(boolean array, String name){
_nameStack.addLast( name );
final BSONObject o = create( array , _nameStack );
_stack.getLast().put( name , o);
_stack.addLast( o );
}
public Object objectDone(){
final BSONObject o =_stack.removeLast();
if ( _nameStack.size() > 0 )
_nameStack.removeLast();
else if ( _stack.size() > 0 )
throw new IllegalStateException( "something is wrong" );
return !BSON.hasDecodeHooks() ? o : (BSONObject)BSON.applyDecodingHooks(o);
}
public void arrayStart(){
objectStart( true );
}
public void arrayStart(String name){
objectStart( true , name );
}
public Object arrayDone(){
return objectDone();
}
public void gotNull( String name ){
cur().put( name , null );
}
public void gotUndefined( String name ) { }
public void gotMinKey( String name ){
cur().put( name , new MinKey() );
}
public void gotMaxKey( String name ){
cur().put( name , new MaxKey() );
}
public void gotBoolean( String name , boolean v ){
_put( name , v );
}
public void gotDouble( final String name , final double v ){
_put( name , v );
}
public void gotInt( final String name , final int v ){
_put( name , v );
}
public void gotLong( final String name , final long v ){
_put( name , v );
}
public void gotDate( String name , long millis ){
_put( name , new Date( millis ) );
}
public void gotRegex( String name , String pattern , String flags ){
_put( name , Pattern.compile( pattern , BSON.regexFlags( flags ) ) );
}
public void gotString( final String name , final String v ){
_put( name , v );
}
public void gotSymbol( String name , String v ){
_put( name , v );
}
public void gotTimestamp( String name , int time , int inc ){
_put( name , new BSONTimestamp( time , inc ) );
}
public void gotObjectId( String name , ObjectId id ){
_put( name , id );
}
public void gotDBRef( String name , String ns , ObjectId id ){
_put( name , new BasicBSONObject( "$ns" , ns ).append( "$id" , id ) );
}
@Deprecated
public void gotBinaryArray( String name , byte[] data ){
gotBinary( name, BSON.B_GENERAL, data );
}
public void gotBinary( String name , byte type , byte[] data ){
if( type == BSON.B_GENERAL || type == BSON.B_BINARY )
_put( name , data );
else
_put( name , new Binary( type , data ) );
}
public void gotUUID( String name , long part1, long part2){
_put( name , new UUID(part1, part2) );
}
public void gotCode( String name , String code ){
_put( name , new Code( code ) );
}
public void gotCodeWScope( String name , String code , Object scope ){
_put( name , new CodeWScope( code, (BSONObject)scope ) );
}
protected void _put( final String name , final Object o ){
cur().put( name , !BSON.hasDecodeHooks() ? o : BSON.applyDecodingHooks( o ) );
}
protected BSONObject cur(){
return _stack.getLast();
}
protected String curName(){
return (!_nameStack.isEmpty()) ? _nameStack.getLast() : null;
}
public Object get(){
return _root;
}
protected void setRoot(Object o) {
_root = o;
}
protected boolean isStackEmpty() {
return _stack.size() < 1;
}
public void reset(){
_root = null;
_stack.clear();
_nameStack.clear();
}
private Object _root;
private final LinkedList<BSONObject> _stack = new LinkedList<>();
private final LinkedList<String> _nameStack = new LinkedList<>();
}

View File

@ -1,639 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson;
import com.massivecraft.massivecore.xlib.bson.io.PoolOutputBuffer;
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import static com.massivecraft.massivecore.xlib.bson.BSON.ARRAY;
import static com.massivecraft.massivecore.xlib.bson.BSON.BINARY;
import static com.massivecraft.massivecore.xlib.bson.BSON.BOOLEAN;
import static com.massivecraft.massivecore.xlib.bson.BSON.B_BINARY;
import static com.massivecraft.massivecore.xlib.bson.BSON.B_GENERAL;
import static com.massivecraft.massivecore.xlib.bson.BSON.B_UUID;
import static com.massivecraft.massivecore.xlib.bson.BSON.CODE;
import static com.massivecraft.massivecore.xlib.bson.BSON.CODE_W_SCOPE;
import static com.massivecraft.massivecore.xlib.bson.BSON.DATE;
import static com.massivecraft.massivecore.xlib.bson.BSON.EOO;
import static com.massivecraft.massivecore.xlib.bson.BSON.MAXKEY;
import static com.massivecraft.massivecore.xlib.bson.BSON.MINKEY;
import static com.massivecraft.massivecore.xlib.bson.BSON.NULL;
import static com.massivecraft.massivecore.xlib.bson.BSON.NUMBER;
import static com.massivecraft.massivecore.xlib.bson.BSON.NUMBER_INT;
import static com.massivecraft.massivecore.xlib.bson.BSON.NUMBER_LONG;
import static com.massivecraft.massivecore.xlib.bson.BSON.OBJECT;
import static com.massivecraft.massivecore.xlib.bson.BSON.OID;
import static com.massivecraft.massivecore.xlib.bson.BSON.REF;
import static com.massivecraft.massivecore.xlib.bson.BSON.REGEX;
import static com.massivecraft.massivecore.xlib.bson.BSON.STRING;
import static com.massivecraft.massivecore.xlib.bson.BSON.SYMBOL;
import static com.massivecraft.massivecore.xlib.bson.BSON.TIMESTAMP;
import static com.massivecraft.massivecore.xlib.bson.BSON.UNDEFINED;
/**
* Basic implementation of BSONDecoder interface that creates BasicBSONObject instances.
*
* <h3>Migration instructions</h3>
* In driver versions before <b>2.12</b> {@code BasicBSONDecoder} exposed several protected members to its subclasses:
* <br/><br/>
* <b>Fields:</b>
* <ul>
* <li>{@code protected BSONInput _in}</li>
* <li>{@code protected BSONCallback _callback}</li>
* <li>{@code protected int _len}</li>
* <li>{@code protected int _pos}</li>
*
* </ul>
* <br/>
* <b>Methods:</b>
* <ul>
* <li>{@code protected void _binary(String)}</li>
* </ul>
* <br/>
* <b>Nested Classes:</b>
* <ul>
* <li>{@code protected class BSONInput}</li>
* </ul>
* <br/>
*
*<h4>Solution 1: Custom {@link BSONCallback} implementation</h4>
* With callbacks you can handle the process of creating objects from bytes in BSON format.
* <p>
* For example to get away from overriging <b>{@code BasicBSONDecoder._binary(String)}</b>
* you can use the following piece of code:
* </p>
* <pre>
* <code style="background:#eee;display:inline-block;padding:10px">public class CustomBSONCallback extends BasicBSONCallback {
*
* public void gotBinary(String name, byte type, byte[] data) {
* _put(name,toHex(data));
* }
*
* private static String toHex(byte[] bytes) {...}
*}
*</code></pre>
*
* This solution covers majority of the cases.
*
* <h4>Solution 2: Custom {@link BSONDecoder} implementation</h4>
* If you need to customize byte-level decoding at the lowest layer you have to provide you own
* implementation of the {@link BSONDecoder} interface.
* <br/>
* Please check <a href="http://bsonspec.org/">http://bsonspec.org/</a> for more information.
*
*/
@SuppressWarnings("deprecation")
public class BasicBSONDecoder implements BSONDecoder {
public BSONObject readObject( byte[] b ){
try {
return readObject( new ByteArrayInputStream( b ) );
}
catch ( IOException ioe ){
throw new BSONException( "should be impossible" , ioe );
}
}
public BSONObject readObject( InputStream in )
throws IOException {
BasicBSONCallback c = new BasicBSONCallback();
decode( in , c );
return (BSONObject)c.get();
}
public int decode( byte[] b , BSONCallback callback ){
try {
return _decode( new BSONInput( new ByteArrayInputStream(b) ) , callback );
}
catch ( IOException ioe ){
throw new BSONException( "should be impossible" , ioe );
}
}
public int decode( InputStream in , BSONCallback callback )
throws IOException {
return _decode( new BSONInput( in ) , callback );
}
private int _decode( BSONInput in , BSONCallback callback )
throws IOException {
if ( _in != null || _callback != null )
throw new IllegalStateException( "not ready" );
_in = in;
_callback = callback;
if ( in.numRead() != 0 )
throw new IllegalArgumentException( "i'm confused" );
try {
final int len = _in.readInt();
_in.setMax(len);
_callback.objectStart();
while ( decodeElement() );
_callback.objectDone();
if ( _in.numRead() != len )
throw new IllegalArgumentException( "bad data. lengths don't match read:" + _in.numRead() + " != len:" + len );
return len;
}
finally {
_in = null;
_callback = null;
}
}
int decode( boolean first )
throws IOException {
final int start = _in.numRead();
final int len = _in.readInt();
if ( first )
_in.setMax(len);
_callback.objectStart();
while ( decodeElement() );
_callback.objectDone();
final int read = _in.numRead() - start;
if ( read != len ){
//throw new IllegalArgumentException( "bad data. lengths don't match " + read + " != " + len );
}
return len;
}
boolean decodeElement()
throws IOException {
final byte type = _in.read();
if ( type == EOO )
return false;
String name = _in.readCStr();
switch ( type ){
case NULL:
_callback.gotNull( name );
break;
case UNDEFINED:
_callback.gotUndefined( name );
break;
case BOOLEAN:
_callback.gotBoolean( name , _in.read() > 0 );
break;
case NUMBER:
_callback.gotDouble( name , _in.readDouble() );
break;
case NUMBER_INT:
_callback.gotInt( name , _in.readInt() );
break;
case NUMBER_LONG:
_callback.gotLong( name , _in.readLong() );
break;
case SYMBOL:
_callback.gotSymbol( name , _in.readUTF8String() );
break;
case STRING:
_callback.gotString(name, _in.readUTF8String() );
break;
case OID:
// OID is stored as big endian
_callback.gotObjectId( name , new ObjectId( _in.readIntBE() , _in.readIntBE() , _in.readIntBE() ) );
break;
case REF:
_in.readInt(); // length of ctring that follows
String ns = _in.readCStr();
ObjectId theOID = new ObjectId( _in.readInt() , _in.readInt() , _in.readInt() );
_callback.gotDBRef( name , ns , theOID );
break;
case DATE:
_callback.gotDate( name , _in.readLong() );
break;
case REGEX:
_callback.gotRegex( name , _in.readCStr() , _in.readCStr() );
break;
case BINARY:
_binary( name );
break;
case CODE:
_callback.gotCode( name , _in.readUTF8String() );
break;
case CODE_W_SCOPE:
_in.readInt();
_callback.gotCodeWScope( name , _in.readUTF8String() , _readBasicObject() );
break;
case ARRAY:
_in.readInt(); // total size - we don't care....
_callback.arrayStart( name );
while ( decodeElement() );
_callback.arrayDone();
break;
case OBJECT:
_in.readInt(); // total size - we don't care....
_callback.objectStart( name );
while ( decodeElement() );
_callback.objectDone();
break;
case TIMESTAMP:
int i = _in.readInt();
int time = _in.readInt();
_callback.gotTimestamp( name , time , i );
break;
case MINKEY:
_callback.gotMinKey( name );
break;
case MAXKEY:
_callback.gotMaxKey( name );
break;
default:
throw new UnsupportedOperationException( "BSONDecoder doesn't understand type : " + type + " name: " + name );
}
return true;
}
/**
*
* @param name the field name
* @throws IOException
*
* @deprecated This method should not be a part of API.
* Please see the class-level documentation for a migration instructions.
*/
@Deprecated
protected void _binary( final String name )
throws IOException {
final int totalLen = _in.readInt();
final byte bType = _in.read();
switch ( bType ){
case B_GENERAL: {
final byte[] data = new byte[totalLen];
_in.fill( data );
_callback.gotBinary( name, bType, data );
return;
}
case B_BINARY:
final int len = _in.readInt();
if ( len + 4 != totalLen )
throw new IllegalArgumentException( "bad data size subtype 2 len: " + len + " totalLen: " + totalLen );
final byte [] data = new byte[len];
_in.fill( data );
_callback.gotBinary( name , bType , data );
return;
case B_UUID:
if ( totalLen != 16 )
throw new IllegalArgumentException( "bad data size subtype 3 len: " + totalLen + " != 16");
final long part1 = _in.readLong();
final long part2 = _in.readLong();
_callback.gotUUID(name, part1, part2);
return;
}
final byte [] data = new byte[totalLen];
_in.fill( data );
_callback.gotBinary( name , bType , data );
}
Object _readBasicObject()
throws IOException {
_in.readInt();
final BSONCallback save = _callback;
final BSONCallback _basic = _callback.createBSONCallback();
_callback = _basic;
_basic.reset();
_basic.objectStart(false);
while( decodeElement() );
_callback = save;
return _basic.get();
}
/**
* @deprecated This class should not be a part of API.
* Please see the class-level documentation for a migration instructions.
*/
@Deprecated
protected class BSONInput {
public BSONInput(final InputStream in){
_raw = in;
_read = 0;
_pos = 0;
_len = 0;
}
/**
* ensure that there are num bytes to read
* _pos is where to start reading from
* @return where to start reading from
*/
protected int _need( final int num )
throws IOException {
//System.out.println( "p: " + _pos + " l: " + _len + " want: " + num );
if ( _len - _pos >= num ){
final int ret = _pos;
_pos += num;
_read += num;
return ret;
}
if ( num >= _inputBuffer.length )
throw new IllegalArgumentException( "you can't need that much" );
final int remaining = _len - _pos;
if ( _pos > 0 ){
System.arraycopy( _inputBuffer , _pos , _inputBuffer , 0 , remaining );
_pos = 0;
_len = remaining;
}
// read as much as possible into buffer
int maxToRead = Math.min( _max - _read - remaining , _inputBuffer.length - _len );
while ( maxToRead > 0 ){
int x = _raw.read( _inputBuffer , _len , maxToRead);
if ( x <= 0 )
throw new IOException( "unexpected EOF" );
maxToRead -= x;
_len += x;
}
int ret = _pos;
_pos += num;
_read += num;
return ret;
}
public int readInt()
throws IOException {
return com.massivecraft.massivecore.xlib.bson.io.Bits.readInt( _inputBuffer , _need(4) );
}
public int readIntBE()
throws IOException {
return com.massivecraft.massivecore.xlib.bson.io.Bits.readIntBE( _inputBuffer , _need(4) );
}
public long readLong()
throws IOException {
return com.massivecraft.massivecore.xlib.bson.io.Bits.readLong( _inputBuffer , _need(8) );
}
public double readDouble()
throws IOException {
return Double.longBitsToDouble( readLong() );
}
public byte read()
throws IOException {
if ( _pos < _len ){
++_read;
return _inputBuffer[_pos++];
}
return _inputBuffer[_need(1)];
}
public void fill( byte b[] )
throws IOException {
fill( b , b.length );
}
public void fill( byte b[] , int len )
throws IOException {
// first use what we have
final int have = _len - _pos;
final int tocopy = Math.min( len , have );
System.arraycopy( _inputBuffer , _pos , b , 0 , tocopy );
_pos += tocopy;
_read += tocopy;
len -= tocopy;
int off = tocopy;
while ( len > 0 ){
final int x = _raw.read( b , off , len );
if (x <= 0)
throw new IOException( "unexpected EOF" );
_read += x;
off += x;
len -= x;
}
}
protected boolean _isAscii( byte b ){
return b >=0 && b <= 127;
}
public String readCStr() throws IOException {
boolean isAscii = true;
// short circuit 1 byte strings
_random[0] = read();
if (_random[0] == 0) {
return "";
}
_random[1] = read();
if (_random[1] == 0) {
final String out = ONE_BYTE_STRINGS[_random[0]];
return (out != null) ? out : new String(_random, 0, 1, DEFAULT_ENCODING);
}
_stringBuffer.reset();
_stringBuffer.write(_random, 0, 2);
isAscii = _isAscii(_random[0]) && _isAscii(_random[1]);
byte b;
while ((b = read()) != 0) {
_stringBuffer.write( b );
isAscii = isAscii && _isAscii( b );
}
String out = null;
if ( isAscii ){
out = _stringBuffer.asAscii();
}
else {
try {
out = _stringBuffer.asString( DEFAULT_ENCODING );
}
catch ( UnsupportedOperationException e ){
throw new BSONException( "impossible" , e );
}
}
_stringBuffer.reset();
return out;
}
public String readUTF8String()
throws IOException {
final int size = readInt();
// this is just protection in case it's corrupted, to avoid huge strings
if ( size <= 0 || size > MAX_STRING )
throw new BSONException( "bad string size: " + size );
if ( size < _inputBuffer.length / 2 ){
if ( size == 1 ){
read();
return "";
}
return new String( _inputBuffer , _need(size) , size - 1 , DEFAULT_ENCODING );
}
final byte [] b = size < _random.length ? _random : new byte[size];
fill( b , size );
try {
return new String( b , 0 , size - 1 , DEFAULT_ENCODING );
}
catch ( java.io.UnsupportedEncodingException uee ){
throw new BSONException( "impossible" , uee );
}
}
public int numRead() {
return _read;
}
public int getPos() {
return _pos;
}
public int getMax() {
return _max;
}
public void setMax(int _max) {
this._max = _max;
}
int _read;
final InputStream _raw;
int _max = 4; // max number of total bytes allowed to ready
}
/**
* @deprecated This field should not be a part of API.
* Please see the class-level documentation for a migration instructions.
*/
@Deprecated
protected BSONInput _in;
/**
* @deprecated This field should not be a part of API.
* Please see the class-level documentation for a migration instructions.
*/
@Deprecated
protected BSONCallback _callback;
private byte [] _random = new byte[1024]; // has to be used within a single function
private byte [] _inputBuffer = new byte[1024];
private PoolOutputBuffer _stringBuffer = new PoolOutputBuffer();
/**
* @deprecated This field should not be a part of API.
* Please see the class-level documentation for a migration instructions.
*/
@Deprecated
protected int _pos; // current offset into _inputBuffer
/**
* @deprecated This field should not be a part of API.
* Please see the class-level documentation for a migration instructions.
*/
@Deprecated
protected int _len; // length of valid data in _inputBuffer
private static final int MAX_STRING = ( 32 * 1024 * 1024 );
private static final String DEFAULT_ENCODING = "UTF-8";
@SuppressWarnings("unused")
private static final boolean _isAscii( final byte b ){
return b >=0 && b <= 127;
}
static final String[] ONE_BYTE_STRINGS = new String[128];
static void _fillRange( byte min, byte max ){
while ( min < max ){
String s = "";
s += (char)min;
ONE_BYTE_STRINGS[(int)min] = s;
min++;
}
}
static {
_fillRange( (byte)'0' , (byte)'9' );
_fillRange( (byte)'a' , (byte)'z' );
_fillRange( (byte)'A' , (byte)'Z' );
}
}

View File

@ -1,537 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// BSONEncoder.java
package com.massivecraft.massivecore.xlib.bson;
import com.massivecraft.massivecore.xlib.bson.io.BasicOutputBuffer;
import com.massivecraft.massivecore.xlib.bson.io.OutputBuffer;
import com.massivecraft.massivecore.xlib.bson.types.BSONTimestamp;
import com.massivecraft.massivecore.xlib.bson.types.Binary;
import com.massivecraft.massivecore.xlib.bson.types.Code;
import com.massivecraft.massivecore.xlib.bson.types.CodeWScope;
import com.massivecraft.massivecore.xlib.bson.types.MaxKey;
import com.massivecraft.massivecore.xlib.bson.types.MinKey;
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
import com.massivecraft.massivecore.xlib.bson.types.Symbol;
import com.massivecraft.massivecore.xlib.mongodb.DBRefBase;
import java.lang.reflect.Array;
import java.nio.Buffer;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Pattern;
import static com.massivecraft.massivecore.xlib.bson.BSON.ARRAY;
import static com.massivecraft.massivecore.xlib.bson.BSON.BINARY;
import static com.massivecraft.massivecore.xlib.bson.BSON.BOOLEAN;
import static com.massivecraft.massivecore.xlib.bson.BSON.B_BINARY;
import static com.massivecraft.massivecore.xlib.bson.BSON.B_GENERAL;
import static com.massivecraft.massivecore.xlib.bson.BSON.B_UUID;
import static com.massivecraft.massivecore.xlib.bson.BSON.CODE;
import static com.massivecraft.massivecore.xlib.bson.BSON.CODE_W_SCOPE;
import static com.massivecraft.massivecore.xlib.bson.BSON.DATE;
import static com.massivecraft.massivecore.xlib.bson.BSON.EOO;
import static com.massivecraft.massivecore.xlib.bson.BSON.MAXKEY;
import static com.massivecraft.massivecore.xlib.bson.BSON.MINKEY;
import static com.massivecraft.massivecore.xlib.bson.BSON.NULL;
import static com.massivecraft.massivecore.xlib.bson.BSON.NUMBER;
import static com.massivecraft.massivecore.xlib.bson.BSON.NUMBER_INT;
import static com.massivecraft.massivecore.xlib.bson.BSON.NUMBER_LONG;
import static com.massivecraft.massivecore.xlib.bson.BSON.OBJECT;
import static com.massivecraft.massivecore.xlib.bson.BSON.OID;
import static com.massivecraft.massivecore.xlib.bson.BSON.REGEX;
import static com.massivecraft.massivecore.xlib.bson.BSON.STRING;
import static com.massivecraft.massivecore.xlib.bson.BSON.SYMBOL;
import static com.massivecraft.massivecore.xlib.bson.BSON.TIMESTAMP;
import static com.massivecraft.massivecore.xlib.bson.BSON.UNDEFINED;
import static com.massivecraft.massivecore.xlib.bson.BSON.regexFlags;
/**
* this is meant to be pooled or cached
* there is some per instance memory for string conversion, etc...
*/
@SuppressWarnings({"unchecked", "rawtypes", "deprecation", "unused"})
public class BasicBSONEncoder implements BSONEncoder {
static final boolean DEBUG = false;
public BasicBSONEncoder(){
}
public byte[] encode( BSONObject o ){
BasicOutputBuffer buf = new BasicOutputBuffer();
set( buf );
putObject( o );
done();
return buf.toByteArray();
}
public void set( OutputBuffer out ){
if ( _buf != null )
throw new IllegalStateException( "in the middle of something" );
_buf = out;
}
/**
* Gets the buffer this encoder is writing to.
*
* @return the output buffer
*/
protected OutputBuffer getOutputBuffer() {
return _buf;
}
public void done(){
_buf = null;
}
/**
* @return true if object was handled
*
* @deprecated Override {@link #putSpecial(String, Object)} if you need to you need to handle custom types.
*/
@Deprecated
protected boolean handleSpecialObjects( String name , BSONObject o ){
return false;
}
protected boolean putSpecial( String name , Object o ){
return false;
}
/** Encodes a <code>BSONObject</code>.
* This is for the higher level api calls
* @param o the object to encode
* @return the number of characters in the encoding
*/
public int putObject( BSONObject o ){
return putObject( null , o );
}
/**
* this is really for embedded objects
*/
protected int putObject( String name , BSONObject o ){
if ( o == null )
throw new NullPointerException( "can't save a null object" );
if ( DEBUG ) System.out.println( "putObject : " + name + " [" + o.getClass() + "]" + " # keys " + o.keySet().size() );
final int start = _buf.getPosition();
byte myType = OBJECT;
if ( o instanceof List )
myType = ARRAY;
if ( handleSpecialObjects( name , o ) )
return _buf.getPosition() - start;
if ( name != null ){
_put( myType , name );
}
final int sizePos = _buf.getPosition();
_buf.writeInt( 0 ); // leaving space for this. set it at the end
List transientFields = null;
boolean rewriteID = myType == OBJECT && name == null;
if ( myType == OBJECT ) {
if ( rewriteID && o.containsField( "_id" ) )
_putObjectField( "_id" , o.get( "_id" ) );
{
Object temp = o.get( "_transientFields" );
if ( temp instanceof List )
transientFields = (List)temp;
}
}
//TODO: reduce repeated code below.
if ( o instanceof Map ){
for ( Entry<String, Object> e : ((Map<String, Object>)o).entrySet() ){
if ( rewriteID && e.getKey().equals( "_id" ) )
continue;
if ( transientFields != null && transientFields.contains( e.getKey() ) )
continue;
_putObjectField( e.getKey() , e.getValue() );
}
} else {
for ( String s : o.keySet() ){
if ( rewriteID && s.equals( "_id" ) )
continue;
if ( transientFields != null && transientFields.contains( s ) )
continue;
Object val = o.get( s );
_putObjectField( s , val );
}
}
_buf.write( EOO );
_buf.writeInt( sizePos , _buf.getPosition() - sizePos );
return _buf.getPosition() - start;
}
protected void _putObjectField( String name , Object val ){
if ( name.equals( "_transientFields" ) )
return;
if ( DEBUG ) System.out.println( "\t put thing : " + name );
if ( name.contains( "\0" ) )
throw new IllegalArgumentException( "Document field names can't have a NULL character. (Bad Key: '" + name + "')" );
if ( name.equals( "$where") && val instanceof String ){
_put( CODE , name );
_putValueString( val.toString() );
return;
}
val = BSON.applyEncodingHooks( val );
if ( val == null )
putNull(name);
else if ( val instanceof Date )
putDate( name , (Date)val );
else if ( val instanceof Number )
putNumber(name, (Number)val );
else if ( val instanceof Character )
putString(name, val.toString() );
else if ( val instanceof String )
putString(name, val.toString() );
else if ( val instanceof ObjectId )
putObjectId(name, (ObjectId)val );
else if ( val instanceof BSONObject )
putObject(name, (BSONObject)val );
else if ( val instanceof Boolean )
putBoolean(name, (Boolean)val );
else if ( val instanceof Pattern )
putPattern(name, (Pattern)val );
else if ( val instanceof Map )
putMap( name , (Map)val );
else if ( val instanceof Iterable)
putIterable( name , (Iterable)val );
else if ( val instanceof byte[] )
putBinary( name , (byte[])val );
else if ( val instanceof Binary )
putBinary( name , (Binary)val );
else if ( val instanceof UUID )
putUUID( name , (UUID)val );
else if ( val.getClass().isArray() )
putArray( name , val );
else if (val instanceof Symbol) {
putSymbol(name, (Symbol) val);
}
else if (val instanceof BSONTimestamp) {
putTimestamp( name , (BSONTimestamp)val );
}
else if (val instanceof CodeWScope) {
putCodeWScope( name , (CodeWScope)val );
}
else if (val instanceof Code) {
putCode( name , (Code)val );
}
else if (val instanceof DBRefBase) {
BSONObject temp = new BasicBSONObject();
temp.put("$ref", ((DBRefBase)val).getRef());
temp.put("$id", ((DBRefBase)val).getId());
putObject( name, temp );
}
else if ( val instanceof MinKey )
putMinKey( name );
else if ( val instanceof MaxKey )
putMaxKey( name );
else if ( putSpecial( name , val ) ){
// no-op
}
else {
throw new IllegalArgumentException( "can't serialize " + val.getClass() );
}
}
private void putArray( String name , Object array ) {
_put( ARRAY , name );
final int sizePos = _buf.getPosition();
_buf.writeInt( 0 );
int size = Array.getLength(array);
for ( int i = 0; i < size; i++ )
_putObjectField( String.valueOf( i ) , Array.get( array, i ) );
_buf.write( EOO );
_buf.writeInt( sizePos , _buf.getPosition() - sizePos );
}
private void putIterable( String name , Iterable l ){
_put( ARRAY , name );
final int sizePos = _buf.getPosition();
_buf.writeInt( 0 );
int i=0;
for ( Object obj: l ) {
_putObjectField( String.valueOf( i ) , obj );
i++;
}
_buf.write( EOO );
_buf.writeInt( sizePos , _buf.getPosition() - sizePos );
}
private void putMap( String name , Map m ){
_put( OBJECT , name );
final int sizePos = _buf.getPosition();
_buf.writeInt( 0 );
for ( Map.Entry entry : (Set<Map.Entry>)m.entrySet() )
_putObjectField( entry.getKey().toString() , entry.getValue() );
_buf.write( EOO );
_buf.writeInt( sizePos , _buf.getPosition() - sizePos );
}
protected void putNull( String name ){
_put( NULL , name );
}
protected void putUndefined(String name){
_put(UNDEFINED, name);
}
protected void putTimestamp(String name, BSONTimestamp ts ){
_put( TIMESTAMP , name );
_buf.writeInt( ts.getInc() );
_buf.writeInt( ts.getTime() );
}
protected void putCodeWScope( String name , CodeWScope code ){
_put( CODE_W_SCOPE , name );
int temp = _buf.getPosition();
_buf.writeInt( 0 );
_putValueString( code.getCode() );
putObject( code.getScope() );
_buf.writeInt( temp , _buf.getPosition() - temp );
}
protected void putCode( String name , Code code ){
_put( CODE , name );
int temp = _buf.getPosition();
_putValueString( code.getCode() );
}
protected void putBoolean( String name , Boolean b ){
_put( BOOLEAN , name );
_buf.write( b ? (byte)0x1 : (byte)0x0 );
}
protected void putDate( String name , Date d ){
_put( DATE , name );
_buf.writeLong( d.getTime() );
}
protected void putNumber( String name , Number n ){
if ( n instanceof Integer ||
n instanceof Short ||
n instanceof Byte ||
n instanceof AtomicInteger ){
_put( NUMBER_INT , name );
_buf.writeInt( n.intValue() );
}
else if ( n instanceof Long || n instanceof AtomicLong ) {
_put( NUMBER_LONG , name );
_buf.writeLong( n.longValue() );
}
else if ( n instanceof Float || n instanceof Double ) {
_put( NUMBER , name );
_buf.writeDouble( n.doubleValue() );
}
else {
throw new IllegalArgumentException( "can't serialize " + n.getClass() );
}
}
protected void putBinary( String name , byte[] data ){
putBinary( name, B_GENERAL, data );
}
protected void putBinary( String name , Binary val ){
putBinary( name, val.getType(), val.getData() );
}
private void putBinary( String name , int type , byte[] data ){
_put( BINARY , name );
int totalLen = data.length;
if (type == B_BINARY)
totalLen += 4;
_buf.writeInt( totalLen );
_buf.write( type );
if (type == B_BINARY)
_buf.writeInt( totalLen -4 );
int before = _buf.getPosition();
_buf.write( data );
int after = _buf.getPosition();
}
protected void putUUID( String name , UUID val ){
_put( BINARY , name );
_buf.writeInt( 16 );
_buf.write( B_UUID );
_buf.writeLong( val.getMostSignificantBits());
_buf.writeLong( val.getLeastSignificantBits());
}
protected void putSymbol( String name , Symbol s ){
_putString(name, s.getSymbol(), SYMBOL);
}
protected void putString(String name, String s) {
_putString(name, s, STRING);
}
private void _putString( String name , String s, byte type ){
_put( type , name );
_putValueString( s );
}
protected void putObjectId( String name , ObjectId oid ){
_put( OID , name );
// according to spec, values should be stored big endian
_buf.writeIntBE( oid._time() );
_buf.writeIntBE( oid._machine() );
_buf.writeIntBE( oid._inc() );
}
private void putPattern( String name, Pattern p ) {
_put( REGEX , name );
_buf.writeCString( p.pattern() );
_buf.writeCString( regexFlags( p.flags() ) );
}
private void putMinKey( String name ) {
_put( MINKEY , name );
}
private void putMaxKey( String name ) {
_put( MAXKEY , name );
}
// ----------------------------------------------
/**
* Encodes the type and key.
*
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
* Access buffer directly via {@link #getOutputBuffer()} if you need to change how BSON is written.
*/
@Deprecated
protected void _put(byte type, String name) {
_buf.write(type);
_buf.writeCString(name);
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
* Access buffer directly via {@link #getOutputBuffer()} if you need to change how BSON is written.
* Otherwise override {@link #putString(String, String)}.
*/
@Deprecated
protected void _putValueString( String s ){
_buf.writeString(s);
}
void _reset( Buffer b ){
b.position(0);
b.limit(b.capacity());
}
/**
* puts as utf-8 string
*
* @deprecated Replaced by {@code getOutputBuffer().writeCString(String)}.
*/
@Deprecated
protected int _put( String str ){
return _buf.writeCString(str);
}
/**
* Writes integer to underlying buffer.
*
* @param x the integer number
* @deprecated Replaced by {@code getOutputBuffer().writeInt(int)}.
*/
@Deprecated
public void writeInt( int x ){
_buf.writeInt( x );
}
/**
* Writes long to underlying buffer.
*
* @param x the long number
* @deprecated Replaced by {@code getOutputBuffer().writeLong(long)}.
*/
@Deprecated
public void writeLong( long x ){
_buf.writeLong(x);
}
/**
* Writes C string (null-terminated string) to underlying buffer.
*
* @param s the string
* @deprecated Replaced by {@code getOutputBuffer().writeCString(String)}.
*/
@Deprecated
public void writeCString( String s ){
_buf.writeCString(s);
}
/**
* @deprecated Replaced by {@link #getOutputBuffer()}.
*/
@Deprecated
protected OutputBuffer _buf;
}

View File

@ -1,399 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// BasicBSONObject.java
package com.massivecraft.massivecore.xlib.bson;
// BSON
import com.massivecraft.massivecore.xlib.bson.types.BasicBSONList;
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
import com.massivecraft.massivecore.xlib.mongodb.util.JSONSerializers;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
// Java
/**
* A simple implementation of <code>DBObject</code>.
* A <code>DBObject</code> can be created as follows, using this class:
* <blockquote><pre>
* DBObject obj = new BasicBSONObject();
* obj.put( "foo", "bar" );
* </pre></blockquote>
*/
@SuppressWarnings({"unchecked", "rawtypes", "unused"})
public class BasicBSONObject extends LinkedHashMap<String,Object> implements BSONObject {
private static final long serialVersionUID = -4415279469780082174L;
/**
* Creates an empty object.
*/
public BasicBSONObject(){
}
public BasicBSONObject(int size){
super(size);
}
/**
* Convenience CTOR
* @param key key under which to store
* @param value value to stor
*/
public BasicBSONObject(String key, Object value){
put(key, value);
}
/**
* Creates a DBObject from a map.
* @param m map to convert
*/
public BasicBSONObject(Map m) {
super(m);
}
/**
* Converts a DBObject to a map.
* @return the DBObject
*/
public Map toMap() {
return new LinkedHashMap<>(this);
}
/** Deletes a field from this object.
* @param key the field name to remove
* @return the object removed
*/
public Object removeField( String key ){
return remove( key );
}
/** Checks if this object contains a given field
* @param field field name
* @return if the field exists
*/
public boolean containsField( String field ){
return super.containsKey(field);
}
/**
* @deprecated
*/
@Deprecated
public boolean containsKey( String key ){
return containsField(key);
}
/** Gets a value from this object
* @param key field name
* @return the value
*/
public Object get( String key ){
return super.get(key);
}
/** Returns the value of a field as an <code>int</code>.
* @param key the field to look for
* @return the field value (or default)
*/
public int getInt( String key ){
Object o = get(key);
if ( o == null )
throw new NullPointerException( "no value for: " + key );
return BSON.toInt(o);
}
/** Returns the value of a field as an <code>int</code>.
* @param key the field to look for
* @param def the default to return
* @return the field value (or default)
*/
public int getInt( String key , int def ){
Object foo = get( key );
if ( foo == null )
return def;
return BSON.toInt(foo);
}
/**
* Returns the value of a field as a <code>long</code>.
*
* @param key the field to return
* @return the field value
*/
public long getLong( String key){
Object foo = get( key );
return ((Number)foo).longValue();
}
/**
* Returns the value of a field as an <code>long</code>.
* @param key the field to look for
* @param def the default to return
* @return the field value (or default)
*/
public long getLong( String key , long def ) {
Object foo = get( key );
if ( foo == null )
return def;
return ((Number)foo).longValue();
}
/**
* Returns the value of a field as a <code>double</code>.
*
* @param key the field to return
* @return the field value
*/
public double getDouble( String key){
Object foo = get( key );
return ((Number)foo).doubleValue();
}
/**
* Returns the value of a field as an <code>double</code>.
* @param key the field to look for
* @param def the default to return
* @return the field value (or default)
*/
public double getDouble( String key , double def ) {
Object foo = get( key );
if ( foo == null )
return def;
return ((Number)foo).doubleValue();
}
/** Returns the value of a field as a string
* @param key the field to look up
* @return the value of the field, converted to a string
*/
public String getString( String key ){
Object foo = get( key );
if ( foo == null )
return null;
return foo.toString();
}
/**
* Returns the value of a field as a string
* @param key the field to look up
* @param def the default to return
* @return the value of the field, converted to a string
*/
public String getString( String key, final String def ) {
Object foo = get( key );
if ( foo == null )
return def;
return foo.toString();
}
/** Returns the value of a field as a boolean.
* @param key the field to look up
* @return the value of the field, or false if field does not exist
*/
public boolean getBoolean( String key ){
return getBoolean(key, false);
}
/** Returns the value of a field as a boolean
* @param key the field to look up
* @param def the default value in case the field is not found
* @return the value of the field, converted to a string
*/
public boolean getBoolean( String key , boolean def ){
Object foo = get( key );
if ( foo == null )
return def;
if ( foo instanceof Number )
return ((Number)foo).intValue() > 0;
if ( foo instanceof Boolean )
return ((Boolean)foo).booleanValue();
throw new IllegalArgumentException( "can't coerce to bool:" + foo.getClass() );
}
/**
* Returns the object id or null if not set.
* @param field The field to return
* @return The field object value or null if not found (or if null :-^).
*/
public ObjectId getObjectId( final String field ) {
return (ObjectId) get( field );
}
/**
* Returns the object id or def if not set.
* @param field The field to return
* @param def the default value in case the field is not found
* @return The field object value or def if not set.
*/
public ObjectId getObjectId( final String field, final ObjectId def ) {
final Object foo = get( field );
return (foo != null) ? (ObjectId)foo : def;
}
/**
* Returns the date or null if not set.
* @param field The field to return
* @return The field object value or null if not found.
*/
public Date getDate( final String field ) {
return (Date) get( field );
}
/**
* Returns the date or def if not set.
* @param field The field to return
* @param def the default value in case the field is not found
* @return The field object value or def if not set.
*/
public Date getDate( final String field, final Date def ) {
final Object foo = get( field );
return (foo != null) ? (Date)foo : def;
}
/** Add a key/value pair to this object
* @param key the field name
* @param val the field value
* @return the <code>val</code> parameter
*/
public Object put( String key , Object val ){
return super.put( key , val );
}
public void putAll( Map m ){
for ( Map.Entry entry : (Set<Map.Entry>)m.entrySet() ){
put( entry.getKey().toString() , entry.getValue() );
}
}
public void putAll( BSONObject o ){
for ( String k : o.keySet() ){
put( k , o.get( k ) );
}
}
/** Add a key/value pair to this object
* @param key the field name
* @param val the field value
* @return <code>this</code>
*/
public BasicBSONObject append( String key , Object val ){
put( key , val );
return this;
}
/** Returns a JSON serialization of this object
* @return JSON serialization
*/
public String toString(){
return JSONSerializers.getStrict().serialize(this);
}
/**
* Compares two documents according to their serialized form, ignoring the order of keys.
*
* @param o the document to compare to, which must be an instance of {@link com.massivecraft.massivecore.xlib.bson.BSONObject}.
* @return true if the documents have the same serialized form, ignoring key order.
*/
@Override
public boolean equals( Object o ) {
if (o == this) {
return true;
}
if (! (o instanceof BSONObject)) {
return false;
}
BSONObject other = (BSONObject) o;
if (!keySet().equals(other.keySet())) {
return false;
}
return Arrays.equals(canonicalizeBSONObject(this).encode(), canonicalizeBSONObject(other).encode());
}
@Override
public int hashCode() {
return Arrays.hashCode(canonicalizeBSONObject(this).encode());
}
private byte[] encode() {
return new BasicBSONEncoder().encode(this);
}
private BSONObject decode(final byte[] encodedBytes) {
return new BasicBSONDecoder().readObject(encodedBytes);
}
// create a copy of "from", but with keys ordered alphabetically
private static Object canonicalize(final Object from) {
if (from instanceof BSONObject && !(from instanceof BasicBSONList)) {
return canonicalizeBSONObject((BSONObject) from);
} else if (from instanceof List) {
return canonicalizeList((List<Object>) from);
} else if (from instanceof Map) {
return canonicalizeMap((Map<String, Object>) from);
} else {
return from;
}
}
private static Map<String, Object> canonicalizeMap(final Map<String, Object> from) {
Map<String, Object> canonicalized = new LinkedHashMap<>(from.size());
TreeSet<String> keysInOrder = new TreeSet<>(from.keySet());
for (String key : keysInOrder) {
Object val = from.get(key);
canonicalized.put(key, canonicalize(val));
}
return canonicalized;
}
private static BasicBSONObject canonicalizeBSONObject(final BSONObject from) {
BasicBSONObject canonicalized = new BasicBSONObject();
TreeSet<String> keysInOrder = new TreeSet<>(from.keySet());
for (String key : keysInOrder) {
Object val = from.get(key);
canonicalized.put(key, canonicalize(val));
}
return canonicalized;
}
private static List canonicalizeList(final List<Object> list) {
List<Object> canonicalized = new ArrayList<>(list.size());
for (Object cur : list) {
canonicalized.add(canonicalize(cur));
}
return canonicalized;
}
}

View File

@ -1,144 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson;
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
public class EmptyBSONCallback implements BSONCallback {
public void objectStart(){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void objectStart( String name ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void objectStart( boolean array ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public Object objectDone(){
throw new UnsupportedOperationException( "Not supported yet." );
}
public BSONCallback createBSONCallback(){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void arrayStart(){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void arrayStart( String name ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public Object arrayDone(){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void gotNull( String name ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void gotUndefined( String name ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void gotMinKey( String name ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void gotMaxKey( String name ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void gotBoolean( String name , boolean v ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void gotDouble( String name , double v ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void gotInt( String name , int v ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void gotLong( String name , long v ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void gotDate( String name , long millis ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void gotString( String name , String v ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void gotSymbol( String name , String v ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void gotRegex( String name , String pattern , String flags ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void gotTimestamp( String name , int time , int inc ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void gotObjectId( String name , ObjectId id ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void gotDBRef( String name , String ns , ObjectId id ){
throw new UnsupportedOperationException( "Not supported yet." );
}
@Deprecated
public void gotBinaryArray( String name , byte[] data ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void gotUUID( String name , long part1 , long part2 ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void gotCode( String name , String code ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void gotCodeWScope( String name , String code , Object scope ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void reset(){
throw new UnsupportedOperationException( "Not supported yet." );
}
public Object get(){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void gotBinary( String name , byte type , byte[] data ){
throw new UnsupportedOperationException( "Not supported yet." );
}
}

View File

@ -1,74 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson;
import com.massivecraft.massivecore.xlib.bson.io.BSONByteBuffer;
import java.util.HashMap;
/**
* @author brendan
* @author scotthernandez
*
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public class KeyCachingLazyBSONObject extends LazyBSONObject {
public KeyCachingLazyBSONObject(byte[] data , LazyBSONCallback cbk) { super( data , cbk ); }
public KeyCachingLazyBSONObject(byte[] data , int offset , LazyBSONCallback cbk) { super( data , offset , cbk ); }
public KeyCachingLazyBSONObject( BSONByteBuffer buffer, LazyBSONCallback callback ){ super( buffer, callback ); }
public KeyCachingLazyBSONObject( BSONByteBuffer buffer, int offset, LazyBSONCallback callback ){ super( buffer, offset, callback ); }
@Override
public Object get( String key ) {
ensureFieldList();
return super.get( key );
}
@Override
public boolean containsField( String s ) {
ensureFieldList();
if (! fieldIndex.containsKey( s ) )
return false;
else
return super.containsField( s );
}
synchronized private void ensureFieldList() {
//only run once
if (fieldIndex == null) return;
try {
int offset = _doc_start_offset + FIRST_ELMT_OFFSET;
while ( !isElementEmpty( offset ) ){
int fieldSize = sizeCString( offset );
int elementSize = getElementBSONSize( offset++ );
String name = _input.getCString( offset );
ElementRecord _t_record = new ElementRecord( name, offset );
fieldIndex.put( name, _t_record );
offset += ( fieldSize + elementSize );
}
} catch (Exception e) {
fieldIndex = new HashMap<>();
}
}
private HashMap<String, ElementRecord> fieldIndex = new HashMap<>();
}

View File

@ -1,91 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson;
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
import com.massivecraft.massivecore.xlib.mongodb.LazyDBObject;
import java.util.List;
import java.util.logging.Logger;
/**
*
*/
@SuppressWarnings({"rawtypes", "unused"})
public class LazyBSONCallback extends EmptyBSONCallback {
public void objectStart(){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void objectStart( String name ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void objectStart( boolean array ){
throw new UnsupportedOperationException( "Not supported yet." );
}
public Object objectDone(){
throw new UnsupportedOperationException( "Not supported yet." );
}
public void reset(){
_root = null;
}
public Object get(){
return _root;
}
public void gotBinary( String name, byte type, byte[] data ){
setRootObject( createObject( data, 0 ) );
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public void setRootObject( Object root ){
_root = root;
}
public Object createObject( byte[] data, int offset ){
return new LazyDBObject( data, offset, this );
}
public List createArray( byte[] data, int offset ){
return new LazyBSONList( data, offset, this );
}
public Object createDBRef( String ns, ObjectId id ){
return new BasicBSONObject( "$ns", ns ).append( "$id", id );
}
/* public Object createObject(InputStream input, int offset) {
try {
return new LazyBSONObject(input, offset, this);
}
catch ( IOException e ) {
e.printStackTrace();
return null;
}
}*/
private Object _root;
private static final Logger log = Logger.getLogger( "org.bson.LazyBSONCallback" );
}

View File

@ -1,71 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson;
import com.massivecraft.massivecore.xlib.bson.io.Bits;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Logger;
/**
* implementation of BSONDecoder that creates LazyBSONObject instances
*/
public class LazyBSONDecoder implements BSONDecoder {
static final Logger LOG = Logger.getLogger( LazyBSONDecoder.class.getName() );
public BSONObject readObject(byte[] b) {
try {
return readObject( new ByteArrayInputStream( b ) );
}
catch ( IOException ioe ){
throw new BSONException( "should be impossible" , ioe );
}
}
public BSONObject readObject(InputStream in) throws IOException {
BSONCallback c = new LazyBSONCallback();
decode( in , c );
return (BSONObject)c.get();
}
public int decode(byte[] b, BSONCallback callback) {
try {
return decode( new ByteArrayInputStream( b ), callback );
}
catch ( IOException ioe ) {
throw new BSONException( "should be impossible" , ioe );
}
}
public int decode(InputStream in, BSONCallback callback) throws IOException {
byte[] objSizeBuffer = new byte[BYTES_IN_INTEGER];
Bits.readFully(in, objSizeBuffer, 0, BYTES_IN_INTEGER);
int objSize = Bits.readInt(objSizeBuffer);
byte[] data = new byte[objSize];
System.arraycopy(objSizeBuffer, 0, data, 0, BYTES_IN_INTEGER);
Bits.readFully(in, data, BYTES_IN_INTEGER, objSize - BYTES_IN_INTEGER);
// note that we are handing off ownership of the data byte array to the callback
callback.gotBinary(null, (byte) 0, data);
return objSize;
}
private static int BYTES_IN_INTEGER = 4;
}

View File

@ -1,196 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson;
import com.massivecraft.massivecore.xlib.bson.io.BSONByteBuffer;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
@SuppressWarnings({"rawtypes", "deprecation"})
public class LazyBSONList extends LazyBSONObject implements List {
public LazyBSONList(byte[] data , LazyBSONCallback callback) { super( data , callback ); }
public LazyBSONList(byte[] data , int offset , LazyBSONCallback callback) { super( data , offset , callback ); }
public LazyBSONList(BSONByteBuffer buffer , LazyBSONCallback callback) { super( buffer , callback ); }
public LazyBSONList(BSONByteBuffer buffer , int offset , LazyBSONCallback callback) { super( buffer , offset , callback ); }
@Override
public boolean contains( Object arg0 ){
return indexOf(arg0) > -1;
}
@Override
public boolean containsAll( Collection arg0 ){
for ( Object obj : arg0 ) {
if ( !contains( obj ) )
return false;
}
return true;
}
@Override
public Object get( int pos ){
return get("" + pos);
}
@Override
public Iterator iterator(){
return new LazyBSONListIterator();
}
@Override
public int indexOf( Object arg0 ){
int pos = 0;
Iterator it = iterator();
while ( it.hasNext() ) {
Object curr = it.next();
if ( arg0.equals( curr ) )
return pos;
pos++;
}
return -1;
}
@Override
public int lastIndexOf( Object arg0 ){
int pos = 0;
int lastFound = -1;
Iterator it = iterator();
while(it.hasNext()) {
Object curr = it.next();
if(arg0.equals( curr ))
lastFound = pos;
pos++;
}
return lastFound;
}
@Override
public int size(){
//TODO check the last one and get the key/field name to see the ordinal position in case the array is stored with missing elements.
return getElements().size();
}
public class LazyBSONListIterator implements Iterator {
List<ElementRecord> elements;
int pos=0;
public LazyBSONListIterator() {
elements = getElements();
}
@Override
public boolean hasNext(){
return pos < elements.size();
}
@Override
public Object next(){
return getElementValue(elements.get(pos++));
}
@Override
public void remove(){
throw new UnsupportedOperationException( "Read Only" );
}
}
@Override
public ListIterator listIterator( int arg0 ){
throw new UnsupportedOperationException( "Not Supported" );
}
@Override
public ListIterator listIterator(){
throw new UnsupportedOperationException( "Not Supported" );
}
@Override
public boolean add( Object arg0 ){
throw new UnsupportedOperationException( "Read Only" );
}
@Override
public void add( int arg0 , Object arg1 ){
throw new UnsupportedOperationException( "Read Only" );
}
@Override
public boolean addAll( Collection arg0 ){
throw new UnsupportedOperationException( "Read Only" );
}
@Override
public boolean addAll( int arg0 , Collection arg1 ){
throw new UnsupportedOperationException( "Read Only" );
}
@Override
public void clear(){
throw new UnsupportedOperationException( "Read Only" );
}
@Override
public boolean remove( Object arg0 ){
throw new UnsupportedOperationException( "Read Only" );
}
@Override
public Object remove( int arg0 ){
throw new UnsupportedOperationException( "Read Only" );
}
@Override
public boolean removeAll( Collection arg0 ){
throw new UnsupportedOperationException( "Read Only" );
}
@Override
public boolean retainAll( Collection arg0 ){
throw new UnsupportedOperationException( "Read Only" );
}
@Override
public Object set( int arg0 , Object arg1 ){
throw new UnsupportedOperationException( "Read Only" );
}
@Override
public List subList( int arg0 , int arg1 ){
throw new UnsupportedOperationException( "Not Supported" );
}
@Override
public Object[] toArray(){
throw new UnsupportedOperationException( "Not Supported" );
}
@Override
public Object[] toArray( Object[] arg0 ){
throw new UnsupportedOperationException( "Not Supported" );
}
}

View File

@ -1,744 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson;
import com.massivecraft.massivecore.xlib.bson.io.BSONByteBuffer;
import com.massivecraft.massivecore.xlib.bson.types.BSONTimestamp;
import com.massivecraft.massivecore.xlib.bson.types.Code;
import com.massivecraft.massivecore.xlib.bson.types.CodeWScope;
import com.massivecraft.massivecore.xlib.bson.types.MaxKey;
import com.massivecraft.massivecore.xlib.bson.types.MinKey;
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
import com.massivecraft.massivecore.xlib.bson.types.Symbol;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Logger;
import java.util.regex.Pattern;
/**
* @author antoine
* @author brendan
* @author scotthernandez
* @author Kilroy Wuz Here
*/
@SuppressWarnings({"unchecked", "rawtypes", "unused"})
public class LazyBSONObject implements BSONObject {
public LazyBSONObject( byte[] data, LazyBSONCallback callback ){
this( BSONByteBuffer.wrap( data ), callback );
}
public LazyBSONObject( byte[] data, int offset, LazyBSONCallback callback ){
this( BSONByteBuffer.wrap( data, offset, data.length - offset ), offset, callback );
}
public LazyBSONObject( BSONByteBuffer buffer, LazyBSONCallback callback ){
this( buffer, 0, callback );
}
public LazyBSONObject( BSONByteBuffer buffer, int offset, LazyBSONCallback callback ){
_callback = callback;
_input = buffer;
_doc_start_offset = offset;
}
class ElementRecord {
ElementRecord( final String name, final int offset ){
this.name = name;
this.offset = offset;
this.type = getElementType( offset - 1 );
this.fieldNameSize = sizeCString( offset );
this.valueOffset = offset + fieldNameSize;
}
final String name;
/**
* The offset the record begins at.
*/
final byte type;
final int fieldNameSize;
final int valueOffset;
final int offset;
}
class LazyBSONKeyIterator implements Iterator<String> {
public boolean hasNext(){
return !isElementEmpty( offset );
}
public String next(){
int fieldSize = sizeCString( offset + 1);
int elementSize = getElementBSONSize( offset );
String key = _input.getCString( offset + 1);
offset += fieldSize + elementSize + 1;
return key;
}
public void remove(){
throw new UnsupportedOperationException( "Read only" );
}
int offset = _doc_start_offset + FIRST_ELMT_OFFSET;
}
/**
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public class LazyBSONKeySet extends ReadOnlySet<String> {
/**
* This method runs in time linear to the total size of all keys in the document.
*
* @return the number of keys in the document
*/
@Override
public int size(){
int size = 0;
Iterator<String> iter = iterator();
while(iter.hasNext()) {
iter.next();
++size;
}
return size;
}
@Override
public boolean isEmpty(){
return LazyBSONObject.this.isEmpty();
}
@Override
public boolean contains( Object o ){
for ( String key : this ){
if ( key.equals( o ) ){
return true;
}
}
return false;
}
@Override
public Iterator<String> iterator(){
return new LazyBSONKeyIterator();
}
@Override
public String[] toArray(){
String[] a = new String[size()];
return toArray(a);
}
@Override
public <T> T[] toArray(T[] a) {
int size = size();
T[] localArray = a.length >= size ? a :
(T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
int i = 0;
for ( String key : this ){
localArray[i++] = (T) key;
}
if (localArray.length > i) {
localArray[i] = null;
}
return localArray;
}
@Override
public boolean add( String e ){
throw new UnsupportedOperationException( "Not supported yet." );
}
@Override
public boolean remove( Object o ){
throw new UnsupportedOperationException( "Not supported yet." );
}
@Override
public boolean containsAll( Collection<?> collection ){
for ( Object item : collection ){
if ( !contains( item ) ){
return false;
}
}
return true;
}
}
class LazyBSONEntryIterator implements Iterator<Map.Entry<String, Object>> {
public boolean hasNext(){
return !isElementEmpty( offset );
}
public Map.Entry<String, Object> next(){
int fieldSize = sizeCString(offset + 1);
int elementSize = getElementBSONSize(offset);
String key = _input.getCString(offset + 1);
final ElementRecord nextElementRecord = new ElementRecord(key, ++offset);
offset += fieldSize + elementSize;
return new Map.Entry<String, Object>() {
@Override
public String getKey() {
return nextElementRecord.name;
}
@Override
public Object getValue() {
return getElementValue(nextElementRecord);
}
@Override
public Object setValue(Object value) {
throw new UnsupportedOperationException("Read only");
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry e = (Map.Entry) o;
return getKey().equals(e.getKey()) && getValue().equals(e.getValue());
}
@Override
public int hashCode() {
return getKey().hashCode() ^ getValue().hashCode();
}
@Override
public String toString() {
return getKey() + "=" + getValue();
}
};
}
public void remove(){
throw new UnsupportedOperationException( "Read only" );
}
int offset = _doc_start_offset + FIRST_ELMT_OFFSET;
}
class LazyBSONEntrySet extends ReadOnlySet<Map.Entry<String, Object>> {
@Override
public int size() {
return LazyBSONObject.this.keySet().size();
}
@Override
public boolean isEmpty() {
return LazyBSONObject.this.isEmpty();
}
@Override
public boolean contains(Object o) {
Iterator<Map.Entry<String, Object>> iter = iterator();
while (iter.hasNext()) {
if (iter.next().equals(o)) {
return true;
}
}
return false;
}
@Override
public boolean containsAll(Collection<?> c) {
for (Object cur : c) {
if (!contains(cur)) {
return false;
}
}
return true;
}
@Override
public Iterator<Map.Entry<String, Object>> iterator() {
return new LazyBSONEntryIterator();
}
@Override
public Object[] toArray() {
Map.Entry[] array = new Map.Entry[size()];
return toArray(array);
}
@Override
public <T> T[] toArray(T[] a) {
int size = size();
T[] localArray = a.length >= size ? a :
(T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
Iterator<Map.Entry<String, Object>> iter = iterator();
int i = 0;
while(iter.hasNext()) {
localArray[i++] = (T) iter.next();
}
if (localArray.length > i) {
localArray[i] = null;
}
return localArray;
}
}
// Base class that throws UnsupportedOperationException for any method that writes to the Set
abstract class ReadOnlySet<E> implements Set<E> {
@Override
public boolean add(E e) {
throw new UnsupportedOperationException("Read-only Set");
}
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException("Read-only Set");
}
@Override
public boolean addAll(Collection<? extends E> c) {
throw new UnsupportedOperationException("Read-only Set");
}
@Override
public boolean retainAll(Collection<?> c) {
throw new UnsupportedOperationException("Read-only Set");
}
@Override
public boolean removeAll(Collection<?> c) {
throw new UnsupportedOperationException("Read-only Set");
}
@Override
public void clear() {
throw new UnsupportedOperationException("Read-only Set");
}
}
public Object put( String key, Object v ){
throw new UnsupportedOperationException( "Object is read only" );
}
public void putAll( BSONObject o ){
throw new UnsupportedOperationException( "Object is read only" );
}
public void putAll( Map m ){
throw new UnsupportedOperationException( "Object is read only" );
}
public Object get( String key ){
//get element up to the key
ElementRecord element = getElement(key);
//no found if null/empty
if (element == null) {
return null;
}
return getElementValue(element);
}
/**
* returns the ElementRecord for the given key, or null if not found
* @param key the field/key to find
* @return ElementRecord for key, or null
*/
ElementRecord getElement(String key){
int offset = _doc_start_offset + FIRST_ELMT_OFFSET;
while ( !isElementEmpty( offset ) ){
int fieldSize = sizeCString( offset + 1 );
int elementSize = getElementBSONSize( offset );
String name = _input.getCString( ++offset);
if (name.equals(key)) {
return new ElementRecord( name, offset );
}
offset += ( fieldSize + elementSize);
}
return null;
}
/**
* returns all the ElementRecords in this document
* @return list of ElementRecord
*/
List<ElementRecord> getElements(){
int offset = _doc_start_offset + FIRST_ELMT_OFFSET;
ArrayList<ElementRecord> elements = new ArrayList<>();
while ( !isElementEmpty( offset ) ){
int fieldSize = sizeCString( offset + 1 );
int elementSize = getElementBSONSize( offset );
String name = _input.getCString( ++offset );
ElementRecord rec = new ElementRecord( name, offset );
elements.add( rec );
offset += ( fieldSize + elementSize );
}
return elements;
}
public Map toMap(){
throw new UnsupportedOperationException( "Not Supported" );
}
public Object removeField( String key ){
throw new UnsupportedOperationException( "Object is read only" );
}
@Deprecated
public boolean containsKey( String s ){
return containsField( s );
}
public boolean containsField( String s ){
return keySet().contains( s );
}
/**
*
* @return the set of all keys in the document
*/
public Set<String> keySet(){
return new LazyBSONKeySet();
}
/**
* This method will be more efficient than using a combination of keySet() and get(String key)
* @return the set of entries (key, value) in the document
*/
public Set<Map.Entry<String, Object>> entrySet(){
return new LazyBSONEntrySet();
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
protected boolean isElementEmpty( int offset ){
return getElementType( offset ) == BSON.EOO;
}
public boolean isEmpty(){
return isElementEmpty( _doc_start_offset + FIRST_ELMT_OFFSET );
}
private int getBSONSize( final int offset ){
return _input.getInt( offset );
}
public int getBSONSize(){
return getBSONSize( _doc_start_offset );
}
public int pipe(OutputStream os) throws IOException {
os.write(_input.array(), _doc_start_offset, getBSONSize());
return getBSONSize();
}
private String getElementFieldName( final int offset ){
return _input.getCString( offset );
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
protected byte getElementType( final int offset ){
return _input.get( offset );
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
protected int getElementBSONSize( int offset ){
int x = 0;
byte type = getElementType( offset++ );
int n = sizeCString( offset );
int valueOffset = offset + n;
switch ( type ){
case BSON.EOO:
case BSON.UNDEFINED:
case BSON.NULL:
case BSON.MAXKEY:
case BSON.MINKEY:
break;
case BSON.BOOLEAN:
x = 1;
break;
case BSON.NUMBER_INT:
x = 4;
break;
case BSON.TIMESTAMP:
case BSON.DATE:
case BSON.NUMBER_LONG:
case BSON.NUMBER:
x = 8;
break;
case BSON.OID:
x = 12;
break;
case BSON.SYMBOL:
case BSON.CODE:
case BSON.STRING:
x = _input.getInt( valueOffset ) + 4;
break;
case BSON.CODE_W_SCOPE:
x = _input.getInt( valueOffset );
break;
case BSON.REF:
x = _input.getInt( valueOffset ) + 4 + 12;
break;
case BSON.OBJECT:
case BSON.ARRAY:
x = _input.getInt( valueOffset );
break;
case BSON.BINARY:
x = _input.getInt( valueOffset ) + 4 + 1/*subtype*/;
break;
case BSON.REGEX:
// 2 cstrs
int part1 = sizeCString( valueOffset );
int part2 = sizeCString( valueOffset + part1 );
x = part1 + part2;
break;
default:
throw new BSONException( "Invalid type " + type + " for field " + getElementFieldName( offset ) );
}
return x;
}
/**
* Returns the size of the BSON cstring at the given offset in the buffer
* @param offset the offset into the buffer
* @return the size of the BSON cstring, including the null terminator
*
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
protected int sizeCString( int offset ){
int end = offset;
while ( true ){
byte b = _input.get( end );
if ( b == 0 )
break;
else
end++;
}
return end - offset + 1;
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
protected Object getElementValue( ElementRecord record ){
switch ( record.type ){
case BSON.EOO:
case BSON.UNDEFINED:
case BSON.NULL:
return null;
case BSON.MAXKEY:
return new MaxKey();
case BSON.MINKEY:
return new MinKey();
case BSON.BOOLEAN:
return ( _input.get( record.valueOffset ) != 0 );
case BSON.NUMBER_INT:
return _input.getInt( record.valueOffset );
case BSON.TIMESTAMP:
int inc = _input.getInt( record.valueOffset );
int time = _input.getInt( record.valueOffset + 4 );
return new BSONTimestamp( time, inc );
case BSON.DATE:
return new Date( _input.getLong( record.valueOffset ) );
case BSON.NUMBER_LONG:
return _input.getLong( record.valueOffset );
case BSON.NUMBER:
return Double.longBitsToDouble( _input.getLong( record.valueOffset ) );
case BSON.OID:
return new ObjectId( _input.getIntBE( record.valueOffset ),
_input.getIntBE( record.valueOffset + 4 ),
_input.getIntBE( record.valueOffset + 8 ) );
case BSON.SYMBOL:
return new Symbol( _input.getUTF8String( record.valueOffset ) );
case BSON.CODE:
return new Code( _input.getUTF8String( record.valueOffset ) );
case BSON.STRING:
return _input.getUTF8String( record.valueOffset );
case BSON.CODE_W_SCOPE:
int strsize = _input.getInt( record.valueOffset + 4 );
String code = _input.getUTF8String( record.valueOffset + 4 );
BSONObject scope =
(BSONObject) _callback.createObject( _input.array(), record.valueOffset + 4 + 4 + strsize );
return new CodeWScope( code, scope );
case BSON.REF:
int csize = _input.getInt( record.valueOffset );
String ns = _input.getCString( record.valueOffset + 4 );
int oidOffset = record.valueOffset + csize + 4;
ObjectId oid = new ObjectId( _input.getIntBE( oidOffset ),
_input.getIntBE( oidOffset + 4 ),
_input.getIntBE( oidOffset + 8 ) );
return _callback.createDBRef( ns, oid );
case BSON.OBJECT:
return _callback.createObject( _input.array(), record.valueOffset );
case BSON.ARRAY:
return _callback.createArray( _input.array(), record.valueOffset );
case BSON.BINARY:
return readBinary( record.valueOffset );
case BSON.REGEX:
int patternCStringSize = sizeCString( record.valueOffset );
String pattern = _input.getCString( record.valueOffset );
String flags = _input.getCString( record.valueOffset + patternCStringSize );
return Pattern.compile( pattern, BSON.regexFlags( flags ) );
default:
throw new BSONException(
"Invalid type " + record.type + " for field " + getElementFieldName( record.offset ) );
}
}
private Object readBinary( int valueOffset ){
final int totalLen = _input.getInt( valueOffset );
valueOffset += 4;
final byte bType = _input.get( valueOffset );
valueOffset += 1;
byte[] bin;
switch ( bType ){
case BSON.B_GENERAL:{
bin = new byte[totalLen];
for ( int n = 0; n < totalLen; n++ ){
bin[n] = _input.get( valueOffset + n );
}
return bin;
}
case BSON.B_BINARY:
final int len = _input.getInt( valueOffset );
if ( len + 4 != totalLen )
throw new IllegalArgumentException(
"Bad Data Size; Binary Subtype 2. { actual len: " + len + " expected totalLen: " + totalLen
+ "}" );
valueOffset += 4;
bin = new byte[len];
for ( int n = 0; n < len; n++ ){
bin[n] = _input.get( valueOffset + n );
}
return bin;
case BSON.B_UUID:
if ( totalLen != 16 )
throw new IllegalArgumentException(
"Bad Data Size; Binary Subtype 3 (UUID). { total length: " + totalLen + " != 16" );
long part1 = _input.getLong( valueOffset );
valueOffset += 8;
long part2 = _input.getLong( valueOffset );
return new UUID( part1, part2 );
}
bin = new byte[totalLen];
for ( int n = 0; n < totalLen; n++ ){
bin[n] = _input.get( valueOffset + n );
}
return bin;
}
protected int getOffset(){
return _doc_start_offset;
}
protected byte[] getBytes() {
return _input.array();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
LazyBSONObject that = (LazyBSONObject) o;
return Arrays.equals(this._input.array(), that._input.array());
}
@Override
public int hashCode() {
return Arrays.hashCode(_input.array());
}
/**
* Returns a JSON serialization of this object
*
* @return JSON serialization
*/
public String toString(){
return com.massivecraft.massivecore.xlib.mongodb.util.JSON.serialize( this );
}
/**
* In a "normal" (aka not embedded) doc, this will be the offset of the first element.
*
* In an embedded doc because we use ByteBuffers to avoid unecessary copying the offset must be manually set in
* _doc_start_offset
*/
final static int FIRST_ELMT_OFFSET = 4;
/**
* @deprecated Please use {@link #getOffset()} instead.
*/
@Deprecated
protected final int _doc_start_offset;
/**
* @deprecated Please use {@link #getBytes()} to access underlying bytes.
*/
@Deprecated
protected final BSONByteBuffer _input; // TODO - Guard this with synchronicity?
// callback is kept to create sub-objects on the fly
/**
* @deprecated This field is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
protected final LazyBSONCallback _callback;
private static final Logger log = Logger.getLogger( "org.bson.LazyBSONObject" );
}

View File

@ -1,58 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
*/
package com.massivecraft.massivecore.xlib.bson;
import com.massivecraft.massivecore.xlib.bson.io.BSONByteBuffer;
import com.massivecraft.massivecore.xlib.mongodb.DBObject;
import com.massivecraft.massivecore.xlib.mongodb.util.JSON;
/**
* @author scotthernandez
* @deprecated Please use {@link com.massivecraft.massivecore.xlib.mongodb.LazyDBList} instead.
*/
@Deprecated
@SuppressWarnings({"unused"})
public class LazyDBList extends LazyBSONList implements DBObject {
private static final long serialVersionUID = -4415279469780082174L;
public LazyDBList(byte[] data, LazyBSONCallback callback) { super(data, callback); }
public LazyDBList(byte[] data, int offset, LazyBSONCallback callback) { super(data, offset, callback); }
public LazyDBList(BSONByteBuffer buffer, LazyBSONCallback callback) { super(buffer, callback); }
public LazyDBList(BSONByteBuffer buffer, int offset, LazyBSONCallback callback) { super(buffer, offset, callback); }
/**
* Returns a JSON serialization of this object
* @return JSON serialization
*/
@Override
public String toString(){
return JSON.serialize( this );
}
public boolean isPartialObject(){
return _isPartialObject;
}
public void markAsPartialObject(){
_isPartialObject = true;
}
private boolean _isPartialObject;
}

View File

@ -1,331 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson;
import com.massivecraft.massivecore.xlib.bson.io.Bits;
import com.massivecraft.massivecore.xlib.bson.types.ObjectId;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import static com.massivecraft.massivecore.xlib.bson.BSON.ARRAY;
import static com.massivecraft.massivecore.xlib.bson.BSON.BINARY;
import static com.massivecraft.massivecore.xlib.bson.BSON.BOOLEAN;
import static com.massivecraft.massivecore.xlib.bson.BSON.B_BINARY;
import static com.massivecraft.massivecore.xlib.bson.BSON.B_GENERAL;
import static com.massivecraft.massivecore.xlib.bson.BSON.B_UUID;
import static com.massivecraft.massivecore.xlib.bson.BSON.CODE;
import static com.massivecraft.massivecore.xlib.bson.BSON.CODE_W_SCOPE;
import static com.massivecraft.massivecore.xlib.bson.BSON.DATE;
import static com.massivecraft.massivecore.xlib.bson.BSON.EOO;
import static com.massivecraft.massivecore.xlib.bson.BSON.MAXKEY;
import static com.massivecraft.massivecore.xlib.bson.BSON.MINKEY;
import static com.massivecraft.massivecore.xlib.bson.BSON.NULL;
import static com.massivecraft.massivecore.xlib.bson.BSON.NUMBER;
import static com.massivecraft.massivecore.xlib.bson.BSON.NUMBER_INT;
import static com.massivecraft.massivecore.xlib.bson.BSON.NUMBER_LONG;
import static com.massivecraft.massivecore.xlib.bson.BSON.OBJECT;
import static com.massivecraft.massivecore.xlib.bson.BSON.OID;
import static com.massivecraft.massivecore.xlib.bson.BSON.REF;
import static com.massivecraft.massivecore.xlib.bson.BSON.REGEX;
import static com.massivecraft.massivecore.xlib.bson.BSON.STRING;
import static com.massivecraft.massivecore.xlib.bson.BSON.SYMBOL;
import static com.massivecraft.massivecore.xlib.bson.BSON.TIMESTAMP;
import static com.massivecraft.massivecore.xlib.bson.BSON.UNDEFINED;
// Java
/**
* A new implementation of the bson decoder.
*
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public class NewBSONDecoder implements BSONDecoder {
@Override
public BSONObject readObject(final byte [] pData) {
_length = pData.length;
final BasicBSONCallback c = new BasicBSONCallback();
decode(pData, c);
return (BSONObject)c.get();
}
@Override
public BSONObject readObject(final InputStream pIn) throws IOException {
// Slurp in the data and convert to a byte array.
_length = Bits.readInt(pIn);
if (_data == null || _data.length < _length) {
_data = new byte[_length];
}
(new DataInputStream(pIn)).readFully(_data, 4, (_length - 4));
return readObject(_data);
}
@Override
public int decode(final byte [] pData, final BSONCallback pCallback) {
_data = pData;
_pos = 4;
_callback = pCallback;
_decode();
return _length;
}
@Override
public int decode(final InputStream pIn, final BSONCallback pCallback) throws IOException {
_length = Bits.readInt(pIn);
if (_data == null || _data.length < _length) {
_data = new byte[_length];
}
(new DataInputStream(pIn)).readFully(_data, 4, (_length - 4));
return decode(_data, pCallback);
}
private final void _decode() {
_callback.objectStart();
while (decodeElement());
_callback.objectDone();
}
private final String readCstr() {
int length = 0;
final int offset = _pos;
while (_data[_pos++] != 0) length++;
try {
return new String(_data, offset, length, DEFAULT_ENCODING);
} catch (final UnsupportedEncodingException uee) {
return new String(_data, offset, length);
}
}
private final String readUtf8Str() {
final int length = Bits.readInt(_data, _pos);
_pos += 4;
if (length <= 0 || length > MAX_STRING) throw new BSONException("String invalid - corruption");
try {
final String str = new String(_data, _pos, (length - 1), DEFAULT_ENCODING);
_pos += length;
return str;
} catch (final UnsupportedEncodingException uee) {
throw new BSONException("What is in the db", uee);
}
}
private final Object _readBasicObject() {
_pos += 4;
final BSONCallback save = _callback;
final BSONCallback _basic = _callback.createBSONCallback();
_callback = _basic;
_basic.reset();
_basic.objectStart(false);
while( decodeElement() );
_callback = save;
return _basic.get();
}
private final void _binary(final String pName) {
final int totalLen = Bits.readInt(_data, _pos);
_pos += 4;
final byte bType = _data[_pos];
_pos += 1;
switch ( bType ){
case B_GENERAL: {
final byte [] data = new byte[totalLen];
System.arraycopy(_data, _pos, data, 0, totalLen);
_pos += totalLen;
_callback.gotBinary(pName, bType, data);
return;
}
case B_BINARY: {
final int len = Bits.readInt(_data, _pos);
_pos += 4;
if ( len + 4 != totalLen )
throw new IllegalArgumentException( "bad data size subtype 2 len: " + len + " totalLen: " + totalLen );
final byte [] data = new byte[len];
System.arraycopy(_data, _pos, data, 0, len);
_pos += len;
_callback.gotBinary(pName, bType, data);
return;
}
case B_UUID: {
if ( totalLen != 16 )
throw new IllegalArgumentException( "bad data size subtype 3 len: " + totalLen + " != 16");
final long part1 = Bits.readLong(_data, _pos);
_pos += 8;
final long part2 = Bits.readLong(_data, _pos);
_pos += 8;
_callback.gotUUID(pName, part1, part2);
return;
}
}
final byte [] data = new byte[totalLen];
System.arraycopy(_data, _pos, data, 0, totalLen);
_pos += totalLen;
_callback.gotBinary(pName, bType, data);
}
private final boolean decodeElement() {
final byte type = _data[_pos];
_pos += 1;
if (type == EOO) return false;
final String name = readCstr();
switch (type) {
case NULL: { _callback.gotNull(name); return true; }
case UNDEFINED: { _callback.gotUndefined(name); return true; }
case BOOLEAN: { _callback.gotBoolean(name, (_data[_pos] > 0)); _pos += 1; return true; }
case NUMBER: { _callback.gotDouble(name, Double.longBitsToDouble(Bits.readLong(_data, _pos))); _pos += 8; return true; }
case NUMBER_INT: { _callback.gotInt(name, Bits.readInt(_data, _pos)); _pos += 4; return true; }
case NUMBER_LONG: {
_callback.gotLong(name, Bits.readLong(_data, _pos));
_pos += 8;
return true;
}
case SYMBOL: { _callback.gotSymbol(name, readUtf8Str()); return true; }
case STRING: { _callback.gotString(name, readUtf8Str()); return true; }
case OID: {
// OID is stored as big endian
final int p1 = Bits.readIntBE(_data, _pos);
_pos += 4;
final int p2 = Bits.readIntBE(_data, _pos);
_pos += 4;
final int p3 = Bits.readIntBE(_data, _pos);
_pos += 4;
_callback.gotObjectId(name , new ObjectId(p1, p2, p3));
return true;
}
case REF: {
_pos += 4;
final String ns = readCstr();
final int p1 = Bits.readInt(_data, _pos);
_pos += 4;
final int p2 = Bits.readInt(_data, _pos);
_pos += 4;
final int p3 = Bits.readInt(_data, _pos);
_pos += 4;
_callback.gotDBRef(name , ns, new ObjectId(p1, p2, p3));
return true;
}
case DATE: { _callback.gotDate(name , Bits.readLong(_data, _pos)); _pos += 8; return true; }
case REGEX: {
_callback.gotRegex(name, readCstr(), readCstr());
return true;
}
case BINARY: { _binary(name); return true; }
case CODE: { _callback.gotCode(name, readUtf8Str()); return true; }
case CODE_W_SCOPE: {
_pos += 4;
_callback.gotCodeWScope(name, readUtf8Str(), _readBasicObject());
return true;
}
case ARRAY:
_pos += 4;
_callback.arrayStart(name);
while (decodeElement());
_callback.arrayDone();
return true;
case OBJECT:
_pos += 4;
_callback.objectStart(name);
while (decodeElement());
_callback.objectDone();
return true;
case TIMESTAMP:
int i = Bits.readInt(_data, _pos);
_pos += 4;
int time = Bits.readInt(_data, _pos);
_pos += 4;
_callback.gotTimestamp(name, time, i);
return true;
case MINKEY: _callback.gotMinKey(name); return true;
case MAXKEY: _callback.gotMaxKey(name); return true;
default: throw new UnsupportedOperationException( "BSONDecoder doesn't understand type : " + type + " name: " + name );
}
}
private static final int MAX_STRING = ( 32 * 1024 * 1024 );
private static final String DEFAULT_ENCODING = "UTF-8";
private byte [] _data;
private int _length;
private int _pos = 0;
private BSONCallback _callback;
}

View File

@ -1,27 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Transformer.java
package com.massivecraft.massivecore.xlib.bson;
public interface Transformer {
/**
* @return the new object. return passed in object if no change
*/
Object transform(Object o);
}

View File

@ -1,146 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson.io;
import com.massivecraft.massivecore.xlib.bson.BSONException;
import java.io.UnsupportedEncodingException;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* Pseudo byte buffer, delegates as it is too hard to properly override / extend the ByteBuffer API
*
* @author brendan
*/
public class BSONByteBuffer {
private BSONByteBuffer( ByteBuffer buf ){
this.buf = buf;
buf.order( ByteOrder.LITTLE_ENDIAN );
}
public static BSONByteBuffer wrap( byte[] bytes, int offset, int length ){
return new BSONByteBuffer( ByteBuffer.wrap( bytes, offset, length ) );
}
public static BSONByteBuffer wrap( byte[] bytes ){
return new BSONByteBuffer( ByteBuffer.wrap( bytes ) );
}
public byte get( int i ){
return buf.get(i);
}
public ByteBuffer get( byte[] bytes, int offset, int length ){
return buf.get(bytes, offset, length);
}
public ByteBuffer get( byte[] bytes ){
return buf.get(bytes);
}
public byte[] array(){
return buf.array();
}
public String toString(){
return buf.toString();
}
public int hashCode(){
return buf.hashCode();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BSONByteBuffer that = (BSONByteBuffer) o;
if (buf != null ? !buf.equals(that.buf) : that.buf != null) return false;
return true;
}
/**
* Gets a Little Endian Integer
*
* @param i Index to read from
*
* @return
*/
public int getInt( int i ){
return getIntLE( i );
}
public int getIntLE( int i ){
int x = 0;
x |= ( 0xFF & buf.get( i + 0 ) ) << 0;
x |= ( 0xFF & buf.get( i + 1 ) ) << 8;
x |= ( 0xFF & buf.get( i + 2 ) ) << 16;
x |= ( 0xFF & buf.get( i + 3 ) ) << 24;
return x;
}
public int getIntBE( int i ){
int x = 0;
x |= ( 0xFF & buf.get( i + 0 ) ) << 24;
x |= ( 0xFF & buf.get( i + 1 ) ) << 16;
x |= ( 0xFF & buf.get( i + 2 ) ) << 8;
x |= ( 0xFF & buf.get( i + 3 ) ) << 0;
return x;
}
public long getLong( int i ){
return buf.getLong( i );
}
public String getCString(int offset) {
int end = offset;
while (get(end) != 0) {
++end;
}
int len = end - offset;
return new String(array(), offset, len);
}
public String getUTF8String(int valueOffset) {
int size = getInt(valueOffset) - 1;
try {
return new String(array(), valueOffset + 4, size, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new BSONException( "Cannot decode string as UTF-8." );
}
}
public Buffer position( int i ){
return buf.position(i);
}
public Buffer reset(){
return buf.reset();
}
public int size(){
return getInt( 0 );
}
protected ByteBuffer buf;
}

View File

@ -1,146 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// BasicOutputBuffer.java
package com.massivecraft.massivecore.xlib.bson.io;
import java.io.DataOutput;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
public class BasicOutputBuffer extends OutputBuffer {
@Override
public void write(byte[] b){
write( b , 0 , b.length );
}
@Override
public void write(byte[] b, int off, int len){
_ensure( len );
System.arraycopy( b , off , _buffer , _cur , len );
_cur += len;
_size = Math.max( _cur , _size );
}
@Override
public void write(int b){
_ensure(1);
_buffer[_cur++] = (byte)(0xFF&b);
_size = Math.max( _cur , _size );
}
@Override
public int getPosition(){
return _cur;
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Override
@Deprecated
public void setPosition( int position ){
_cur = position;
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Override
@Deprecated
public void seekEnd(){
_cur = _size;
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
@Override
public void seekStart(){
_cur = 0;
}
/**
* @return size of data so far
*/
@Override
public int size(){
return _size;
}
/**
* @return bytes written
*/
@Override
public int pipe( OutputStream out )
throws IOException {
out.write( _buffer , 0 , _size );
return _size;
}
/**
* @return bytes written
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public int pipe( DataOutput out )
throws IOException {
out.write( _buffer , 0 , _size );
return _size;
}
void _ensure( int more ){
final int need = _cur + more;
if ( need < _buffer.length )
return;
int newSize = _buffer.length*2;
if ( newSize <= need )
newSize = need + 128;
byte[] n = new byte[newSize];
System.arraycopy( _buffer , 0 , n , 0 , _size );
_buffer = n;
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Override
@Deprecated
public String asString(){
return new String( _buffer , 0 , _size );
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Override
@Deprecated
public String asString( String encoding )
throws UnsupportedEncodingException {
return new String( _buffer , 0 , _size , encoding );
}
private int _cur;
private int _size;
private byte[] _buffer = new byte[512];
}

View File

@ -1,117 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Bits.java
package com.massivecraft.massivecore.xlib.bson.io;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
public class Bits {
public static void readFully( InputStream in, byte[] b )
throws IOException {
readFully( in , b , b.length );
}
public static void readFully( InputStream in, byte[] b, int length )
throws IOException {
readFully(in, b, 0, length);
}
public static void readFully( InputStream in, byte[] b, int startOffset, int length )
throws IOException {
if (b.length < length + startOffset) {
throw new IllegalArgumentException("Buffer is too small");
}
int offset = startOffset;
int toRead = length;
while ( toRead > 0 ){
int bytesRead = in.read( b, offset , toRead );
if ( bytesRead < 0 )
throw new EOFException();
toRead -= bytesRead;
offset += bytesRead;
}
}
public static int readInt( InputStream in )
throws IOException {
return readInt( in , new byte[4] );
}
public static int readInt( InputStream in , byte[] data )
throws IOException {
readFully(in, data, 4);
return readInt(data);
}
public static int readInt( byte[] data ) {
return readInt( data , 0 );
}
public static int readInt( byte[] data , int offset ) {
int x = 0;
x |= ( 0xFF & data[offset+0] ) << 0;
x |= ( 0xFF & data[offset+1] ) << 8;
x |= ( 0xFF & data[offset+2] ) << 16;
x |= ( 0xFF & data[offset+3] ) << 24;
return x;
}
public static int readIntBE( byte[] data , int offset ) {
int x = 0;
x |= ( 0xFF & data[offset+0] ) << 24;
x |= ( 0xFF & data[offset+1] ) << 16;
x |= ( 0xFF & data[offset+2] ) << 8;
x |= ( 0xFF & data[offset+3] ) << 0;
return x;
}
public static long readLong( InputStream in )
throws IOException {
return readLong( in , new byte[8] );
}
public static long readLong( InputStream in , byte[] data )
throws IOException {
readFully(in, data, 8);
return readLong(data);
}
public static long readLong( byte[] data ) {
return readLong( data , 0 );
}
public static long readLong( byte[] data , int offset ) {
long x = 0;
x |= ( 0xFFL & data[offset+0] ) << 0;
x |= ( 0xFFL & data[offset+1] ) << 8;
x |= ( 0xFFL & data[offset+2] ) << 16;
x |= ( 0xFFL & data[offset+3] ) << 24;
x |= ( 0xFFL & data[offset+4] ) << 32;
x |= ( 0xFFL & data[offset+5] ) << 40;
x |= ( 0xFFL & data[offset+6] ) << 48;
x |= ( 0xFFL & data[offset+7] ) << 56;
return x;
}
}

View File

@ -1,291 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// OutputBuffer.java
package com.massivecraft.massivecore.xlib.bson.io;
import com.massivecraft.massivecore.xlib.bson.BSONException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public abstract class OutputBuffer extends OutputStream {
public abstract void write(byte[] b);
public abstract void write(byte[] b, int off, int len);
public abstract void write(int b);
public abstract int getPosition();
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public abstract void setPosition( int position );
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public abstract void seekEnd();
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public abstract void seekStart();
/**
* @return size of data so far
*/
public abstract int size();
/**
* @return bytes written
*/
public abstract int pipe( OutputStream out )
throws IOException;
/**
* mostly for testing
*/
public byte [] toByteArray(){
try {
final ByteArrayOutputStream bout = new ByteArrayOutputStream( size() );
pipe( bout );
return bout.toByteArray();
}
catch ( IOException ioe ){
throw new RuntimeException( "should be impossible" , ioe );
}
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public String asString(){
return new String( toByteArray() );
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public String asString( String encoding )
throws UnsupportedEncodingException {
return new String( toByteArray() , encoding );
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public String hex(){
final StringBuilder buf = new StringBuilder();
try {
pipe( new OutputStream(){
public void write( int b ){
String s = Integer.toHexString(0xff & b);
if (s.length() < 2)
buf.append("0");
buf.append(s);
}
}
);
}
catch ( IOException ioe ){
throw new RuntimeException( "impossible" );
}
return buf.toString();
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public String md5(){
final MessageDigest md5 ;
try {
md5 = MessageDigest.getInstance("MD5");
}
catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Error - this implementation of Java doesn't support MD5.");
}
md5.reset();
try {
pipe( new OutputStream(){
public void write( byte[] b , int off , int len ){
md5.update( b , off , len );
}
public void write( int b ){
md5.update( (byte)(b&0xFF) );
}
}
);
}
catch ( IOException ioe ){
throw new RuntimeException( "impossible" );
}
return com.massivecraft.massivecore.xlib.mongodb.util.Util.toHex( md5.digest() );
}
public void writeInt( int x ){
write( x >> 0 );
write( x >> 8 );
write( x >> 16 );
write( x >> 24 );
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public void writeIntBE( int x ){
write( x >> 24 );
write(x >> 16);
write(x >> 8);
write(x);
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public void writeInt( int pos , int x ){
final int save = getPosition();
setPosition(pos);
writeInt(x);
setPosition(save);
}
public void writeLong( long x ){
write( (byte)(0xFFL & ( x >> 0 ) ) );
write( (byte)(0xFFL & ( x >> 8 ) ) );
write( (byte)(0xFFL & ( x >> 16 ) ) );
write( (byte)(0xFFL & ( x >> 24 ) ) );
write( (byte)(0xFFL & ( x >> 32 ) ) );
write( (byte)(0xFFL & ( x >> 40 ) ) );
write( (byte)(0xFFL & ( x >> 48 ) ) );
write((byte) (0xFFL & (x >> 56)));
}
public void writeDouble( double x ){
writeLong(Double.doubleToRawLongBits(x));
}
public void writeString(final String str) {
writeInt(0); // making space for size
final int strLen = writeCString(str, false);
backpatchSize(strLen, 4);
}
/**
* Writes C string (null-terminated string) to underlying buffer.
*
* @param str the string
* @return number of bytes written
*/
public int writeCString(final String str) {
return writeCString(str, true);
}
private int writeCString(final String str, final boolean checkForNullCharacters) {
final int len = str.length();
int total = 0;
for (int i = 0; i < len;/*i gets incremented*/) {
final int c = Character.codePointAt(str, i);
if (checkForNullCharacters && c == 0x0) {
throw new BSONException(
String.format("BSON cstring '%s' is not valid because it contains a null character at index %d", str, i));
}
if (c < 0x80) {
write((byte) c);
total += 1;
} else if (c < 0x800) {
write((byte) (0xc0 + (c >> 6)));
write((byte) (0x80 + (c & 0x3f)));
total += 2;
} else if (c < 0x10000) {
write((byte) (0xe0 + (c >> 12)));
write((byte) (0x80 + ((c >> 6) & 0x3f)));
write((byte) (0x80 + (c & 0x3f)));
total += 3;
} else {
write((byte) (0xf0 + (c >> 18)));
write((byte) (0x80 + ((c >> 12) & 0x3f)));
write((byte) (0x80 + ((c >> 6) & 0x3f)));
write((byte) (0x80 + (c & 0x3f)));
total += 4;
}
i += Character.charCount(c);
}
write((byte) 0);
total++;
return total;
}
public String toString(){
return getClass().getName() + " size: " + size() + " pos: " + getPosition() ;
}
/**
* Backpatches the size of a document or string by writing the size into the four bytes starting at getPosition() -
* size.
*
* @param size the size of the document/string
*/
public void backpatchSize(final int size) {
writeInt(getPosition() - size, size);
}
/**
* Backpatches the size of a document or string by writing the size into the four bytes starting at {@code getPosition() - size -
* additionalOffset}.
*
* @param size the size of the document/string
* @param additionalOffset the offset from the current position to write the size
*/
protected void backpatchSize(final int size, final int additionalOffset) {
writeInt(getPosition() - size - additionalOffset, size);
}
/**
* Truncates the buffer to the given new position, which must be greater than or equal to zero and less than or equal to the current
* size of this buffer.
*
* @param newPosition the position to truncate this buffer to
*/
public void truncateToPosition(int newPosition) {
setPosition(newPosition);
}
}

View File

@ -1,272 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// PoolOutputBuffer.java
package com.massivecraft.massivecore.xlib.bson.io;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
/**
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public class PoolOutputBuffer extends OutputBuffer {
public static final int BUF_SIZE = 1024 * 16;
public PoolOutputBuffer(){
reset();
}
public void reset(){
_cur.reset();
_end.reset();
for ( int i=0; i<_fromPool.size(); i++ )
_extra.done( _fromPool.get(i) );
_fromPool.clear();
}
public int getPosition(){
return _cur.pos();
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public void setPosition( int position ){
_cur.reset( position );
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public void seekEnd(){
_cur.reset( _end );
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public void seekStart(){
_cur.reset();
}
public int size(){
return _end.pos();
}
public void write(byte[] b){
write( b , 0 , b.length );
}
public void write(byte[] b, int off, int len){
while ( len > 0 ){
byte[] bs = _cur();
int space = Math.min( bs.length - _cur.y , len );
System.arraycopy( b , off , bs , _cur.y , space );
_cur.inc( space );
len -= space;
off += space;
_afterWrite();
}
}
public void write(int b){
byte[] bs = _cur();
bs[_cur.getAndInc()] = (byte)(b&0xFF);
_afterWrite();
}
@Override
public void truncateToPosition(final int newPosition) {
setPosition(newPosition);
_end.reset(_cur);
}
void _afterWrite(){
if ( _cur.pos() < _end.pos() ){
// we're in the middle of the total space
// just need to make sure we're not at the end of a buffer
if ( _cur.y == BUF_SIZE )
_cur.nextBuffer();
return;
}
_end.reset( _cur );
if ( _end.y < BUF_SIZE )
return;
_fromPool.add( _extra.get() );
_end.nextBuffer();
_cur.reset( _end );
}
byte[] _cur(){
return _get( _cur.x );
}
byte[] _get( int z ){
if ( z < 0 )
return _mine;
return _fromPool.get(z);
}
public int pipe( final OutputStream out )
throws IOException {
if ( out == null )
throw new NullPointerException( "out is null" );
int total = 0;
for ( int i=-1; i<_fromPool.size(); i++ ){
final byte[] b = _get( i );
final int amt = _end.len( i );
if (amt == 0) {
break;
}
out.write( b , 0 , amt );
total += amt;
}
return total;
}
static class Position {
Position(){
reset();
}
void reset(){
x = -1;
y = 0;
}
void reset( Position other ){
x = other.x;
y = other.y;
}
void reset( int pos ){
x = ( pos / BUF_SIZE ) - 1;
y = pos % BUF_SIZE;
}
int pos(){
return ( ( x + 1 ) * BUF_SIZE ) + y;
}
int getAndInc(){
return y++;
}
void inc( int amt ){
y += amt;
if ( y > BUF_SIZE )
throw new IllegalArgumentException( "something is wrong" );
}
void nextBuffer(){
if ( y != BUF_SIZE )
throw new IllegalArgumentException( "broken" );
x++;
y = 0;
}
int len( int which ){
if ( which < x )
return BUF_SIZE;
else if (which == x)
return y;
else
return 0;
}
public String toString(){
return x + "," + y;
}
int x; // which buffer -1 == _mine
int y; // position in buffer
}
public String asAscii(){
if ( _fromPool.size() > 0 )
return super.asString();
final int m = size();
final char c[] = m < _chars.length ? _chars : new char[m];
for ( int i=0; i<m; i++ )
c[i] = (char)_mine[i];
return new String( c , 0 , m );
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public String asString( String encoding )
throws UnsupportedEncodingException {
if ( _fromPool.size() > 0 )
return super.asString( encoding );
if ( encoding.equals( DEFAULT_ENCODING_1 ) || encoding.equals( DEFAULT_ENCODING_2) ){
try {
return _encoding.decode( _mine , 0 , size() );
}
catch ( IOException ioe ){
// we failed, fall back
}
}
return new String( _mine , 0 , size() , encoding );
}
final byte[] _mine = new byte[BUF_SIZE];
final char[] _chars = new char[BUF_SIZE];
final List<byte[]> _fromPool = new ArrayList<>();
final UTF8Encoding _encoding = new UTF8Encoding();
private static final String DEFAULT_ENCODING_1 = "UTF-8";
private static final String DEFAULT_ENCODING_2 = "UTF8";
private final Position _cur = new Position();
private final Position _end = new Position();
private static com.massivecraft.massivecore.xlib.bson.util.SimplePool<byte[]> _extra =
new com.massivecraft.massivecore.xlib.bson.util.SimplePool<byte[]>( ( 1024 * 1024 * 10 ) / BUF_SIZE ){
protected byte[] createNew(){
return new byte[BUF_SIZE];
}
};
}

View File

@ -1,201 +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);
}
}

View File

@ -1,18 +0,0 @@
<!--
~ Copyright (c) 2008-2014 MongoDB, Inc.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<body>
<p>Contains classes implementing I/O operations used by BSON objects.</p>
</body>

View File

@ -1,18 +0,0 @@
<!--
~ Copyright (c) 2008-2014 MongoDB, Inc.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<body>
<p>Contains the base BSON classes and Encoder/Decoder.</p>
</body>

View File

@ -1,96 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// BSONTimestamp.java
package com.massivecraft.massivecore.xlib.bson.types;
import java.io.Serializable;
import java.util.Date;
/**
* this is used for internal increment values.
* for storing normal dates in MongoDB, you should use java.util.Date
* <b>time</b> is seconds since epoch
* <b>inc<b> is an ordinal
*/
public class BSONTimestamp implements Comparable<BSONTimestamp>, Serializable {
private static final long serialVersionUID = -3268482672267936464L;
static final boolean D = Boolean.getBoolean( "DEBUG.DBTIMESTAMP" );
public BSONTimestamp(){
_inc = 0;
_time = null;
}
public BSONTimestamp(int time, int inc ){
_time = new Date( time * 1000L );
_inc = inc;
}
/**
* @return get time in seconds since epoch
*/
public int getTime(){
if ( _time == null )
return 0;
return (int)(_time.getTime() / 1000);
}
public int getInc(){
return _inc;
}
public String toString(){
return "TS time:" + _time + " inc:" + _inc;
}
@Override
public int compareTo(BSONTimestamp ts) {
if(getTime() != ts.getTime()) {
return getTime() - ts.getTime();
}
else{
return getInc() - ts.getInc();
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + _inc;
result = prime * result + getTime();
return result;
}
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (obj instanceof BSONTimestamp) {
BSONTimestamp t2 = (BSONTimestamp) obj;
return getTime() == t2.getTime() && getInc() == t2.getInc();
}
return false;
}
final int _inc;
final Date _time;
}

View File

@ -1,168 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// BasicBSONList.java
package com.massivecraft.massivecore.xlib.bson.types;
import com.massivecraft.massivecore.xlib.bson.BSONObject;
import com.massivecraft.massivecore.xlib.bson.util.StringRangeSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* Utility class to allow array <code>DBObject</code>s to be created.
* <p>
* Note: MongoDB will also create arrays from <code>java.util.List</code>s.
* </p>
* <p>
* <blockquote><pre>
* DBObject obj = new BasicBSONList();
* obj.put( "0", value1 );
* obj.put( "4", value2 );
* obj.put( 2, value3 );
* </pre></blockquote>
* This simulates the array [ value1, null, value3, null, value2 ] by creating the
* <code>DBObject</code> <code>{ "0" : value1, "1" : null, "2" : value3, "3" : null, "4" : value2 }</code>.
* </p>
* <p>
* BasicBSONList only supports numeric keys. Passing strings that cannot be converted to ints will cause an
* IllegalArgumentException.
* <blockquote><pre>
* BasicBSONList list = new BasicBSONList();
* list.put("1", "bar"); // ok
* list.put("1E1", "bar"); // throws exception
* </pre></blockquote>
* </p>
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public class BasicBSONList extends ArrayList<Object> implements BSONObject {
private static final long serialVersionUID = -4415279469780082174L;
public BasicBSONList() { }
/**
* Puts a value at an index.
* For interface compatibility. Must be passed a String that is parsable to an int.
* @param key the index at which to insert the value
* @param v the value to insert
* @return the value
* @throws IllegalArgumentException if <code>key</code> cannot be parsed into an <code>int</code>
*/
public Object put( String key , Object v ){
return put(_getInt( key ), v);
}
/**
* Puts a value at an index.
* This will fill any unset indexes less than <code>index</code> with <code>null</code>.
* @param key the index at which to insert the value
* @param v the value to insert
* @return the value
*/
public Object put( int key, Object v ) {
while ( key >= size() )
add( null );
set( key , v );
return v;
}
public void putAll( Map m ){
for ( Map.Entry entry : (Set<Map.Entry>)m.entrySet() ){
put( entry.getKey().toString() , entry.getValue() );
}
}
public void putAll( BSONObject o ){
for ( String k : o.keySet() ){
put( k , o.get( k ) );
}
}
/**
* Gets a value at an index.
* For interface compatibility. Must be passed a String that is parsable to an int.
* @param key the index
* @return the value, if found, or null
* @throws IllegalArgumentException if <code>key</code> cannot be parsed into an <code>int</code>
*/
public Object get( String key ){
int i = _getInt( key );
if ( i < 0 )
return null;
if ( i >= size() )
return null;
return get( i );
}
public Object removeField( String key ){
int i = _getInt( key );
if ( i < 0 )
return null;
if ( i >= size() )
return null;
return remove( i );
}
/**
* @deprecated
*/
@Deprecated
public boolean containsKey( String key ){
return containsField(key);
}
public boolean containsField( String key ){
int i = _getInt( key , false );
if ( i < 0 )
return false;
return i >= 0 && i < size();
}
public Set<String> keySet(){
return new StringRangeSet(size());
}
public Map toMap() {
Map m = new HashMap();
Iterator i = this.keySet().iterator();
while (i.hasNext()) {
Object s = i.next();
m.put(s, this.get(String.valueOf(s)));
}
return m;
}
int _getInt( String s ){
return _getInt( s , true );
}
int _getInt( String s , boolean err ){
try {
return Integer.parseInt( s );
}
catch ( Exception e ){
if ( err )
throw new IllegalArgumentException( "BasicBSONList can only work with numeric keys, not: [" + s + "]" );
return -1;
}
}
}

View File

@ -1,95 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Binary.java
package com.massivecraft.massivecore.xlib.bson.types;
import com.massivecraft.massivecore.xlib.bson.BSON;
import java.io.Serializable;
import java.util.Arrays;
/**
* generic binary holder
*/
public class Binary implements Serializable {
private static final long serialVersionUID = 7902997490338209467L;
/**
* Creates a Binary object with the default binary type of 0
*
* @param data raw data
*/
public Binary(byte[] data) {
this(BSON.B_GENERAL, data);
}
/**
* Creates a Binary object
*
* @param type type of the field as encoded in BSON
* @param data raw data
*/
public Binary(byte type, byte[] data) {
_type = type;
_data = data;
}
public byte getType() {
return _type;
}
public byte[] getData() {
return _data;
}
public int length() {
return _data.length;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Binary)) {
return false;
}
Binary binary = (Binary) o;
if (_type != binary._type) {
return false;
}
if (!Arrays.equals(_data, binary._data)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = (int) _type;
result = 31 * result + (_data != null ? Arrays.hashCode(_data) : 0);
return result;
}
final byte _type;
final byte[] _data;
}

View File

@ -1,58 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Code.java
package com.massivecraft.massivecore.xlib.bson.types;
import java.io.Serializable;
/**
* for using the Code type
*/
public class Code implements Serializable {
private static final long serialVersionUID = 475535263314046697L;
public Code( String code ){
_code = code;
}
public String getCode(){
return _code;
}
public boolean equals( Object o ){
if ( ! ( o instanceof Code ) )
return false;
Code c = (Code)o;
return _code.equals( c._code );
}
public int hashCode(){
return _code.hashCode();
}
@Override
public String toString() {
return getCode();
}
final String _code;
}

View File

@ -1,53 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// CodeWScope.java
package com.massivecraft.massivecore.xlib.bson.types;
import com.massivecraft.massivecore.xlib.bson.BSONObject;
/**
* for using the CodeWScope type
*/
public class CodeWScope extends Code {
private static final long serialVersionUID = -6284832275113680002L;
public CodeWScope( String code , BSONObject scope ){
super( code );
_scope = scope;
}
public BSONObject getScope(){
return _scope;
}
public boolean equals( Object o ){
if ( ! ( o instanceof CodeWScope ) )
return false;
CodeWScope c = (CodeWScope)o;
return _code.equals( c._code ) && _scope.equals( c._scope );
}
public int hashCode(){
return _code.hashCode() ^ _scope.hashCode();
}
final BSONObject _scope;
}

View File

@ -1,47 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson.types;
import java.io.Serializable;
/**
* Represent the maximum key value regardless of the key's type
*/
public class MaxKey implements Serializable {
private static final long serialVersionUID = 5123414776151687185L;
public MaxKey() {
}
@Override
public boolean equals(Object o) {
return o instanceof MaxKey;
}
@Override
public int hashCode() {
return 0;
}
@Override
public String toString() {
return "MaxKey";
}
}

View File

@ -1,47 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson.types;
import java.io.Serializable;
/**
* Represent the minimum key value regardless of the key's type
*/
public class MinKey implements Serializable {
private static final long serialVersionUID = 4075901136671855684L;
public MinKey() {
}
@Override
public boolean equals(Object o) {
return o instanceof MinKey;
}
@Override
public int hashCode() {
return 0;
}
@Override
public String toString() {
return "MinKey";
}
}

View File

@ -1,592 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// ObjectId.java
package com.massivecraft.massivecore.xlib.bson.types;
import java.net.NetworkInterface;
import java.nio.ByteBuffer;
import java.util.Date;
import java.util.Enumeration;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A globally unique identifier for objects.
* <p>Consists of 12 bytes, divided as follows:
* <blockquote><pre>
* <table border="1">
* <tr><td>0</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td>
* <td>7</td><td>8</td><td>9</td><td>10</td><td>11</td></tr>
* <tr><td colspan="4">time</td><td colspan="3">machine</td>
* <td colspan="2">pid</td><td colspan="3">inc</td></tr>
* </table>
* </pre></blockquote>
*
* @dochub objectids
*/
public class ObjectId implements Comparable<ObjectId> , java.io.Serializable {
private static final long serialVersionUID = -4415279469780082174L;
static final Logger LOGGER = Logger.getLogger( "org.bson.ObjectId" );
/** Gets a new object id.
* @return the new id
*/
public static ObjectId get(){
return new ObjectId();
}
/**
* Creates an ObjectId using time, machine and inc values. The Java driver has done it this way for a long time, but it
* does not match the <a href="http://docs.mongodb.org/manual/reference/object-id/">ObjectId specification</a>,
* which requires four values, not three. The next major release of the Java driver will conform to this specification,
* but will still need to support clients that are relying on the current behavior. To that end,
* the constructors that takes these three arguments are now deprecated in favor of this more explicit factory method,
* and in the next major release those constructors will be removed.
* <p>
* NOTE: This will not break any application that use ObjectIds. The 12-byte representation will be round-trippable from old to new
* driver releases.
*
* </p>
*
* @param time time in seconds
* @param machine machine ID
* @param inc incremental value
* @see com.massivecraft.massivecore.xlib.bson.types.ObjectId#ObjectId(int, int, int)
* @since 2.12.0
*/
public static ObjectId createFromLegacyFormat(final int time, final int machine, final int inc) {
return new ObjectId(time, machine, inc);
}
/** Checks if a string could be an <code>ObjectId</code>.
* @return whether the string could be an object id
*/
public static boolean isValid( String s ){
if ( s == null )
return false;
final int len = s.length();
if ( len != 24 )
return false;
for ( int i=0; i<len; i++ ){
char c = s.charAt( i );
if ( c >= '0' && c <= '9' )
continue;
if ( c >= 'a' && c <= 'f' )
continue;
if ( c >= 'A' && c <= 'F' )
continue;
return false;
}
return true;
}
/** Turn an object into an <code>ObjectId</code>, if possible.
* Strings will be converted into <code>ObjectId</code>s, if possible, and <code>ObjectId</code>s will
* be cast and returned. Passing in <code>null</code> returns <code>null</code>.
* @param o the object to convert
* @return an <code>ObjectId</code> if it can be massaged, null otherwise
*
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public static ObjectId massageToObjectId( Object o ){
if ( o == null )
return null;
if ( o instanceof ObjectId )
return (ObjectId)o;
if ( o instanceof String ){
String s = o.toString();
if ( isValid( s ) )
return new ObjectId( s );
}
return null;
}
public ObjectId( Date time ){
this(time, _genmachine, _nextInc.getAndIncrement());
}
public ObjectId( Date time , int inc ){
this( time , _genmachine , inc );
}
/**
* Constructs an ObjectId using time, machine and inc values. The Java driver has done it this way for a long time, but it
* does not match the <a href="http://docs.mongodb.org/manual/reference/object-id/">ObjectId specification</a>,
* which requires four values, not three. The next major release of the Java driver will conform to this specification,
* but will still need to support clients that are relying on the current behavior. To that end,
* this constructor is now deprecated in favor of the more explicit factory method ObjectId#createFromLegacyFormat(int, int, int)},
* and in the next major release this constructor will be removed.
*
* @see ObjectId#createFromLegacyFormat(int, int, int)
* @deprecated {@code ObjectId}'s constructed this way do not conform to
* the <a href="http://docs.mongodb.org/manual/reference/object-id/">ObjectId specification</a>.
* Please use {@link com.massivecraft.massivecore.xlib.bson.types.ObjectId#ObjectId(byte[])} or
* {@link ObjectId#createFromLegacyFormat(int, int, int)} instead.
*/
@Deprecated
public ObjectId( Date time , int machine , int inc ){
_time = (int)(time.getTime() / 1000);
_machine = machine;
_inc = inc;
_new = false;
}
/** Creates a new instance from a string.
* @param s the string to convert
* @throws IllegalArgumentException if the string is not a valid id
*/
public ObjectId( String s ){
this( s , false );
}
/**
* Constructs a new instance of {@code ObjectId} from a string.
* @param s the string representation of ObjectId. Can contains only [0-9]|[a-f]|[A-F] characters.
* @param babble if {@code true} - convert to 'babble' objectId format
*
* @deprecated 'babble' format is deprecated. Please use {@link #ObjectId(String)} instead.
*/
@Deprecated
public ObjectId( String s , boolean babble ){
if ( ! isValid( s ) )
throw new IllegalArgumentException( "invalid ObjectId [" + s + "]" );
if ( babble )
s = babbleToMongod( s );
byte b[] = new byte[12];
for ( int i=0; i<b.length; i++ ){
b[i] = (byte)Integer.parseInt( s.substring( i*2 , i*2 + 2) , 16 );
}
ByteBuffer bb = ByteBuffer.wrap( b );
_time = bb.getInt();
_machine = bb.getInt();
_inc = bb.getInt();
_new = false;
}
/**
* Constructs an ObjectId given its 12-byte binary representation.
* @param b a byte array of length 12
*/
public ObjectId( byte[] b ){
if ( b.length != 12 )
throw new IllegalArgumentException( "need 12 bytes" );
ByteBuffer bb = ByteBuffer.wrap( b );
_time = bb.getInt();
_machine = bb.getInt();
_inc = bb.getInt();
_new = false;
}
/**
* Constructs an ObjectId using time, machine and inc values. The Java driver has done it this way for a long time, but it
* does not match the <a href="http://docs.mongodb.org/manual/reference/object-id/">ObjectId specification</a>,
* which requires four values, not three. The next major release of the Java driver will conform to this specification,
* but we will still need to support clients that are relying on the current behavior. To that end,
* this constructor is now deprecated in favor of the more explicit factory method ObjectId#createFromLegacyFormat(int, int, int)},
* and in the next major release this constructor will be removed.
*
* @param time time in seconds
* @param machine machine ID
* @param inc incremental value
* @see ObjectId#createFromLegacyFormat(int, int, int)
* @deprecated {@code ObjectId}'s constructed this way do not conform to
* the <a href="http://docs.mongodb.org/manual/reference/object-id/">ObjectId specification</a>.
* Please use {@link com.massivecraft.massivecore.xlib.bson.types.ObjectId#ObjectId(byte[])} or
* {@link ObjectId#createFromLegacyFormat(int, int, int)} instead.
*/
@Deprecated
public ObjectId(int time, int machine, int inc) {
_time = time;
_machine = machine;
_inc = inc;
_new = false;
}
/** Create a new object id.
*/
public ObjectId(){
_time = (int) (System.currentTimeMillis() / 1000);
_machine = _genmachine;
_inc = _nextInc.getAndIncrement();
_new = true;
}
public int hashCode(){
int x = _time;
x += ( _machine * 111 );
x += ( _inc * 17 );
return x;
}
public boolean equals( Object o ){
if ( this == o )
return true;
ObjectId other = massageToObjectId( o );
if ( other == null )
return false;
return
_time == other._time &&
_machine == other._machine &&
_inc == other._inc;
}
/**
* @deprecated 'babble' format is deprecated. Please use {@link #toHexString()} instead.
*/
@Deprecated
public String toStringBabble(){
return babbleToMongod( toStringMongod() );
}
/**
* Converts this instance into a 24-byte hexadecimal string representation.
*
* @return a string representation of the ObjectId in hexadecimal format
*/
public String toHexString() {
final StringBuilder buf = new StringBuilder(24);
for (final byte b : toByteArray()) {
buf.append(String.format("%02x", b & 0xff));
}
return buf.toString();
}
/**
* @return a string representation of the ObjectId in hexadecimal format
*
* @deprecated Please use {@link #toHexString()} instead.
*/
@Deprecated
public String toStringMongod(){
byte b[] = toByteArray();
StringBuilder buf = new StringBuilder(24);
for ( int i=0; i<b.length; i++ ){
int x = b[i] & 0xFF;
String s = Integer.toHexString( x );
if ( s.length() == 1 )
buf.append( "0" );
buf.append( s );
}
return buf.toString();
}
public byte[] toByteArray(){
byte b[] = new byte[12];
ByteBuffer bb = ByteBuffer.wrap( b );
// by default BB is big endian like we need
bb.putInt( _time );
bb.putInt( _machine );
bb.putInt( _inc );
return b;
}
static String _pos( String s , int p ){
return s.substring( p * 2 , ( p * 2 ) + 2 );
}
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public static String babbleToMongod( String b ){
if ( ! isValid( b ) )
throw new IllegalArgumentException( "invalid object id: " + b );
StringBuilder buf = new StringBuilder( 24 );
for ( int i=7; i>=0; i-- )
buf.append( _pos( b , i ) );
for ( int i=11; i>=8; i-- )
buf.append( _pos( b , i ) );
return buf.toString();
}
public String toString(){
return toStringMongod();
}
int _compareUnsigned( int i , int j ){
long li = 0xFFFFFFFFL;
li = i & li;
long lj = 0xFFFFFFFFL;
lj = j & lj;
long diff = li - lj;
if (diff < Integer.MIN_VALUE)
return Integer.MIN_VALUE;
if (diff > Integer.MAX_VALUE)
return Integer.MAX_VALUE;
return (int) diff;
}
public int compareTo( ObjectId id ){
if ( id == null )
return -1;
int x = _compareUnsigned( _time , id._time );
if ( x != 0 )
return x;
x = _compareUnsigned( _machine , id._machine );
if ( x != 0 )
return x;
return _compareUnsigned( _inc , id._inc );
}
/**
* Gets the timestamp (number of seconds since the Unix epoch).
*
* @return the timestamp
*/
public int getTimestamp() {
return _time;
}
/**
* Gets the timestamp as a {@code Date} instance.
*
* @return the Date
*/
public Date getDate() {
return new Date(_time * 1000L);
}
/**
* Gets the time of this ID, in milliseconds
*
* @deprecated Please use {@link #getDate()} ()} instead.
*/
@Deprecated
public long getTime(){
return _time * 1000L;
}
/**
* Gets the time of this ID, in seconds.
* @deprecated Please use {@link #getTimestamp()} ()} instead.
*/
@Deprecated
public int getTimeSecond() {
return _time;
}
/**
* Gets the counter.
*
* @return the counter
* @deprecated Please use the {@link #toByteArray()} instead.
*/
@Deprecated
public int getInc() {
return _inc;
}
/**
* Gets the timestamp.
*
* @return the timestamp
* @deprecated Please use {@link #getTimestamp()} ()} instead.
*/
@Deprecated
public int _time(){
return _time;
}
/**
* Gets the machine identifier.
*
* @return the machine identifier
* @see #createFromLegacyFormat(int, int, int)
* @deprecated Please use {@code #toByteArray()} instead.
*/
@Deprecated
public int getMachine() {
return _machine;
}
/**
* Gets the machine identifier.
*
* @return the machine identifier
* @see #createFromLegacyFormat(int, int, int)
* @deprecated Please use {@link #toByteArray()} instead.
*/
@Deprecated
public int _machine(){
return _machine;
}
/**
* Gets the counter.
*
* @return the counter
* @see #createFromLegacyFormat(int, int, int)
* @deprecated Please use {@link #toByteArray()} instead.
*/
@Deprecated
public int _inc(){
return _inc;
}
/**
* @deprecated 'new' flag breaks the immutability of the {@code ObjectId} class
* and will be dropped in 3.x versions of the driver
*/
@Deprecated
public boolean isNew() {
return _new;
}
/**
* @deprecated 'new' flag breaks the immutability of the {@code ObjectId} class
* and will be dropped in 3.x versions of the driver
*/
@Deprecated
public void notNew(){
_new = false;
}
/**
* Gets the machine identifier.
*
* @return the machine identifier
* @see #createFromLegacyFormat(int, int, int)
* @deprecated
*/
@Deprecated
public static int getGenMachineId() {
return _genmachine;
}
/**
* Gets the current value of the auto-incrementing counter.
*/
public static int getCurrentCounter() {
return _nextInc.get();
}
/**
* Gets the current value of the auto-incrementing counter.
*
* @deprecated Please use {@link #getCurrentCounter()} instead.
*/
@Deprecated
public static int getCurrentInc() {
return _nextInc.get();
}
final int _time;
final int _machine;
final int _inc;
boolean _new;
/**
* @deprecated This method is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public static int _flip( int x ){
int z = 0;
z |= ( ( x << 24 ) & 0xFF000000 );
z |= ( ( x << 8 ) & 0x00FF0000 );
z |= ( ( x >> 8 ) & 0x0000FF00 );
z |= ( ( x >> 24 ) & 0x000000FF );
return z;
}
private static AtomicInteger _nextInc = new AtomicInteger( (new java.util.Random()).nextInt() );
private static final int _genmachine;
static {
try {
// build a 2-byte machine piece based on NICs info
int machinePiece;
{
try {
StringBuilder sb = new StringBuilder();
Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();
while ( e.hasMoreElements() ){
NetworkInterface ni = e.nextElement();
sb.append( ni.toString() );
}
machinePiece = sb.toString().hashCode() << 16;
} catch (Throwable e) {
// exception sometimes happens with IBM JVM, use random
LOGGER.log(Level.WARNING, e.getMessage(), e);
machinePiece = (new Random().nextInt()) << 16;
}
LOGGER.fine( "machine piece post: " + Integer.toHexString( machinePiece ) );
}
// add a 2 byte process piece. It must represent not only the JVM but the class loader.
// Since static var belong to class loader there could be collisions otherwise
final int processPiece;
{
int processId = new java.util.Random().nextInt();
try {
processId = java.lang.management.ManagementFactory.getRuntimeMXBean().getName().hashCode();
}
catch ( Throwable t ){
}
ClassLoader loader = ObjectId.class.getClassLoader();
int loaderId = loader != null ? System.identityHashCode(loader) : 0;
StringBuilder sb = new StringBuilder();
sb.append(Integer.toHexString(processId));
sb.append(Integer.toHexString(loaderId));
processPiece = sb.toString().hashCode() & 0xFFFF;
LOGGER.fine( "process piece: " + Integer.toHexString( processPiece ) );
}
_genmachine = machinePiece | processPiece;
LOGGER.fine( "machine : " + Integer.toHexString( _genmachine ) );
}
catch ( Exception e ){
throw new RuntimeException( e );
}
}
}

View File

@ -1,74 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Symbol.java
package com.massivecraft.massivecore.xlib.bson.types;
import java.io.Serializable;
/**
* Class to hold a BSON symbol object, which is an interned string in Ruby
*/
public class Symbol implements Serializable {
private static final long serialVersionUID = 1326269319883146072L;
public Symbol(String s) {
_symbol = s;
}
public String getSymbol(){
return _symbol;
}
/**
* Will compare equal to a String that is equal to the String that this holds
* @param o
* @return
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
String otherSymbol;
if (o instanceof Symbol) {
otherSymbol = ((Symbol) o)._symbol;
}
else if (o instanceof String) {
otherSymbol = (String) o;
}
else {
return false;
}
if (_symbol != null ? !_symbol.equals(otherSymbol) : otherSymbol != null) return false;
return true;
}
@Override
public int hashCode() {
return _symbol != null ? _symbol.hashCode() : 0;
}
public String toString(){
return _symbol;
}
private final String _symbol;
}

View File

@ -1,18 +0,0 @@
<!--
~ Copyright (c) 2008-2014 MongoDB, Inc.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<body>
<p>Contains classes implementing various BSON types.</p>
</body>

View File

@ -1,632 +0,0 @@
/*
* Copyright (c) 2008 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson.util;
import com.massivecraft.massivecore.xlib.bson.util.annotations.GuardedBy;
import com.massivecraft.massivecore.xlib.bson.util.annotations.ThreadSafe;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static com.massivecraft.massivecore.xlib.bson.util.Assertions.notNull;
import static java.util.Collections.unmodifiableCollection;
import static java.util.Collections.unmodifiableSet;
/**
* Abstract base class for COW {@link Map} implementations that delegate to an
* internal map.
*
* @param <K> The key type
* @param <V> The value type
* @param <M> the internal {@link Map} or extension for things like sorted and
* navigable maps.
*/
@SuppressWarnings("deprecation")
@ThreadSafe
abstract class AbstractCopyOnWriteMap<K, V, M extends Map<K, V>> implements ConcurrentMap<K, V>, Serializable {
private static final long serialVersionUID = 4508989182041753878L;
@GuardedBy("lock")
private volatile M delegate;
// import edu.umd.cs.findbugs.annotations.@SuppressWarnings
private final transient Lock lock = new ReentrantLock();
// private final transient EntrySet entrySet = new EntrySet();
// private final transient KeySet keySet = new KeySet();
// private final transient Values values = new Values();
// private final View.Type viewType;
private final View<K, V> view;
/**
* Create a new {@link CopyOnWriteMap} with the supplied {@link Map} to
* initialize the values.
*
* @param map the initial map to initialize with
* @param viewType for writable or read-only key, value and entrySet views
*/
protected <N extends Map<? extends K, ? extends V>> AbstractCopyOnWriteMap(final N map, final View.Type viewType) {
this.delegate = notNull("delegate", copy(notNull("map", map)));
this.view = notNull("viewType", viewType).get(this);
}
/**
* Copy function, implemented by sub-classes.
*
* @param <N> the map to copy and return.
* @param map the initial values of the newly created map.
* @return a new map. Will never be modified after construction.
*/
@GuardedBy("lock")
abstract <N extends Map<? extends K, ? extends V>> M copy(N map);
//
// mutable operations
//
public final void clear() {
lock.lock();
try {
set(copy(Collections.<K, V> emptyMap()));
} finally {
lock.unlock();
}
}
public final V remove(final Object key) {
lock.lock();
try {
// short circuit if key doesn't exist
if (!delegate.containsKey(key)) {
return null;
}
final M map = copy();
try {
return map.remove(key);
} finally {
set(map);
}
} finally {
lock.unlock();
}
}
public boolean remove(final Object key, final Object value) {
lock.lock();
try {
if (delegate.containsKey(key) && equals(value, delegate.get(key))) {
final M map = copy();
map.remove(key);
set(map);
return true;
} else {
return false;
}
} finally {
lock.unlock();
}
}
public boolean replace(final K key, final V oldValue, final V newValue) {
lock.lock();
try {
if (!delegate.containsKey(key) || !equals(oldValue, delegate.get(key))) {
return false;
}
final M map = copy();
map.put(key, newValue);
set(map);
return true;
} finally {
lock.unlock();
}
}
public V replace(final K key, final V value) {
lock.lock();
try {
if (!delegate.containsKey(key)) {
return null;
}
final M map = copy();
try {
return map.put(key, value);
} finally {
set(map);
}
} finally {
lock.unlock();
}
}
public final V put(final K key, final V value) {
lock.lock();
try {
final M map = copy();
try {
return map.put(key, value);
} finally {
set(map);
}
} finally {
lock.unlock();
}
}
public V putIfAbsent(final K key, final V value) {
lock.lock();
try {
if (!delegate.containsKey(key)) {
final M map = copy();
try {
return map.put(key, value);
} finally {
set(map);
}
}
return delegate.get(key);
} finally {
lock.unlock();
}
}
public final void putAll(final Map<? extends K, ? extends V> t) {
lock.lock();
try {
final M map = copy();
map.putAll(t);
set(map);
} finally {
lock.unlock();
}
}
protected M copy() {
lock.lock();
try {
return copy(delegate);
} finally {
lock.unlock();
}
}
@GuardedBy("lock")
protected void set(final M map) {
delegate = map;
}
//
// Collection views
//
public final Set<Map.Entry<K, V>> entrySet() {
return view.entrySet();
}
public final Set<K> keySet() {
return view.keySet();
}
public final Collection<V> values() {
return view.values();
}
//
// delegate operations
//
public final boolean containsKey(final Object key) {
return delegate.containsKey(key);
}
public final boolean containsValue(final Object value) {
return delegate.containsValue(value);
}
public final V get(final Object key) {
return delegate.get(key);
}
public final boolean isEmpty() {
return delegate.isEmpty();
}
public final int size() {
return delegate.size();
}
@Override
public final boolean equals(final Object o) {
return delegate.equals(o);
}
@Override
public final int hashCode() {
return delegate.hashCode();
}
protected final M getDelegate() {
return delegate;
}
@Override
public String toString() {
return delegate.toString();
}
//
// inner classes
//
private class KeySet extends CollectionView<K> implements Set<K> {
@Override
Collection<K> getDelegate() {
return delegate.keySet();
}
//
// mutable operations
//
public void clear() {
lock.lock();
try {
final M map = copy();
map.keySet().clear();
set(map);
} finally {
lock.unlock();
}
}
public boolean remove(final Object o) {
return AbstractCopyOnWriteMap.this.remove(o) != null;
}
public boolean removeAll(final Collection<?> c) {
lock.lock();
try {
final M map = copy();
try {
return map.keySet().removeAll(c);
} finally {
set(map);
}
} finally {
lock.unlock();
}
}
public boolean retainAll(final Collection<?> c) {
lock.lock();
try {
final M map = copy();
try {
return map.keySet().retainAll(c);
} finally {
set(map);
}
} finally {
lock.unlock();
}
}
}
private final class Values extends CollectionView<V> {
@Override
Collection<V> getDelegate() {
return delegate.values();
}
public void clear() {
lock.lock();
try {
final M map = copy();
map.values().clear();
set(map);
} finally {
lock.unlock();
}
}
public boolean remove(final Object o) {
lock.lock();
try {
if (!contains(o)) {
return false;
}
final M map = copy();
try {
return map.values().remove(o);
} finally {
set(map);
}
} finally {
lock.unlock();
}
}
public boolean removeAll(final Collection<?> c) {
lock.lock();
try {
final M map = copy();
try {
return map.values().removeAll(c);
} finally {
set(map);
}
} finally {
lock.unlock();
}
}
public boolean retainAll(final Collection<?> c) {
lock.lock();
try {
final M map = copy();
try {
return map.values().retainAll(c);
} finally {
set(map);
}
} finally {
lock.unlock();
}
}
}
private class EntrySet extends CollectionView<Entry<K, V>> implements Set<Map.Entry<K, V>> {
@Override
Collection<java.util.Map.Entry<K, V>> getDelegate() {
return delegate.entrySet();
}
public void clear() {
lock.lock();
try {
final M map = copy();
map.entrySet().clear();
set(map);
} finally {
lock.unlock();
}
}
public boolean remove(final Object o) {
lock.lock();
try {
if (!contains(o)) {
return false;
}
final M map = copy();
try {
return map.entrySet().remove(o);
} finally {
set(map);
}
} finally {
lock.unlock();
}
}
public boolean removeAll(final Collection<?> c) {
lock.lock();
try {
final M map = copy();
try {
return map.entrySet().removeAll(c);
} finally {
set(map);
}
} finally {
lock.unlock();
}
}
public boolean retainAll(final Collection<?> c) {
lock.lock();
try {
final M map = copy();
try {
return map.entrySet().retainAll(c);
} finally {
set(map);
}
} finally {
lock.unlock();
}
}
}
private static class UnmodifiableIterator<T> implements Iterator<T> {
private final Iterator<T> delegate;
public UnmodifiableIterator(final Iterator<T> delegate) {
this.delegate = delegate;
}
public boolean hasNext() {
return delegate.hasNext();
}
public T next() {
return delegate.next();
}
public void remove() {
throw new UnsupportedOperationException();
}
}
protected static abstract class CollectionView<E> implements Collection<E> {
abstract Collection<E> getDelegate();
//
// delegate operations
//
public final boolean contains(final Object o) {
return getDelegate().contains(o);
}
public final boolean containsAll(final Collection<?> c) {
return getDelegate().containsAll(c);
}
public final Iterator<E> iterator() {
return new UnmodifiableIterator<>(getDelegate().iterator());
}
public final boolean isEmpty() {
return getDelegate().isEmpty();
}
public final int size() {
return getDelegate().size();
}
public final Object[] toArray() {
return getDelegate().toArray();
}
public final <T> T[] toArray(final T[] a) {
return getDelegate().toArray(a);
}
@Override
public int hashCode() {
return getDelegate().hashCode();
}
@Override
public boolean equals(final Object obj) {
return getDelegate().equals(obj);
}
@Override
public String toString() {
return getDelegate().toString();
}
//
// unsupported operations
//
public final boolean add(final E o) {
throw new UnsupportedOperationException();
}
public final boolean addAll(final Collection<? extends E> c) {
throw new UnsupportedOperationException();
}
}
private boolean equals(final Object o1, final Object o2) {
if (o1 == null) {
return o2 == null;
}
return o1.equals(o2);
}
/**
* Provides access to the views of the underlying key, value and entry
* collections.
*/
public static abstract class View<K, V> {
View() {}
abstract Set<K> keySet();
abstract Set<Entry<K, V>> entrySet();
abstract Collection<V> values();
/**
* The different types of {@link View} available
*/
public enum Type {
STABLE {
@Override
<K, V, M extends Map<K, V>> View<K, V> get(final AbstractCopyOnWriteMap<K, V, M> host) {
return host.new Immutable();
}
},
LIVE {
@Override
<K, V, M extends Map<K, V>> View<K, V> get(final AbstractCopyOnWriteMap<K, V, M> host) {
return host.new Mutable();
}
};
abstract <K, V, M extends Map<K, V>> View<K, V> get(AbstractCopyOnWriteMap<K, V, M> host);
}
}
final class Immutable extends View<K, V> implements Serializable {
private static final long serialVersionUID = -4158727180429303818L;
@Override
public Set<K> keySet() {
return unmodifiableSet(delegate.keySet());
}
@Override
public Set<Entry<K, V>> entrySet() {
return unmodifiableSet(delegate.entrySet());
}
@Override
public Collection<V> values() {
return unmodifiableCollection(delegate.values());
}
}
final class Mutable extends View<K, V> implements Serializable {
private static final long serialVersionUID = 1624520291194797634L;
private final transient KeySet keySet = new KeySet();
private final transient EntrySet entrySet = new EntrySet();
private final transient Values values = new Values();
@Override
public Set<K> keySet() {
return keySet;
}
@Override
public Set<Entry<K, V>> entrySet() {
return entrySet;
}
@Override
public Collection<V> values() {
return values;
}
}
}

View File

@ -1,58 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
* Copyright (c) 2008 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson.util;
/**
* Design by contract assertions.
*
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public class Assertions {
public static <T> T notNull(final String name, final T notNull) throws IllegalArgumentException {
if (notNull == null) {
throw new NullArgumentException(name);
}
return notNull;
}
public static void isTrue(final String name, final boolean check) throws IllegalArgumentException {
if (!check) {
throw new IllegalStateException(name);
}
}
public static void isTrueArgument(final String name, final boolean check) {
if (!check) {
throw new IllegalArgumentException("state should be: " + name);
}
}
// /CLOVER:OFF
private Assertions() {}
// /CLOVER:ON
static class NullArgumentException extends IllegalArgumentException {
private static final long serialVersionUID = 6178592463723624585L;
NullArgumentException(final String name) {
super(name + " should not be null!");
}
}
}

View File

@ -1,88 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import static com.massivecraft.massivecore.xlib.bson.util.CopyOnWriteMap.newHashMap;
import static java.util.Collections.unmodifiableList;
class ClassAncestry {
/**
* getAncestry
*
* Walks superclass and interface graph, superclasses first, then
* interfaces, to compute an ancestry list. Supertypes are visited left to
* right. Duplicates are removed such that no Class will appear in the list
* before one of its subtypes.
*
* Does not need to be synchronized, races are harmless as the Class graph
* does not change at runtime.
*/
public static <T> List<Class<?>> getAncestry(Class<T> c) {
final ConcurrentMap<Class<?>, List<Class<?>>> cache = getClassAncestryCache();
while (true) {
List<Class<?>> cachedResult = cache.get(c);
if (cachedResult != null) {
return cachedResult;
}
cache.putIfAbsent(c, computeAncestry(c));
}
}
/**
* computeAncestry, starting with children and going back to parents
*/
private static List<Class<?>> computeAncestry(Class<?> c) {
final List<Class<?>> result = new ArrayList<>();
result.add(Object.class);
computeAncestry(c, result);
Collections.reverse(result);
return unmodifiableList(new ArrayList<>(result));
}
private static <T> void computeAncestry(Class<T> c, List<Class<?>> result) {
if ((c == null) || (c == Object.class)) {
return;
}
// first interfaces (looks backwards but is not)
Class<?>[] interfaces = c.getInterfaces();
for (int i = interfaces.length - 1; i >= 0; i--) {
computeAncestry(interfaces[i], result);
}
// next superclass
computeAncestry(c.getSuperclass(), result);
if (!result.contains(c))
result.add(c);
}
/**
* classAncestryCache
*/
private static ConcurrentMap<Class<?>, List<Class<?>>> getClassAncestryCache() {
return (_ancestryCache);
}
private static final ConcurrentMap<Class<?>, List<Class<?>>> _ancestryCache = newHashMap();
}

View File

@ -1,100 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// ClassMap.java
package com.massivecraft.massivecore.xlib.bson.util;
import java.util.List;
import java.util.Map;
/**
* Maps Class objects to values. A ClassMap is different from a regular Map in
* that get(c) does not only look to see if 'c' is a key in the Map, but also
* walks the up superclass and interface graph of 'c' to find matches. Derived
* matches of this sort are then "cached" in the registry so that matches are
* faster on future gets.
*
* This is a very useful class for Class based registries.
*
* Example:
*
* ClassMap<String> m = new ClassMap<String>(); m.put(Animal.class, "Animal");
* m.put(Fox.class, "Fox"); m.Fox.class) --> "Fox" m.get(Dog.class) --> "Animal"
*
* (assuming Dog.class &lt; Animal.class)
*/
public class ClassMap<T> {
/**
* Walks superclass and interface graph, superclasses first, then
* interfaces, to compute an ancestry list. Supertypes are visited left to
* right. Duplicates are removed such that no Class will appear in the list
* before one of its subtypes.
*/
public static <T> List<Class<?>> getAncestry(Class<T> c) {
return ClassAncestry.getAncestry(c);
}
private final class ComputeFunction implements Function<Class<?>, T> {
@Override
public T apply(Class<?> a) {
for (Class<?> cls : getAncestry(a)) {
T result = map.get(cls);
if (result != null) {
return result;
}
}
return null;
}
}
private final Map<Class<?>, T> map = CopyOnWriteMap.newHashMap();
private final Map<Class<?>, T> cache = ComputingMap.create(new ComputeFunction());
public T get(Object key) {
return cache.get(key);
}
public T put(Class<?> key, T value) {
try {
return map.put(key, value);
} finally {
cache.clear();
}
}
public T remove(Object key) {
try {
return map.remove(key);
} finally {
cache.clear();
}
}
public void clear() {
map.clear();
cache.clear();
}
public int size() {
return map.size();
}
public boolean isEmpty() {
return map.isEmpty();
}
}

View File

@ -1,125 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson.util;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import static com.massivecraft.massivecore.xlib.bson.util.Assertions.notNull;
@SuppressWarnings({"unchecked", "deprecation"})
final class ComputingMap<K, V> implements Map<K, V>, Function<K, V> {
public static <K, V> Map<K, V> create(Function<K, V> function) {
return new ComputingMap<>(CopyOnWriteMap.<K, V>newHashMap(), function);
}
private final ConcurrentMap<K, V> map;
private final Function<K, V> function;
ComputingMap(ConcurrentMap<K, V> map, Function<K, V> function) {
this.map = notNull("map", map);
this.function = notNull("function", function);
}
public V get(Object key) {
while (true) {
V v = map.get(key);
if (v != null)
return v;
K k = (K) key;
V value = function.apply(k);
if (value == null)
return null;
map.putIfAbsent(k, value);
}
}
public V apply(K k) {
return get(k);
}
public V putIfAbsent(K key, V value) {
return map.putIfAbsent(key, value);
}
public boolean remove(Object key, Object value) {
return map.remove(key, value);
}
public boolean replace(K key, V oldValue, V newValue) {
return map.replace(key, oldValue, newValue);
}
public V replace(K key, V value) {
return map.replace(key, value);
}
public int size() {
return map.size();
}
public boolean isEmpty() {
return map.isEmpty();
}
public boolean containsKey(Object key) {
return map.containsKey(key);
}
public boolean containsValue(Object value) {
return map.containsValue(value);
}
public V put(K key, V value) {
return map.put(key, value);
}
public V remove(Object key) {
return map.remove(key);
}
public void putAll(Map<? extends K, ? extends V> m) {
map.putAll(m);
}
public void clear() {
map.clear();
}
public Set<K> keySet() {
return map.keySet();
}
public Collection<V> values() {
return map.values();
}
public Set<java.util.Map.Entry<K, V>> entrySet() {
return map.entrySet();
}
public boolean equals(Object o) {
return map.equals(o);
}
public int hashCode() {
return map.hashCode();
}
}

View File

@ -1,273 +0,0 @@
/*
* Copyright (c) 2008 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson.util;
import com.massivecraft.massivecore.xlib.bson.util.AbstractCopyOnWriteMap.View.Type;
import com.massivecraft.massivecore.xlib.bson.util.annotations.GuardedBy;
import com.massivecraft.massivecore.xlib.bson.util.annotations.ThreadSafe;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.WeakHashMap;
/**
* A thread-safe variant of {@link Map} in which all mutative operations (the
* "destructive" operations described by {@link Map} put, remove and so on) are
* implemented by making a fresh copy of the underlying map.
* <p>
* This is ordinarily too costly, but may be <em>more</em> efficient than
* alternatives when traversal operations vastly out-number mutations, and is
* useful when you cannot or don't want to synchronize traversals, yet need to
* preclude interference among concurrent threads. The "snapshot" style
* iterators on the collections returned by {@link #entrySet()},
* {@link #keySet()} and {@link #values()} use a reference to the internal map
* at the point that the iterator was created. This map never changes during the
* lifetime of the iterator, so interference is impossible and the iterator is
* guaranteed not to throw <tt>ConcurrentModificationException</tt>. The
* iterators will not reflect additions, removals, or changes to the list since
* the iterator was created. Removing elements via these iterators is not
* supported. The mutable operations on these collections (remove, retain etc.)
* are supported but as with the {@link Map} interface, add and addAll are not
* and throw {@link UnsupportedOperationException}.
* <p>
* The actual copy is performed by an abstract {@link #copy(Map)} method. The
* method is responsible for the underlying Map implementation (for instance a
* {@link HashMap}, {@link TreeMap}, {@link LinkedHashMap} etc.) and therefore
* the semantics of what this map will cope with as far as null keys and values,
* iteration ordering etc. See the note below about suitable candidates for
* underlying Map implementations
* <p>
* There are supplied implementations for the common j.u.c {@link Map}
* implementations via the {@link CopyOnWriteMap} static {@link Builder}.
* <p>
* Collection views of the keys, values and entries are optionally
* {@link View.Type.LIVE live} or {@link View.Type.STABLE stable}. Live views
* are modifiable will cause a copy if a modifying method is called on them.
* Methods on these will reflect the current state of the collection, although
* iterators will be snapshot style. If the collection views are stable they are
* unmodifiable, and will be a snapshot of the state of the map at the time the
* collection was asked for.
* <p>
* <strong>Please note</strong> that the thread-safety guarantees are limited to
* the thread-safety of the non-mutative (non-destructive) operations of the
* underlying map implementation. For instance some implementations such as
* {@link WeakHashMap} and {@link LinkedHashMap} with access ordering are
* actually structurally modified by the {@link #get(Object)} method and are
* therefore not suitable candidates as delegates for this class.
*
* @param <K> the key type
* @param <V> the value type
* @author Jed Wesley-Smith
*/
@ThreadSafe
@SuppressWarnings({"deprecation"})
abstract class CopyOnWriteMap<K, V> extends AbstractCopyOnWriteMap<K, V, Map<K, V>> {
private static final long serialVersionUID = 7935514534647505917L;
/**
* Get a {@link Builder} for a {@link CopyOnWriteMap} instance.
*
* @param <K> key type
* @param <V> value type
* @return a fresh builder
*/
public static <K, V> Builder<K, V> builder() {
return new Builder<>();
}
/**
* 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<>();
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<>(initialValues, viewType);
}
public CopyOnWriteMap<K, V> newLinkedMap() {
return new Linked<>(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<>(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<>(map);
}
}
}

View File

@ -1,21 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson.util;
interface Function<A, B> {
B apply(A a);
}

View File

@ -1,62 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// SimplePool.java
package com.massivecraft.massivecore.xlib.bson.util;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
*/
@Deprecated
public abstract class SimplePool<T> {
public SimplePool( int max ){
_max = max;
}
public SimplePool(){
_max = 1000;
}
protected abstract T createNew();
protected boolean ok( T t ){
return true;
}
public T get(){
T t = _stored.poll();
if ( t != null )
return t;
return createNew();
}
public void done( T t ){
if ( ! ok( t ) )
return;
if ( _stored.size() > _max )
return;
_stored.add( t );
}
final int _max;
private Queue<T> _stored = new ConcurrentLinkedQueue<>();
}

View File

@ -1,131 +0,0 @@
/*
* Copyright (c) 2008-2014 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.bson.util;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
public class StringRangeSet implements Set<String> {
private final int size;
private final static int NUMSTR_LEN = 100;
private final static String[] NUMSTRS = new String[100];
static {
for (int i = 0; i < NUMSTR_LEN; ++i)
NUMSTRS[i] = String.valueOf(i);
}
public StringRangeSet(int size) {
this.size = size;
}
public int size() {
return size;
}
public Iterator<String> iterator() {
return new Iterator<String>() {
int index = 0;
public boolean hasNext() {
return index < size;
}
public String next() {
if (index < NUMSTR_LEN)
return NUMSTRS[index++];
return String.valueOf(index++);
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
@Override
public boolean add(String e) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(Collection<? extends String> c) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public boolean contains(Object o) {
int t = Integer.parseInt(String.valueOf(o));
return t >= 0 && t < size;
}
@Override
public boolean containsAll(Collection<?> c) {
for (Object o : c) {
if (!contains(o)) {
return false;
}
}
return true;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
@Override
public Object[] toArray() {
String[] array = new String[size()];
for (int i = 0; i < size; ++i) {
if (i < NUMSTR_LEN) {
array[i] = NUMSTRS[i];
} else {
array[i] = String.valueOf(i);
}
}
return array;
}
@Override
public <T> T[] toArray(T[] a) {
throw new UnsupportedOperationException();
}
}

View File

@ -1,57 +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>
*
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
*/
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Deprecated
public @interface GuardedBy {
String value();
}

View File

@ -1,42 +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.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* The class to which this annotation is applied is immutable. This means that
* its state cannot be seen to change by callers, which implies that
* <ul>
* <li> all public fields are final, </li>
* <li> all public final reference fields refer to other immutable objects, and </li>
* <li> constructors and methods do not publish references to any internal state
* which is potentially mutable by the implementation. </li>
* </ul>
* Immutable objects may still have internal mutable state for purposes of performance
* optimization; some state variables may be lazily computed, so long as they are computed
* from immutable state and that callers cannot tell the difference.
* <p>
* Immutable objects are inherently thread-safe; they may be passed between threads or
* published without synchronization.
*
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
*/
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Deprecated
public @interface Immutable {
}

View File

@ -1,34 +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.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* The class to which this annotation is applied is not thread-safe.
* This annotation primarily exists for clarifying the non-thread-safety of a class
* that might otherwise be assumed to be thread-safe, despite the fact that it is a bad
* idea to assume a class is thread-safe without good reason.
* @see ThreadSafe
*
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
*/
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Deprecated
public @interface NotThreadSafe {
}

View File

@ -1,33 +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.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* The class to which this annotation is applied is thread-safe. This means that
* no sequences of accesses (reads and writes to public fields, calls to public methods)
* may put the object into an invalid state, regardless of the interleaving of those actions
* by the runtime, and without requiring any additional synchronization or coordination on the
* part of the caller.
* @deprecated This class is NOT a part of public API and will be dropped in 3.x versions.
*/
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Deprecated
public @interface ThreadSafe {
}

View File

@ -1,18 +0,0 @@
<!--
~ Copyright (c) 2008-2014 MongoDB, Inc.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<body>
<p>Misc utils used by BSON.</p>
</body>

View File

@ -1,118 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
import com.massivecraft.massivecore.xlib.gson.internal.bind.util.ISO8601Utils;
import java.lang.reflect.Type;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
/**
* This type adapter supports three subclasses of date: Date, Timestamp, and
* java.sql.Date.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
final class DefaultDateTypeAdapter implements JsonSerializer<Date>, JsonDeserializer<Date> {
// TODO: migrate to streaming adapter
private final DateFormat enUsFormat;
private final DateFormat localFormat;
DefaultDateTypeAdapter() {
this(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US),
DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT));
}
DefaultDateTypeAdapter(String datePattern) {
this(new SimpleDateFormat(datePattern, Locale.US), new SimpleDateFormat(datePattern));
}
DefaultDateTypeAdapter(int style) {
this(DateFormat.getDateInstance(style, Locale.US), DateFormat.getDateInstance(style));
}
public DefaultDateTypeAdapter(int dateStyle, int timeStyle) {
this(DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.US),
DateFormat.getDateTimeInstance(dateStyle, timeStyle));
}
DefaultDateTypeAdapter(DateFormat enUsFormat, DateFormat localFormat) {
this.enUsFormat = enUsFormat;
this.localFormat = localFormat;
}
// These methods need to be synchronized since JDK DateFormat classes are not thread-safe
// See issue 162
@Override
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
synchronized (localFormat) {
String dateFormatAsString = enUsFormat.format(src);
return new JsonPrimitive(dateFormatAsString);
}
}
@Override
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
if (!(json instanceof JsonPrimitive)) {
throw new JsonParseException("The date should be a string value");
}
Date date = deserializeToDate(json);
if (typeOfT == Date.class) {
return date;
} else if (typeOfT == Timestamp.class) {
return new Timestamp(date.getTime());
} else if (typeOfT == java.sql.Date.class) {
return new java.sql.Date(date.getTime());
} else {
throw new IllegalArgumentException(getClass() + " cannot deserialize to " + typeOfT);
}
}
private Date deserializeToDate(JsonElement json) {
synchronized (localFormat) {
try {
return localFormat.parse(json.getAsString());
} catch (ParseException ignored) {}
try {
return enUsFormat.parse(json.getAsString());
} catch (ParseException ignored) {}
try {
return ISO8601Utils.parse(json.getAsString(), new ParsePosition(0));
} catch (ParseException e) {
throw new JsonSyntaxException(json.getAsString(), e);
}
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(DefaultDateTypeAdapter.class.getSimpleName());
sb.append('(').append(localFormat.getClass().getSimpleName()).append(')');
return sb.toString();
}
}

View File

@ -1,109 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
/**
* A strategy (or policy) definition that is used to decide whether or not a field or top-level
* class should be serialized or deserialized as part of the JSON output/input. For serialization,
* if the {@link #shouldSkipClass(Class)} method returns true then that class or field type
* will not be part of the JSON output. For deserialization, if {@link #shouldSkipClass(Class)}
* returns true, then it will not be set as part of the Java object structure.
*
* <p>The following are a few examples that shows how you can use this exclusion mechanism.
*
* <p><strong>Exclude fields and objects based on a particular class type:</strong>
* <pre class="code">
* private static class SpecificClassExclusionStrategy implements ExclusionStrategy {
* private final Class&lt;?&gt; excludedThisClass;
*
* public SpecificClassExclusionStrategy(Class&lt;?&gt; excludedThisClass) {
* this.excludedThisClass = excludedThisClass;
* }
*
* public boolean shouldSkipClass(Class&lt;?&gt; clazz) {
* return excludedThisClass.equals(clazz);
* }
*
* public boolean shouldSkipField(FieldAttributes f) {
* return excludedThisClass.equals(f.getDeclaredClass());
* }
* }
* </pre>
*
* <p><strong>Excludes fields and objects based on a particular annotation:</strong>
* <pre class="code">
* public &#64interface FooAnnotation {
* // some implementation here
* }
*
* // Excludes any field (or class) that is tagged with an "&#64FooAnnotation"
* private static class FooAnnotationExclusionStrategy implements ExclusionStrategy {
* public boolean shouldSkipClass(Class&lt;?&gt; clazz) {
* return clazz.getAnnotation(FooAnnotation.class) != null;
* }
*
* public boolean shouldSkipField(FieldAttributes f) {
* return f.getAnnotation(FooAnnotation.class) != null;
* }
* }
* </pre>
*
* <p>Now if you want to configure {@code Gson} to use a user defined exclusion strategy, then
* the {@code GsonBuilder} is required. The following is an example of how you can use the
* {@code GsonBuilder} to configure Gson to use one of the above sample:
* <pre class="code">
* ExclusionStrategy excludeStrings = new UserDefinedExclusionStrategy(String.class);
* Gson gson = new GsonBuilder()
* .setExclusionStrategies(excludeStrings)
* .create();
* </pre>
*
* <p>For certain model classes, you may only want to serialize a field, but exclude it for
* deserialization. To do that, you can write an {@code ExclusionStrategy} as per normal;
* however, you would register it with the
* {@link GsonBuilder#addDeserializationExclusionStrategy(ExclusionStrategy)} method.
* For example:
* <pre class="code">
* ExclusionStrategy excludeStrings = new UserDefinedExclusionStrategy(String.class);
* Gson gson = new GsonBuilder()
* .addDeserializationExclusionStrategy(excludeStrings)
* .create();
* </pre>
*
* @author Inderjeet Singh
* @author Joel Leitch
*
* @see GsonBuilder#setExclusionStrategies(ExclusionStrategy...)
* @see GsonBuilder#addDeserializationExclusionStrategy(ExclusionStrategy)
* @see GsonBuilder#addSerializationExclusionStrategy(ExclusionStrategy)
*
* @since 1.4
*/
public interface ExclusionStrategy {
/**
* @param f the field object that is under test
* @return true if the field should be ignored; otherwise false
*/
public boolean shouldSkipField(FieldAttributes f);
/**
* @param clazz the class object that is under test
* @return true if the class should be ignored; otherwise false
*/
public boolean shouldSkipClass(Class<?> clazz);
}

View File

@ -1,158 +0,0 @@
/*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
import com.massivecraft.massivecore.xlib.gson.internal.$Gson$Preconditions;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collection;
/**
* A data object that stores attributes of a field.
*
* <p>This class is immutable; therefore, it can be safely shared across threads.
*
* @author Inderjeet Singh
* @author Joel Leitch
*
* @since 1.4
*/
public final class FieldAttributes {
private final Field field;
/**
* Constructs a Field Attributes object from the {@code f}.
*
* @param f the field to pull attributes from
*/
public FieldAttributes(Field f) {
$Gson$Preconditions.checkNotNull(f);
this.field = f;
}
/**
* @return the declaring class that contains this field
*/
public Class<?> getDeclaringClass() {
return field.getDeclaringClass();
}
/**
* @return the name of the field
*/
public String getName() {
return field.getName();
}
/**
* <p>For example, assume the following class definition:
* <pre class="code">
* public class Foo {
* private String bar;
* private List&lt;String&gt; red;
* }
*
* Type listParameterizedType = new TypeToken&lt;List&lt;String&gt;&gt;() {}.getType();
* </pre>
*
* <p>This method would return {@code String.class} for the {@code bar} field and
* {@code listParameterizedType} for the {@code red} field.
*
* @return the specific type declared for this field
*/
public Type getDeclaredType() {
return field.getGenericType();
}
/**
* Returns the {@code Class} object that was declared for this field.
*
* <p>For example, assume the following class definition:
* <pre class="code">
* public class Foo {
* private String bar;
* private List&lt;String&gt; red;
* }
* </pre>
*
* <p>This method would return {@code String.class} for the {@code bar} field and
* {@code List.class} for the {@code red} field.
*
* @return the specific class object that was declared for the field
*/
public Class<?> getDeclaredClass() {
return field.getType();
}
/**
* Return the {@code T} annotation object from this field if it exist; otherwise returns
* {@code null}.
*
* @param annotation the class of the annotation that will be retrieved
* @return the annotation instance if it is bound to the field; otherwise {@code null}
*/
public <T extends Annotation> T getAnnotation(Class<T> annotation) {
return field.getAnnotation(annotation);
}
/**
* Return the annotations that are present on this field.
*
* @return an array of all the annotations set on the field
* @since 1.4
*/
public Collection<Annotation> getAnnotations() {
return Arrays.asList(field.getAnnotations());
}
/**
* Returns {@code true} if the field is defined with the {@code modifier}.
*
* <p>This method is meant to be called as:
* <pre class="code">
* boolean hasPublicModifier = fieldAttribute.hasModifier(java.lang.reflect.Modifier.PUBLIC);
* </pre>
*
* @see java.lang.reflect.Modifier
*/
public boolean hasModifier(int modifier) {
return (field.getModifiers() & modifier) != 0;
}
/**
* This is exposed internally only for the removing synthetic fields from the JSON output.
*
* @return true if the field is synthetic; otherwise false
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
Object get(Object instance) throws IllegalAccessException {
return field.get(instance);
}
/**
* This is exposed internally only for the removing synthetic fields from the JSON output.
*
* @return true if the field is synthetic; otherwise false
*/
boolean isSynthetic() {
return field.isSynthetic();
}
}

View File

@ -1,169 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
import java.lang.reflect.Field;
import java.util.Locale;
/**
* An enumeration that defines a few standard naming conventions for JSON field names.
* This enumeration should be used in conjunction with {@link GsonBuilder}
* to configure a {@link Gson} instance to properly translate Java field
* names into the desired JSON field names.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public enum FieldNamingPolicy implements FieldNamingStrategy {
/**
* Using this naming policy with Gson will ensure that the field name is
* unchanged.
*/
IDENTITY() {
@Override public String translateName(Field f) {
return f.getName();
}
},
/**
* Using this naming policy with Gson will ensure that the first "letter" of the Java
* field name is capitalized when serialized to its JSON form.
*
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
* <ul>
* <li>someFieldName ---> SomeFieldName</li>
* <li>_someFieldName ---> _SomeFieldName</li>
* </ul>
*/
UPPER_CAMEL_CASE() {
@Override public String translateName(Field f) {
return upperCaseFirstLetter(f.getName());
}
},
/**
* Using this naming policy with Gson will ensure that the first "letter" of the Java
* field name is capitalized when serialized to its JSON form and the words will be
* separated by a space.
*
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
* <ul>
* <li>someFieldName ---> Some Field Name</li>
* <li>_someFieldName ---> _Some Field Name</li>
* </ul>
*
* @since 1.4
*/
UPPER_CAMEL_CASE_WITH_SPACES() {
@Override public String translateName(Field f) {
return upperCaseFirstLetter(separateCamelCase(f.getName(), " "));
}
},
/**
* Using this naming policy with Gson will modify the Java Field name from its camel cased
* form to a lower case field name where each word is separated by an underscore (_).
*
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
* <ul>
* <li>someFieldName ---> some_field_name</li>
* <li>_someFieldName ---> _some_field_name</li>
* <li>aStringField ---> a_string_field</li>
* <li>aURL ---> a_u_r_l</li>
* </ul>
*/
LOWER_CASE_WITH_UNDERSCORES() {
@Override public String translateName(Field f) {
return separateCamelCase(f.getName(), "_").toLowerCase(Locale.ENGLISH);
}
},
/**
* Using this naming policy with Gson will modify the Java Field name from its camel cased
* form to a lower case field name where each word is separated by a dash (-).
*
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
* <ul>
* <li>someFieldName ---> some-field-name</li>
* <li>_someFieldName ---> _some-field-name</li>
* <li>aStringField ---> a-string-field</li>
* <li>aURL ---> a-u-r-l</li>
* </ul>
* Using dashes in JavaScript is not recommended since dash is also used for a minus sign in
* expressions. This requires that a field named with dashes is always accessed as a quoted
* property like {@code myobject['my-field']}. Accessing it as an object field
* {@code myobject.my-field} will result in an unintended javascript expression.
* @since 1.4
*/
LOWER_CASE_WITH_DASHES() {
@Override public String translateName(Field f) {
return separateCamelCase(f.getName(), "-").toLowerCase(Locale.ENGLISH);
}
};
/**
* Converts the field name that uses camel-case define word separation into
* separate words that are separated by the provided {@code separatorString}.
*/
static String separateCamelCase(String name, String separator) {
StringBuilder translation = new StringBuilder();
for (int i = 0; i < name.length(); i++) {
char character = name.charAt(i);
if (Character.isUpperCase(character) && translation.length() != 0) {
translation.append(separator);
}
translation.append(character);
}
return translation.toString();
}
/**
* Ensures the JSON field names begins with an upper case letter.
*/
static String upperCaseFirstLetter(String name) {
StringBuilder fieldNameBuilder = new StringBuilder();
int index = 0;
char firstCharacter = name.charAt(index);
while (index < name.length() - 1) {
if (Character.isLetter(firstCharacter)) {
break;
}
fieldNameBuilder.append(firstCharacter);
firstCharacter = name.charAt(++index);
}
if (index == name.length()) {
return fieldNameBuilder.toString();
}
if (!Character.isUpperCase(firstCharacter)) {
String modifiedTarget = modifyString(Character.toUpperCase(firstCharacter), name, ++index);
return fieldNameBuilder.append(modifiedTarget).toString();
} else {
return name;
}
}
private static String modifyString(char firstCharacter, String srcString, int indexOfSubstring) {
return (indexOfSubstring < srcString.length())
? firstCharacter + srcString.substring(indexOfSubstring)
: String.valueOf(firstCharacter);
}
}

View File

@ -1,40 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
import java.lang.reflect.Field;
/**
* A mechanism for providing custom field naming in Gson. This allows the client code to translate
* field names into a particular convention that is not supported as a normal Java field
* declaration rules. For example, Java does not support "-" characters in a field name.
*
* @author Inderjeet Singh
* @author Joel Leitch
* @since 1.3
*/
public interface FieldNamingStrategy {
/**
* Translates the field name into its JSON field name representation.
*
* @param f the field object that we are translating
* @return the translated field name.
* @since 1.3
*/
public String translateName(Field f);
}

View File

@ -1,971 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
import com.massivecraft.massivecore.xlib.gson.annotations.Expose;
import com.massivecraft.massivecore.xlib.gson.annotations.Since;
import com.massivecraft.massivecore.xlib.gson.internal.ConstructorConstructor;
import com.massivecraft.massivecore.xlib.gson.internal.Excluder;
import com.massivecraft.massivecore.xlib.gson.internal.Primitives;
import com.massivecraft.massivecore.xlib.gson.internal.Streams;
import com.massivecraft.massivecore.xlib.gson.internal.bind.*;
import com.massivecraft.massivecore.xlib.gson.reflect.TypeToken;
import com.massivecraft.massivecore.xlib.gson.stream.JsonReader;
import com.massivecraft.massivecore.xlib.gson.stream.JsonToken;
import com.massivecraft.massivecore.xlib.gson.stream.JsonWriter;
import com.massivecraft.massivecore.xlib.gson.stream.MalformedJsonException;
import java.io.*;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicLongArray;
/**
* This is the main class for using Gson. Gson is typically used by first constructing a
* Gson instance and then invoking {@link #toJson(Object)} or {@link #fromJson(String, Class)}
* methods on it. Gson instances are Thread-safe so you can reuse them freely across multiple
* threads.
*
* <p>You can create a Gson instance by invoking {@code new Gson()} if the default configuration
* is all you need. You can also use {@link GsonBuilder} to build a Gson instance with various
* configuration options such as versioning support, pretty printing, custom
* {@link JsonSerializer}s, {@link JsonDeserializer}s, and {@link InstanceCreator}s.</p>
*
* <p>Here is an example of how Gson is used for a simple Class:
*
* <pre>
* Gson gson = new Gson(); // Or use new GsonBuilder().create();
* MyType target = new MyType();
* String json = gson.toJson(target); // serializes target to Json
* MyType target2 = gson.fromJson(json, MyType.class); // deserializes json into target2
* </pre></p>
*
* <p>If the object that your are serializing/deserializing is a {@code ParameterizedType}
* (i.e. contains at least one type parameter and may be an array) then you must use the
* {@link #toJson(Object, Type)} or {@link #fromJson(String, Type)} method. Here is an
* example for serializing and deserializing a {@code ParameterizedType}:
*
* <pre>
* Type listType = new TypeToken&lt;List&lt;String&gt;&gt;() {}.getType();
* List&lt;String&gt; target = new LinkedList&lt;String&gt;();
* target.add("blah");
*
* Gson gson = new Gson();
* String json = gson.toJson(target, listType);
* List&lt;String&gt; target2 = gson.fromJson(json, listType);
* </pre></p>
*
* <p>See the <a href="https://sites.google.com/site/gson/gson-user-guide">Gson User Guide</a>
* for a more complete set of examples.</p>
*
* @see TypeToken
*
* @author Inderjeet Singh
* @author Joel Leitch
* @author Jesse Wilson
*/
public final class Gson {
static final boolean DEFAULT_JSON_NON_EXECUTABLE = false;
static final boolean DEFAULT_LENIENT = false;
static final boolean DEFAULT_PRETTY_PRINT = false;
static final boolean DEFAULT_ESCAPE_HTML = true;
static final boolean DEFAULT_SERIALIZE_NULLS = false;
static final boolean DEFAULT_COMPLEX_MAP_KEYS = false;
static final boolean DEFAULT_SPECIALIZE_FLOAT_VALUES = false;
private static final TypeToken<?> NULL_KEY_SURROGATE = new TypeToken<Object>() {};
private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n";
/**
* This thread local guards against reentrant calls to getAdapter(). In
* certain object graphs, creating an adapter for a type may recursively
* require an adapter for the same type! Without intervention, the recursive
* lookup would stack overflow. We cheat by returning a proxy type adapter.
* The proxy is wired up once the initial adapter has been created.
*/
private final ThreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>> calls
= new ThreadLocal<>();
private final Map<TypeToken<?>, TypeAdapter<?>> typeTokenCache = new ConcurrentHashMap<>();
private final List<TypeAdapterFactory> factories;
private final ConstructorConstructor constructorConstructor;
private final Excluder excluder;
private final FieldNamingStrategy fieldNamingStrategy;
private final boolean serializeNulls;
private final boolean htmlSafe;
private final boolean generateNonExecutableJson;
private final boolean prettyPrinting;
private final boolean lenient;
private final JsonAdapterAnnotationTypeAdapterFactory jsonAdapterFactory;
/**
* Constructs a Gson object with default configuration. The default configuration has the
* following settings:
* <ul>
* <li>The JSON generated by <code>toJson</code> methods is in compact representation. This
* means that all the unneeded white-space is removed. You can change this behavior with
* {@link GsonBuilder#setPrettyPrinting()}. </li>
* <li>The generated JSON omits all the fields that are null. Note that nulls in arrays are
* kept as is since an array is an ordered list. Moreover, if a field is not null, but its
* generated JSON is empty, the field is kept. You can configure Gson to serialize null values
* by setting {@link GsonBuilder#serializeNulls()}.</li>
* <li>Gson provides default serialization and deserialization for Enums, {@link Map},
* {@link java.net.URL}, {@link java.net.URI}, {@link java.util.Locale}, {@link java.util.Date},
* {@link java.math.BigDecimal}, and {@link java.math.BigInteger} classes. If you would prefer
* to change the default representation, you can do so by registering a type adapter through
* {@link GsonBuilder#registerTypeAdapter(Type, Object)}. </li>
* <li>The default Date format is same as {@link java.text.DateFormat#DEFAULT}. This format
* ignores the millisecond portion of the date during serialization. You can change
* this by invoking {@link GsonBuilder#setDateFormat(int)} or
* {@link GsonBuilder#setDateFormat(String)}. </li>
* <li>By default, Gson ignores the {@link Expose} annotation.
* You can enable Gson to serialize/deserialize only those fields marked with this annotation
* through {@link GsonBuilder#excludeFieldsWithoutExposeAnnotation()}. </li>
* <li>By default, Gson ignores the {@link Since} annotation. You
* can enable Gson to use this annotation through {@link GsonBuilder#setVersion(double)}.</li>
* <li>The default field naming policy for the output Json is same as in Java. So, a Java class
* field <code>versionNumber</code> will be output as <code>&quot;versionNumber&quot;</code> in
* Json. The same rules are applied for mapping incoming Json to the Java classes. You can
* change this policy through {@link GsonBuilder#setFieldNamingPolicy(FieldNamingPolicy)}.</li>
* <li>By default, Gson excludes <code>transient</code> or <code>static</code> fields from
* consideration for serialization and deserialization. You can change this behavior through
* {@link GsonBuilder#excludeFieldsWithModifiers(int...)}.</li>
* </ul>
*/
public Gson() {
this(Excluder.DEFAULT, FieldNamingPolicy.IDENTITY,
Collections.<Type, InstanceCreator<?>>emptyMap(), DEFAULT_SERIALIZE_NULLS,
DEFAULT_COMPLEX_MAP_KEYS, DEFAULT_JSON_NON_EXECUTABLE, DEFAULT_ESCAPE_HTML,
DEFAULT_PRETTY_PRINT, DEFAULT_LENIENT, DEFAULT_SPECIALIZE_FLOAT_VALUES,
LongSerializationPolicy.DEFAULT, Collections.<TypeAdapterFactory>emptyList());
}
Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingStrategy,
final Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues,
LongSerializationPolicy longSerializationPolicy,
List<TypeAdapterFactory> typeAdapterFactories) {
this.constructorConstructor = new ConstructorConstructor(instanceCreators);
this.excluder = excluder;
this.fieldNamingStrategy = fieldNamingStrategy;
this.serializeNulls = serializeNulls;
this.generateNonExecutableJson = generateNonExecutableGson;
this.htmlSafe = htmlSafe;
this.prettyPrinting = prettyPrinting;
this.lenient = lenient;
List<TypeAdapterFactory> factories = new ArrayList<>();
// built-in type adapters that cannot be overridden
factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
factories.add(ObjectTypeAdapter.FACTORY);
// the excluder must precede all adapters that handle user-defined types
factories.add(excluder);
// user's type adapters
factories.addAll(typeAdapterFactories);
// type adapters for basic platform types
factories.add(TypeAdapters.STRING_FACTORY);
factories.add(TypeAdapters.INTEGER_FACTORY);
factories.add(TypeAdapters.BOOLEAN_FACTORY);
factories.add(TypeAdapters.BYTE_FACTORY);
factories.add(TypeAdapters.SHORT_FACTORY);
TypeAdapter<Number> longAdapter = longAdapter(longSerializationPolicy);
factories.add(TypeAdapters.newFactory(long.class, Long.class, longAdapter));
factories.add(TypeAdapters.newFactory(double.class, Double.class,
doubleAdapter(serializeSpecialFloatingPointValues)));
factories.add(TypeAdapters.newFactory(float.class, Float.class,
floatAdapter(serializeSpecialFloatingPointValues)));
factories.add(TypeAdapters.NUMBER_FACTORY);
factories.add(TypeAdapters.ATOMIC_INTEGER_FACTORY);
factories.add(TypeAdapters.ATOMIC_BOOLEAN_FACTORY);
factories.add(TypeAdapters.newFactory(AtomicLong.class, atomicLongAdapter(longAdapter)));
factories.add(TypeAdapters.newFactory(AtomicLongArray.class, atomicLongArrayAdapter(longAdapter)));
factories.add(TypeAdapters.ATOMIC_INTEGER_ARRAY_FACTORY);
factories.add(TypeAdapters.CHARACTER_FACTORY);
factories.add(TypeAdapters.STRING_BUILDER_FACTORY);
factories.add(TypeAdapters.STRING_BUFFER_FACTORY);
factories.add(TypeAdapters.newFactory(BigDecimal.class, TypeAdapters.BIG_DECIMAL));
factories.add(TypeAdapters.newFactory(BigInteger.class, TypeAdapters.BIG_INTEGER));
factories.add(TypeAdapters.URL_FACTORY);
factories.add(TypeAdapters.URI_FACTORY);
factories.add(TypeAdapters.UUID_FACTORY);
factories.add(TypeAdapters.CURRENCY_FACTORY);
factories.add(TypeAdapters.LOCALE_FACTORY);
factories.add(TypeAdapters.INET_ADDRESS_FACTORY);
factories.add(TypeAdapters.BIT_SET_FACTORY);
factories.add(DateTypeAdapter.FACTORY);
factories.add(TypeAdapters.CALENDAR_FACTORY);
factories.add(TimeTypeAdapter.FACTORY);
factories.add(SqlDateTypeAdapter.FACTORY);
factories.add(TypeAdapters.TIMESTAMP_FACTORY);
factories.add(ArrayTypeAdapter.FACTORY);
factories.add(TypeAdapters.CLASS_FACTORY);
// type adapters for composite and user-defined types
factories.add(new CollectionTypeAdapterFactory(constructorConstructor));
factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));
this.jsonAdapterFactory = new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor);
factories.add(jsonAdapterFactory);
factories.add(TypeAdapters.ENUM_FACTORY);
factories.add(new ReflectiveTypeAdapterFactory(
constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory));
this.factories = Collections.unmodifiableList(factories);
}
public Excluder excluder() {
return excluder;
}
public FieldNamingStrategy fieldNamingStrategy() {
return fieldNamingStrategy;
}
public boolean serializeNulls() {
return serializeNulls;
}
public boolean htmlSafe() {
return htmlSafe;
}
private TypeAdapter<Number> doubleAdapter(boolean serializeSpecialFloatingPointValues) {
if (serializeSpecialFloatingPointValues) {
return TypeAdapters.DOUBLE;
}
return new TypeAdapter<Number>() {
@Override public Double read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
return in.nextDouble();
}
@Override public void write(JsonWriter out, Number value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
double doubleValue = value.doubleValue();
checkValidFloatingPoint(doubleValue);
out.value(value);
}
};
}
private TypeAdapter<Number> floatAdapter(boolean serializeSpecialFloatingPointValues) {
if (serializeSpecialFloatingPointValues) {
return TypeAdapters.FLOAT;
}
return new TypeAdapter<Number>() {
@Override public Float read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
return (float) in.nextDouble();
}
@Override public void write(JsonWriter out, Number value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
float floatValue = value.floatValue();
checkValidFloatingPoint(floatValue);
out.value(value);
}
};
}
static void checkValidFloatingPoint(double value) {
if (Double.isNaN(value) || Double.isInfinite(value)) {
throw new IllegalArgumentException(value
+ " is not a valid double value as per JSON specification. To override this"
+ " behavior, use GsonBuilder.serializeSpecialFloatingPointValues() method.");
}
}
private static TypeAdapter<Number> longAdapter(LongSerializationPolicy longSerializationPolicy) {
if (longSerializationPolicy == LongSerializationPolicy.DEFAULT) {
return TypeAdapters.LONG;
}
return new TypeAdapter<Number>() {
@Override public Number read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
return in.nextLong();
}
@Override public void write(JsonWriter out, Number value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
out.value(value.toString());
}
};
}
private static TypeAdapter<AtomicLong> atomicLongAdapter(final TypeAdapter<Number> longAdapter) {
return new TypeAdapter<AtomicLong>() {
@Override public void write(JsonWriter out, AtomicLong value) throws IOException {
longAdapter.write(out, value.get());
}
@Override public AtomicLong read(JsonReader in) throws IOException {
Number value = longAdapter.read(in);
return new AtomicLong(value.longValue());
}
}.nullSafe();
}
private static TypeAdapter<AtomicLongArray> atomicLongArrayAdapter(final TypeAdapter<Number> longAdapter) {
return new TypeAdapter<AtomicLongArray>() {
@Override public void write(JsonWriter out, AtomicLongArray value) throws IOException {
out.beginArray();
for (int i = 0, length = value.length(); i < length; i++) {
longAdapter.write(out, value.get(i));
}
out.endArray();
}
@Override public AtomicLongArray read(JsonReader in) throws IOException {
List<Long> list = new ArrayList<>();
in.beginArray();
while (in.hasNext()) {
long value = longAdapter.read(in).longValue();
list.add(value);
}
in.endArray();
int length = list.size();
AtomicLongArray array = new AtomicLongArray(length);
for (int i = 0; i < length; ++i) {
array.set(i, list.get(i));
}
return array;
}
}.nullSafe();
}
/**
* Returns the type adapter for {@code} type.
*
* @throws IllegalArgumentException if this GSON cannot serialize and
* deserialize {@code type}.
*/
@SuppressWarnings("unchecked")
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
if (cached != null) {
return (TypeAdapter<T>) cached;
}
Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();
boolean requiresThreadLocalCleanup = false;
if (threadCalls == null) {
threadCalls = new HashMap<>();
calls.set(threadCalls);
requiresThreadLocalCleanup = true;
}
// the key and value type parameters always agree
FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type);
if (ongoingCall != null) {
return ongoingCall;
}
try {
FutureTypeAdapter<T> call = new FutureTypeAdapter<>();
threadCalls.put(type, call);
for (TypeAdapterFactory factory : factories) {
TypeAdapter<T> candidate = factory.create(this, type);
if (candidate != null) {
call.setDelegate(candidate);
typeTokenCache.put(type, candidate);
return candidate;
}
}
throw new IllegalArgumentException("GSON cannot handle " + type);
} finally {
threadCalls.remove(type);
if (requiresThreadLocalCleanup) {
calls.remove();
}
}
}
/**
* This method is used to get an alternate type adapter for the specified type. This is used
* to access a type adapter that is overridden by a {@link TypeAdapterFactory} that you
* may have registered. This features is typically used when you want to register a type
* adapter that does a little bit of work but then delegates further processing to the Gson
* default type adapter. Here is an example:
* <p>Let's say we want to write a type adapter that counts the number of objects being read
* from or written to JSON. We can achieve this by writing a type adapter factory that uses
* the <code>getDelegateAdapter</code> method:
* <pre> {@code
* class StatsTypeAdapterFactory implements TypeAdapterFactory {
* public int numReads = 0;
* public int numWrites = 0;
* public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
* final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
* return new TypeAdapter<T>() {
* public void write(JsonWriter out, T value) throws IOException {
* ++numWrites;
* delegate.write(out, value);
* }
* public T read(JsonReader in) throws IOException {
* ++numReads;
* return delegate.read(in);
* }
* };
* }
* }
* } </pre>
* This factory can now be used like this:
* <pre> {@code
* StatsTypeAdapterFactory stats = new StatsTypeAdapterFactory();
* Gson gson = new GsonBuilder().registerTypeAdapterFactory(stats).create();
* // Call gson.toJson() and fromJson methods on objects
* System.out.println("Num JSON reads" + stats.numReads);
* System.out.println("Num JSON writes" + stats.numWrites);
* }</pre>
* Note that this call will skip all factories registered before {@code skipPast}. In case of
* multiple TypeAdapterFactories registered it is up to the caller of this function to insure
* that the order of registration does not prevent this method from reaching a factory they
* would expect to reply from this call.
* Note that since you can not override type adapter factories for String and Java primitive
* types, our stats factory will not count the number of String or primitives that will be
* read or written.
* @param skipPast The type adapter factory that needs to be skipped while searching for
* a matching type adapter. In most cases, you should just pass <i>this</i> (the type adapter
* factory from where {@link #getDelegateAdapter} method is being invoked).
* @param type Type for which the delegate adapter is being searched for.
*
* @since 2.2
*/
public <T> TypeAdapter<T> getDelegateAdapter(TypeAdapterFactory skipPast, TypeToken<T> type) {
// Hack. If the skipPast factory isn't registered, assume the factory is being requested via
// our @JsonAdapter annotation.
if (!factories.contains(skipPast)) {
skipPast = jsonAdapterFactory;
}
boolean skipPastFound = false;
for (TypeAdapterFactory factory : factories) {
if (!skipPastFound) {
if (factory == skipPast) {
skipPastFound = true;
}
continue;
}
TypeAdapter<T> candidate = factory.create(this, type);
if (candidate != null) {
return candidate;
}
}
throw new IllegalArgumentException("GSON cannot serialize " + type);
}
/**
* Returns the type adapter for {@code} type.
*
* @throws IllegalArgumentException if this GSON cannot serialize and
* deserialize {@code type}.
*/
public <T> TypeAdapter<T> getAdapter(Class<T> type) {
return getAdapter(TypeToken.get(type));
}
/**
* This method serializes the specified object into its equivalent representation as a tree of
* {@link JsonElement}s. This method should be used when the specified object is not a generic
* type. This method uses {@link Class#getClass()} to get the type for the specified object, but
* the {@code getClass()} loses the generic type information because of the Type Erasure feature
* of Java. Note that this method works fine if the any of the object fields are of generic type,
* just the object itself should not be of a generic type. If the object is of generic type, use
* {@link #toJsonTree(Object, Type)} instead.
*
* @param src the object for which Json representation is to be created setting for Gson
* @return Json representation of {@code src}.
* @since 1.4
*/
public JsonElement toJsonTree(Object src) {
if (src == null) {
return JsonNull.INSTANCE;
}
return toJsonTree(src, src.getClass());
}
/**
* This method serializes the specified object, including those of generic types, into its
* equivalent representation as a tree of {@link JsonElement}s. This method must be used if the
* specified object is a generic type. For non-generic objects, use {@link #toJsonTree(Object)}
* instead.
*
* @param src the object for which JSON representation is to be created
* @param typeOfSrc The specific genericized type of src. You can obtain
* this type by using the {@link TypeToken} class. For example,
* to get the type for {@code Collection<Foo>}, you should use:
* <pre>
* Type typeOfSrc = new TypeToken&lt;Collection&lt;Foo&gt;&gt;(){}.getType();
* </pre>
* @return Json representation of {@code src}
* @since 1.4
*/
public JsonElement toJsonTree(Object src, Type typeOfSrc) {
JsonTreeWriter writer = new JsonTreeWriter();
toJson(src, typeOfSrc, writer);
return writer.get();
}
/**
* This method serializes the specified object into its equivalent Json representation.
* This method should be used when the specified object is not a generic type. This method uses
* {@link Class#getClass()} to get the type for the specified object, but the
* {@code getClass()} loses the generic type information because of the Type Erasure feature
* of Java. Note that this method works fine if the any of the object fields are of generic type,
* just the object itself should not be of a generic type. If the object is of generic type, use
* {@link #toJson(Object, Type)} instead. If you want to write out the object to a
* {@link Writer}, use {@link #toJson(Object, Appendable)} instead.
*
* @param src the object for which Json representation is to be created setting for Gson
* @return Json representation of {@code src}.
*/
public String toJson(Object src) {
if (src == null) {
return toJson(JsonNull.INSTANCE);
}
return toJson(src, src.getClass());
}
/**
* This method serializes the specified object, including those of generic types, into its
* equivalent Json representation. This method must be used if the specified object is a generic
* type. For non-generic objects, use {@link #toJson(Object)} instead. If you want to write out
* the object to a {@link Appendable}, use {@link #toJson(Object, Type, Appendable)} instead.
*
* @param src the object for which JSON representation is to be created
* @param typeOfSrc The specific genericized type of src. You can obtain
* this type by using the {@link TypeToken} class. For example,
* to get the type for {@code Collection<Foo>}, you should use:
* <pre>
* Type typeOfSrc = new TypeToken&lt;Collection&lt;Foo&gt;&gt;(){}.getType();
* </pre>
* @return Json representation of {@code src}
*/
public String toJson(Object src, Type typeOfSrc) {
StringWriter writer = new StringWriter();
toJson(src, typeOfSrc, writer);
return writer.toString();
}
/**
* This method serializes the specified object into its equivalent Json representation.
* This method should be used when the specified object is not a generic type. This method uses
* {@link Class#getClass()} to get the type for the specified object, but the
* {@code getClass()} loses the generic type information because of the Type Erasure feature
* of Java. Note that this method works fine if the any of the object fields are of generic type,
* just the object itself should not be of a generic type. If the object is of generic type, use
* {@link #toJson(Object, Type, Appendable)} instead.
*
* @param src the object for which Json representation is to be created setting for Gson
* @param writer Writer to which the Json representation needs to be written
* @throws JsonIOException if there was a problem writing to the writer
* @since 1.2
*/
public void toJson(Object src, Appendable writer) throws JsonIOException {
if (src != null) {
toJson(src, src.getClass(), writer);
} else {
toJson(JsonNull.INSTANCE, writer);
}
}
/**
* This method serializes the specified object, including those of generic types, into its
* equivalent Json representation. This method must be used if the specified object is a generic
* type. For non-generic objects, use {@link #toJson(Object, Appendable)} instead.
*
* @param src the object for which JSON representation is to be created
* @param typeOfSrc The specific genericized type of src. You can obtain
* this type by using the {@link TypeToken} class. For example,
* to get the type for {@code Collection<Foo>}, you should use:
* <pre>
* Type typeOfSrc = new TypeToken&lt;Collection&lt;Foo&gt;&gt;(){}.getType();
* </pre>
* @param writer Writer to which the Json representation of src needs to be written.
* @throws JsonIOException if there was a problem writing to the writer
* @since 1.2
*/
public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOException {
try {
JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer));
toJson(src, typeOfSrc, jsonWriter);
} catch (IOException e) {
throw new JsonIOException(e);
}
}
/**
* Writes the JSON representation of {@code src} of type {@code typeOfSrc} to
* {@code writer}.
* @throws JsonIOException if there was a problem writing to the writer
*/
@SuppressWarnings("unchecked")
public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException {
TypeAdapter<?> adapter = getAdapter(TypeToken.get(typeOfSrc));
boolean oldLenient = writer.isLenient();
writer.setLenient(true);
boolean oldHtmlSafe = writer.isHtmlSafe();
writer.setHtmlSafe(htmlSafe);
boolean oldSerializeNulls = writer.getSerializeNulls();
writer.setSerializeNulls(serializeNulls);
try {
((TypeAdapter<Object>) adapter).write(writer, src);
} catch (IOException e) {
throw new JsonIOException(e);
} finally {
writer.setLenient(oldLenient);
writer.setHtmlSafe(oldHtmlSafe);
writer.setSerializeNulls(oldSerializeNulls);
}
}
/**
* Converts a tree of {@link JsonElement}s into its equivalent JSON representation.
*
* @param jsonElement root of a tree of {@link JsonElement}s
* @return JSON String representation of the tree
* @since 1.4
*/
public String toJson(JsonElement jsonElement) {
StringWriter writer = new StringWriter();
toJson(jsonElement, writer);
return writer.toString();
}
/**
* Writes out the equivalent JSON for a tree of {@link JsonElement}s.
*
* @param jsonElement root of a tree of {@link JsonElement}s
* @param writer Writer to which the Json representation needs to be written
* @throws JsonIOException if there was a problem writing to the writer
* @since 1.4
*/
public void toJson(JsonElement jsonElement, Appendable writer) throws JsonIOException {
try {
JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer));
toJson(jsonElement, jsonWriter);
} catch (IOException e) {
throw new JsonIOException(e);
}
}
/**
* Returns a new JSON writer configured for the settings on this Gson instance.
*/
public JsonWriter newJsonWriter(Writer writer) throws IOException {
if (generateNonExecutableJson) {
writer.write(JSON_NON_EXECUTABLE_PREFIX);
}
JsonWriter jsonWriter = new JsonWriter(writer);
if (prettyPrinting) {
jsonWriter.setIndent(" ");
}
jsonWriter.setSerializeNulls(serializeNulls);
return jsonWriter;
}
/**
* Returns a new JSON reader configured for the settings on this Gson instance.
*/
public JsonReader newJsonReader(Reader reader) {
JsonReader jsonReader = new JsonReader(reader);
jsonReader.setLenient(lenient);
return jsonReader;
}
/**
* Writes the JSON for {@code jsonElement} to {@code writer}.
* @throws JsonIOException if there was a problem writing to the writer
*/
public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOException {
boolean oldLenient = writer.isLenient();
writer.setLenient(true);
boolean oldHtmlSafe = writer.isHtmlSafe();
writer.setHtmlSafe(htmlSafe);
boolean oldSerializeNulls = writer.getSerializeNulls();
writer.setSerializeNulls(serializeNulls);
try {
Streams.write(jsonElement, writer);
} catch (IOException e) {
throw new JsonIOException(e);
} finally {
writer.setLenient(oldLenient);
writer.setHtmlSafe(oldHtmlSafe);
writer.setSerializeNulls(oldSerializeNulls);
}
}
/**
* This method deserializes the specified Json into an object of the specified class. It is not
* suitable to use if the specified class is a generic type since it will not have the generic
* type information because of the Type Erasure feature of Java. Therefore, this method should not
* be used if the desired type is a generic type. Note that this method works fine if the any of
* the fields of the specified object are generics, just the object itself should not be a
* generic type. For the cases when the object is of generic type, invoke
* {@link #fromJson(String, Type)}. If you have the Json in a {@link Reader} instead of
* a String, use {@link #fromJson(Reader, Class)} instead.
*
* @param <T> the type of the desired object
* @param json the string from which the object is to be deserialized
* @param classOfT the class of T
* @return an object of type T from the string. Returns {@code null} if {@code json} is {@code null}.
* @throws JsonSyntaxException if json is not a valid representation for an object of type
* classOfT
*/
public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
Object object = fromJson(json, (Type) classOfT);
return Primitives.wrap(classOfT).cast(object);
}
/**
* This method deserializes the specified Json into an object of the specified type. This method
* is useful if the specified object is a generic type. For non-generic objects, use
* {@link #fromJson(String, Class)} instead. If you have the Json in a {@link Reader} instead of
* a String, use {@link #fromJson(Reader, Type)} instead.
*
* @param <T> the type of the desired object
* @param json the string from which the object is to be deserialized
* @param typeOfT The specific genericized type of src. You can obtain this type by using the
* {@link TypeToken} class. For example, to get the type for
* {@code Collection<Foo>}, you should use:
* <pre>
* Type typeOfT = new TypeToken&lt;Collection&lt;Foo&gt;&gt;(){}.getType();
* </pre>
* @return an object of type T from the string. Returns {@code null} if {@code json} is {@code null}.
* @throws JsonParseException if json is not a valid representation for an object of type typeOfT
* @throws JsonSyntaxException if json is not a valid representation for an object of type
*/
@SuppressWarnings("unchecked")
public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
if (json == null) {
return null;
}
StringReader reader = new StringReader(json);
T target = (T) fromJson(reader, typeOfT);
return target;
}
/**
* This method deserializes the Json read from the specified reader into an object of the
* specified class. It is not suitable to use if the specified class is a generic type since it
* will not have the generic type information because of the Type Erasure feature of Java.
* Therefore, this method should not be used if the desired type is a generic type. Note that
* this method works fine if the any of the fields of the specified object are generics, just the
* object itself should not be a generic type. For the cases when the object is of generic type,
* invoke {@link #fromJson(Reader, Type)}. If you have the Json in a String form instead of a
* {@link Reader}, use {@link #fromJson(String, Class)} instead.
*
* @param <T> the type of the desired object
* @param json the reader producing the Json from which the object is to be deserialized.
* @param classOfT the class of T
* @return an object of type T from the string. Returns {@code null} if {@code json} is at EOF.
* @throws JsonIOException if there was a problem reading from the Reader
* @throws JsonSyntaxException if json is not a valid representation for an object of type
* @since 1.2
*/
public <T> T fromJson(Reader json, Class<T> classOfT) throws JsonSyntaxException, JsonIOException {
JsonReader jsonReader = newJsonReader(json);
Object object = fromJson(jsonReader, classOfT);
assertFullConsumption(object, jsonReader);
return Primitives.wrap(classOfT).cast(object);
}
/**
* This method deserializes the Json read from the specified reader into an object of the
* specified type. This method is useful if the specified object is a generic type. For
* non-generic objects, use {@link #fromJson(Reader, Class)} instead. If you have the Json in a
* String form instead of a {@link Reader}, use {@link #fromJson(String, Type)} instead.
*
* @param <T> the type of the desired object
* @param json the reader producing Json from which the object is to be deserialized
* @param typeOfT The specific genericized type of src. You can obtain this type by using the
* {@link TypeToken} class. For example, to get the type for
* {@code Collection<Foo>}, you should use:
* <pre>
* Type typeOfT = new TypeToken&lt;Collection&lt;Foo&gt;&gt;(){}.getType();
* </pre>
* @return an object of type T from the json. Returns {@code null} if {@code json} is at EOF.
* @throws JsonIOException if there was a problem reading from the Reader
* @throws JsonSyntaxException if json is not a valid representation for an object of type
* @since 1.2
*/
@SuppressWarnings("unchecked")
public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
JsonReader jsonReader = newJsonReader(json);
T object = (T) fromJson(jsonReader, typeOfT);
assertFullConsumption(object, jsonReader);
return object;
}
private static void assertFullConsumption(Object obj, JsonReader reader) {
try {
if (obj != null && reader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonIOException("JSON document was not fully consumed.");
}
} catch (MalformedJsonException e) {
throw new JsonSyntaxException(e);
} catch (IOException e) {
throw new JsonIOException(e);
}
}
/**
* Reads the next JSON value from {@code reader} and convert it to an object
* of type {@code typeOfT}. Returns {@code null}, if the {@code reader} is at EOF.
* Since Type is not parameterized by T, this method is type unsafe and should be used carefully
*
* @throws JsonIOException if there was a problem writing to the Reader
* @throws JsonSyntaxException if json is not a valid representation for an object of type
*/
@SuppressWarnings("unchecked")
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
boolean isEmpty = true;
boolean oldLenient = reader.isLenient();
reader.setLenient(true);
try {
reader.peek();
isEmpty = false;
TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
TypeAdapter<T> typeAdapter = getAdapter(typeToken);
T object = typeAdapter.read(reader);
return object;
} catch (EOFException e) {
/*
* For compatibility with JSON 1.5 and earlier, we return null for empty
* documents instead of throwing.
*/
if (isEmpty) {
return null;
}
throw new JsonSyntaxException(e);
} catch (IllegalStateException e) {
throw new JsonSyntaxException(e);
} catch (IOException e) {
// TODO(inder): Figure out whether it is indeed right to rethrow this as JsonSyntaxException
throw new JsonSyntaxException(e);
} finally {
reader.setLenient(oldLenient);
}
}
/**
* This method deserializes the Json read from the specified parse tree into an object of the
* specified type. It is not suitable to use if the specified class is a generic type since it
* will not have the generic type information because of the Type Erasure feature of Java.
* Therefore, this method should not be used if the desired type is a generic type. Note that
* this method works fine if the any of the fields of the specified object are generics, just the
* object itself should not be a generic type. For the cases when the object is of generic type,
* invoke {@link #fromJson(JsonElement, Type)}.
* @param <T> the type of the desired object
* @param json the root of the parse tree of {@link JsonElement}s from which the object is to
* be deserialized
* @param classOfT The class of T
* @return an object of type T from the json. Returns {@code null} if {@code json} is {@code null}.
* @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
* @since 1.3
*/
public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException {
Object object = fromJson(json, (Type) classOfT);
return Primitives.wrap(classOfT).cast(object);
}
/**
* This method deserializes the Json read from the specified parse tree into an object of the
* specified type. This method is useful if the specified object is a generic type. For
* non-generic objects, use {@link #fromJson(JsonElement, Class)} instead.
*
* @param <T> the type of the desired object
* @param json the root of the parse tree of {@link JsonElement}s from which the object is to
* be deserialized
* @param typeOfT The specific genericized type of src. You can obtain this type by using the
* {@link TypeToken} class. For example, to get the type for
* {@code Collection<Foo>}, you should use:
* <pre>
* Type typeOfT = new TypeToken&lt;Collection&lt;Foo&gt;&gt;(){}.getType();
* </pre>
* @return an object of type T from the json. Returns {@code null} if {@code json} is {@code null}.
* @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
* @since 1.3
*/
@SuppressWarnings("unchecked")
public <T> T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException {
if (json == null) {
return null;
}
return (T) fromJson(new JsonTreeReader(json), typeOfT);
}
static class FutureTypeAdapter<T> extends TypeAdapter<T> {
private TypeAdapter<T> delegate;
public void setDelegate(TypeAdapter<T> typeAdapter) {
if (delegate != null) {
throw new AssertionError();
}
delegate = typeAdapter;
}
@Override public T read(JsonReader in) throws IOException {
if (delegate == null) {
throw new IllegalStateException();
}
return delegate.read(in);
}
@Override public void write(JsonWriter out, T value) throws IOException {
if (delegate == null) {
throw new IllegalStateException();
}
delegate.write(out, value);
}
}
@Override
public String toString() {
return new StringBuilder("{serializeNulls:")
.append(serializeNulls)
.append("factories:").append(factories)
.append(",instanceCreators:").append(constructorConstructor)
.append("}")
.toString();
}
}

View File

@ -1,578 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
import com.massivecraft.massivecore.xlib.gson.annotations.Expose;
import com.massivecraft.massivecore.xlib.gson.internal.$Gson$Preconditions;
import com.massivecraft.massivecore.xlib.gson.internal.Excluder;
import com.massivecraft.massivecore.xlib.gson.internal.bind.TreeTypeAdapter;
import com.massivecraft.massivecore.xlib.gson.internal.bind.TypeAdapters;
import com.massivecraft.massivecore.xlib.gson.reflect.TypeToken;
import com.massivecraft.massivecore.xlib.gson.stream.JsonReader;
import java.lang.reflect.Type;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.util.*;
/**
* <p>Use this builder to construct a {@link Gson} instance when you need to set configuration
* options other than the default. For {@link Gson} with default configuration, it is simpler to
* use {@code new Gson()}. {@code GsonBuilder} is best used by creating it, and then invoking its
* various configuration methods, and finally calling create.</p>
*
* <p>The following is an example shows how to use the {@code GsonBuilder} to construct a Gson
* instance:
*
* <pre>
* Gson gson = new GsonBuilder()
* .registerTypeAdapter(Id.class, new IdTypeAdapter())
* .enableComplexMapKeySerialization()
* .serializeNulls()
* .setDateFormat(DateFormat.LONG)
* .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
* .setPrettyPrinting()
* .setVersion(1.0)
* .create();
* </pre></p>
*
* <p>NOTES:
* <ul>
* <li> the order of invocation of configuration methods does not matter.</li>
* <li> The default serialization of {@link Date} and its subclasses in Gson does
* not contain time-zone information. So, if you are using date/time instances,
* use {@code GsonBuilder} and its {@code setDateFormat} methods.</li>
* </ul>
* </p>
*
* @author Inderjeet Singh
* @author Joel Leitch
* @author Jesse Wilson
*/
public final class GsonBuilder {
private Excluder excluder = Excluder.DEFAULT;
private LongSerializationPolicy longSerializationPolicy = LongSerializationPolicy.DEFAULT;
private FieldNamingStrategy fieldNamingPolicy = FieldNamingPolicy.IDENTITY;
private final Map<Type, InstanceCreator<?>> instanceCreators
= new HashMap<>();
private final List<TypeAdapterFactory> factories = new ArrayList<>();
/** tree-style hierarchy factories. These come after factories for backwards compatibility. */
private final List<TypeAdapterFactory> hierarchyFactories = new ArrayList<>();
private boolean serializeNulls = Gson.DEFAULT_SERIALIZE_NULLS;
private String datePattern;
private int dateStyle = DateFormat.DEFAULT;
private int timeStyle = DateFormat.DEFAULT;
private boolean complexMapKeySerialization = Gson.DEFAULT_COMPLEX_MAP_KEYS;
private boolean serializeSpecialFloatingPointValues = Gson.DEFAULT_SPECIALIZE_FLOAT_VALUES;
private boolean escapeHtmlChars = Gson.DEFAULT_ESCAPE_HTML;
private boolean prettyPrinting = Gson.DEFAULT_PRETTY_PRINT;
private boolean generateNonExecutableJson = Gson.DEFAULT_JSON_NON_EXECUTABLE;
private boolean lenient = Gson.DEFAULT_LENIENT;
/**
* Creates a GsonBuilder instance that can be used to build Gson with various configuration
* settings. GsonBuilder follows the builder pattern, and it is typically used by first
* invoking various configuration methods to set desired options, and finally calling
* {@link #create()}.
*/
public GsonBuilder() {
}
/**
* Configures Gson to enable versioning support.
*
* @param ignoreVersionsAfter any field or type marked with a version higher than this value
* are ignored during serialization or deserialization.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
public GsonBuilder setVersion(double ignoreVersionsAfter) {
excluder = excluder.withVersion(ignoreVersionsAfter);
return this;
}
/**
* Configures Gson to excludes all class fields that have the specified modifiers. By default,
* Gson will exclude all fields marked transient or static. This method will override that
* behavior.
*
* @param modifiers the field modifiers. You must use the modifiers specified in the
* {@link java.lang.reflect.Modifier} class. For example,
* {@link java.lang.reflect.Modifier#TRANSIENT},
* {@link java.lang.reflect.Modifier#STATIC}.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
public GsonBuilder excludeFieldsWithModifiers(int... modifiers) {
excluder = excluder.withModifiers(modifiers);
return this;
}
/**
* Makes the output JSON non-executable in Javascript by prefixing the generated JSON with some
* special text. This prevents attacks from third-party sites through script sourcing. See
* <a href="http://code.google.com/p/google-gson/issues/detail?id=42">Gson Issue 42</a>
* for details.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public GsonBuilder generateNonExecutableJson() {
this.generateNonExecutableJson = true;
return this;
}
/**
* Configures Gson to exclude all fields from consideration for serialization or deserialization
* that do not have the {@link Expose} annotation.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
public GsonBuilder excludeFieldsWithoutExposeAnnotation() {
excluder = excluder.excludeFieldsWithoutExposeAnnotation();
return this;
}
/**
* Configure Gson to serialize null fields. By default, Gson omits all fields that are null
* during serialization.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.2
*/
public GsonBuilder serializeNulls() {
this.serializeNulls = true;
return this;
}
/**
* Enabling this feature will only change the serialized form if the map key is
* a complex type (i.e. non-primitive) in its <strong>serialized</strong> JSON
* form. The default implementation of map serialization uses {@code toString()}
* on the key; however, when this is called then one of the following cases
* apply:
*
* <h3>Maps as JSON objects</h3>
* For this case, assume that a type adapter is registered to serialize and
* deserialize some {@code Point} class, which contains an x and y coordinate,
* to/from the JSON Primitive string value {@code "(x,y)"}. The Java map would
* then be serialized as a {@link JsonObject}.
*
* <p>Below is an example:
* <pre> {@code
* Gson gson = new GsonBuilder()
* .register(Point.class, new MyPointTypeAdapter())
* .enableComplexMapKeySerialization()
* .create();
*
* Map<Point, String> original = new LinkedHashMap<Point, String>();
* original.put(new Point(5, 6), "a");
* original.put(new Point(8, 8), "b");
* System.out.println(gson.toJson(original, type));
* }</pre>
* The above code prints this JSON object:<pre> {@code
* {
* "(5,6)": "a",
* "(8,8)": "b"
* }
* }</pre>
*
* <h3>Maps as JSON arrays</h3>
* For this case, assume that a type adapter was NOT registered for some
* {@code Point} class, but rather the default Gson serialization is applied.
* In this case, some {@code new Point(2,3)} would serialize as {@code
* {"x":2,"y":5}}.
*
* <p>Given the assumption above, a {@code Map<Point, String>} will be
* serialize as an array of arrays (can be viewed as an entry set of pairs).
*
* <p>Below is an example of serializing complex types as JSON arrays:
* <pre> {@code
* Gson gson = new GsonBuilder()
* .enableComplexMapKeySerialization()
* .create();
*
* Map<Point, String> original = new LinkedHashMap<Point, String>();
* original.put(new Point(5, 6), "a");
* original.put(new Point(8, 8), "b");
* System.out.println(gson.toJson(original, type));
* }
*
* The JSON output would look as follows:
* <pre> {@code
* [
* [
* {
* "x": 5,
* "y": 6
* },
* "a"
* ],
* [
* {
* "x": 8,
* "y": 8
* },
* "b"
* ]
* ]
* }</pre>
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.7
*/
public GsonBuilder enableComplexMapKeySerialization() {
complexMapKeySerialization = true;
return this;
}
/**
* Configures Gson to exclude inner classes during serialization.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public GsonBuilder disableInnerClassSerialization() {
excluder = excluder.disableInnerClassSerialization();
return this;
}
/**
* Configures Gson to apply a specific serialization policy for {@code Long} and {@code long}
* objects.
*
* @param serializationPolicy the particular policy to use for serializing longs.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public GsonBuilder setLongSerializationPolicy(LongSerializationPolicy serializationPolicy) {
this.longSerializationPolicy = serializationPolicy;
return this;
}
/**
* Configures Gson to apply a specific naming policy to an object's field during serialization
* and deserialization.
*
* @param namingConvention the JSON field naming convention to use for serialization and
* deserialization.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
public GsonBuilder setFieldNamingPolicy(FieldNamingPolicy namingConvention) {
this.fieldNamingPolicy = namingConvention;
return this;
}
/**
* Configures Gson to apply a specific naming policy strategy to an object's field during
* serialization and deserialization.
*
* @param fieldNamingStrategy the actual naming strategy to apply to the fields
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public GsonBuilder setFieldNamingStrategy(FieldNamingStrategy fieldNamingStrategy) {
this.fieldNamingPolicy = fieldNamingStrategy;
return this;
}
/**
* Configures Gson to apply a set of exclusion strategies during both serialization and
* deserialization. Each of the {@code strategies} will be applied as a disjunction rule.
* This means that if one of the {@code strategies} suggests that a field (or class) should be
* skipped then that field (or object) is skipped during serialization/deserialization.
*
* @param strategies the set of strategy object to apply during object (de)serialization.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.4
*/
public GsonBuilder setExclusionStrategies(ExclusionStrategy... strategies) {
for (ExclusionStrategy strategy : strategies) {
excluder = excluder.withExclusionStrategy(strategy, true, true);
}
return this;
}
/**
* Configures Gson to apply the passed in exclusion strategy during serialization.
* If this method is invoked numerous times with different exclusion strategy objects
* then the exclusion strategies that were added will be applied as a disjunction rule.
* This means that if one of the added exclusion strategies suggests that a field (or
* class) should be skipped then that field (or object) is skipped during its
* serialization.
*
* @param strategy an exclusion strategy to apply during serialization.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.7
*/
public GsonBuilder addSerializationExclusionStrategy(ExclusionStrategy strategy) {
excluder = excluder.withExclusionStrategy(strategy, true, false);
return this;
}
/**
* Configures Gson to apply the passed in exclusion strategy during deserialization.
* If this method is invoked numerous times with different exclusion strategy objects
* then the exclusion strategies that were added will be applied as a disjunction rule.
* This means that if one of the added exclusion strategies suggests that a field (or
* class) should be skipped then that field (or object) is skipped during its
* deserialization.
*
* @param strategy an exclusion strategy to apply during deserialization.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.7
*/
public GsonBuilder addDeserializationExclusionStrategy(ExclusionStrategy strategy) {
excluder = excluder.withExclusionStrategy(strategy, false, true);
return this;
}
/**
* Configures Gson to output Json that fits in a page for pretty printing. This option only
* affects Json serialization.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
public GsonBuilder setPrettyPrinting() {
prettyPrinting = true;
return this;
}
/**
* By default, Gson is strict and only accepts JSON as specified by
* <a href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>. This option makes the parser
* liberal in what it accepts.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @see JsonReader#setLenient(boolean)
*/
public GsonBuilder setLenient() {
lenient = true;
return this;
}
/**
* By default, Gson escapes HTML characters such as &lt; &gt; etc. Use this option to configure
* Gson to pass-through HTML characters as is.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public GsonBuilder disableHtmlEscaping() {
this.escapeHtmlChars = false;
return this;
}
/**
* Configures Gson to serialize {@code Date} objects according to the pattern provided. You can
* call this method or {@link #setDateFormat(int)} multiple times, but only the last invocation
* will be used to decide the serialization format.
*
* <p>The date format will be used to serialize and deserialize {@link java.util.Date}, {@link
* java.sql.Timestamp} and {@link java.sql.Date}.
*
* <p>Note that this pattern must abide by the convention provided by {@code SimpleDateFormat}
* class. See the documentation in {@link java.text.SimpleDateFormat} for more information on
* valid date and time patterns.</p>
*
* @param pattern the pattern that dates will be serialized/deserialized to/from
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.2
*/
public GsonBuilder setDateFormat(String pattern) {
// TODO(Joel): Make this fail fast if it is an invalid date format
this.datePattern = pattern;
return this;
}
/**
* Configures Gson to to serialize {@code Date} objects according to the style value provided.
* You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
* invocation will be used to decide the serialization format.
*
* <p>Note that this style value should be one of the predefined constants in the
* {@code DateFormat} class. See the documentation in {@link java.text.DateFormat} for more
* information on the valid style constants.</p>
*
* @param style the predefined date style that date objects will be serialized/deserialized
* to/from
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.2
*/
public GsonBuilder setDateFormat(int style) {
this.dateStyle = style;
this.datePattern = null;
return this;
}
/**
* Configures Gson to to serialize {@code Date} objects according to the style value provided.
* You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
* invocation will be used to decide the serialization format.
*
* <p>Note that this style value should be one of the predefined constants in the
* {@code DateFormat} class. See the documentation in {@link java.text.DateFormat} for more
* information on the valid style constants.</p>
*
* @param dateStyle the predefined date style that date objects will be serialized/deserialized
* to/from
* @param timeStyle the predefined style for the time portion of the date objects
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.2
*/
public GsonBuilder setDateFormat(int dateStyle, int timeStyle) {
this.dateStyle = dateStyle;
this.timeStyle = timeStyle;
this.datePattern = null;
return this;
}
/**
* Configures Gson for custom serialization or deserialization. This method combines the
* registration of an {@link TypeAdapter}, {@link InstanceCreator}, {@link JsonSerializer}, and a
* {@link JsonDeserializer}. It is best used when a single object {@code typeAdapter} implements
* all the required interfaces for custom serialization with Gson. If a type adapter was
* previously registered for the specified {@code type}, it is overwritten.
*
* <p>This registers the type specified and no other types: you must manually register related
* types! For example, applications registering {@code boolean.class} should also register {@code
* Boolean.class}.
*
* @param type the type definition for the type adapter being registered
* @param typeAdapter This object must implement at least one of the {@link TypeAdapter},
* {@link InstanceCreator}, {@link JsonSerializer}, and a {@link JsonDeserializer} interfaces.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
$Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
|| typeAdapter instanceof JsonDeserializer<?>
|| typeAdapter instanceof InstanceCreator<?>
|| typeAdapter instanceof TypeAdapter<?>);
if (typeAdapter instanceof InstanceCreator<?>) {
instanceCreators.put(type, (InstanceCreator) typeAdapter);
}
if (typeAdapter instanceof JsonSerializer<?> || typeAdapter instanceof JsonDeserializer<?>) {
TypeToken<?> typeToken = TypeToken.get(type);
factories.add(TreeTypeAdapter.newFactoryWithMatchRawType(typeToken, typeAdapter));
}
if (typeAdapter instanceof TypeAdapter<?>) {
factories.add(TypeAdapters.newFactory(TypeToken.get(type), (TypeAdapter)typeAdapter));
}
return this;
}
/**
* Register a factory for type adapters. Registering a factory is useful when the type
* adapter needs to be configured based on the type of the field being processed. Gson
* is designed to handle a large number of factories, so you should consider registering
* them to be at par with registering an individual type adapter.
*
* @since 2.1
*/
public GsonBuilder registerTypeAdapterFactory(TypeAdapterFactory factory) {
factories.add(factory);
return this;
}
/**
* Configures Gson for custom serialization or deserialization for an inheritance type hierarchy.
* This method combines the registration of a {@link TypeAdapter}, {@link JsonSerializer} and
* a {@link JsonDeserializer}. If a type adapter was previously registered for the specified
* type hierarchy, it is overridden. If a type adapter is registered for a specific type in
* the type hierarchy, it will be invoked instead of the one registered for the type hierarchy.
*
* @param baseType the class definition for the type adapter being registered for the base class
* or interface
* @param typeAdapter This object must implement at least one of {@link TypeAdapter},
* {@link JsonSerializer} or {@link JsonDeserializer} interfaces.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.7
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public GsonBuilder registerTypeHierarchyAdapter(Class<?> baseType, Object typeAdapter) {
$Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
|| typeAdapter instanceof JsonDeserializer<?>
|| typeAdapter instanceof TypeAdapter<?>);
if (typeAdapter instanceof JsonDeserializer || typeAdapter instanceof JsonSerializer) {
hierarchyFactories.add(0,
TreeTypeAdapter.newTypeHierarchyFactory(baseType, typeAdapter));
}
if (typeAdapter instanceof TypeAdapter<?>) {
factories.add(TypeAdapters.newTypeHierarchyFactory(baseType, (TypeAdapter)typeAdapter));
}
return this;
}
/**
* Section 2.4 of <a href="http://www.ietf.org/rfc/rfc4627.txt">JSON specification</a> disallows
* special double values (NaN, Infinity, -Infinity). However,
* <a href="http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf">Javascript
* specification</a> (see section 4.3.20, 4.3.22, 4.3.23) allows these values as valid Javascript
* values. Moreover, most JavaScript engines will accept these special values in JSON without
* problem. So, at a practical level, it makes sense to accept these values as valid JSON even
* though JSON specification disallows them.
*
* <p>Gson always accepts these special values during deserialization. However, it outputs
* strictly compliant JSON. Hence, if it encounters a float value {@link Float#NaN},
* {@link Float#POSITIVE_INFINITY}, {@link Float#NEGATIVE_INFINITY}, or a double value
* {@link Double#NaN}, {@link Double#POSITIVE_INFINITY}, {@link Double#NEGATIVE_INFINITY}, it
* will throw an {@link IllegalArgumentException}. This method provides a way to override the
* default behavior when you know that the JSON receiver will be able to handle these special
* values.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public GsonBuilder serializeSpecialFloatingPointValues() {
this.serializeSpecialFloatingPointValues = true;
return this;
}
/**
* Creates a {@link Gson} instance based on the current configuration. This method is free of
* side-effects to this {@code GsonBuilder} instance and hence can be called multiple times.
*
* @return an instance of Gson configured with the options currently set in this builder
*/
public Gson create() {
List<TypeAdapterFactory> factories = new ArrayList<>();
factories.addAll(this.factories);
Collections.reverse(factories);
factories.addAll(this.hierarchyFactories);
addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, factories);
return new Gson(excluder, fieldNamingPolicy, instanceCreators,
serializeNulls, complexMapKeySerialization,
generateNonExecutableJson, escapeHtmlChars, prettyPrinting, lenient,
serializeSpecialFloatingPointValues, longSerializationPolicy, factories);
}
private void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle,
List<TypeAdapterFactory> factories) {
DefaultDateTypeAdapter dateTypeAdapter;
if (datePattern != null && !"".equals(datePattern.trim())) {
dateTypeAdapter = new DefaultDateTypeAdapter(datePattern);
} else if (dateStyle != DateFormat.DEFAULT && timeStyle != DateFormat.DEFAULT) {
dateTypeAdapter = new DefaultDateTypeAdapter(dateStyle, timeStyle);
} else {
return;
}
factories.add(TreeTypeAdapter.newFactory(TypeToken.get(Date.class), dateTypeAdapter));
factories.add(TreeTypeAdapter.newFactory(TypeToken.get(Timestamp.class), dateTypeAdapter));
factories.add(TreeTypeAdapter.newFactory(TypeToken.get(java.sql.Date.class), dateTypeAdapter));
}
}

View File

@ -1,92 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
import java.lang.reflect.Type;
/**
* This interface is implemented to create instances of a class that does not define a no-args
* constructor. If you can modify the class, you should instead add a private, or public
* no-args constructor. However, that is not possible for library classes, such as JDK classes, or
* a third-party library that you do not have source-code of. In such cases, you should define an
* instance creator for the class. Implementations of this interface should be registered with
* {@link GsonBuilder#registerTypeAdapter(Type, Object)} method before Gson will be able to use
* them.
* <p>Let us look at an example where defining an InstanceCreator might be useful. The
* {@code Id} class defined below does not have a default no-args constructor.</p>
*
* <pre>
* public class Id&lt;T&gt; {
* private final Class&lt;T&gt; clazz;
* private final long value;
* public Id(Class&lt;T&gt; clazz, long value) {
* this.clazz = clazz;
* this.value = value;
* }
* }
* </pre>
*
* <p>If Gson encounters an object of type {@code Id} during deserialization, it will throw an
* exception. The easiest way to solve this problem will be to add a (public or private) no-args
* constructor as follows:</p>
*
* <pre>
* private Id() {
* this(Object.class, 0L);
* }
* </pre>
*
* <p>However, let us assume that the developer does not have access to the source-code of the
* {@code Id} class, or does not want to define a no-args constructor for it. The developer
* can solve this problem by defining an {@code InstanceCreator} for {@code Id}:</p>
*
* <pre>
* class IdInstanceCreator implements InstanceCreator&lt;Id&gt; {
* public Id createInstance(Type type) {
* return new Id(Object.class, 0L);
* }
* }
* </pre>
*
* <p>Note that it does not matter what the fields of the created instance contain since Gson will
* overwrite them with the deserialized values specified in Json. You should also ensure that a
* <i>new</i> object is returned, not a common object since its fields will be overwritten.
* The developer will need to register {@code IdInstanceCreator} with Gson as follows:</p>
*
* <pre>
* Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdInstanceCreator()).create();
* </pre>
*
* @param <T> the type of object that will be created by this implementation.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public interface InstanceCreator<T> {
/**
* Gson invokes this call-back method during deserialization to create an instance of the
* specified type. The fields of the returned instance are overwritten with the data present
* in the Json. Since the prior contents of the object are destroyed and overwritten, do not
* return an instance that is useful elsewhere. In particular, do not return a common instance,
* always use {@code new} to create a new instance.
*
* @param type the parameterized T represented as a {@link Type}.
* @return a default object instance of type T.
*/
public T createInstance(Type type);
}

View File

@ -1,373 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* A class representing an array type in Json. An array is a list of {@link JsonElement}s each of
* which can be of a different type. This is an ordered list, meaning that the order in which
* elements are added is preserved.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public final class JsonArray extends JsonElement implements Iterable<JsonElement> {
private final List<JsonElement> elements;
/**
* Creates an empty JsonArray.
*/
public JsonArray() {
elements = new ArrayList<>();
}
@Override
JsonArray deepCopy() {
JsonArray result = new JsonArray();
for (JsonElement element : elements) {
result.add(element.deepCopy());
}
return result;
}
/**
* Adds the specified boolean to self.
*
* @param bool the boolean that needs to be added to the array.
*/
public void add(Boolean bool) {
elements.add(bool == null ? JsonNull.INSTANCE : new JsonPrimitive(bool));
}
/**
* Adds the specified character to self.
*
* @param character the character that needs to be added to the array.
*/
public void add(Character character) {
elements.add(character == null ? JsonNull.INSTANCE : new JsonPrimitive(character));
}
/**
* Adds the specified number to self.
*
* @param number the number that needs to be added to the array.
*/
public void add(Number number) {
elements.add(number == null ? JsonNull.INSTANCE : new JsonPrimitive(number));
}
/**
* Adds the specified string to self.
*
* @param string the string that needs to be added to the array.
*/
public void add(String string) {
elements.add(string == null ? JsonNull.INSTANCE : new JsonPrimitive(string));
}
/**
* Adds the specified element to self.
*
* @param element the element that needs to be added to the array.
*/
public void add(JsonElement element) {
if (element == null) {
element = JsonNull.INSTANCE;
}
elements.add(element);
}
/**
* Adds all the elements of the specified array to self.
*
* @param array the array whose elements need to be added to the array.
*/
public void addAll(JsonArray array) {
elements.addAll(array.elements);
}
/**
* Replaces the element at the specified position in this array with the specified element.
* Element can be null.
* @param index index of the element to replace
* @param element element to be stored at the specified position
* @return the element previously at the specified position
* @throws IndexOutOfBoundsException if the specified index is outside the array bounds
*/
public JsonElement set(int index, JsonElement element) {
return elements.set(index, element);
}
/**
* Removes the first occurrence of the specified element from this array, if it is present.
* If the array does not contain the element, it is unchanged.
* @param element element to be removed from this array, if present
* @return true if this array contained the specified element, false otherwise
* @since 2.3
*/
public boolean remove(JsonElement element) {
return elements.remove(element);
}
/**
* Removes the element at the specified position in this array. Shifts any subsequent elements
* to the left (subtracts one from their indices). Returns the element that was removed from
* the array.
* @param index index the index of the element to be removed
* @return the element previously at the specified position
* @throws IndexOutOfBoundsException if the specified index is outside the array bounds
* @since 2.3
*/
public JsonElement remove(int index) {
return elements.remove(index);
}
/**
* Returns true if this array contains the specified element.
* @return true if this array contains the specified element.
* @param element whose presence in this array is to be tested
* @since 2.3
*/
public boolean contains(JsonElement element) {
return elements.contains(element);
}
/**
* Returns the number of elements in the array.
*
* @return the number of elements in the array.
*/
public int size() {
return elements.size();
}
/**
* Returns an iterator to navigate the elements of the array. Since the array is an ordered list,
* the iterator navigates the elements in the order they were inserted.
*
* @return an iterator to navigate the elements of the array.
*/
public Iterator<JsonElement> iterator() {
return elements.iterator();
}
/**
* Returns the ith element of the array.
*
* @param i the index of the element that is being sought.
* @return the element present at the ith index.
* @throws IndexOutOfBoundsException if i is negative or greater than or equal to the
* {@link #size()} of the array.
*/
public JsonElement get(int i) {
return elements.get(i);
}
/**
* convenience method to get this array as a {@link Number} if it contains a single element.
*
* @return get this element as a number if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
* is not a valid Number.
* @throws IllegalStateException if the array has more than one element.
*/
@Override
public Number getAsNumber() {
if (elements.size() == 1) {
return elements.get(0).getAsNumber();
}
throw new IllegalStateException();
}
/**
* convenience method to get this array as a {@link String} if it contains a single element.
*
* @return get this element as a String if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
* is not a valid String.
* @throws IllegalStateException if the array has more than one element.
*/
@Override
public String getAsString() {
if (elements.size() == 1) {
return elements.get(0).getAsString();
}
throw new IllegalStateException();
}
/**
* convenience method to get this array as a double if it contains a single element.
*
* @return get this element as a double if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
* is not a valid double.
* @throws IllegalStateException if the array has more than one element.
*/
@Override
public double getAsDouble() {
if (elements.size() == 1) {
return elements.get(0).getAsDouble();
}
throw new IllegalStateException();
}
/**
* convenience method to get this array as a {@link BigDecimal} if it contains a single element.
*
* @return get this element as a {@link BigDecimal} if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive}.
* @throws NumberFormatException if the element at index 0 is not a valid {@link BigDecimal}.
* @throws IllegalStateException if the array has more than one element.
* @since 1.2
*/
@Override
public BigDecimal getAsBigDecimal() {
if (elements.size() == 1) {
return elements.get(0).getAsBigDecimal();
}
throw new IllegalStateException();
}
/**
* convenience method to get this array as a {@link BigInteger} if it contains a single element.
*
* @return get this element as a {@link BigInteger} if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive}.
* @throws NumberFormatException if the element at index 0 is not a valid {@link BigInteger}.
* @throws IllegalStateException if the array has more than one element.
* @since 1.2
*/
@Override
public BigInteger getAsBigInteger() {
if (elements.size() == 1) {
return elements.get(0).getAsBigInteger();
}
throw new IllegalStateException();
}
/**
* convenience method to get this array as a float if it contains a single element.
*
* @return get this element as a float if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
* is not a valid float.
* @throws IllegalStateException if the array has more than one element.
*/
@Override
public float getAsFloat() {
if (elements.size() == 1) {
return elements.get(0).getAsFloat();
}
throw new IllegalStateException();
}
/**
* convenience method to get this array as a long if it contains a single element.
*
* @return get this element as a long if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
* is not a valid long.
* @throws IllegalStateException if the array has more than one element.
*/
@Override
public long getAsLong() {
if (elements.size() == 1) {
return elements.get(0).getAsLong();
}
throw new IllegalStateException();
}
/**
* convenience method to get this array as an integer if it contains a single element.
*
* @return get this element as an integer if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
* is not a valid integer.
* @throws IllegalStateException if the array has more than one element.
*/
@Override
public int getAsInt() {
if (elements.size() == 1) {
return elements.get(0).getAsInt();
}
throw new IllegalStateException();
}
@Override
public byte getAsByte() {
if (elements.size() == 1) {
return elements.get(0).getAsByte();
}
throw new IllegalStateException();
}
@Override
public char getAsCharacter() {
if (elements.size() == 1) {
return elements.get(0).getAsCharacter();
}
throw new IllegalStateException();
}
/**
* convenience method to get this array as a primitive short if it contains a single element.
*
* @return get this element as a primitive short if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
* is not a valid short.
* @throws IllegalStateException if the array has more than one element.
*/
@Override
public short getAsShort() {
if (elements.size() == 1) {
return elements.get(0).getAsShort();
}
throw new IllegalStateException();
}
/**
* convenience method to get this array as a boolean if it contains a single element.
*
* @return get this element as a boolean if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
* is not a valid boolean.
* @throws IllegalStateException if the array has more than one element.
*/
@Override
public boolean getAsBoolean() {
if (elements.size() == 1) {
return elements.get(0).getAsBoolean();
}
throw new IllegalStateException();
}
@Override
public boolean equals(Object o) {
return (o == this) || (o instanceof JsonArray && ((JsonArray) o).elements.equals(elements));
}
@Override
public int hashCode() {
return elements.hashCode();
}
}

View File

@ -1,44 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
import java.lang.reflect.Type;
/**
* Context for deserialization that is passed to a custom deserializer during invocation of its
* {@link JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext)}
* method.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public interface JsonDeserializationContext {
/**
* Invokes default deserialization on the specified object. It should never be invoked on
* the element received as a parameter of the
* {@link JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext)} method. Doing
* so will result in an infinite loop since Gson will in-turn call the custom deserializer again.
*
* @param json the parse tree.
* @param typeOfT type of the expected return value.
* @param <T> The type of the deserialized object.
* @return An object of type typeOfT.
* @throws JsonParseException if the parse tree does not contain expected data.
*/
public <T> T deserialize(JsonElement json, Type typeOfT) throws JsonParseException;
}

View File

@ -1,91 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
import java.lang.reflect.Type;
/**
* <p>Interface representing a custom deserializer for Json. You should write a custom
* deserializer, if you are not happy with the default deserialization done by Gson. You will
* also need to register this deserializer through
* {@link GsonBuilder#registerTypeAdapter(Type, Object)}.</p>
*
* <p>Let us look at example where defining a deserializer will be useful. The {@code Id} class
* defined below has two fields: {@code clazz} and {@code value}.</p>
*
* <pre>
* public class Id&lt;T&gt; {
* private final Class&lt;T&gt; clazz;
* private final long value;
* public Id(Class&lt;T&gt; clazz, long value) {
* this.clazz = clazz;
* this.value = value;
* }
* public long getValue() {
* return value;
* }
* }
* </pre>
*
* <p>The default deserialization of {@code Id(com.foo.MyObject.class, 20L)} will require the
* Json string to be <code>{"clazz":com.foo.MyObject,"value":20}</code>. Suppose, you already know
* the type of the field that the {@code Id} will be deserialized into, and hence just want to
* deserialize it from a Json string {@code 20}. You can achieve that by writing a custom
* deserializer:</p>
*
* <pre>
* class IdDeserializer implements JsonDeserializer&lt;Id&gt;() {
* public Id deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
* throws JsonParseException {
* return new Id((Class)typeOfT, id.getValue());
* }
* </pre>
*
* <p>You will also need to register {@code IdDeserializer} with Gson as follows:</p>
*
* <pre>
* Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdDeserializer()).create();
* </pre>
*
* <p>New applications should prefer {@link TypeAdapter}, whose streaming API
* is more efficient than this interface's tree API.
*
* @author Inderjeet Singh
* @author Joel Leitch
*
* @param <T> type for which the deserializer is being registered. It is possible that a
* deserializer may be asked to deserialize a specific generic type of the T.
*/
public interface JsonDeserializer<T> {
/**
* Gson invokes this call-back method during deserialization when it encounters a field of the
* specified type.
* <p>In the implementation of this call-back method, you should consider invoking
* {@link JsonDeserializationContext#deserialize(JsonElement, Type)} method to create objects
* for any non-trivial field of the returned object. However, you should never invoke it on the
* the same type passing {@code json} since that will cause an infinite loop (Gson will call your
* call-back method again).
*
* @param json The Json data being deserialized
* @param typeOfT The type of the Object to deserialize to
* @return a deserialized object of the specified type typeOfT which is a subclass of {@code T}
* @throws JsonParseException if json is not in the expected format of {@code typeofT}
*/
public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException;
}

View File

@ -1,331 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
import com.massivecraft.massivecore.xlib.gson.internal.Streams;
import com.massivecraft.massivecore.xlib.gson.stream.JsonWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
* A class representing an element of Json. It could either be a {@link JsonObject}, a
* {@link JsonArray}, a {@link JsonPrimitive} or a {@link JsonNull}.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public abstract class JsonElement {
/**
* Returns a deep copy of this element. Immutable elements like primitives
* and nulls are not copied.
*/
abstract JsonElement deepCopy();
/**
* provides check for verifying if this element is an array or not.
*
* @return true if this element is of type {@link JsonArray}, false otherwise.
*/
public boolean isJsonArray() {
return this instanceof JsonArray;
}
/**
* provides check for verifying if this element is a Json object or not.
*
* @return true if this element is of type {@link JsonObject}, false otherwise.
*/
public boolean isJsonObject() {
return this instanceof JsonObject;
}
/**
* provides check for verifying if this element is a primitive or not.
*
* @return true if this element is of type {@link JsonPrimitive}, false otherwise.
*/
public boolean isJsonPrimitive() {
return this instanceof JsonPrimitive;
}
/**
* provides check for verifying if this element represents a null value or not.
*
* @return true if this element is of type {@link JsonNull}, false otherwise.
* @since 1.2
*/
public boolean isJsonNull() {
return this instanceof JsonNull;
}
/**
* convenience method to get this element as a {@link JsonObject}. If the element is of some
* other type, a {@link IllegalStateException} will result. Hence it is best to use this method
* after ensuring that this element is of the desired type by calling {@link #isJsonObject()}
* first.
*
* @return get this element as a {@link JsonObject}.
* @throws IllegalStateException if the element is of another type.
*/
public JsonObject getAsJsonObject() {
if (isJsonObject()) {
return (JsonObject) this;
}
throw new IllegalStateException("Not a JSON Object: " + this);
}
/**
* convenience method to get this element as a {@link JsonArray}. If the element is of some
* other type, a {@link IllegalStateException} will result. Hence it is best to use this method
* after ensuring that this element is of the desired type by calling {@link #isJsonArray()}
* first.
*
* @return get this element as a {@link JsonArray}.
* @throws IllegalStateException if the element is of another type.
*/
public JsonArray getAsJsonArray() {
if (isJsonArray()) {
return (JsonArray) this;
}
throw new IllegalStateException("This is not a JSON Array.");
}
/**
* convenience method to get this element as a {@link JsonPrimitive}. If the element is of some
* other type, a {@link IllegalStateException} will result. Hence it is best to use this method
* after ensuring that this element is of the desired type by calling {@link #isJsonPrimitive()}
* first.
*
* @return get this element as a {@link JsonPrimitive}.
* @throws IllegalStateException if the element is of another type.
*/
public JsonPrimitive getAsJsonPrimitive() {
if (isJsonPrimitive()) {
return (JsonPrimitive) this;
}
throw new IllegalStateException("This is not a JSON Primitive.");
}
/**
* convenience method to get this element as a {@link JsonNull}. If the element is of some
* other type, a {@link IllegalStateException} will result. Hence it is best to use this method
* after ensuring that this element is of the desired type by calling {@link #isJsonNull()}
* first.
*
* @return get this element as a {@link JsonNull}.
* @throws IllegalStateException if the element is of another type.
* @since 1.2
*/
public JsonNull getAsJsonNull() {
if (isJsonNull()) {
return (JsonNull) this;
}
throw new IllegalStateException("This is not a JSON Null.");
}
/**
* convenience method to get this element as a boolean value.
*
* @return get this element as a primitive boolean value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* boolean value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
*/
public boolean getAsBoolean() {
throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
* convenience method to get this element as a {@link Boolean} value.
*
* @return get this element as a {@link Boolean} value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* boolean value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
*/
Boolean getAsBooleanWrapper() {
throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
* convenience method to get this element as a {@link Number}.
*
* @return get this element as a {@link Number}.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* number.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
*/
public Number getAsNumber() {
throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
* convenience method to get this element as a string value.
*
* @return get this element as a string value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* string value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
*/
public String getAsString() {
throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
* convenience method to get this element as a primitive double value.
*
* @return get this element as a primitive double value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* double value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
*/
public double getAsDouble() {
throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
* convenience method to get this element as a primitive float value.
*
* @return get this element as a primitive float value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* float value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
*/
public float getAsFloat() {
throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
* convenience method to get this element as a primitive long value.
*
* @return get this element as a primitive long value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* long value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
*/
public long getAsLong() {
throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
* convenience method to get this element as a primitive integer value.
*
* @return get this element as a primitive integer value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* integer value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
*/
public int getAsInt() {
throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
* convenience method to get this element as a primitive byte value.
*
* @return get this element as a primitive byte value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* byte value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
* @since 1.3
*/
public byte getAsByte() {
throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
* convenience method to get this element as a primitive character value.
*
* @return get this element as a primitive char value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* char value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
* @since 1.3
*/
public char getAsCharacter() {
throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
* convenience method to get this element as a {@link BigDecimal}.
*
* @return get this element as a {@link BigDecimal}.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive}.
* * @throws NumberFormatException if the element is not a valid {@link BigDecimal}.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
* @since 1.2
*/
public BigDecimal getAsBigDecimal() {
throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
* convenience method to get this element as a {@link BigInteger}.
*
* @return get this element as a {@link BigInteger}.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive}.
* @throws NumberFormatException if the element is not a valid {@link BigInteger}.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
* @since 1.2
*/
public BigInteger getAsBigInteger() {
throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
* convenience method to get this element as a primitive short value.
*
* @return get this element as a primitive short value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* short value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
*/
public short getAsShort() {
throw new UnsupportedOperationException(getClass().getSimpleName());
}
/**
* Returns a String representation of this element.
*/
@Override
public String toString() {
try {
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
jsonWriter.setLenient(true);
Streams.write(this, jsonWriter);
return stringWriter.toString();
} catch (IOException e) {
throw new AssertionError(e);
}
}
}

View File

@ -1,45 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
/**
* This exception is raised when Gson was unable to read an input stream
* or write to one.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public final class JsonIOException extends JsonParseException {
private static final long serialVersionUID = 1L;
public JsonIOException(String msg) {
super(msg);
}
public JsonIOException(String msg, Throwable cause) {
super(msg, cause);
}
/**
* Creates exception with the specified cause. Consider using
* {@link #JsonIOException(String, Throwable)} instead if you can describe what happened.
*
* @param cause root exception that caused this exception to be thrown.
*/
public JsonIOException(Throwable cause) {
super(cause);
}
}

View File

@ -1,63 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
/**
* A class representing a Json {@code null} value.
*
* @author Inderjeet Singh
* @author Joel Leitch
* @since 1.2
*/
public final class JsonNull extends JsonElement {
/**
* singleton for JsonNull
*
* @since 1.8
*/
public static final JsonNull INSTANCE = new JsonNull();
/**
* Creates a new JsonNull object.
* Deprecated since Gson version 1.8. Use {@link #INSTANCE} instead
*/
@Deprecated
public JsonNull() {
// Do nothing
}
@Override
JsonNull deepCopy() {
return INSTANCE;
}
/**
* All instances of JsonNull have the same hash code since they are indistinguishable
*/
@Override
public int hashCode() {
return JsonNull.class.hashCode();
}
/**
* All instances of JsonNull are the same
*/
@Override
public boolean equals(Object other) {
return this == other || other instanceof JsonNull;
}
}

View File

@ -1,204 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
import com.massivecraft.massivecore.xlib.gson.internal.LinkedTreeMap;
import java.util.Map;
import java.util.Set;
/**
* A class representing an object type in Json. An object consists of name-value pairs where names
* are strings, and values are any other type of {@link JsonElement}. This allows for a creating a
* tree of JsonElements. The member elements of this object are maintained in order they were added.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public final class JsonObject extends JsonElement {
private final LinkedTreeMap<String, JsonElement> members =
new LinkedTreeMap<>();
@Override
JsonObject deepCopy() {
JsonObject result = new JsonObject();
for (Map.Entry<String, JsonElement> entry : members.entrySet()) {
result.add(entry.getKey(), entry.getValue().deepCopy());
}
return result;
}
/**
* Adds a member, which is a name-value pair, to self. The name must be a String, but the value
* can be an arbitrary JsonElement, thereby allowing you to build a full tree of JsonElements
* rooted at this node.
*
* @param property name of the member.
* @param value the member object.
*/
public void add(String property, JsonElement value) {
if (value == null) {
value = JsonNull.INSTANCE;
}
members.put(property, value);
}
/**
* Removes the {@code property} from this {@link JsonObject}.
*
* @param property name of the member that should be removed.
* @return the {@link JsonElement} object that is being removed.
* @since 1.3
*/
public JsonElement remove(String property) {
return members.remove(property);
}
/**
* Convenience method to add a primitive member. The specified value is converted to a
* JsonPrimitive of String.
*
* @param property name of the member.
* @param value the string value associated with the member.
*/
public void addProperty(String property, String value) {
add(property, createJsonElement(value));
}
/**
* Convenience method to add a primitive member. The specified value is converted to a
* JsonPrimitive of Number.
*
* @param property name of the member.
* @param value the number value associated with the member.
*/
public void addProperty(String property, Number value) {
add(property, createJsonElement(value));
}
/**
* Convenience method to add a boolean member. The specified value is converted to a
* JsonPrimitive of Boolean.
*
* @param property name of the member.
* @param value the number value associated with the member.
*/
public void addProperty(String property, Boolean value) {
add(property, createJsonElement(value));
}
/**
* Convenience method to add a char member. The specified value is converted to a
* JsonPrimitive of Character.
*
* @param property name of the member.
* @param value the number value associated with the member.
*/
public void addProperty(String property, Character value) {
add(property, createJsonElement(value));
}
/**
* Creates the proper {@link JsonElement} object from the given {@code value} object.
*
* @param value the object to generate the {@link JsonElement} for
* @return a {@link JsonPrimitive} if the {@code value} is not null, otherwise a {@link JsonNull}
*/
private JsonElement createJsonElement(Object value) {
return value == null ? JsonNull.INSTANCE : new JsonPrimitive(value);
}
/**
* Returns a set of members of this object. The set is ordered, and the order is in which the
* elements were added.
*
* @return a set of members of this object.
*/
public Set<Map.Entry<String, JsonElement>> entrySet() {
return members.entrySet();
}
/**
* Returns the number of key/value pairs in the object.
*
* @return the number of key/value pairs in the object.
*/
public int size() {
return members.size();
}
/**
* Convenience method to check if a member with the specified name is present in this object.
*
* @param memberName name of the member that is being checked for presence.
* @return true if there is a member with the specified name, false otherwise.
*/
public boolean has(String memberName) {
return members.containsKey(memberName);
}
/**
* Returns the member with the specified name.
*
* @param memberName name of the member that is being requested.
* @return the member matching the name. Null if no such member exists.
*/
public JsonElement get(String memberName) {
return members.get(memberName);
}
/**
* Convenience method to get the specified member as a JsonPrimitive element.
*
* @param memberName name of the member being requested.
* @return the JsonPrimitive corresponding to the specified member.
*/
public JsonPrimitive getAsJsonPrimitive(String memberName) {
return (JsonPrimitive) members.get(memberName);
}
/**
* Convenience method to get the specified member as a JsonArray.
*
* @param memberName name of the member being requested.
* @return the JsonArray corresponding to the specified member.
*/
public JsonArray getAsJsonArray(String memberName) {
return (JsonArray) members.get(memberName);
}
/**
* Convenience method to get the specified member as a JsonObject.
*
* @param memberName name of the member being requested.
* @return the JsonObject corresponding to the specified member.
*/
public JsonObject getAsJsonObject(String memberName) {
return (JsonObject) members.get(memberName);
}
@Override
public boolean equals(Object o) {
return (o == this) || (o instanceof JsonObject
&& ((JsonObject) o).members.equals(members));
}
@Override
public int hashCode() {
return members.hashCode();
}
}

View File

@ -1,64 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
/**
* This exception is raised if there is a serious issue that occurs during parsing of a Json
* string. One of the main usages for this class is for the Gson infrastructure. If the incoming
* Json is bad/malicious, an instance of this exception is raised.
*
* <p>This exception is a {@link RuntimeException} because it is exposed to the client. Using a
* {@link RuntimeException} avoids bad coding practices on the client side where they catch the
* exception and do nothing. It is often the case that you want to blow up if there is a parsing
* error (i.e. often clients do not know how to recover from a {@link JsonParseException}.</p>
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public class JsonParseException extends RuntimeException {
static final long serialVersionUID = -4086729973971783390L;
/**
* Creates exception with the specified message. If you are wrapping another exception, consider
* using {@link #JsonParseException(String, Throwable)} instead.
*
* @param msg error message describing a possible cause of this exception.
*/
public JsonParseException(String msg) {
super(msg);
}
/**
* Creates exception with the specified message and cause.
*
* @param msg error message describing what happened.
* @param cause root exception that caused this exception to be thrown.
*/
public JsonParseException(String msg, Throwable cause) {
super(msg, cause);
}
/**
* Creates exception with the specified cause. Consider using
* {@link #JsonParseException(String, Throwable)} instead if you can describe what happened.
*
* @param cause root exception that caused this exception to be thrown.
*/
public JsonParseException(Throwable cause) {
super(cause);
}
}

View File

@ -1,93 +0,0 @@
/*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
import com.massivecraft.massivecore.xlib.gson.internal.Streams;
import com.massivecraft.massivecore.xlib.gson.stream.JsonReader;
import com.massivecraft.massivecore.xlib.gson.stream.JsonToken;
import com.massivecraft.massivecore.xlib.gson.stream.MalformedJsonException;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
/**
* A parser to parse Json into a parse tree of {@link JsonElement}s
*
* @author Inderjeet Singh
* @author Joel Leitch
* @since 1.3
*/
public final class JsonParser {
/**
* Parses the specified JSON string into a parse tree
*
* @param json JSON text
* @return a parse tree of {@link JsonElement}s corresponding to the specified JSON
* @throws JsonParseException if the specified text is not valid JSON
* @since 1.3
*/
public JsonElement parse(String json) throws JsonSyntaxException {
return parse(new StringReader(json));
}
/**
* Parses the specified JSON string into a parse tree
*
* @param json JSON text
* @return a parse tree of {@link JsonElement}s corresponding to the specified JSON
* @throws JsonParseException if the specified text is not valid JSON
* @since 1.3
*/
public JsonElement parse(Reader json) throws JsonIOException, JsonSyntaxException {
try {
JsonReader jsonReader = new JsonReader(json);
JsonElement element = parse(jsonReader);
if (!element.isJsonNull() && jsonReader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonSyntaxException("Did not consume the entire document.");
}
return element;
} catch (MalformedJsonException e) {
throw new JsonSyntaxException(e);
} catch (IOException e) {
throw new JsonIOException(e);
} catch (NumberFormatException e) {
throw new JsonSyntaxException(e);
}
}
/**
* Returns the next value from the JSON stream as a parse tree.
*
* @throws JsonParseException if there is an IOException or if the specified
* text is not valid JSON
* @since 1.6
*/
public JsonElement parse(JsonReader json) throws JsonIOException, JsonSyntaxException {
boolean lenient = json.isLenient();
json.setLenient(true);
try {
return Streams.parse(json);
} catch (StackOverflowError e) {
throw new JsonParseException("Failed parsing JSON source: " + json + " to Json", e);
} catch (OutOfMemoryError e) {
throw new JsonParseException("Failed parsing JSON source: " + json + " to Json", e);
} finally {
json.setLenient(lenient);
}
}
}

View File

@ -1,341 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
import com.massivecraft.massivecore.xlib.gson.internal.$Gson$Preconditions;
import com.massivecraft.massivecore.xlib.gson.internal.LazilyParsedNumber;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
* A class representing a Json primitive value. A primitive value
* is either a String, a Java primitive, or a Java primitive
* wrapper type.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public final class JsonPrimitive extends JsonElement {
private static final Class<?>[] PRIMITIVE_TYPES = { int.class, long.class, short.class,
float.class, double.class, byte.class, boolean.class, char.class, Integer.class, Long.class,
Short.class, Float.class, Double.class, Byte.class, Boolean.class, Character.class };
private Object value;
/**
* Create a primitive containing a boolean value.
*
* @param bool the value to create the primitive with.
*/
public JsonPrimitive(Boolean bool) {
setValue(bool);
}
/**
* Create a primitive containing a {@link Number}.
*
* @param number the value to create the primitive with.
*/
public JsonPrimitive(Number number) {
setValue(number);
}
/**
* Create a primitive containing a String value.
*
* @param string the value to create the primitive with.
*/
public JsonPrimitive(String string) {
setValue(string);
}
/**
* Create a primitive containing a character. The character is turned into a one character String
* since Json only supports String.
*
* @param c the value to create the primitive with.
*/
public JsonPrimitive(Character c) {
setValue(c);
}
/**
* Create a primitive using the specified Object. It must be an instance of {@link Number}, a
* Java primitive type, or a String.
*
* @param primitive the value to create the primitive with.
*/
JsonPrimitive(Object primitive) {
setValue(primitive);
}
@Override
JsonPrimitive deepCopy() {
return this;
}
void setValue(Object primitive) {
if (primitive instanceof Character) {
// convert characters to strings since in JSON, characters are represented as a single
// character string
char c = ((Character) primitive).charValue();
this.value = String.valueOf(c);
} else {
$Gson$Preconditions.checkArgument(primitive instanceof Number
|| isPrimitiveOrString(primitive));
this.value = primitive;
}
}
/**
* Check whether this primitive contains a boolean value.
*
* @return true if this primitive contains a boolean value, false otherwise.
*/
public boolean isBoolean() {
return value instanceof Boolean;
}
/**
* convenience method to get this element as a {@link Boolean}.
*
* @return get this element as a {@link Boolean}.
*/
@Override
Boolean getAsBooleanWrapper() {
return (Boolean) value;
}
/**
* convenience method to get this element as a boolean value.
*
* @return get this element as a primitive boolean value.
*/
@Override
public boolean getAsBoolean() {
if (isBoolean()) {
return getAsBooleanWrapper().booleanValue();
} else {
// Check to see if the value as a String is "true" in any case.
return Boolean.parseBoolean(getAsString());
}
}
/**
* Check whether this primitive contains a Number.
*
* @return true if this primitive contains a Number, false otherwise.
*/
public boolean isNumber() {
return value instanceof Number;
}
/**
* convenience method to get this element as a Number.
*
* @return get this element as a Number.
* @throws NumberFormatException if the value contained is not a valid Number.
*/
@Override
public Number getAsNumber() {
return value instanceof String ? new LazilyParsedNumber((String) value) : (Number) value;
}
/**
* Check whether this primitive contains a String value.
*
* @return true if this primitive contains a String value, false otherwise.
*/
public boolean isString() {
return value instanceof String;
}
/**
* convenience method to get this element as a String.
*
* @return get this element as a String.
*/
@Override
public String getAsString() {
if (isNumber()) {
return getAsNumber().toString();
} else if (isBoolean()) {
return getAsBooleanWrapper().toString();
} else {
return (String) value;
}
}
/**
* convenience method to get this element as a primitive double.
*
* @return get this element as a primitive double.
* @throws NumberFormatException if the value contained is not a valid double.
*/
@Override
public double getAsDouble() {
return isNumber() ? getAsNumber().doubleValue() : Double.parseDouble(getAsString());
}
/**
* convenience method to get this element as a {@link BigDecimal}.
*
* @return get this element as a {@link BigDecimal}.
* @throws NumberFormatException if the value contained is not a valid {@link BigDecimal}.
*/
@Override
public BigDecimal getAsBigDecimal() {
return value instanceof BigDecimal ? (BigDecimal) value : new BigDecimal(value.toString());
}
/**
* convenience method to get this element as a {@link BigInteger}.
*
* @return get this element as a {@link BigInteger}.
* @throws NumberFormatException if the value contained is not a valid {@link BigInteger}.
*/
@Override
public BigInteger getAsBigInteger() {
return value instanceof BigInteger ?
(BigInteger) value : new BigInteger(value.toString());
}
/**
* convenience method to get this element as a float.
*
* @return get this element as a float.
* @throws NumberFormatException if the value contained is not a valid float.
*/
@Override
public float getAsFloat() {
return isNumber() ? getAsNumber().floatValue() : Float.parseFloat(getAsString());
}
/**
* convenience method to get this element as a primitive long.
*
* @return get this element as a primitive long.
* @throws NumberFormatException if the value contained is not a valid long.
*/
@Override
public long getAsLong() {
return isNumber() ? getAsNumber().longValue() : Long.parseLong(getAsString());
}
/**
* convenience method to get this element as a primitive short.
*
* @return get this element as a primitive short.
* @throws NumberFormatException if the value contained is not a valid short value.
*/
@Override
public short getAsShort() {
return isNumber() ? getAsNumber().shortValue() : Short.parseShort(getAsString());
}
/**
* convenience method to get this element as a primitive integer.
*
* @return get this element as a primitive integer.
* @throws NumberFormatException if the value contained is not a valid integer.
*/
@Override
public int getAsInt() {
return isNumber() ? getAsNumber().intValue() : Integer.parseInt(getAsString());
}
@Override
public byte getAsByte() {
return isNumber() ? getAsNumber().byteValue() : Byte.parseByte(getAsString());
}
@Override
public char getAsCharacter() {
return getAsString().charAt(0);
}
private static boolean isPrimitiveOrString(Object target) {
if (target instanceof String) {
return true;
}
Class<?> classOfPrimitive = target.getClass();
for (Class<?> standardPrimitive : PRIMITIVE_TYPES) {
if (standardPrimitive.isAssignableFrom(classOfPrimitive)) {
return true;
}
}
return false;
}
@Override
public int hashCode() {
if (value == null) {
return 31;
}
// Using recommended hashing algorithm from Effective Java for longs and doubles
if (isIntegral(this)) {
long value = getAsNumber().longValue();
return (int) (value ^ (value >>> 32));
}
if (value instanceof Number) {
long value = Double.doubleToLongBits(getAsNumber().doubleValue());
return (int) (value ^ (value >>> 32));
}
return value.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
JsonPrimitive other = (JsonPrimitive)obj;
if (value == null) {
return other.value == null;
}
if (isIntegral(this) && isIntegral(other)) {
return getAsNumber().longValue() == other.getAsNumber().longValue();
}
if (value instanceof Number && other.value instanceof Number) {
double a = getAsNumber().doubleValue();
// Java standard types other than double return true for two NaN. So, need
// special handling for double.
double b = other.getAsNumber().doubleValue();
return a == b || (Double.isNaN(a) && Double.isNaN(b));
}
return value.equals(other.value);
}
/**
* Returns true if the specified number is an integral type
* (Long, Integer, Short, Byte, BigInteger)
*/
private static boolean isIntegral(JsonPrimitive primitive) {
if (primitive.value instanceof Number) {
Number number = (Number) primitive.value;
return number instanceof BigInteger || number instanceof Long || number instanceof Integer
|| number instanceof Short || number instanceof Byte;
}
return false;
}
}

View File

@ -1,49 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
import java.lang.reflect.Type;
/**
* Context for serialization that is passed to a custom serializer during invocation of its
* {@link JsonSerializer#serialize(Object, Type, JsonSerializationContext)} method.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public interface JsonSerializationContext {
/**
* Invokes default serialization on the specified object.
*
* @param src the object that needs to be serialized.
* @return a tree of {@link JsonElement}s corresponding to the serialized form of {@code src}.
*/
public JsonElement serialize(Object src);
/**
* Invokes default serialization on the specified object passing the specific type information.
* It should never be invoked on the element received as a parameter of the
* {@link JsonSerializer#serialize(Object, Type, JsonSerializationContext)} method. Doing
* so will result in an infinite loop since Gson will in-turn call the custom serializer again.
*
* @param src the object that needs to be serialized.
* @param typeOfSrc the actual genericized type of src object.
* @return a tree of {@link JsonElement}s corresponding to the serialized form of {@code src}.
*/
public JsonElement serialize(Object src, Type typeOfSrc);
}

View File

@ -1,89 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
import java.lang.reflect.Type;
/**
* Interface representing a custom serializer for Json. You should write a custom serializer, if
* you are not happy with the default serialization done by Gson. You will also need to register
* this serializer through {@link GsonBuilder#registerTypeAdapter(Type, Object)}.
*
* <p>Let us look at example where defining a serializer will be useful. The {@code Id} class
* defined below has two fields: {@code clazz} and {@code value}.</p>
*
* <p><pre>
* public class Id&lt;T&gt; {
* private final Class&lt;T&gt; clazz;
* private final long value;
*
* public Id(Class&lt;T&gt; clazz, long value) {
* this.clazz = clazz;
* this.value = value;
* }
*
* public long getValue() {
* return value;
* }
* }
* </pre></p>
*
* <p>The default serialization of {@code Id(com.foo.MyObject.class, 20L)} will be
* <code>{"clazz":com.foo.MyObject,"value":20}</code>. Suppose, you just want the output to be
* the value instead, which is {@code 20} in this case. You can achieve that by writing a custom
* serializer:</p>
*
* <p><pre>
* class IdSerializer implements JsonSerializer&lt;Id&gt;() {
* public JsonElement serialize(Id id, Type typeOfId, JsonSerializationContext context) {
* return new JsonPrimitive(id.getValue());
* }
* }
* </pre></p>
*
* <p>You will also need to register {@code IdSerializer} with Gson as follows:</p>
* <pre>
* Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdSerializer()).create();
* </pre>
*
* <p>New applications should prefer {@link TypeAdapter}, whose streaming API
* is more efficient than this interface's tree API.
*
* @author Inderjeet Singh
* @author Joel Leitch
*
* @param <T> type for which the serializer is being registered. It is possible that a serializer
* may be asked to serialize a specific generic type of the T.
*/
public interface JsonSerializer<T> {
/**
* Gson invokes this call-back method during serialization when it encounters a field of the
* specified type.
*
* <p>In the implementation of this call-back method, you should consider invoking
* {@link JsonSerializationContext#serialize(Object, Type)} method to create JsonElements for any
* non-trivial field of the {@code src} object. However, you should never invoke it on the
* {@code src} object itself since that will cause an infinite loop (Gson will call your
* call-back method again).</p>
*
* @param src the object that needs to be converted to Json.
* @param typeOfSrc the actual type (fully genericized version) of the source object.
* @return a JsonElement corresponding to the specified object.
*/
public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context);
}

View File

@ -1,122 +0,0 @@
/*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
import com.massivecraft.massivecore.xlib.gson.internal.Streams;
import com.massivecraft.massivecore.xlib.gson.stream.JsonReader;
import com.massivecraft.massivecore.xlib.gson.stream.JsonToken;
import com.massivecraft.massivecore.xlib.gson.stream.MalformedJsonException;
import java.io.EOFException;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* A streaming parser that allows reading of multiple {@link JsonElement}s from the specified reader
* asynchronously.
*
* <p>This class is conditionally thread-safe (see Item 70, Effective Java second edition). To
* properly use this class across multiple threads, you will need to add some external
* synchronization. For example:
*
* <pre>
* JsonStreamParser parser = new JsonStreamParser("['first'] {'second':10} 'third'");
* JsonElement element;
* synchronized (parser) { // synchronize on an object shared by threads
* if (parser.hasNext()) {
* element = parser.next();
* }
* }
* </pre>
*
* @author Inderjeet Singh
* @author Joel Leitch
* @since 1.4
*/
public final class JsonStreamParser implements Iterator<JsonElement> {
private final JsonReader parser;
private final Object lock;
/**
* @param json The string containing JSON elements concatenated to each other.
* @since 1.4
*/
public JsonStreamParser(String json) {
this(new StringReader(json));
}
/**
* @param reader The data stream containing JSON elements concatenated to each other.
* @since 1.4
*/
public JsonStreamParser(Reader reader) {
parser = new JsonReader(reader);
parser.setLenient(true);
lock = new Object();
}
/**
* Returns the next available {@link JsonElement} on the reader. Null if none available.
*
* @return the next available {@link JsonElement} on the reader. Null if none available.
* @throws JsonParseException if the incoming stream is malformed JSON.
* @since 1.4
*/
public JsonElement next() throws JsonParseException {
if (!hasNext()) {
throw new NoSuchElementException();
}
try {
return Streams.parse(parser);
} catch (StackOverflowError e) {
throw new JsonParseException("Failed parsing JSON source to Json", e);
} catch (OutOfMemoryError e) {
throw new JsonParseException("Failed parsing JSON source to Json", e);
} catch (JsonParseException e) {
throw e.getCause() instanceof EOFException ? new NoSuchElementException() : e;
}
}
/**
* Returns true if a {@link JsonElement} is available on the input for consumption
* @return true if a {@link JsonElement} is available on the input, false otherwise
* @since 1.4
*/
public boolean hasNext() {
synchronized (lock) {
try {
return parser.peek() != JsonToken.END_DOCUMENT;
} catch (MalformedJsonException e) {
throw new JsonSyntaxException(e);
} catch (IOException e) {
throw new JsonIOException(e);
}
}
}
/**
* This optional {@link Iterator} method is not relevant for stream parsing and hence is not
* implemented.
* @since 1.4
*/
public void remove() {
throw new UnsupportedOperationException();
}
}

View File

@ -1,47 +0,0 @@
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
/**
* This exception is raised when Gson attempts to read (or write) a malformed
* JSON element.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public final class JsonSyntaxException extends JsonParseException {
private static final long serialVersionUID = 1L;
public JsonSyntaxException(String msg) {
super(msg);
}
public JsonSyntaxException(String msg, Throwable cause) {
super(msg, cause);
}
/**
* Creates exception with the specified cause. Consider using
* {@link #JsonSyntaxException(String, Throwable)} instead if you can
* describe what actually happened.
*
* @param cause root exception that caused this exception to be thrown.
*/
public JsonSyntaxException(Throwable cause) {
super(cause);
}
}

View File

@ -1,58 +0,0 @@
/*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
/**
* Defines the expected format for a {@code long} or {@code Long} type when its serialized.
*
* @since 1.3
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public enum LongSerializationPolicy {
/**
* This is the "default" serialization policy that will output a {@code long} object as a JSON
* number. For example, assume an object has a long field named "f" then the serialized output
* would be:
* {@code {"f":123}}.
*/
DEFAULT() {
@Override public JsonElement serialize(Long value) {
return new JsonPrimitive(value);
}
},
/**
* Serializes a long value as a quoted string. For example, assume an object has a long field
* named "f" then the serialized output would be:
* {@code {"f":"123"}}.
*/
STRING() {
@Override public JsonElement serialize(Long value) {
return new JsonPrimitive(String.valueOf(value));
}
};
/**
* Serialize this {@code value} using this serialization policy.
*
* @param value the long value to be serialized into a {@link JsonElement}
* @return the serialized version of {@code value}
*/
public abstract JsonElement serialize(Long value);
}

View File

@ -1,287 +0,0 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
import com.massivecraft.massivecore.xlib.gson.internal.bind.JsonTreeReader;
import com.massivecraft.massivecore.xlib.gson.internal.bind.JsonTreeWriter;
import com.massivecraft.massivecore.xlib.gson.stream.JsonReader;
import com.massivecraft.massivecore.xlib.gson.stream.JsonToken;
import com.massivecraft.massivecore.xlib.gson.stream.JsonWriter;
import java.io.*;
/**
* Converts Java objects to and from JSON.
*
* <h3>Defining a type's JSON form</h3>
* By default Gson converts application classes to JSON using its built-in type
* adapters. If Gson's default JSON conversion isn't appropriate for a type,
* extend this class to customize the conversion. Here's an example of a type
* adapter for an (X,Y) coordinate point: <pre> {@code
*
* public class PointAdapter extends TypeAdapter<Point> {
* public Point read(JsonReader reader) throws IOException {
* if (reader.peek() == JsonToken.NULL) {
* reader.nextNull();
* return null;
* }
* String xy = reader.nextString();
* String[] parts = xy.split(",");
* int x = Integer.parseInt(parts[0]);
* int y = Integer.parseInt(parts[1]);
* return new Point(x, y);
* }
* public void write(JsonWriter writer, Point value) throws IOException {
* if (value == null) {
* writer.nullValue();
* return;
* }
* String xy = value.getX() + "," + value.getY();
* writer.value(xy);
* }
* }}</pre>
* With this type adapter installed, Gson will convert {@code Points} to JSON as
* strings like {@code "5,8"} rather than objects like {@code {"x":5,"y":8}}. In
* this case the type adapter binds a rich Java class to a compact JSON value.
*
* <p>The {@link #read(JsonReader) read()} method must read exactly one value
* and {@link #write(JsonWriter,Object) write()} must write exactly one value.
* For primitive types this is means readers should make exactly one call to
* {@code nextBoolean()}, {@code nextDouble()}, {@code nextInt()}, {@code
* nextLong()}, {@code nextString()} or {@code nextNull()}. Writers should make
* exactly one call to one of <code>value()</code> or <code>nullValue()</code>.
* For arrays, type adapters should start with a call to {@code beginArray()},
* convert all elements, and finish with a call to {@code endArray()}. For
* objects, they should start with {@code beginObject()}, convert the object,
* and finish with {@code endObject()}. Failing to convert a value or converting
* too many values may cause the application to crash.
*
* <p>Type adapters should be prepared to read null from the stream and write it
* to the stream. Alternatively, they should use {@link #nullSafe()} method while
* registering the type adapter with Gson. If your {@code Gson} instance
* has been configured to {@link GsonBuilder#serializeNulls()}, these nulls will be
* written to the final document. Otherwise the value (and the corresponding name
* when writing to a JSON object) will be omitted automatically. In either case
* your type adapter must handle null.
*
* <p>To use a custom type adapter with Gson, you must <i>register</i> it with a
* {@link GsonBuilder}: <pre> {@code
*
* GsonBuilder builder = new GsonBuilder();
* builder.registerTypeAdapter(Point.class, new PointAdapter());
* // if PointAdapter didn't check for nulls in its read/write methods, you should instead use
* // builder.registerTypeAdapter(Point.class, new PointAdapter().nullSafe());
* ...
* Gson gson = builder.create();
* }</pre>
*
* @since 2.1
*/
// non-Javadoc:
//
// <h3>JSON Conversion</h3>
// <p>A type adapter registered with Gson is automatically invoked while serializing
// or deserializing JSON. However, you can also use type adapters directly to serialize
// and deserialize JSON. Here is an example for deserialization: <pre> {@code
//
// String json = "{'origin':'0,0','points':['1,2','3,4']}";
// TypeAdapter<Graph> graphAdapter = gson.getAdapter(Graph.class);
// Graph graph = graphAdapter.fromJson(json);
// }</pre>
// And an example for serialization: <pre> {@code
//
// Graph graph = new Graph(...);
// TypeAdapter<Graph> graphAdapter = gson.getAdapter(Graph.class);
// String json = graphAdapter.toJson(graph);
// }</pre>
//
// <p>Type adapters are <strong>type-specific</strong>. For example, a {@code
// TypeAdapter<Date>} can convert {@code Date} instances to JSON and JSON to
// instances of {@code Date}, but cannot convert any other types.
//
public abstract class TypeAdapter<T> {
/**
* Writes one JSON value (an array, object, string, number, boolean or null)
* for {@code value}.
*
* @param value the Java object to write. May be null.
*/
public abstract void write(JsonWriter out, T value) throws IOException;
/**
* Converts {@code value} to a JSON document and writes it to {@code out}.
* Unlike Gson's similar {@link Gson#toJson(JsonElement, Appendable) toJson}
* method, this write is strict. Create a {@link
* JsonWriter#setLenient(boolean) lenient} {@code JsonWriter} and call
* {@link #write(JsonWriter, Object)} for lenient
* writing.
*
* @param value the Java object to convert. May be null.
* @since 2.2
*/
public final void toJson(Writer out, T value) throws IOException {
JsonWriter writer = new JsonWriter(out);
write(writer, value);
}
/**
* This wrapper method is used to make a type adapter null tolerant. In general, a
* type adapter is required to handle nulls in write and read methods. Here is how this
* is typically done:<br>
* <pre> {@code
*
* Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class,
* new TypeAdapter<Foo>() {
* public Foo read(JsonReader in) throws IOException {
* if (in.peek() == JsonToken.NULL) {
* in.nextNull();
* return null;
* }
* // read a Foo from in and return it
* }
* public void write(JsonWriter out, Foo src) throws IOException {
* if (src == null) {
* out.nullValue();
* return;
* }
* // write src as JSON to out
* }
* }).create();
* }</pre>
* You can avoid this boilerplate handling of nulls by wrapping your type adapter with
* this method. Here is how we will rewrite the above example:
* <pre> {@code
*
* Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class,
* new TypeAdapter<Foo>() {
* public Foo read(JsonReader in) throws IOException {
* // read a Foo from in and return it
* }
* public void write(JsonWriter out, Foo src) throws IOException {
* // write src as JSON to out
* }
* }.nullSafe()).create();
* }</pre>
* Note that we didn't need to check for nulls in our type adapter after we used nullSafe.
*/
public final TypeAdapter<T> nullSafe() {
return new TypeAdapter<T>() {
@Override public void write(JsonWriter out, T value) throws IOException {
if (value == null) {
out.nullValue();
} else {
TypeAdapter.this.write(out, value);
}
}
@Override public T read(JsonReader reader) throws IOException {
if (reader.peek() == JsonToken.NULL) {
reader.nextNull();
return null;
}
return TypeAdapter.this.read(reader);
}
};
}
/**
* Converts {@code value} to a JSON document. Unlike Gson's similar {@link
* Gson#toJson(Object) toJson} method, this write is strict. Create a {@link
* JsonWriter#setLenient(boolean) lenient} {@code JsonWriter} and call
* {@link #write(JsonWriter, Object)} for lenient
* writing.
*
* @param value the Java object to convert. May be null.
* @since 2.2
*/
public final String toJson(T value) {
StringWriter stringWriter = new StringWriter();
try {
toJson(stringWriter, value);
} catch (IOException e) {
throw new AssertionError(e); // No I/O writing to a StringWriter.
}
return stringWriter.toString();
}
/**
* Converts {@code value} to a JSON tree.
*
* @param value the Java object to convert. May be null.
* @return the converted JSON tree. May be {@link JsonNull}.
* @since 2.2
*/
public final JsonElement toJsonTree(T value) {
try {
JsonTreeWriter jsonWriter = new JsonTreeWriter();
write(jsonWriter, value);
return jsonWriter.get();
} catch (IOException e) {
throw new JsonIOException(e);
}
}
/**
* Reads one JSON value (an array, object, string, number, boolean or null)
* and converts it to a Java object. Returns the converted object.
*
* @return the converted Java object. May be null.
*/
public abstract T read(JsonReader in) throws IOException;
/**
* Converts the JSON document in {@code in} to a Java object. Unlike Gson's
* similar {@link Gson#fromJson(java.io.Reader, Class) fromJson} method, this
* read is strict. Create a {@link JsonReader#setLenient(boolean) lenient}
* {@code JsonReader} and call {@link #read(JsonReader)} for lenient reading.
*
* @return the converted Java object. May be null.
* @since 2.2
*/
public final T fromJson(Reader in) throws IOException {
JsonReader reader = new JsonReader(in);
return read(reader);
}
/**
* Converts the JSON document in {@code json} to a Java object. Unlike Gson's
* similar {@link Gson#fromJson(String, Class) fromJson} method, this read is
* strict. Create a {@link JsonReader#setLenient(boolean) lenient} {@code
* JsonReader} and call {@link #read(JsonReader)} for lenient reading.
*
* @return the converted Java object. May be null.
* @since 2.2
*/
public final T fromJson(String json) throws IOException {
return fromJson(new StringReader(json));
}
/**
* Converts {@code jsonTree} to a Java object.
*
* @param jsonTree the Java object to convert. May be {@link JsonNull}.
* @since 2.2
*/
public final T fromJsonTree(JsonElement jsonTree) {
try {
JsonReader jsonReader = new JsonTreeReader(jsonTree);
return read(jsonReader);
} catch (IOException e) {
throw new JsonIOException(e);
}
}
}

View File

@ -1,170 +0,0 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson;
import com.massivecraft.massivecore.xlib.gson.reflect.TypeToken;
/**
* Creates type adapters for set of related types. Type adapter factories are
* most useful when several types share similar structure in their JSON form.
*
* <h3>Example: Converting enums to lowercase</h3>
* In this example, we implement a factory that creates type adapters for all
* enums. The type adapters will write enums in lowercase, despite the fact
* that they're defined in {@code CONSTANT_CASE} in the corresponding Java
* model: <pre> {@code
*
* public class LowercaseEnumTypeAdapterFactory implements TypeAdapterFactory {
* public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
* Class<T> rawType = (Class<T>) type.getRawType();
* if (!rawType.isEnum()) {
* return null;
* }
*
* final Map<String, T> lowercaseToConstant = new HashMap<String, T>();
* for (T constant : rawType.getEnumConstants()) {
* lowercaseToConstant.put(toLowercase(constant), constant);
* }
*
* return new TypeAdapter<T>() {
* public void write(JsonWriter out, T value) throws IOException {
* if (value == null) {
* out.nullValue();
* } else {
* out.value(toLowercase(value));
* }
* }
*
* public T read(JsonReader reader) throws IOException {
* if (reader.peek() == JsonToken.NULL) {
* reader.nextNull();
* return null;
* } else {
* return lowercaseToConstant.get(reader.nextString());
* }
* }
* };
* }
*
* private String toLowercase(Object o) {
* return o.toString().toLowerCase(Locale.US);
* }
* }
* }</pre>
*
* <p>Type adapter factories select which types they provide type adapters
* for. If a factory cannot support a given type, it must return null when
* that type is passed to {@link #create}. Factories should expect {@code
* create()} to be called on them for many types and should return null for
* most of those types. In the above example the factory returns null for
* calls to {@code create()} where {@code type} is not an enum.
*
* <p>A factory is typically called once per type, but the returned type
* adapter may be used many times. It is most efficient to do expensive work
* like reflection in {@code create()} so that the type adapter's {@code
* read()} and {@code write()} methods can be very fast. In this example the
* mapping from lowercase name to enum value is computed eagerly.
*
* <p>As with type adapters, factories must be <i>registered</i> with a {@link
* GsonBuilder} for them to take effect: <pre> {@code
*
* GsonBuilder builder = new GsonBuilder();
* builder.registerTypeAdapterFactory(new LowercaseEnumTypeAdapterFactory());
* ...
* Gson gson = builder.create();
* }</pre>
* If multiple factories support the same type, the factory registered earlier
* takes precedence.
*
* <h3>Example: composing other type adapters</h3>
* In this example we implement a factory for Guava's {@code Multiset}
* collection type. The factory can be used to create type adapters for
* multisets of any element type: the type adapter for {@code
* Multiset<String>} is different from the type adapter for {@code
* Multiset<URL>}.
*
* <p>The type adapter <i>delegates</i> to another type adapter for the
* multiset elements. It figures out the element type by reflecting on the
* multiset's type token. A {@code Gson} is passed in to {@code create} for
* just this purpose: <pre> {@code
*
* public class MultisetTypeAdapterFactory implements TypeAdapterFactory {
* public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
* Type type = typeToken.getType();
* if (typeToken.getRawType() != Multiset.class
* || !(type instanceof ParameterizedType)) {
* return null;
* }
*
* Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0];
* TypeAdapter<?> elementAdapter = gson.getAdapter(TypeToken.get(elementType));
* return (TypeAdapter<T>) newMultisetAdapter(elementAdapter);
* }
*
* private <E> TypeAdapter<Multiset<E>> newMultisetAdapter(
* final TypeAdapter<E> elementAdapter) {
* return new TypeAdapter<Multiset<E>>() {
* public void write(JsonWriter out, Multiset<E> value) throws IOException {
* if (value == null) {
* out.nullValue();
* return;
* }
*
* out.beginArray();
* for (Multiset.Entry<E> entry : value.entrySet()) {
* out.value(entry.getCount());
* elementAdapter.write(out, entry.getElement());
* }
* out.endArray();
* }
*
* public Multiset<E> read(JsonReader in) throws IOException {
* if (in.peek() == JsonToken.NULL) {
* in.nextNull();
* return null;
* }
*
* Multiset<E> result = LinkedHashMultiset.create();
* in.beginArray();
* while (in.hasNext()) {
* int count = in.nextInt();
* E element = elementAdapter.read(in);
* result.add(element, count);
* }
* in.endArray();
* return result;
* }
* };
* }
* }
* }</pre>
* Delegating from one type adapter to another is extremely powerful; it's
* the foundation of how Gson converts Java objects and collections. Whenever
* possible your factory should retrieve its delegate type adapter in the
* {@code create()} method; this ensures potentially-expensive type adapter
* creation happens only once.
*
* @since 2.1
*/
public interface TypeAdapterFactory {
/**
* Returns a type adapter for {@code type}, or null if this factory doesn't
* support {@code type}.
*/
<T> TypeAdapter<T> create(Gson gson, TypeToken<T> type);
}

View File

@ -1,80 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.annotations;
import com.massivecraft.massivecore.xlib.gson.Gson;
import com.massivecraft.massivecore.xlib.gson.GsonBuilder;
import java.lang.annotation.*;
/**
* An annotation that indicates this member should be exposed for JSON
* serialization or deserialization.
*
* <p>This annotation has no effect unless you build {@link Gson}
* with a {@link GsonBuilder} and invoke
* {@link GsonBuilder#excludeFieldsWithoutExposeAnnotation()}
* method.</p>
*
* <p>Here is an example of how this annotation is meant to be used:
* <p><pre>
* public class User {
* &#64Expose private String firstName;
* &#64Expose(serialize = false) private String lastName;
* &#64Expose (serialize = false, deserialize = false) private String emailAddress;
* private String password;
* }
* </pre></p>
* If you created Gson with {@code new Gson()}, the {@code toJson()} and {@code fromJson()}
* methods will use the {@code password} field along-with {@code firstName}, {@code lastName},
* and {@code emailAddress} for serialization and deserialization. However, if you created Gson
* with {@code Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()}
* then the {@code toJson()} and {@code fromJson()} methods of Gson will exclude the
* {@code password} field. This is because the {@code password} field is not marked with the
* {@code @Expose} annotation. Gson will also exclude {@code lastName} and {@code emailAddress}
* from serialization since {@code serialize} is set to {@code false}. Similarly, Gson will
* exclude {@code emailAddress} from deserialization since {@code deserialize} is set to false.
*
* <p>Note that another way to achieve the same effect would have been to just mark the
* {@code password} field as {@code transient}, and Gson would have excluded it even with default
* settings. The {@code @Expose} annotation is useful in a style of programming where you want to
* explicitly specify all fields that should get considered for serialization or deserialization.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Expose {
/**
* If {@code true}, the field marked with this annotation is written out in the JSON while
* serializing. If {@code false}, the field marked with this annotation is skipped from the
* serialized output. Defaults to {@code true}.
* @since 1.4
*/
public boolean serialize() default true;
/**
* If {@code true}, the field marked with this annotation is deserialized from the JSON.
* If {@code false}, the field marked with this annotation is skipped during deserialization.
* Defaults to {@code true}.
* @since 1.4
*/
public boolean deserialize() default true;
}

View File

@ -1,102 +0,0 @@
/*
* Copyright (C) 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.annotations;
import com.massivecraft.massivecore.xlib.gson.GsonBuilder;
import com.massivecraft.massivecore.xlib.gson.TypeAdapter;
import com.massivecraft.massivecore.xlib.gson.TypeAdapterFactory;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* An annotation that indicates the Gson {@link TypeAdapter} to use with a class
* or field.
*
* <p>Here is an example of how this annotation is used:</p>
* <pre>
* &#64JsonAdapter(UserJsonAdapter.class)
* public class User {
* public final String firstName, lastName;
* private User(String firstName, String lastName) {
* this.firstName = firstName;
* this.lastName = lastName;
* }
* }
* public class UserJsonAdapter extends TypeAdapter&lt;User&gt; {
* &#64Override public void write(JsonWriter out, User user) throws IOException {
* // implement write: combine firstName and lastName into name
* out.beginObject();
* out.name("name");
* out.value(user.firstName + " " + user.lastName);
* out.endObject();
* // implement the write method
* }
* &#64Override public User read(JsonReader in) throws IOException {
* // implement read: split name into firstName and lastName
* in.beginObject();
* in.nextName();
* String[] nameParts = in.nextString().split(" ");
* in.endObject();
* return new User(nameParts[0], nameParts[1]);
* }
* }
* </pre>
*
* Since User class specified UserJsonAdapter.class in &#64JsonAdapter annotation, it
* will automatically be invoked to serialize/deserialize User instances. <br>
*
* <p> Here is an example of how to apply this annotation to a field.
* <pre>
* private static final class Gadget {
* &#64JsonAdapter(UserJsonAdapter2.class)
* final User user;
* Gadget(User user) {
* this.user = user;
* }
* }
* </pre>
*
* It's possible to specify different type adapters on a field, that
* field's type, and in the {@link GsonBuilder}. Field
* annotations take precedence over {@code GsonBuilder}-registered type
* adapters, which in turn take precedence over annotated types.
*
* <p>The class referenced by this annotation must be either a {@link
* TypeAdapter} or a {@link TypeAdapterFactory}. Using the factory interface
* makes it possible to delegate to the enclosing {@code Gson} instance.
*
* @since 2.3
*
* @author Inderjeet Singh
* @author Joel Leitch
* @author Jesse Wilson
*/
// Note that the above example is taken from AdaptAnnotationTest.
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface JsonAdapter {
/** Either a {@link TypeAdapter} or {@link TypeAdapterFactory}. */
Class<?> value();
/** false, to be able to handle {@code null} values within the adapter, default value is true. */
boolean nullSafe() default true;
}

View File

@ -1,93 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.annotations;
import com.massivecraft.massivecore.xlib.gson.FieldNamingPolicy;
import com.massivecraft.massivecore.xlib.gson.Gson;
import com.massivecraft.massivecore.xlib.gson.GsonBuilder;
import java.lang.annotation.*;
/**
* An annotation that indicates this member should be serialized to JSON with
* the provided name value as its field name.
*
* <p>This annotation will override any {@link FieldNamingPolicy}, including
* the default field naming policy, that may have been set on the {@link Gson}
* instance. A different naming policy can set using the {@code GsonBuilder} class. See
* {@link GsonBuilder#setFieldNamingPolicy(FieldNamingPolicy)}
* for more information.</p>
*
* <p>Here is an example of how this annotation is meant to be used:</p>
* <pre>
* public class MyClass {
* &#64SerializedName("name") String a;
* &#64SerializedName(value="name1", alternate={"name2", "name3"}) String b;
* String c;
*
* public MyClass(String a, String b, String c) {
* this.a = a;
* this.b = b;
* this.c = c;
* }
* }
* </pre>
*
* <p>The following shows the output that is generated when serializing an instance of the
* above example class:</p>
* <pre>
* MyClass target = new MyClass("v1", "v2", "v3");
* Gson gson = new Gson();
* String json = gson.toJson(target);
* System.out.println(json);
*
* ===== OUTPUT =====
* {"name":"v1","name1":"v2","c":"v3"}
* </pre>
*
* <p>NOTE: The value you specify in this annotation must be a valid JSON field name.</p>
* While deserializing, all values specified in the annotation will be deserialized into the field.
* For example:
* <pre>
* MyClass target = gson.fromJson("{'name1':'v1'}", MyClass.class);
* assertEquals("v1", target.b);
* target = gson.fromJson("{'name2':'v2'}", MyClass.class);
* assertEquals("v2", target.b);
* target = gson.fromJson("{'name3':'v3'}", MyClass.class);
* assertEquals("v3", target.b);
* </pre>
* Note that MyClass.b is now deserialized from either name1, name2 or name3.
*
* @see FieldNamingPolicy
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface SerializedName {
/**
* @return the desired name of the field when it is serialized or deserialized
*/
String value();
/**
* @return the alternative names of the field when it is deserialized
*/
String[] alternate() default {};
}

View File

@ -1,62 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.annotations;
import com.massivecraft.massivecore.xlib.gson.Gson;
import com.massivecraft.massivecore.xlib.gson.GsonBuilder;
import java.lang.annotation.*;
/**
* An annotation that indicates the version number since a member or a type has been present.
* This annotation is useful to manage versioning of your Json classes for a web-service.
*
* <p>
* This annotation has no effect unless you build {@link Gson} with a
* {@link GsonBuilder} and invoke
* {@link GsonBuilder#setVersion(double)} method.
*
* <p>Here is an example of how this annotation is meant to be used:</p>
* <pre>
* public class User {
* private String firstName;
* private String lastName;
* &#64Since(1.0) private String emailAddress;
* &#64Since(1.0) private String password;
* &#64Since(1.1) private Address address;
* }
* </pre>
*
* <p>If you created Gson with {@code new Gson()}, the {@code toJson()} and {@code fromJson()}
* methods will use all the fields for serialization and deserialization. However, if you created
* Gson with {@code Gson gson = new GsonBuilder().setVersion(1.0).create()} then the
* {@code toJson()} and {@code fromJson()} methods of Gson will exclude the {@code address} field
* since it's version number is set to {@code 1.1}.</p>
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Since {
/**
* the value indicating a version number since this member
* or type has been present.
*/
double value();
}

View File

@ -1,67 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.annotations;
import com.massivecraft.massivecore.xlib.gson.Gson;
import com.massivecraft.massivecore.xlib.gson.GsonBuilder;
import java.lang.annotation.*;
/**
* An annotation that indicates the version number until a member or a type should be present.
* Basically, if Gson is created with a version number that exceeds the value stored in the
* {@code Until} annotation then the field will be ignored from the JSON output. This annotation
* is useful to manage versioning of your JSON classes for a web-service.
*
* <p>
* This annotation has no effect unless you build {@link Gson} with a
* {@link GsonBuilder} and invoke
* {@link GsonBuilder#setVersion(double)} method.
*
* <p>Here is an example of how this annotation is meant to be used:</p>
* <pre>
* public class User {
* private String firstName;
* private String lastName;
* &#64Until(1.1) private String emailAddress;
* &#64Until(1.1) private String password;
* }
* </pre>
*
* <p>If you created Gson with {@code new Gson()}, the {@code toJson()} and {@code fromJson()}
* methods will use all the fields for serialization and deserialization. However, if you created
* Gson with {@code Gson gson = new GsonBuilder().setVersion(1.2).create()} then the
* {@code toJson()} and {@code fromJson()} methods of Gson will exclude the {@code emailAddress}
* and {@code password} fields from the example above, because the version number passed to the
* GsonBuilder, {@code 1.2}, exceeds the version number set on the {@code Until} annotation,
* {@code 1.1}, for those fields.
*
* @author Inderjeet Singh
* @author Joel Leitch
* @since 1.3
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Until {
/**
* the value indicating a version number until this member
* or type should be ignored.
*/
double value();
}

View File

@ -1,6 +0,0 @@
/**
* This package provides annotations that can be used with {@link com.massivecraft.massivecore.xlib.gson.Gson}.
*
* @author Inderjeet Singh, Joel Leitch
*/
package com.massivecraft.massivecore.xlib.gson.annotations;

View File

@ -1,49 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.internal;
/**
* A simple utility class used to check method Preconditions.
*
* <pre>
* public long divideBy(long value) {
* Preconditions.checkArgument(value != 0);
* return this.value / value;
* }
* </pre>
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public final class $Gson$Preconditions {
private $Gson$Preconditions() {
throw new UnsupportedOperationException();
}
public static <T> T checkNotNull(T obj) {
if (obj == null) {
throw new NullPointerException();
}
return obj;
}
public static void checkArgument(boolean condition) {
if (!condition) {
throw new IllegalArgumentException();
}
}
}

View File

@ -1,577 +0,0 @@
/**
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.internal;
import java.io.Serializable;
import java.lang.reflect.*;
import java.util.*;
import static com.massivecraft.massivecore.xlib.gson.internal.$Gson$Preconditions.checkArgument;
import static com.massivecraft.massivecore.xlib.gson.internal.$Gson$Preconditions.checkNotNull;
/**
* Static methods for working with types.
*
* @author Bob Lee
* @author Jesse Wilson
*/
public final class $Gson$Types {
static final Type[] EMPTY_TYPE_ARRAY = new Type[] {};
private $Gson$Types() {
throw new UnsupportedOperationException();
}
/**
* Returns a new parameterized type, applying {@code typeArguments} to
* {@code rawType} and enclosed by {@code ownerType}.
*
* @return a {@link java.io.Serializable serializable} parameterized type.
*/
public static ParameterizedType newParameterizedTypeWithOwner(
Type ownerType, Type rawType, Type... typeArguments) {
return new ParameterizedTypeImpl(ownerType, rawType, typeArguments);
}
/**
* Returns an array type whose elements are all instances of
* {@code componentType}.
*
* @return a {@link java.io.Serializable serializable} generic array type.
*/
public static GenericArrayType arrayOf(Type componentType) {
return new GenericArrayTypeImpl(componentType);
}
/**
* Returns a type that represents an unknown type that extends {@code bound}.
* For example, if {@code bound} is {@code CharSequence.class}, this returns
* {@code ? extends CharSequence}. If {@code bound} is {@code Object.class},
* this returns {@code ?}, which is shorthand for {@code ? extends Object}.
*/
public static WildcardType subtypeOf(Type bound) {
return new WildcardTypeImpl(new Type[] { bound }, EMPTY_TYPE_ARRAY);
}
/**
* Returns a type that represents an unknown supertype of {@code bound}. For
* example, if {@code bound} is {@code String.class}, this returns {@code ?
* super String}.
*/
public static WildcardType supertypeOf(Type bound) {
return new WildcardTypeImpl(new Type[] { Object.class }, new Type[] { bound });
}
/**
* Returns a type that is functionally equal but not necessarily equal
* according to {@link Object#equals(Object) Object.equals()}. The returned
* type is {@link java.io.Serializable}.
*/
public static Type canonicalize(Type type) {
if (type instanceof Class) {
Class<?> c = (Class<?>) type;
return c.isArray() ? new GenericArrayTypeImpl(canonicalize(c.getComponentType())) : c;
} else if (type instanceof ParameterizedType) {
ParameterizedType p = (ParameterizedType) type;
return new ParameterizedTypeImpl(p.getOwnerType(),
p.getRawType(), p.getActualTypeArguments());
} else if (type instanceof GenericArrayType) {
GenericArrayType g = (GenericArrayType) type;
return new GenericArrayTypeImpl(g.getGenericComponentType());
} else if (type instanceof WildcardType) {
WildcardType w = (WildcardType) type;
return new WildcardTypeImpl(w.getUpperBounds(), w.getLowerBounds());
} else {
// type is either serializable as-is or unsupported
return type;
}
}
public static Class<?> getRawType(Type type) {
if (type instanceof Class<?>) {
// type is a normal class.
return (Class<?>) type;
} else if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
// I'm not exactly sure why getRawType() returns Type instead of Class.
// Neal isn't either but suspects some pathological case related
// to nested classes exists.
Type rawType = parameterizedType.getRawType();
checkArgument(rawType instanceof Class);
return (Class<?>) rawType;
} else if (type instanceof GenericArrayType) {
Type componentType = ((GenericArrayType)type).getGenericComponentType();
return Array.newInstance(getRawType(componentType), 0).getClass();
} else if (type instanceof TypeVariable) {
// we could use the variable's bounds, but that won't work if there are multiple.
// having a raw type that's more general than necessary is okay
return Object.class;
} else if (type instanceof WildcardType) {
return getRawType(((WildcardType) type).getUpperBounds()[0]);
} else {
String className = type == null ? "null" : type.getClass().getName();
throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
+ "GenericArrayType, but <" + type + "> is of type " + className);
}
}
static boolean equal(Object a, Object b) {
return a == b || (a != null && a.equals(b));
}
/**
* Returns true if {@code a} and {@code b} are equal.
*/
public static boolean equals(Type a, Type b) {
if (a == b) {
// also handles (a == null && b == null)
return true;
} else if (a instanceof Class) {
// Class already specifies equals().
return a.equals(b);
} else if (a instanceof ParameterizedType) {
if (!(b instanceof ParameterizedType)) {
return false;
}
// TODO: save a .clone() call
ParameterizedType pa = (ParameterizedType) a;
ParameterizedType pb = (ParameterizedType) b;
return equal(pa.getOwnerType(), pb.getOwnerType())
&& pa.getRawType().equals(pb.getRawType())
&& Arrays.equals(pa.getActualTypeArguments(), pb.getActualTypeArguments());
} else if (a instanceof GenericArrayType) {
if (!(b instanceof GenericArrayType)) {
return false;
}
GenericArrayType ga = (GenericArrayType) a;
GenericArrayType gb = (GenericArrayType) b;
return equals(ga.getGenericComponentType(), gb.getGenericComponentType());
} else if (a instanceof WildcardType) {
if (!(b instanceof WildcardType)) {
return false;
}
WildcardType wa = (WildcardType) a;
WildcardType wb = (WildcardType) b;
return Arrays.equals(wa.getUpperBounds(), wb.getUpperBounds())
&& Arrays.equals(wa.getLowerBounds(), wb.getLowerBounds());
} else if (a instanceof TypeVariable) {
if (!(b instanceof TypeVariable)) {
return false;
}
TypeVariable<?> va = (TypeVariable<?>) a;
TypeVariable<?> vb = (TypeVariable<?>) b;
return va.getGenericDeclaration() == vb.getGenericDeclaration()
&& va.getName().equals(vb.getName());
} else {
// This isn't a type we support. Could be a generic array type, wildcard type, etc.
return false;
}
}
static int hashCodeOrZero(Object o) {
return o != null ? o.hashCode() : 0;
}
public static String typeToString(Type type) {
return type instanceof Class ? ((Class<?>) type).getName() : type.toString();
}
/**
* Returns the generic supertype for {@code supertype}. For example, given a class {@code
* IntegerSet}, the result for when supertype is {@code Set.class} is {@code Set<Integer>} and the
* result when the supertype is {@code Collection.class} is {@code Collection<Integer>}.
*/
static Type getGenericSupertype(Type context, Class<?> rawType, Class<?> toResolve) {
if (toResolve == rawType) {
return context;
}
// we skip searching through interfaces if unknown is an interface
if (toResolve.isInterface()) {
Class<?>[] interfaces = rawType.getInterfaces();
for (int i = 0, length = interfaces.length; i < length; i++) {
if (interfaces[i] == toResolve) {
return rawType.getGenericInterfaces()[i];
} else if (toResolve.isAssignableFrom(interfaces[i])) {
return getGenericSupertype(rawType.getGenericInterfaces()[i], interfaces[i], toResolve);
}
}
}
// check our supertypes
if (!rawType.isInterface()) {
while (rawType != Object.class) {
Class<?> rawSupertype = rawType.getSuperclass();
if (rawSupertype == toResolve) {
return rawType.getGenericSuperclass();
} else if (toResolve.isAssignableFrom(rawSupertype)) {
return getGenericSupertype(rawType.getGenericSuperclass(), rawSupertype, toResolve);
}
rawType = rawSupertype;
}
}
// we can't resolve this further
return toResolve;
}
/**
* Returns the generic form of {@code supertype}. For example, if this is {@code
* ArrayList<String>}, this returns {@code Iterable<String>} given the input {@code
* Iterable.class}.
*
* @param supertype a superclass of, or interface implemented by, this.
*/
static Type getSupertype(Type context, Class<?> contextRawType, Class<?> supertype) {
checkArgument(supertype.isAssignableFrom(contextRawType));
return resolve(context, contextRawType,
$Gson$Types.getGenericSupertype(context, contextRawType, supertype));
}
/**
* Returns the component type of this array type.
* @throws ClassCastException if this type is not an array.
*/
public static Type getArrayComponentType(Type array) {
return array instanceof GenericArrayType
? ((GenericArrayType) array).getGenericComponentType()
: ((Class<?>) array).getComponentType();
}
/**
* Returns the element type of this collection type.
* @throws IllegalArgumentException if this type is not a collection.
*/
public static Type getCollectionElementType(Type context, Class<?> contextRawType) {
Type collectionType = getSupertype(context, contextRawType, Collection.class);
if (collectionType instanceof WildcardType) {
collectionType = ((WildcardType)collectionType).getUpperBounds()[0];
}
if (collectionType instanceof ParameterizedType) {
return ((ParameterizedType) collectionType).getActualTypeArguments()[0];
}
return Object.class;
}
/**
* Returns a two element array containing this map's key and value types in
* positions 0 and 1 respectively.
*/
public static Type[] getMapKeyAndValueTypes(Type context, Class<?> contextRawType) {
/*
* Work around a problem with the declaration of java.util.Properties. That
* class should extend Hashtable<String, String>, but it's declared to
* extend Hashtable<Object, Object>.
*/
if (context == Properties.class) {
return new Type[] { String.class, String.class }; // TODO: test subclasses of Properties!
}
Type mapType = getSupertype(context, contextRawType, Map.class);
// TODO: strip wildcards?
if (mapType instanceof ParameterizedType) {
ParameterizedType mapParameterizedType = (ParameterizedType) mapType;
return mapParameterizedType.getActualTypeArguments();
}
return new Type[] { Object.class, Object.class };
}
public static Type resolve(Type context, Class<?> contextRawType, Type toResolve) {
// this implementation is made a little more complicated in an attempt to avoid object-creation
while (true) {
if (toResolve instanceof TypeVariable) {
TypeVariable<?> typeVariable = (TypeVariable<?>) toResolve;
toResolve = resolveTypeVariable(context, contextRawType, typeVariable);
if (toResolve == typeVariable) {
return toResolve;
}
} else if (toResolve instanceof Class && ((Class<?>) toResolve).isArray()) {
Class<?> original = (Class<?>) toResolve;
Type componentType = original.getComponentType();
Type newComponentType = resolve(context, contextRawType, componentType);
return componentType == newComponentType
? original
: arrayOf(newComponentType);
} else if (toResolve instanceof GenericArrayType) {
GenericArrayType original = (GenericArrayType) toResolve;
Type componentType = original.getGenericComponentType();
Type newComponentType = resolve(context, contextRawType, componentType);
return componentType == newComponentType
? original
: arrayOf(newComponentType);
} else if (toResolve instanceof ParameterizedType) {
ParameterizedType original = (ParameterizedType) toResolve;
Type ownerType = original.getOwnerType();
Type newOwnerType = resolve(context, contextRawType, ownerType);
boolean changed = newOwnerType != ownerType;
Type[] args = original.getActualTypeArguments();
for (int t = 0, length = args.length; t < length; t++) {
Type resolvedTypeArgument = resolve(context, contextRawType, args[t]);
if (resolvedTypeArgument != args[t]) {
if (!changed) {
args = args.clone();
changed = true;
}
args[t] = resolvedTypeArgument;
}
}
return changed
? newParameterizedTypeWithOwner(newOwnerType, original.getRawType(), args)
: original;
} else if (toResolve instanceof WildcardType) {
WildcardType original = (WildcardType) toResolve;
Type[] originalLowerBound = original.getLowerBounds();
Type[] originalUpperBound = original.getUpperBounds();
if (originalLowerBound.length == 1) {
Type lowerBound = resolve(context, contextRawType, originalLowerBound[0]);
if (lowerBound != originalLowerBound[0]) {
return supertypeOf(lowerBound);
}
} else if (originalUpperBound.length == 1) {
Type upperBound = resolve(context, contextRawType, originalUpperBound[0]);
if (upperBound != originalUpperBound[0]) {
return subtypeOf(upperBound);
}
}
return original;
} else {
return toResolve;
}
}
}
static Type resolveTypeVariable(Type context, Class<?> contextRawType, TypeVariable<?> unknown) {
Class<?> declaredByRaw = declaringClassOf(unknown);
// we can't reduce this further
if (declaredByRaw == null) {
return unknown;
}
Type declaredBy = getGenericSupertype(context, contextRawType, declaredByRaw);
if (declaredBy instanceof ParameterizedType) {
int index = indexOf(declaredByRaw.getTypeParameters(), unknown);
return ((ParameterizedType) declaredBy).getActualTypeArguments()[index];
}
return unknown;
}
private static int indexOf(Object[] array, Object toFind) {
for (int i = 0; i < array.length; i++) {
if (toFind.equals(array[i])) {
return i;
}
}
throw new NoSuchElementException();
}
/**
* Returns the declaring class of {@code typeVariable}, or {@code null} if it was not declared by
* a class.
*/
private static Class<?> declaringClassOf(TypeVariable<?> typeVariable) {
GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
return genericDeclaration instanceof Class
? (Class<?>) genericDeclaration
: null;
}
static void checkNotPrimitive(Type type) {
checkArgument(!(type instanceof Class<?>) || !((Class<?>) type).isPrimitive());
}
private static final class ParameterizedTypeImpl implements ParameterizedType, Serializable {
private final Type ownerType;
private final Type rawType;
private final Type[] typeArguments;
public ParameterizedTypeImpl(Type ownerType, Type rawType, Type... typeArguments) {
// require an owner type if the raw type needs it
if (rawType instanceof Class<?>) {
Class<?> rawTypeAsClass = (Class<?>) rawType;
boolean isStaticOrTopLevelClass = Modifier.isStatic(rawTypeAsClass.getModifiers())
|| rawTypeAsClass.getEnclosingClass() == null;
checkArgument(ownerType != null || isStaticOrTopLevelClass);
}
this.ownerType = ownerType == null ? null : canonicalize(ownerType);
this.rawType = canonicalize(rawType);
this.typeArguments = typeArguments.clone();
for (int t = 0; t < this.typeArguments.length; t++) {
checkNotNull(this.typeArguments[t]);
checkNotPrimitive(this.typeArguments[t]);
this.typeArguments[t] = canonicalize(this.typeArguments[t]);
}
}
public Type[] getActualTypeArguments() {
return typeArguments.clone();
}
public Type getRawType() {
return rawType;
}
public Type getOwnerType() {
return ownerType;
}
@Override public boolean equals(Object other) {
return other instanceof ParameterizedType
&& $Gson$Types.equals(this, (ParameterizedType) other);
}
@Override public int hashCode() {
return Arrays.hashCode(typeArguments)
^ rawType.hashCode()
^ hashCodeOrZero(ownerType);
}
@Override public String toString() {
StringBuilder stringBuilder = new StringBuilder(30 * (typeArguments.length + 1));
stringBuilder.append(typeToString(rawType));
if (typeArguments.length == 0) {
return stringBuilder.toString();
}
stringBuilder.append("<").append(typeToString(typeArguments[0]));
for (int i = 1; i < typeArguments.length; i++) {
stringBuilder.append(", ").append(typeToString(typeArguments[i]));
}
return stringBuilder.append(">").toString();
}
private static final long serialVersionUID = 0;
}
private static final class GenericArrayTypeImpl implements GenericArrayType, Serializable {
private final Type componentType;
public GenericArrayTypeImpl(Type componentType) {
this.componentType = canonicalize(componentType);
}
public Type getGenericComponentType() {
return componentType;
}
@Override public boolean equals(Object o) {
return o instanceof GenericArrayType
&& $Gson$Types.equals(this, (GenericArrayType) o);
}
@Override public int hashCode() {
return componentType.hashCode();
}
@Override public String toString() {
return typeToString(componentType) + "[]";
}
private static final long serialVersionUID = 0;
}
/**
* The WildcardType interface supports multiple upper bounds and multiple
* lower bounds. We only support what the Java 6 language needs - at most one
* bound. If a lower bound is set, the upper bound must be Object.class.
*/
private static final class WildcardTypeImpl implements WildcardType, Serializable {
private final Type upperBound;
private final Type lowerBound;
public WildcardTypeImpl(Type[] upperBounds, Type[] lowerBounds) {
checkArgument(lowerBounds.length <= 1);
checkArgument(upperBounds.length == 1);
if (lowerBounds.length == 1) {
checkNotNull(lowerBounds[0]);
checkNotPrimitive(lowerBounds[0]);
checkArgument(upperBounds[0] == Object.class);
this.lowerBound = canonicalize(lowerBounds[0]);
this.upperBound = Object.class;
} else {
checkNotNull(upperBounds[0]);
checkNotPrimitive(upperBounds[0]);
this.lowerBound = null;
this.upperBound = canonicalize(upperBounds[0]);
}
}
public Type[] getUpperBounds() {
return new Type[] { upperBound };
}
public Type[] getLowerBounds() {
return lowerBound != null ? new Type[] { lowerBound } : EMPTY_TYPE_ARRAY;
}
@Override public boolean equals(Object other) {
return other instanceof WildcardType
&& $Gson$Types.equals(this, (WildcardType) other);
}
@Override public int hashCode() {
// this equals Arrays.hashCode(getLowerBounds()) ^ Arrays.hashCode(getUpperBounds());
return (lowerBound != null ? 31 + lowerBound.hashCode() : 1)
^ (31 + upperBound.hashCode());
}
@Override public String toString() {
if (lowerBound != null) {
return "? super " + typeToString(lowerBound);
} else if (upperBound == Object.class) {
return "?";
} else {
return "? extends " + typeToString(upperBound);
}
}
private static final long serialVersionUID = 0;
}
}

View File

@ -1,224 +0,0 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.internal;
import com.massivecraft.massivecore.xlib.gson.InstanceCreator;
import com.massivecraft.massivecore.xlib.gson.JsonIOException;
import com.massivecraft.massivecore.xlib.gson.reflect.TypeToken;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
/**
* Returns a function that can construct an instance of a requested type.
*/
public final class ConstructorConstructor {
private final Map<Type, InstanceCreator<?>> instanceCreators;
public ConstructorConstructor(Map<Type, InstanceCreator<?>> instanceCreators) {
this.instanceCreators = instanceCreators;
}
public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) {
final Type type = typeToken.getType();
final Class<? super T> rawType = typeToken.getRawType();
// first try an instance creator
@SuppressWarnings("unchecked") // types must agree
final InstanceCreator<T> typeCreator = (InstanceCreator<T>) instanceCreators.get(type);
if (typeCreator != null) {
return new ObjectConstructor<T>() {
@Override public T construct() {
return typeCreator.createInstance(type);
}
};
}
// Next try raw type match for instance creators
@SuppressWarnings("unchecked") // types must agree
final InstanceCreator<T> rawTypeCreator =
(InstanceCreator<T>) instanceCreators.get(rawType);
if (rawTypeCreator != null) {
return new ObjectConstructor<T>() {
@Override public T construct() {
return rawTypeCreator.createInstance(type);
}
};
}
ObjectConstructor<T> defaultConstructor = newDefaultConstructor(rawType);
if (defaultConstructor != null) {
return defaultConstructor;
}
ObjectConstructor<T> defaultImplementation = newDefaultImplementationConstructor(type, rawType);
if (defaultImplementation != null) {
return defaultImplementation;
}
// finally try unsafe
return newUnsafeAllocator(type, rawType);
}
private <T> ObjectConstructor<T> newDefaultConstructor(Class<? super T> rawType) {
try {
final Constructor<? super T> constructor = rawType.getDeclaredConstructor();
if (!constructor.isAccessible()) {
constructor.setAccessible(true);
}
return new ObjectConstructor<T>() {
@SuppressWarnings("unchecked") // T is the same raw type as is requested
@Override public T construct() {
try {
Object[] args = null;
return (T) constructor.newInstance(args);
} catch (InstantiationException e) {
// TODO: JsonParseException ?
throw new RuntimeException("Failed to invoke " + constructor + " with no args", e);
} catch (InvocationTargetException e) {
// TODO: don't wrap if cause is unchecked!
// TODO: JsonParseException ?
throw new RuntimeException("Failed to invoke " + constructor + " with no args",
e.getTargetException());
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
}
};
} catch (NoSuchMethodException e) {
return null;
}
}
/**
* Constructors for common interface types like Map and List and their
* subtypes.
*/
@SuppressWarnings("unchecked") // use runtime checks to guarantee that 'T' is what it is
private <T> ObjectConstructor<T> newDefaultImplementationConstructor(
final Type type, Class<? super T> rawType) {
if (Collection.class.isAssignableFrom(rawType)) {
if (SortedSet.class.isAssignableFrom(rawType)) {
return new ObjectConstructor<T>() {
@Override public T construct() {
return (T) new TreeSet<>();
}
};
} else if (EnumSet.class.isAssignableFrom(rawType)) {
return new ObjectConstructor<T>() {
@SuppressWarnings("rawtypes")
@Override public T construct() {
if (type instanceof ParameterizedType) {
Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0];
if (elementType instanceof Class) {
return (T) EnumSet.noneOf((Class)elementType);
} else {
throw new JsonIOException("Invalid EnumSet type: " + type.toString());
}
} else {
throw new JsonIOException("Invalid EnumSet type: " + type.toString());
}
}
};
} else if (Set.class.isAssignableFrom(rawType)) {
return new ObjectConstructor<T>() {
@Override public T construct() {
return (T) new LinkedHashSet<>();
}
};
} else if (Queue.class.isAssignableFrom(rawType)) {
return new ObjectConstructor<T>() {
@Override public T construct() {
return (T) new ArrayDeque<>();
}
};
} else {
return new ObjectConstructor<T>() {
@Override public T construct() {
return (T) new ArrayList<>();
}
};
}
}
if (Map.class.isAssignableFrom(rawType)) {
if (ConcurrentNavigableMap.class.isAssignableFrom(rawType)) {
return new ObjectConstructor<T>() {
@Override public T construct() {
return (T) new ConcurrentSkipListMap<>();
}
};
} else if (ConcurrentMap.class.isAssignableFrom(rawType)) {
return new ObjectConstructor<T>() {
@Override public T construct() {
return (T) new ConcurrentHashMap<>();
}
};
} else if (SortedMap.class.isAssignableFrom(rawType)) {
return new ObjectConstructor<T>() {
@Override public T construct() {
return (T) new TreeMap<>();
}
};
} else if (type instanceof ParameterizedType && !(String.class.isAssignableFrom(
TypeToken.get(((ParameterizedType) type).getActualTypeArguments()[0]).getRawType()))) {
return new ObjectConstructor<T>() {
@Override public T construct() {
return (T) new LinkedHashMap<>();
}
};
} else {
return new ObjectConstructor<T>() {
@Override public T construct() {
return (T) new LinkedTreeMap<String, Object>();
}
};
}
}
return null;
}
private <T> ObjectConstructor<T> newUnsafeAllocator(
final Type type, final Class<? super T> rawType) {
return new ObjectConstructor<T>() {
private final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create();
@SuppressWarnings("unchecked")
@Override public T construct() {
try {
Object newInstance = unsafeAllocator.newInstance(rawType);
return (T) newInstance;
} catch (Exception e) {
throw new RuntimeException(("Unable to invoke no-args constructor for " + type + ". "
+ "Register an InstanceCreator with Gson for this type may fix this problem."), e);
}
}
};
}
@Override public String toString() {
return instanceCreators.toString();
}
}

View File

@ -1,248 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.internal;
import com.massivecraft.massivecore.xlib.gson.*;
import com.massivecraft.massivecore.xlib.gson.annotations.Expose;
import com.massivecraft.massivecore.xlib.gson.annotations.Since;
import com.massivecraft.massivecore.xlib.gson.annotations.Until;
import com.massivecraft.massivecore.xlib.gson.reflect.TypeToken;
import com.massivecraft.massivecore.xlib.gson.stream.JsonReader;
import com.massivecraft.massivecore.xlib.gson.stream.JsonWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* This class selects which fields and types to omit. It is configurable,
* supporting version attributes {@link Since} and {@link Until}, modifiers,
* synthetic fields, anonymous and local classes, inner classes, and fields with
* the {@link Expose} annotation.
*
* <p>This class is a type adapter factory; types that are excluded will be
* adapted to null. It may delegate to another type adapter if only one
* direction is excluded.
*
* @author Joel Leitch
* @author Jesse Wilson
*/
public final class Excluder implements TypeAdapterFactory, Cloneable {
private static final double IGNORE_VERSIONS = -1.0d;
public static final Excluder DEFAULT = new Excluder();
private double version = IGNORE_VERSIONS;
private int modifiers = Modifier.TRANSIENT | Modifier.STATIC;
private boolean serializeInnerClasses = true;
private boolean requireExpose;
private List<ExclusionStrategy> serializationStrategies = Collections.emptyList();
private List<ExclusionStrategy> deserializationStrategies = Collections.emptyList();
@Override protected Excluder clone() {
try {
return (Excluder) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError(e);
}
}
public Excluder withVersion(double ignoreVersionsAfter) {
Excluder result = clone();
result.version = ignoreVersionsAfter;
return result;
}
public Excluder withModifiers(int... modifiers) {
Excluder result = clone();
result.modifiers = 0;
for (int modifier : modifiers) {
result.modifiers |= modifier;
}
return result;
}
public Excluder disableInnerClassSerialization() {
Excluder result = clone();
result.serializeInnerClasses = false;
return result;
}
public Excluder excludeFieldsWithoutExposeAnnotation() {
Excluder result = clone();
result.requireExpose = true;
return result;
}
public Excluder withExclusionStrategy(ExclusionStrategy exclusionStrategy,
boolean serialization, boolean deserialization) {
Excluder result = clone();
if (serialization) {
result.serializationStrategies = new ArrayList<>(serializationStrategies);
result.serializationStrategies.add(exclusionStrategy);
}
if (deserialization) {
result.deserializationStrategies
= new ArrayList<>(deserializationStrategies);
result.deserializationStrategies.add(exclusionStrategy);
}
return result;
}
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) {
Class<?> rawType = type.getRawType();
final boolean skipSerialize = excludeClass(rawType, true);
final boolean skipDeserialize = excludeClass(rawType, false);
if (!skipSerialize && !skipDeserialize) {
return null;
}
return new TypeAdapter<T>() {
/** The delegate is lazily created because it may not be needed, and creating it may fail. */
private TypeAdapter<T> delegate;
@Override public T read(JsonReader in) throws IOException {
if (skipDeserialize) {
in.skipValue();
return null;
}
return delegate().read(in);
}
@Override public void write(JsonWriter out, T value) throws IOException {
if (skipSerialize) {
out.nullValue();
return;
}
delegate().write(out, value);
}
private TypeAdapter<T> delegate() {
TypeAdapter<T> d = delegate;
return d != null
? d
: (delegate = gson.getDelegateAdapter(Excluder.this, type));
}
};
}
public boolean excludeField(Field field, boolean serialize) {
if ((modifiers & field.getModifiers()) != 0) {
return true;
}
if (version != Excluder.IGNORE_VERSIONS
&& !isValidVersion(field.getAnnotation(Since.class), field.getAnnotation(Until.class))) {
return true;
}
if (field.isSynthetic()) {
return true;
}
if (requireExpose) {
Expose annotation = field.getAnnotation(Expose.class);
if (annotation == null || (serialize ? !annotation.serialize() : !annotation.deserialize())) {
return true;
}
}
if (!serializeInnerClasses && isInnerClass(field.getType())) {
return true;
}
if (isAnonymousOrLocal(field.getType())) {
return true;
}
List<ExclusionStrategy> list = serialize ? serializationStrategies : deserializationStrategies;
if (!list.isEmpty()) {
FieldAttributes fieldAttributes = new FieldAttributes(field);
for (ExclusionStrategy exclusionStrategy : list) {
if (exclusionStrategy.shouldSkipField(fieldAttributes)) {
return true;
}
}
}
return false;
}
public boolean excludeClass(Class<?> clazz, boolean serialize) {
if (version != Excluder.IGNORE_VERSIONS
&& !isValidVersion(clazz.getAnnotation(Since.class), clazz.getAnnotation(Until.class))) {
return true;
}
if (!serializeInnerClasses && isInnerClass(clazz)) {
return true;
}
if (isAnonymousOrLocal(clazz)) {
return true;
}
List<ExclusionStrategy> list = serialize ? serializationStrategies : deserializationStrategies;
for (ExclusionStrategy exclusionStrategy : list) {
if (exclusionStrategy.shouldSkipClass(clazz)) {
return true;
}
}
return false;
}
private boolean isAnonymousOrLocal(Class<?> clazz) {
return !Enum.class.isAssignableFrom(clazz)
&& (clazz.isAnonymousClass() || clazz.isLocalClass());
}
private boolean isInnerClass(Class<?> clazz) {
return clazz.isMemberClass() && !isStatic(clazz);
}
private boolean isStatic(Class<?> clazz) {
return (clazz.getModifiers() & Modifier.STATIC) != 0;
}
private boolean isValidVersion(Since since, Until until) {
return isValidSince(since) && isValidUntil(until);
}
private boolean isValidSince(Since annotation) {
if (annotation != null) {
double annotationVersion = annotation.value();
if (annotationVersion > version) {
return false;
}
}
return true;
}
private boolean isValidUntil(Until annotation) {
if (annotation != null) {
double annotationVersion = annotation.value();
if (annotationVersion <= version) {
return false;
}
}
return true;
}
}

View File

@ -1,33 +0,0 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.internal;
import com.massivecraft.massivecore.xlib.gson.stream.JsonReader;
import java.io.IOException;
/**
* Internal-only APIs of JsonReader available only to other classes in Gson.
*/
public abstract class JsonReaderInternalAccess {
public static JsonReaderInternalAccess INSTANCE;
/**
* Changes the type of the current property name token to a string value.
*/
public abstract void promoteNameToValue(JsonReader reader) throws IOException;
}

View File

@ -1,96 +0,0 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.internal;
import java.io.ObjectStreamException;
import java.math.BigDecimal;
/**
* This class holds a number value that is lazily converted to a specific number type
*
* @author Inderjeet Singh
*/
public final class LazilyParsedNumber extends Number {
private final String value;
/** @param value must not be null */
public LazilyParsedNumber(String value) {
this.value = value;
}
@Override
public int intValue() {
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
try {
return (int) Long.parseLong(value);
} catch (NumberFormatException nfe) {
return new BigDecimal(value).intValue();
}
}
}
@Override
public long longValue() {
try {
return Long.parseLong(value);
} catch (NumberFormatException e) {
return new BigDecimal(value).longValue();
}
}
@Override
public float floatValue() {
return Float.parseFloat(value);
}
@Override
public double doubleValue() {
return Double.parseDouble(value);
}
@Override
public String toString() {
return value;
}
/**
* If somebody is unlucky enough to have to serialize one of these, serialize
* it as a BigDecimal so that they won't need Gson on the other side to
* deserialize it.
*/
private Object writeReplace() throws ObjectStreamException {
return new BigDecimal(value);
}
@Override
public int hashCode() {
return value.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof LazilyParsedNumber) {
LazilyParsedNumber other = (LazilyParsedNumber) obj;
return value == other.value || value.equals(other.value);
}
return false;
}
}

View File

@ -1,856 +0,0 @@
/*
* Copyright (C) 2010 The Android Open Source Project
* Copyright (C) 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.internal;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.util.*;
/**
* A map of comparable keys to values. Unlike {@code TreeMap}, this class uses
* insertion order for iteration order. Comparison order is only used as an
* optimization for efficient insertion and removal.
*
* <p>This implementation was derived from Android 4.1's TreeMap and
* LinkedHashMap classes.
*/
public final class LinkedHashTreeMap<K, V> extends AbstractMap<K, V> implements Serializable {
@SuppressWarnings({ "unchecked", "rawtypes" }) // to avoid Comparable<Comparable<Comparable<...>>>
private static final Comparator<Comparable> NATURAL_ORDER = new Comparator<Comparable>() {
public int compare(Comparable a, Comparable b) {
return a.compareTo(b);
}
};
Comparator<? super K> comparator;
Node<K, V>[] table;
final Node<K, V> header;
int size = 0;
int modCount = 0;
int threshold;
/**
* Create a natural order, empty tree map whose keys must be mutually
* comparable and non-null.
*/
@SuppressWarnings("unchecked") // unsafe! this assumes K is comparable
public LinkedHashTreeMap() {
this((Comparator<? super K>) NATURAL_ORDER);
}
/**
* Create a tree map ordered by {@code comparator}. This map's keys may only
* be null if {@code comparator} permits.
*
* @param comparator the comparator to order elements with, or {@code null} to
* use the natural ordering.
*/
@SuppressWarnings({ "unchecked", "rawtypes" }) // unsafe! if comparator is null, this assumes K is comparable
public LinkedHashTreeMap(Comparator<? super K> comparator) {
this.comparator = comparator != null
? comparator
: (Comparator) NATURAL_ORDER;
this.header = new Node<>();
this.table = new Node[16]; // TODO: sizing/resizing policies
this.threshold = (table.length / 2) + (table.length / 4); // 3/4 capacity
}
@Override public int size() {
return size;
}
@Override public V get(Object key) {
Node<K, V> node = findByObject(key);
return node != null ? node.value : null;
}
@Override public boolean containsKey(Object key) {
return findByObject(key) != null;
}
@Override public V put(K key, V value) {
if (key == null) {
throw new NullPointerException("key == null");
}
Node<K, V> created = find(key, true);
V result = created.value;
created.value = value;
return result;
}
@Override public void clear() {
Arrays.fill(table, null);
size = 0;
modCount++;
// Clear all links to help GC
Node<K, V> header = this.header;
for (Node<K, V> e = header.next; e != header; ) {
Node<K, V> next = e.next;
e.next = e.prev = null;
e = next;
}
header.next = header.prev = header;
}
@Override public V remove(Object key) {
Node<K, V> node = removeInternalByKey(key);
return node != null ? node.value : null;
}
/**
* Returns the node at or adjacent to the given key, creating it if requested.
*
* @throws ClassCastException if {@code key} and the tree's keys aren't
* mutually comparable.
*/
Node<K, V> find(K key, boolean create) {
Comparator<? super K> comparator = this.comparator;
Node<K, V>[] table = this.table;
int hash = secondaryHash(key.hashCode());
int index = hash & (table.length - 1);
Node<K, V> nearest = table[index];
int comparison = 0;
if (nearest != null) {
// Micro-optimization: avoid polymorphic calls to Comparator.compare().
@SuppressWarnings("unchecked") // Throws a ClassCastException below if there's trouble.
Comparable<Object> comparableKey = (comparator == NATURAL_ORDER)
? (Comparable<Object>) key
: null;
while (true) {
comparison = (comparableKey != null)
? comparableKey.compareTo(nearest.key)
: comparator.compare(key, nearest.key);
// We found the requested key.
if (comparison == 0) {
return nearest;
}
// If it exists, the key is in a subtree. Go deeper.
Node<K, V> child = (comparison < 0) ? nearest.left : nearest.right;
if (child == null) {
break;
}
nearest = child;
}
}
// The key doesn't exist in this tree.
if (!create) {
return null;
}
// Create the node and add it to the tree or the table.
Node<K, V> header = this.header;
Node<K, V> created;
if (nearest == null) {
// Check that the value is comparable if we didn't do any comparisons.
if (comparator == NATURAL_ORDER && !(key instanceof Comparable)) {
throw new ClassCastException(key.getClass().getName() + " is not Comparable");
}
created = new Node<>(nearest, key, hash, header, header.prev);
table[index] = created;
} else {
created = new Node<>(nearest, key, hash, header, header.prev);
if (comparison < 0) { // nearest.key is higher
nearest.left = created;
} else { // comparison > 0, nearest.key is lower
nearest.right = created;
}
rebalance(nearest, true);
}
if (size++ > threshold) {
doubleCapacity();
}
modCount++;
return created;
}
@SuppressWarnings("unchecked")
Node<K, V> findByObject(Object key) {
try {
return key != null ? find((K) key, false) : null;
} catch (ClassCastException e) {
return null;
}
}
/**
* Returns this map's entry that has the same key and value as {@code
* entry}, or null if this map has no such entry.
*
* <p>This method uses the comparator for key equality rather than {@code
* equals}. If this map's comparator isn't consistent with equals (such as
* {@code String.CASE_INSENSITIVE_ORDER}), then {@code remove()} and {@code
* contains()} will violate the collections API.
*/
Node<K, V> findByEntry(Entry<?, ?> entry) {
Node<K, V> mine = findByObject(entry.getKey());
boolean valuesEqual = mine != null && equal(mine.value, entry.getValue());
return valuesEqual ? mine : null;
}
private boolean equal(Object a, Object b) {
return a == b || (a != null && a.equals(b));
}
/**
* Applies a supplemental hash function to a given hashCode, which defends
* against poor quality hash functions. This is critical because HashMap
* uses power-of-two length hash tables, that otherwise encounter collisions
* for hashCodes that do not differ in lower or upper bits.
*/
private static int secondaryHash(int h) {
// Doug Lea's supplemental hash function
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
/**
* Removes {@code node} from this tree, rearranging the tree's structure as
* necessary.
*
* @param unlink true to also unlink this node from the iteration linked list.
*/
void removeInternal(Node<K, V> node, boolean unlink) {
if (unlink) {
node.prev.next = node.next;
node.next.prev = node.prev;
node.next = node.prev = null; // Help the GC (for performance)
}
Node<K, V> left = node.left;
Node<K, V> right = node.right;
Node<K, V> originalParent = node.parent;
if (left != null && right != null) {
/*
* To remove a node with both left and right subtrees, move an
* adjacent node from one of those subtrees into this node's place.
*
* Removing the adjacent node may change this node's subtrees. This
* node may no longer have two subtrees once the adjacent node is
* gone!
*/
Node<K, V> adjacent = (left.height > right.height) ? left.last() : right.first();
removeInternal(adjacent, false); // takes care of rebalance and size--
int leftHeight = 0;
left = node.left;
if (left != null) {
leftHeight = left.height;
adjacent.left = left;
left.parent = adjacent;
node.left = null;
}
int rightHeight = 0;
right = node.right;
if (right != null) {
rightHeight = right.height;
adjacent.right = right;
right.parent = adjacent;
node.right = null;
}
adjacent.height = Math.max(leftHeight, rightHeight) + 1;
replaceInParent(node, adjacent);
return;
} else if (left != null) {
replaceInParent(node, left);
node.left = null;
} else if (right != null) {
replaceInParent(node, right);
node.right = null;
} else {
replaceInParent(node, null);
}
rebalance(originalParent, false);
size--;
modCount++;
}
Node<K, V> removeInternalByKey(Object key) {
Node<K, V> node = findByObject(key);
if (node != null) {
removeInternal(node, true);
}
return node;
}
private void replaceInParent(Node<K, V> node, Node<K, V> replacement) {
Node<K, V> parent = node.parent;
node.parent = null;
if (replacement != null) {
replacement.parent = parent;
}
if (parent != null) {
if (parent.left == node) {
parent.left = replacement;
} else {
assert (parent.right == node);
parent.right = replacement;
}
} else {
int index = node.hash & (table.length - 1);
table[index] = replacement;
}
}
/**
* Rebalances the tree by making any AVL rotations necessary between the
* newly-unbalanced node and the tree's root.
*
* @param insert true if the node was unbalanced by an insert; false if it
* was by a removal.
*/
private void rebalance(Node<K, V> unbalanced, boolean insert) {
for (Node<K, V> node = unbalanced; node != null; node = node.parent) {
Node<K, V> left = node.left;
Node<K, V> right = node.right;
int leftHeight = left != null ? left.height : 0;
int rightHeight = right != null ? right.height : 0;
int delta = leftHeight - rightHeight;
if (delta == -2) {
Node<K, V> rightLeft = right.left;
Node<K, V> rightRight = right.right;
int rightRightHeight = rightRight != null ? rightRight.height : 0;
int rightLeftHeight = rightLeft != null ? rightLeft.height : 0;
int rightDelta = rightLeftHeight - rightRightHeight;
if (rightDelta == -1 || (rightDelta == 0 && !insert)) {
rotateLeft(node); // AVL right right
} else {
assert (rightDelta == 1);
rotateRight(right); // AVL right left
rotateLeft(node);
}
if (insert) {
break; // no further rotations will be necessary
}
} else if (delta == 2) {
Node<K, V> leftLeft = left.left;
Node<K, V> leftRight = left.right;
int leftRightHeight = leftRight != null ? leftRight.height : 0;
int leftLeftHeight = leftLeft != null ? leftLeft.height : 0;
int leftDelta = leftLeftHeight - leftRightHeight;
if (leftDelta == 1 || (leftDelta == 0 && !insert)) {
rotateRight(node); // AVL left left
} else {
assert (leftDelta == -1);
rotateLeft(left); // AVL left right
rotateRight(node);
}
if (insert) {
break; // no further rotations will be necessary
}
} else if (delta == 0) {
node.height = leftHeight + 1; // leftHeight == rightHeight
if (insert) {
break; // the insert caused balance, so rebalancing is done!
}
} else {
assert (delta == -1 || delta == 1);
node.height = Math.max(leftHeight, rightHeight) + 1;
if (!insert) {
break; // the height hasn't changed, so rebalancing is done!
}
}
}
}
/**
* Rotates the subtree so that its root's right child is the new root.
*/
private void rotateLeft(Node<K, V> root) {
Node<K, V> left = root.left;
Node<K, V> pivot = root.right;
Node<K, V> pivotLeft = pivot.left;
Node<K, V> pivotRight = pivot.right;
// move the pivot's left child to the root's right
root.right = pivotLeft;
if (pivotLeft != null) {
pivotLeft.parent = root;
}
replaceInParent(root, pivot);
// move the root to the pivot's left
pivot.left = root;
root.parent = pivot;
// fix heights
root.height = Math.max(left != null ? left.height : 0,
pivotLeft != null ? pivotLeft.height : 0) + 1;
pivot.height = Math.max(root.height,
pivotRight != null ? pivotRight.height : 0) + 1;
}
/**
* Rotates the subtree so that its root's left child is the new root.
*/
private void rotateRight(Node<K, V> root) {
Node<K, V> pivot = root.left;
Node<K, V> right = root.right;
Node<K, V> pivotLeft = pivot.left;
Node<K, V> pivotRight = pivot.right;
// move the pivot's right child to the root's left
root.left = pivotRight;
if (pivotRight != null) {
pivotRight.parent = root;
}
replaceInParent(root, pivot);
// move the root to the pivot's right
pivot.right = root;
root.parent = pivot;
// fixup heights
root.height = Math.max(right != null ? right.height : 0,
pivotRight != null ? pivotRight.height : 0) + 1;
pivot.height = Math.max(root.height,
pivotLeft != null ? pivotLeft.height : 0) + 1;
}
private EntrySet entrySet;
private KeySet keySet;
@Override public Set<Entry<K, V>> entrySet() {
EntrySet result = entrySet;
return result != null ? result : (entrySet = new EntrySet());
}
@Override public Set<K> keySet() {
KeySet result = keySet;
return result != null ? result : (keySet = new KeySet());
}
static final class Node<K, V> implements Entry<K, V> {
Node<K, V> parent;
Node<K, V> left;
Node<K, V> right;
Node<K, V> next;
Node<K, V> prev;
final K key;
final int hash;
V value;
int height;
/** Create the header entry */
Node() {
key = null;
hash = -1;
next = prev = this;
}
/** Create a regular entry */
Node(Node<K, V> parent, K key, int hash, Node<K, V> next, Node<K, V> prev) {
this.parent = parent;
this.key = key;
this.hash = hash;
this.height = 1;
this.next = next;
this.prev = prev;
prev.next = this;
next.prev = this;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
public V setValue(V value) {
V oldValue = this.value;
this.value = value;
return oldValue;
}
@SuppressWarnings("rawtypes")
@Override public boolean equals(Object o) {
if (o instanceof Entry) {
Entry other = (Entry) o;
return (key == null ? other.getKey() == null : key.equals(other.getKey()))
&& (value == null ? other.getValue() == null : value.equals(other.getValue()));
}
return false;
}
@Override public int hashCode() {
return (key == null ? 0 : key.hashCode())
^ (value == null ? 0 : value.hashCode());
}
@Override public String toString() {
return key + "=" + value;
}
/**
* Returns the first node in this subtree.
*/
public Node<K, V> first() {
Node<K, V> node = this;
Node<K, V> child = node.left;
while (child != null) {
node = child;
child = node.left;
}
return node;
}
/**
* Returns the last node in this subtree.
*/
public Node<K, V> last() {
Node<K, V> node = this;
Node<K, V> child = node.right;
while (child != null) {
node = child;
child = node.right;
}
return node;
}
}
private void doubleCapacity() {
table = doubleCapacity(table);
threshold = (table.length / 2) + (table.length / 4); // 3/4 capacity
}
/**
* Returns a new array containing the same nodes as {@code oldTable}, but with
* twice as many trees, each of (approximately) half the previous size.
*/
static <K, V> Node<K, V>[] doubleCapacity(Node<K, V>[] oldTable) {
// TODO: don't do anything if we're already at MAX_CAPACITY
int oldCapacity = oldTable.length;
@SuppressWarnings("unchecked") // Arrays and generics don't get along.
Node<K, V>[] newTable = new Node[oldCapacity * 2];
AvlIterator<K, V> iterator = new AvlIterator<>();
AvlBuilder<K, V> leftBuilder = new AvlBuilder<>();
AvlBuilder<K, V> rightBuilder = new AvlBuilder<>();
// Split each tree into two trees.
for (int i = 0; i < oldCapacity; i++) {
Node<K, V> root = oldTable[i];
if (root == null) {
continue;
}
// Compute the sizes of the left and right trees.
iterator.reset(root);
int leftSize = 0;
int rightSize = 0;
for (Node<K, V> node; (node = iterator.next()) != null; ) {
if ((node.hash & oldCapacity) == 0) {
leftSize++;
} else {
rightSize++;
}
}
// Split the tree into two.
leftBuilder.reset(leftSize);
rightBuilder.reset(rightSize);
iterator.reset(root);
for (Node<K, V> node; (node = iterator.next()) != null; ) {
if ((node.hash & oldCapacity) == 0) {
leftBuilder.add(node);
} else {
rightBuilder.add(node);
}
}
// Populate the enlarged array with these new roots.
newTable[i] = leftSize > 0 ? leftBuilder.root() : null;
newTable[i + oldCapacity] = rightSize > 0 ? rightBuilder.root() : null;
}
return newTable;
}
/**
* Walks an AVL tree in iteration order. Once a node has been returned, its
* left, right and parent links are <strong>no longer used</strong>. For this
* reason it is safe to transform these links as you walk a tree.
*
* <p><strong>Warning:</strong> this iterator is destructive. It clears the
* parent node of all nodes in the tree. It is an error to make a partial
* iteration of a tree.
*/
static class AvlIterator<K, V> {
/** This stack is a singly linked list, linked by the 'parent' field. */
private Node<K, V> stackTop;
void reset(Node<K, V> root) {
Node<K, V> stackTop = null;
for (Node<K, V> n = root; n != null; n = n.left) {
n.parent = stackTop;
stackTop = n; // Stack push.
}
this.stackTop = stackTop;
}
public Node<K, V> next() {
Node<K, V> stackTop = this.stackTop;
if (stackTop == null) {
return null;
}
Node<K, V> result = stackTop;
stackTop = result.parent;
result.parent = null;
for (Node<K, V> n = result.right; n != null; n = n.left) {
n.parent = stackTop;
stackTop = n; // Stack push.
}
this.stackTop = stackTop;
return result;
}
}
/**
* Builds AVL trees of a predetermined size by accepting nodes of increasing
* value. To use:
* <ol>
* <li>Call {@link #reset} to initialize the target size <i>size</i>.
* <li>Call {@link #add} <i>size</i> times with increasing values.
* <li>Call {@link #root} to get the root of the balanced tree.
* </ol>
*
* <p>The returned tree will satisfy the AVL constraint: for every node
* <i>N</i>, the height of <i>N.left</i> and <i>N.right</i> is different by at
* most 1. It accomplishes this by omitting deepest-level leaf nodes when
* building trees whose size isn't a power of 2 minus 1.
*
* <p>Unlike rebuilding a tree from scratch, this approach requires no value
* comparisons. Using this class to create a tree of size <i>S</i> is
* {@code O(S)}.
*/
final static class AvlBuilder<K, V> {
/** This stack is a singly linked list, linked by the 'parent' field. */
private Node<K, V> stack;
private int leavesToSkip;
private int leavesSkipped;
private int size;
void reset(int targetSize) {
// compute the target tree size. This is a power of 2 minus one, like 15 or 31.
int treeCapacity = Integer.highestOneBit(targetSize) * 2 - 1;
leavesToSkip = treeCapacity - targetSize;
size = 0;
leavesSkipped = 0;
stack = null;
}
void add(Node<K, V> node) {
node.left = node.parent = node.right = null;
node.height = 1;
// Skip a leaf if necessary.
if (leavesToSkip > 0 && (size & 1) == 0) {
size++;
leavesToSkip--;
leavesSkipped++;
}
node.parent = stack;
stack = node; // Stack push.
size++;
// Skip a leaf if necessary.
if (leavesToSkip > 0 && (size & 1) == 0) {
size++;
leavesToSkip--;
leavesSkipped++;
}
/*
* Combine 3 nodes into subtrees whenever the size is one less than a
* multiple of 4. For example we combine the nodes A, B, C into a
* 3-element tree with B as the root.
*
* Combine two subtrees and a spare single value whenever the size is one
* less than a multiple of 8. For example at 8 we may combine subtrees
* (A B C) and (E F G) with D as the root to form ((A B C) D (E F G)).
*
* Just as we combine single nodes when size nears a multiple of 4, and
* 3-element trees when size nears a multiple of 8, we combine subtrees of
* size (N-1) whenever the total size is 2N-1 whenever N is a power of 2.
*/
for (int scale = 4; (size & scale - 1) == scale - 1; scale *= 2) {
if (leavesSkipped == 0) {
// Pop right, center and left, then make center the top of the stack.
Node<K, V> right = stack;
Node<K, V> center = right.parent;
Node<K, V> left = center.parent;
center.parent = left.parent;
stack = center;
// Construct a tree.
center.left = left;
center.right = right;
center.height = right.height + 1;
left.parent = center;
right.parent = center;
} else if (leavesSkipped == 1) {
// Pop right and center, then make center the top of the stack.
Node<K, V> right = stack;
Node<K, V> center = right.parent;
stack = center;
// Construct a tree with no left child.
center.right = right;
center.height = right.height + 1;
right.parent = center;
leavesSkipped = 0;
} else if (leavesSkipped == 2) {
leavesSkipped = 0;
}
}
}
Node<K, V> root() {
Node<K, V> stackTop = this.stack;
if (stackTop.parent != null) {
throw new IllegalStateException();
}
return stackTop;
}
}
private abstract class LinkedTreeMapIterator<T> implements Iterator<T> {
Node<K, V> next = header.next;
Node<K, V> lastReturned = null;
int expectedModCount = modCount;
LinkedTreeMapIterator() {
}
public final boolean hasNext() {
return next != header;
}
final Node<K, V> nextNode() {
Node<K, V> e = next;
if (e == header) {
throw new NoSuchElementException();
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
next = e.next;
return lastReturned = e;
}
public final void remove() {
if (lastReturned == null) {
throw new IllegalStateException();
}
removeInternal(lastReturned, true);
lastReturned = null;
expectedModCount = modCount;
}
}
final class EntrySet extends AbstractSet<Entry<K, V>> {
@Override public int size() {
return size;
}
@Override public Iterator<Entry<K, V>> iterator() {
return new LinkedTreeMapIterator<Entry<K, V>>() {
public Entry<K, V> next() {
return nextNode();
}
};
}
@Override public boolean contains(Object o) {
return o instanceof Entry && findByEntry((Entry<?, ?>) o) != null;
}
@Override public boolean remove(Object o) {
if (!(o instanceof Entry)) {
return false;
}
Node<K, V> node = findByEntry((Entry<?, ?>) o);
if (node == null) {
return false;
}
removeInternal(node, true);
return true;
}
@Override public void clear() {
LinkedHashTreeMap.this.clear();
}
}
final class KeySet extends AbstractSet<K> {
@Override public int size() {
return size;
}
@Override public Iterator<K> iterator() {
return new LinkedTreeMapIterator<K>() {
public K next() {
return nextNode().key;
}
};
}
@Override public boolean contains(Object o) {
return containsKey(o);
}
@Override public boolean remove(Object key) {
return removeInternalByKey(key) != null;
}
@Override public void clear() {
LinkedHashTreeMap.this.clear();
}
}
/**
* If somebody is unlucky enough to have to serialize one of these, serialize
* it as a LinkedHashMap so that they won't need Gson on the other side to
* deserialize it. Using serialization defeats our DoS defence, so most apps
* shouldn't use it.
*/
private Object writeReplace() throws ObjectStreamException {
return new LinkedHashMap<>(this);
}
}

View File

@ -1,623 +0,0 @@
/*
* Copyright (C) 2010 The Android Open Source Project
* Copyright (C) 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.internal;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.util.*;
/**
* A map of comparable keys to values. Unlike {@code TreeMap}, this class uses
* insertion order for iteration order. Comparison order is only used as an
* optimization for efficient insertion and removal.
*
* <p>This implementation was derived from Android 4.1's TreeMap class.
*/
public final class LinkedTreeMap<K, V> extends AbstractMap<K, V> implements Serializable {
@SuppressWarnings({ "unchecked", "rawtypes" }) // to avoid Comparable<Comparable<Comparable<...>>>
private static final Comparator<Comparable> NATURAL_ORDER = new Comparator<Comparable>() {
public int compare(Comparable a, Comparable b) {
return a.compareTo(b);
}
};
Comparator<? super K> comparator;
Node<K, V> root;
int size = 0;
int modCount = 0;
// Used to preserve iteration order
final Node<K, V> header = new Node<>();
/**
* Create a natural order, empty tree map whose keys must be mutually
* comparable and non-null.
*/
@SuppressWarnings("unchecked") // unsafe! this assumes K is comparable
public LinkedTreeMap() {
this((Comparator<? super K>) NATURAL_ORDER);
}
/**
* Create a tree map ordered by {@code comparator}. This map's keys may only
* be null if {@code comparator} permits.
*
* @param comparator the comparator to order elements with, or {@code null} to
* use the natural ordering.
*/
@SuppressWarnings({ "unchecked", "rawtypes" }) // unsafe! if comparator is null, this assumes K is comparable
public LinkedTreeMap(Comparator<? super K> comparator) {
this.comparator = comparator != null
? comparator
: (Comparator) NATURAL_ORDER;
}
@Override public int size() {
return size;
}
@Override public V get(Object key) {
Node<K, V> node = findByObject(key);
return node != null ? node.value : null;
}
@Override public boolean containsKey(Object key) {
return findByObject(key) != null;
}
@Override public V put(K key, V value) {
if (key == null) {
throw new NullPointerException("key == null");
}
Node<K, V> created = find(key, true);
V result = created.value;
created.value = value;
return result;
}
@Override public void clear() {
root = null;
size = 0;
modCount++;
// Clear iteration order
Node<K, V> header = this.header;
header.next = header.prev = header;
}
@Override public V remove(Object key) {
Node<K, V> node = removeInternalByKey(key);
return node != null ? node.value : null;
}
/**
* Returns the node at or adjacent to the given key, creating it if requested.
*
* @throws ClassCastException if {@code key} and the tree's keys aren't
* mutually comparable.
*/
Node<K, V> find(K key, boolean create) {
Comparator<? super K> comparator = this.comparator;
Node<K, V> nearest = root;
int comparison = 0;
if (nearest != null) {
// Micro-optimization: avoid polymorphic calls to Comparator.compare().
@SuppressWarnings("unchecked") // Throws a ClassCastException below if there's trouble.
Comparable<Object> comparableKey = (comparator == NATURAL_ORDER)
? (Comparable<Object>) key
: null;
while (true) {
comparison = (comparableKey != null)
? comparableKey.compareTo(nearest.key)
: comparator.compare(key, nearest.key);
// We found the requested key.
if (comparison == 0) {
return nearest;
}
// If it exists, the key is in a subtree. Go deeper.
Node<K, V> child = (comparison < 0) ? nearest.left : nearest.right;
if (child == null) {
break;
}
nearest = child;
}
}
// The key doesn't exist in this tree.
if (!create) {
return null;
}
// Create the node and add it to the tree or the table.
Node<K, V> header = this.header;
Node<K, V> created;
if (nearest == null) {
// Check that the value is comparable if we didn't do any comparisons.
if (comparator == NATURAL_ORDER && !(key instanceof Comparable)) {
throw new ClassCastException(key.getClass().getName() + " is not Comparable");
}
created = new Node<>(nearest, key, header, header.prev);
root = created;
} else {
created = new Node<>(nearest, key, header, header.prev);
if (comparison < 0) { // nearest.key is higher
nearest.left = created;
} else { // comparison > 0, nearest.key is lower
nearest.right = created;
}
rebalance(nearest, true);
}
size++;
modCount++;
return created;
}
@SuppressWarnings("unchecked")
Node<K, V> findByObject(Object key) {
try {
return key != null ? find((K) key, false) : null;
} catch (ClassCastException e) {
return null;
}
}
/**
* Returns this map's entry that has the same key and value as {@code
* entry}, or null if this map has no such entry.
*
* <p>This method uses the comparator for key equality rather than {@code
* equals}. If this map's comparator isn't consistent with equals (such as
* {@code String.CASE_INSENSITIVE_ORDER}), then {@code remove()} and {@code
* contains()} will violate the collections API.
*/
Node<K, V> findByEntry(Entry<?, ?> entry) {
Node<K, V> mine = findByObject(entry.getKey());
boolean valuesEqual = mine != null && equal(mine.value, entry.getValue());
return valuesEqual ? mine : null;
}
private boolean equal(Object a, Object b) {
return a == b || (a != null && a.equals(b));
}
/**
* Removes {@code node} from this tree, rearranging the tree's structure as
* necessary.
*
* @param unlink true to also unlink this node from the iteration linked list.
*/
void removeInternal(Node<K, V> node, boolean unlink) {
if (unlink) {
node.prev.next = node.next;
node.next.prev = node.prev;
}
Node<K, V> left = node.left;
Node<K, V> right = node.right;
Node<K, V> originalParent = node.parent;
if (left != null && right != null) {
/*
* To remove a node with both left and right subtrees, move an
* adjacent node from one of those subtrees into this node's place.
*
* Removing the adjacent node may change this node's subtrees. This
* node may no longer have two subtrees once the adjacent node is
* gone!
*/
Node<K, V> adjacent = (left.height > right.height) ? left.last() : right.first();
removeInternal(adjacent, false); // takes care of rebalance and size--
int leftHeight = 0;
left = node.left;
if (left != null) {
leftHeight = left.height;
adjacent.left = left;
left.parent = adjacent;
node.left = null;
}
int rightHeight = 0;
right = node.right;
if (right != null) {
rightHeight = right.height;
adjacent.right = right;
right.parent = adjacent;
node.right = null;
}
adjacent.height = Math.max(leftHeight, rightHeight) + 1;
replaceInParent(node, adjacent);
return;
} else if (left != null) {
replaceInParent(node, left);
node.left = null;
} else if (right != null) {
replaceInParent(node, right);
node.right = null;
} else {
replaceInParent(node, null);
}
rebalance(originalParent, false);
size--;
modCount++;
}
Node<K, V> removeInternalByKey(Object key) {
Node<K, V> node = findByObject(key);
if (node != null) {
removeInternal(node, true);
}
return node;
}
private void replaceInParent(Node<K, V> node, Node<K, V> replacement) {
Node<K, V> parent = node.parent;
node.parent = null;
if (replacement != null) {
replacement.parent = parent;
}
if (parent != null) {
if (parent.left == node) {
parent.left = replacement;
} else {
assert (parent.right == node);
parent.right = replacement;
}
} else {
root = replacement;
}
}
/**
* Rebalances the tree by making any AVL rotations necessary between the
* newly-unbalanced node and the tree's root.
*
* @param insert true if the node was unbalanced by an insert; false if it
* was by a removal.
*/
private void rebalance(Node<K, V> unbalanced, boolean insert) {
for (Node<K, V> node = unbalanced; node != null; node = node.parent) {
Node<K, V> left = node.left;
Node<K, V> right = node.right;
int leftHeight = left != null ? left.height : 0;
int rightHeight = right != null ? right.height : 0;
int delta = leftHeight - rightHeight;
if (delta == -2) {
Node<K, V> rightLeft = right.left;
Node<K, V> rightRight = right.right;
int rightRightHeight = rightRight != null ? rightRight.height : 0;
int rightLeftHeight = rightLeft != null ? rightLeft.height : 0;
int rightDelta = rightLeftHeight - rightRightHeight;
if (rightDelta == -1 || (rightDelta == 0 && !insert)) {
rotateLeft(node); // AVL right right
} else {
assert (rightDelta == 1);
rotateRight(right); // AVL right left
rotateLeft(node);
}
if (insert) {
break; // no further rotations will be necessary
}
} else if (delta == 2) {
Node<K, V> leftLeft = left.left;
Node<K, V> leftRight = left.right;
int leftRightHeight = leftRight != null ? leftRight.height : 0;
int leftLeftHeight = leftLeft != null ? leftLeft.height : 0;
int leftDelta = leftLeftHeight - leftRightHeight;
if (leftDelta == 1 || (leftDelta == 0 && !insert)) {
rotateRight(node); // AVL left left
} else {
assert (leftDelta == -1);
rotateLeft(left); // AVL left right
rotateRight(node);
}
if (insert) {
break; // no further rotations will be necessary
}
} else if (delta == 0) {
node.height = leftHeight + 1; // leftHeight == rightHeight
if (insert) {
break; // the insert caused balance, so rebalancing is done!
}
} else {
assert (delta == -1 || delta == 1);
node.height = Math.max(leftHeight, rightHeight) + 1;
if (!insert) {
break; // the height hasn't changed, so rebalancing is done!
}
}
}
}
/**
* Rotates the subtree so that its root's right child is the new root.
*/
private void rotateLeft(Node<K, V> root) {
Node<K, V> left = root.left;
Node<K, V> pivot = root.right;
Node<K, V> pivotLeft = pivot.left;
Node<K, V> pivotRight = pivot.right;
// move the pivot's left child to the root's right
root.right = pivotLeft;
if (pivotLeft != null) {
pivotLeft.parent = root;
}
replaceInParent(root, pivot);
// move the root to the pivot's left
pivot.left = root;
root.parent = pivot;
// fix heights
root.height = Math.max(left != null ? left.height : 0,
pivotLeft != null ? pivotLeft.height : 0) + 1;
pivot.height = Math.max(root.height,
pivotRight != null ? pivotRight.height : 0) + 1;
}
/**
* Rotates the subtree so that its root's left child is the new root.
*/
private void rotateRight(Node<K, V> root) {
Node<K, V> pivot = root.left;
Node<K, V> right = root.right;
Node<K, V> pivotLeft = pivot.left;
Node<K, V> pivotRight = pivot.right;
// move the pivot's right child to the root's left
root.left = pivotRight;
if (pivotRight != null) {
pivotRight.parent = root;
}
replaceInParent(root, pivot);
// move the root to the pivot's right
pivot.right = root;
root.parent = pivot;
// fixup heights
root.height = Math.max(right != null ? right.height : 0,
pivotRight != null ? pivotRight.height : 0) + 1;
pivot.height = Math.max(root.height,
pivotLeft != null ? pivotLeft.height : 0) + 1;
}
private EntrySet entrySet;
private KeySet keySet;
@Override public Set<Entry<K, V>> entrySet() {
EntrySet result = entrySet;
return result != null ? result : (entrySet = new EntrySet());
}
@Override public Set<K> keySet() {
KeySet result = keySet;
return result != null ? result : (keySet = new KeySet());
}
static final class Node<K, V> implements Entry<K, V> {
Node<K, V> parent;
Node<K, V> left;
Node<K, V> right;
Node<K, V> next;
Node<K, V> prev;
final K key;
V value;
int height;
/** Create the header entry */
Node() {
key = null;
next = prev = this;
}
/** Create a regular entry */
Node(Node<K, V> parent, K key, Node<K, V> next, Node<K, V> prev) {
this.parent = parent;
this.key = key;
this.height = 1;
this.next = next;
this.prev = prev;
prev.next = this;
next.prev = this;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
public V setValue(V value) {
V oldValue = this.value;
this.value = value;
return oldValue;
}
@SuppressWarnings("rawtypes")
@Override public boolean equals(Object o) {
if (o instanceof Entry) {
Entry other = (Entry) o;
return (key == null ? other.getKey() == null : key.equals(other.getKey()))
&& (value == null ? other.getValue() == null : value.equals(other.getValue()));
}
return false;
}
@Override public int hashCode() {
return (key == null ? 0 : key.hashCode())
^ (value == null ? 0 : value.hashCode());
}
@Override public String toString() {
return key + "=" + value;
}
/**
* Returns the first node in this subtree.
*/
public Node<K, V> first() {
Node<K, V> node = this;
Node<K, V> child = node.left;
while (child != null) {
node = child;
child = node.left;
}
return node;
}
/**
* Returns the last node in this subtree.
*/
public Node<K, V> last() {
Node<K, V> node = this;
Node<K, V> child = node.right;
while (child != null) {
node = child;
child = node.right;
}
return node;
}
}
private abstract class LinkedTreeMapIterator<T> implements Iterator<T> {
Node<K, V> next = header.next;
Node<K, V> lastReturned = null;
int expectedModCount = modCount;
LinkedTreeMapIterator() {
}
public final boolean hasNext() {
return next != header;
}
final Node<K, V> nextNode() {
Node<K, V> e = next;
if (e == header) {
throw new NoSuchElementException();
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
next = e.next;
return lastReturned = e;
}
public final void remove() {
if (lastReturned == null) {
throw new IllegalStateException();
}
removeInternal(lastReturned, true);
lastReturned = null;
expectedModCount = modCount;
}
}
class EntrySet extends AbstractSet<Entry<K, V>> {
@Override public int size() {
return size;
}
@Override public Iterator<Entry<K, V>> iterator() {
return new LinkedTreeMapIterator<Entry<K, V>>() {
public Entry<K, V> next() {
return nextNode();
}
};
}
@Override public boolean contains(Object o) {
return o instanceof Entry && findByEntry((Entry<?, ?>) o) != null;
}
@Override public boolean remove(Object o) {
if (!(o instanceof Entry)) {
return false;
}
Node<K, V> node = findByEntry((Entry<?, ?>) o);
if (node == null) {
return false;
}
removeInternal(node, true);
return true;
}
@Override public void clear() {
LinkedTreeMap.this.clear();
}
}
final class KeySet extends AbstractSet<K> {
@Override public int size() {
return size;
}
@Override public Iterator<K> iterator() {
return new LinkedTreeMapIterator<K>() {
public K next() {
return nextNode().key;
}
};
}
@Override public boolean contains(Object o) {
return containsKey(o);
}
@Override public boolean remove(Object key) {
return removeInternalByKey(key) != null;
}
@Override public void clear() {
LinkedTreeMap.this.clear();
}
}
/**
* If somebody is unlucky enough to have to serialize one of these, serialize
* it as a LinkedHashMap so that they won't need Gson on the other side to
* deserialize it. Using serialization defeats our DoS defence, so most apps
* shouldn't use it.
*/
private Object writeReplace() throws ObjectStreamException {
return new LinkedHashMap<>(this);
}
}

View File

@ -1,33 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.internal;
/**
* Defines a generic object construction factory. The purpose of this class
* is to construct a default instance of a class that can be used for object
* navigation while deserialization from its JSON representation.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public interface ObjectConstructor<T> {
/**
* Returns a new instance.
*/
public T construct();
}

View File

@ -1,119 +0,0 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.internal;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* Contains static utility methods pertaining to primitive types and their
* corresponding wrapper types.
*
* @author Kevin Bourrillion
*/
public final class Primitives {
private Primitives() {
throw new UnsupportedOperationException();
}
/** A map from primitive types to their corresponding wrapper types. */
private static final Map<Class<?>, Class<?>> PRIMITIVE_TO_WRAPPER_TYPE;
/** A map from wrapper types to their corresponding primitive types. */
private static final Map<Class<?>, Class<?>> WRAPPER_TO_PRIMITIVE_TYPE;
// Sad that we can't use a BiMap. :(
static {
Map<Class<?>, Class<?>> primToWrap = new HashMap<>(16);
Map<Class<?>, Class<?>> wrapToPrim = new HashMap<>(16);
add(primToWrap, wrapToPrim, boolean.class, Boolean.class);
add(primToWrap, wrapToPrim, byte.class, Byte.class);
add(primToWrap, wrapToPrim, char.class, Character.class);
add(primToWrap, wrapToPrim, double.class, Double.class);
add(primToWrap, wrapToPrim, float.class, Float.class);
add(primToWrap, wrapToPrim, int.class, Integer.class);
add(primToWrap, wrapToPrim, long.class, Long.class);
add(primToWrap, wrapToPrim, short.class, Short.class);
add(primToWrap, wrapToPrim, void.class, Void.class);
PRIMITIVE_TO_WRAPPER_TYPE = Collections.unmodifiableMap(primToWrap);
WRAPPER_TO_PRIMITIVE_TYPE = Collections.unmodifiableMap(wrapToPrim);
}
private static void add(Map<Class<?>, Class<?>> forward,
Map<Class<?>, Class<?>> backward, Class<?> key, Class<?> value) {
forward.put(key, value);
backward.put(value, key);
}
/**
* Returns true if this type is a primitive.
*/
public static boolean isPrimitive(Type type) {
return PRIMITIVE_TO_WRAPPER_TYPE.containsKey(type);
}
/**
* Returns {@code true} if {@code type} is one of the nine
* primitive-wrapper types, such as {@link Integer}.
*
* @see Class#isPrimitive
*/
public static boolean isWrapperType(Type type) {
return WRAPPER_TO_PRIMITIVE_TYPE.containsKey(
$Gson$Preconditions.checkNotNull(type));
}
/**
* Returns the corresponding wrapper type of {@code type} if it is a primitive
* type; otherwise returns {@code type} itself. Idempotent.
* <pre>
* wrap(int.class) == Integer.class
* wrap(Integer.class) == Integer.class
* wrap(String.class) == String.class
* </pre>
*/
public static <T> Class<T> wrap(Class<T> type) {
// cast is safe: long.class and Long.class are both of type Class<Long>
@SuppressWarnings("unchecked")
Class<T> wrapped = (Class<T>) PRIMITIVE_TO_WRAPPER_TYPE.get(
$Gson$Preconditions.checkNotNull(type));
return (wrapped == null) ? type : wrapped;
}
/**
* Returns the corresponding primitive type of {@code type} if it is a
* wrapper type; otherwise returns {@code type} itself. Idempotent.
* <pre>
* unwrap(Integer.class) == int.class
* unwrap(int.class) == int.class
* unwrap(String.class) == String.class
* </pre>
*/
public static <T> Class<T> unwrap(Class<T> type) {
// cast is safe: long.class and Long.class are both of type Class<Long>
@SuppressWarnings("unchecked")
Class<T> unwrapped = (Class<T>) WRAPPER_TO_PRIMITIVE_TYPE.get(
$Gson$Preconditions.checkNotNull(type));
return (unwrapped == null) ? type : unwrapped;
}
}

View File

@ -1,117 +0,0 @@
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.internal;
import com.massivecraft.massivecore.xlib.gson.*;
import com.massivecraft.massivecore.xlib.gson.internal.bind.TypeAdapters;
import com.massivecraft.massivecore.xlib.gson.stream.JsonReader;
import com.massivecraft.massivecore.xlib.gson.stream.JsonWriter;
import com.massivecraft.massivecore.xlib.gson.stream.MalformedJsonException;
import java.io.EOFException;
import java.io.IOException;
import java.io.Writer;
/**
* Reads and writes GSON parse trees over streams.
*/
public final class Streams {
private Streams() {
throw new UnsupportedOperationException();
}
/**
* Takes a reader in any state and returns the next value as a JsonElement.
*/
public static JsonElement parse(JsonReader reader) throws JsonParseException {
boolean isEmpty = true;
try {
reader.peek();
isEmpty = false;
return TypeAdapters.JSON_ELEMENT.read(reader);
} catch (EOFException e) {
/*
* For compatibility with JSON 1.5 and earlier, we return a JsonNull for
* empty documents instead of throwing.
*/
if (isEmpty) {
return JsonNull.INSTANCE;
}
// The stream ended prematurely so it is likely a syntax error.
throw new JsonSyntaxException(e);
} catch (MalformedJsonException e) {
throw new JsonSyntaxException(e);
} catch (IOException e) {
throw new JsonIOException(e);
} catch (NumberFormatException e) {
throw new JsonSyntaxException(e);
}
}
/**
* Writes the JSON element to the writer, recursively.
*/
public static void write(JsonElement element, JsonWriter writer) throws IOException {
TypeAdapters.JSON_ELEMENT.write(writer, element);
}
public static Writer writerForAppendable(Appendable appendable) {
return appendable instanceof Writer ? (Writer) appendable : new AppendableWriter(appendable);
}
/**
* Adapts an {@link Appendable} so it can be passed anywhere a {@link Writer}
* is used.
*/
private static final class AppendableWriter extends Writer {
private final Appendable appendable;
private final CurrentWrite currentWrite = new CurrentWrite();
AppendableWriter(Appendable appendable) {
this.appendable = appendable;
}
@Override public void write(char[] chars, int offset, int length) throws IOException {
currentWrite.chars = chars;
appendable.append(currentWrite, offset, offset + length);
}
@Override public void write(int i) throws IOException {
appendable.append((char) i);
}
@Override public void flush() {}
@Override public void close() {}
/**
* A mutable char sequence pointing at a single char[].
*/
static class CurrentWrite implements CharSequence {
char[] chars;
public int length() {
return chars.length;
}
public char charAt(int i) {
return chars[i];
}
public CharSequence subSequence(int start, int end) {
return new String(chars, start, end - start);
}
}
}
}

View File

@ -1,123 +0,0 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.internal;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* Do sneaky things to allocate objects without invoking their constructors.
*
* @author Joel Leitch
* @author Jesse Wilson
*/
public abstract class UnsafeAllocator {
public abstract <T> T newInstance(Class<T> c) throws Exception;
public static UnsafeAllocator create() {
// try JVM
// public class Unsafe {
// public Object allocateInstance(Class<?> type);
// }
try {
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
Field f = unsafeClass.getDeclaredField("theUnsafe");
f.setAccessible(true);
final Object unsafe = f.get(null);
final Method allocateInstance = unsafeClass.getMethod("allocateInstance", Class.class);
return new UnsafeAllocator() {
@Override
@SuppressWarnings("unchecked")
public <T> T newInstance(Class<T> c) throws Exception {
assertInstantiable(c);
return (T) allocateInstance.invoke(unsafe, c);
}
};
} catch (Exception ignored) {
}
// try dalvikvm, post-gingerbread
// public class ObjectStreamClass {
// private static native int getConstructorId(Class<?> c);
// private static native Object newInstance(Class<?> instantiationClass, int methodId);
// }
try {
Method getConstructorId = ObjectStreamClass.class
.getDeclaredMethod("getConstructorId", Class.class);
getConstructorId.setAccessible(true);
final int constructorId = (Integer) getConstructorId.invoke(null, Object.class);
final Method newInstance = ObjectStreamClass.class
.getDeclaredMethod("newInstance", Class.class, int.class);
newInstance.setAccessible(true);
return new UnsafeAllocator() {
@Override
@SuppressWarnings("unchecked")
public <T> T newInstance(Class<T> c) throws Exception {
assertInstantiable(c);
return (T) newInstance.invoke(null, c, constructorId);
}
};
} catch (Exception ignored) {
}
// try dalvikvm, pre-gingerbread
// public class ObjectInputStream {
// private static native Object newInstance(
// Class<?> instantiationClass, Class<?> constructorClass);
// }
try {
final Method newInstance = ObjectInputStream.class
.getDeclaredMethod("newInstance", Class.class, Class.class);
newInstance.setAccessible(true);
return new UnsafeAllocator() {
@Override
@SuppressWarnings("unchecked")
public <T> T newInstance(Class<T> c) throws Exception {
assertInstantiable(c);
return (T) newInstance.invoke(null, c, Object.class);
}
};
} catch (Exception ignored) {
}
// give up
return new UnsafeAllocator() {
@Override
public <T> T newInstance(Class<T> c) {
throw new UnsupportedOperationException("Cannot allocate " + c);
}
};
}
/**
* Check if the class can be instantiated by unsafe allocator. If the instance has interface or abstract modifiers
* throw an {@link java.lang.UnsupportedOperationException}
* @param c instance of the class to be checked
*/
private static void assertInstantiable(Class<?> c) {
int modifiers = c.getModifiers();
if (Modifier.isInterface(modifiers)) {
throw new UnsupportedOperationException("Interface can't be instantiated! Interface name: " + c.getName());
}
if (Modifier.isAbstract(modifiers)) {
throw new UnsupportedOperationException("Abstract class can't be instantiated! Class name: " + c.getName());
}
}
}

View File

@ -1,97 +0,0 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.internal.bind;
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.internal.$Gson$Types;
import com.massivecraft.massivecore.xlib.gson.reflect.TypeToken;
import com.massivecraft.massivecore.xlib.gson.stream.JsonReader;
import com.massivecraft.massivecore.xlib.gson.stream.JsonToken;
import com.massivecraft.massivecore.xlib.gson.stream.JsonWriter;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
/**
* Adapt an array of objects.
*/
public final class ArrayTypeAdapter<E> extends TypeAdapter<Object> {
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
@SuppressWarnings({"unchecked", "rawtypes"})
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
Type type = typeToken.getType();
if (!(type instanceof GenericArrayType || type instanceof Class && ((Class<?>) type).isArray())) {
return null;
}
Type componentType = $Gson$Types.getArrayComponentType(type);
TypeAdapter<?> componentTypeAdapter = gson.getAdapter(TypeToken.get(componentType));
return new ArrayTypeAdapter(
gson, componentTypeAdapter, $Gson$Types.getRawType(componentType));
}
};
private final Class<E> componentType;
private final TypeAdapter<E> componentTypeAdapter;
public ArrayTypeAdapter(Gson context, TypeAdapter<E> componentTypeAdapter, Class<E> componentType) {
this.componentTypeAdapter =
new TypeAdapterRuntimeTypeWrapper<>(context, componentTypeAdapter, componentType);
this.componentType = componentType;
}
@Override public Object read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
List<E> list = new ArrayList<>();
in.beginArray();
while (in.hasNext()) {
E instance = componentTypeAdapter.read(in);
list.add(instance);
}
in.endArray();
Object array = Array.newInstance(componentType, list.size());
for (int i = 0; i < list.size(); i++) {
Array.set(array, i, list.get(i));
}
return array;
}
@SuppressWarnings("unchecked")
@Override public void write(JsonWriter out, Object array) throws IOException {
if (array == null) {
out.nullValue();
return;
}
out.beginArray();
for (int i = 0, length = Array.getLength(array); i < length; i++) {
E value = (E) Array.get(array, i);
componentTypeAdapter.write(out, value);
}
out.endArray();
}
}

View File

@ -1,103 +0,0 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.internal.bind;
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.internal.$Gson$Types;
import com.massivecraft.massivecore.xlib.gson.internal.ConstructorConstructor;
import com.massivecraft.massivecore.xlib.gson.internal.ObjectConstructor;
import com.massivecraft.massivecore.xlib.gson.reflect.TypeToken;
import com.massivecraft.massivecore.xlib.gson.stream.JsonReader;
import com.massivecraft.massivecore.xlib.gson.stream.JsonToken;
import com.massivecraft.massivecore.xlib.gson.stream.JsonWriter;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Collection;
/**
* Adapt a homogeneous collection of objects.
*/
public final class CollectionTypeAdapterFactory implements TypeAdapterFactory {
private final ConstructorConstructor constructorConstructor;
public CollectionTypeAdapterFactory(ConstructorConstructor constructorConstructor) {
this.constructorConstructor = constructorConstructor;
}
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
Type type = typeToken.getType();
Class<? super T> rawType = typeToken.getRawType();
if (!Collection.class.isAssignableFrom(rawType)) {
return null;
}
Type elementType = $Gson$Types.getCollectionElementType(type, rawType);
TypeAdapter<?> elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType));
ObjectConstructor<T> constructor = constructorConstructor.get(typeToken);
@SuppressWarnings({"unchecked", "rawtypes"}) // create() doesn't define a type parameter
TypeAdapter<T> result = new Adapter(gson, elementType, elementTypeAdapter, constructor);
return result;
}
private static final class Adapter<E> extends TypeAdapter<Collection<E>> {
private final TypeAdapter<E> elementTypeAdapter;
private final ObjectConstructor<? extends Collection<E>> constructor;
public Adapter(Gson context, Type elementType,
TypeAdapter<E> elementTypeAdapter,
ObjectConstructor<? extends Collection<E>> constructor) {
this.elementTypeAdapter =
new TypeAdapterRuntimeTypeWrapper<>(context, elementTypeAdapter, elementType);
this.constructor = constructor;
}
@Override public Collection<E> read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
Collection<E> collection = constructor.construct();
in.beginArray();
while (in.hasNext()) {
E instance = elementTypeAdapter.read(in);
collection.add(instance);
}
in.endArray();
return collection;
}
@Override public void write(JsonWriter out, Collection<E> collection) throws IOException {
if (collection == null) {
out.nullValue();
return;
}
out.beginArray();
for (E element : collection) {
elementTypeAdapter.write(out, element);
}
out.endArray();
}
}
}

View File

@ -1,89 +0,0 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.internal.bind;
import com.massivecraft.massivecore.xlib.gson.Gson;
import com.massivecraft.massivecore.xlib.gson.JsonSyntaxException;
import com.massivecraft.massivecore.xlib.gson.TypeAdapter;
import com.massivecraft.massivecore.xlib.gson.TypeAdapterFactory;
import com.massivecraft.massivecore.xlib.gson.internal.bind.util.ISO8601Utils;
import com.massivecraft.massivecore.xlib.gson.reflect.TypeToken;
import com.massivecraft.massivecore.xlib.gson.stream.JsonReader;
import com.massivecraft.massivecore.xlib.gson.stream.JsonToken;
import com.massivecraft.massivecore.xlib.gson.stream.JsonWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.Date;
import java.util.Locale;
/**
* Adapter for Date. Although this class appears stateless, it is not.
* DateFormat captures its time zone and locale when it is created, which gives
* this class state. DateFormat isn't thread safe either, so this class has
* to synchronize its read and write methods.
*/
public final class DateTypeAdapter extends TypeAdapter<Date> {
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
return typeToken.getRawType() == Date.class ? (TypeAdapter<T>) new DateTypeAdapter() : null;
}
};
private final DateFormat enUsFormat
= DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US);
private final DateFormat localFormat
= DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT);
@Override public Date read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
return deserializeToDate(in.nextString());
}
private synchronized Date deserializeToDate(String json) {
try {
return localFormat.parse(json);
} catch (ParseException ignored) {
}
try {
return enUsFormat.parse(json);
} catch (ParseException ignored) {
}
try {
return ISO8601Utils.parse(json, new ParsePosition(0));
} catch (ParseException e) {
throw new JsonSyntaxException(json, e);
}
}
@Override public synchronized void write(JsonWriter out, Date value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
String dateFormatAsString = enUsFormat.format(value);
out.value(dateFormatAsString);
}
}

View File

@ -1,78 +0,0 @@
/*
* Copyright (C) 2014 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.massivecore.xlib.gson.internal.bind;
import com.massivecraft.massivecore.xlib.gson.*;
import com.massivecraft.massivecore.xlib.gson.annotations.JsonAdapter;
import com.massivecraft.massivecore.xlib.gson.internal.ConstructorConstructor;
import com.massivecraft.massivecore.xlib.gson.reflect.TypeToken;
/**
* Given a type T, looks for the annotation {@link JsonAdapter} and uses an instance of the
* specified class as the default type adapter.
*
* @since 2.3
*/
public final class JsonAdapterAnnotationTypeAdapterFactory implements TypeAdapterFactory {
private final ConstructorConstructor constructorConstructor;
public JsonAdapterAnnotationTypeAdapterFactory(ConstructorConstructor constructorConstructor) {
this.constructorConstructor = constructorConstructor;
}
@SuppressWarnings("unchecked")
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> targetType) {
Class<? super T> rawType = targetType.getRawType();
JsonAdapter annotation = rawType.getAnnotation(JsonAdapter.class);
if (annotation == null) {
return null;
}
return (TypeAdapter<T>) getTypeAdapter(constructorConstructor, gson, targetType, annotation);
}
@SuppressWarnings({ "unchecked", "rawtypes" }) // Casts guarded by conditionals.
TypeAdapter<?> getTypeAdapter(ConstructorConstructor constructorConstructor, Gson gson,
TypeToken<?> type, JsonAdapter annotation) {
Object instance = constructorConstructor.get(TypeToken.get(annotation.value())).construct();
TypeAdapter<?> typeAdapter;
if (instance instanceof TypeAdapter) {
typeAdapter = (TypeAdapter<?>) instance;
} else if (instance instanceof TypeAdapterFactory) {
typeAdapter = ((TypeAdapterFactory) instance).create(gson, type);
} else if (instance instanceof JsonSerializer || instance instanceof JsonDeserializer) {
JsonSerializer<?> serializer = instance instanceof JsonSerializer
? (JsonSerializer) instance
: null;
JsonDeserializer<?> deserializer = instance instanceof JsonDeserializer
? (JsonDeserializer) instance
: null;
typeAdapter = new TreeTypeAdapter(serializer, deserializer, gson, type, null);
} else {
throw new IllegalArgumentException(
"@JsonAdapter value must be TypeAdapter, TypeAdapterFactory, "
+ "JsonSerializer or JsonDeserializer reference.");
}
if (typeAdapter != null && annotation.nullSafe()) {
typeAdapter = typeAdapter.nullSafe();
}
return typeAdapter;
}
}

Some files were not shown because too many files have changed in this diff Show More